Add (slow) support for HiRes graphics.

Signed-off-by: Andrea Odetti <mariofutire@gmail.com>
This commit is contained in:
Andrea Odetti 2017-07-09 20:49:26 +01:00
parent 3da7d4ed55
commit c1b7d96dd1
5 changed files with 136 additions and 40 deletions

View file

@ -0,0 +1,63 @@
#include "graphicscache.h"
#include <QPainter>
namespace
{
void halfScanLines(QPixmap & charset)
{
const int height = charset.height();
const int width = charset.width();
const QColor background = charset.toImage().pixelColor(0, height - 1);
QPainter paint(&charset);
paint.setPen(background);
for (int i = 0; i < height; i += 2)
{
paint.drawLine(0, i, width - 1, i);
}
}
QPixmap buildHiResMono()
{
const QColor black(Qt::black);
const QColor white(Qt::white);
QPixmap hires(14, 128 * 2);
hires.fill(black);
QPainter painter(&hires);
for (int i = 0; i < 128; ++i)
{
for (int j = 0; j < 7; ++j)
{
if (i & (1 << j))
{
painter.setPen(white);
}
else
{
painter.setPen(black);
}
painter.drawLine(j * 2, i * 2, j * 2 + 2, i * 2);
}
}
return hires;
}
}
GraphicsCache::GraphicsCache()
{
myCharset40.load(":/resources/CHARSET4.BMP");
halfScanLines(myCharset40);
myCharset80 = myCharset40.scaled(myCharset40.width() / 2, myCharset40.height());
myHiResMono = buildHiResMono();
}

View file

@ -0,0 +1,34 @@
#ifndef GRAPHICSCACHE_H
#define GRAPHICSCACHE_H
#include <QPixmap>
class GraphicsCache
{
public:
GraphicsCache();
const QPixmap & text40Col() const
{
return myCharset40;
}
const QPixmap & text80Col() const
{
return myCharset80;
}
const QPixmap & hires() const
{
return myHiResMono;
}
private:
QPixmap myCharset40;
QPixmap myCharset80;
QPixmap myHiResMono;
};
#endif // GRAPHICSCACHE_H

View file

@ -16,11 +16,13 @@ SOURCES += main.cpp\
qapple.cpp \
qresources.cpp \
emulator.cpp \
video.cpp
video.cpp \
graphicscache.cpp
HEADERS += qapple.h \
emulator.h \
video.h
video.h \
graphicscache.h
FORMS += qapple.ui \
emulator.ui

View file

@ -3,6 +3,8 @@
#include <QPainter>
#include <QKeyEvent>
#include "graphicscache.h"
#include "StdAfx.h"
#include "Video.h"
#include "Memory.h"
@ -24,22 +26,6 @@ namespace
// bool g_bTextFlashState = false;
void halfScanLines(QPixmap & charset)
{
const int height = charset.height();
const int width = charset.width();
const QColor background = charset.toImage().pixelColor(0, height - 1);
QPainter paint(&charset);
paint.setPen(background);
for (int i = 0; i < height; i += 2)
{
paint.drawLine(0, i, width - 1, i);
}
}
BYTE keyCode = 0;
bool keyWaiting = false;
@ -47,46 +33,52 @@ namespace
bool Video::Update40ColCell (QPainter & painter, int x, int y, int xpixel, int ypixel, int offset)
{
Q_UNUSED(xpixel)
Q_UNUSED(ypixel)
Q_UNUSED(x)
Q_UNUSED(y)
BYTE ch = *(g_pTextBank0+offset);
const BYTE ch = *(g_pTextBank0+offset);
const int base = g_nAltCharSetOffset ? 16 : 0;
const int row = ch / 16;
const int column = ch % 16;
const int sx = 16 * column;
const int sy = 16 * row;
painter.drawPixmap(x * 14, y * 16, myCharset40, sx, sy, 14, 16);
const int sy = 16 * (base + row);
const QPixmap & text40Col = myGraphicsCache->text40Col();
painter.drawPixmap(xpixel, ypixel, text40Col, sx, sy, 14, 16);
return true;
}
bool Video::Update80ColCell(QPainter & painter, int x, int y, int xpixel, int ypixel, int offset)
{
Q_UNUSED(xpixel)
Q_UNUSED(ypixel)
Q_UNUSED(x)
Q_UNUSED(y)
const QPixmap & text80Col = myGraphicsCache->text80Col();
{
BYTE ch1 = *(g_pTextBank1+offset);
const BYTE ch1 = *(g_pTextBank1+offset);
const int row = ch1 / 16;
const int column = ch1 % 16;
const int sx = 8 * column;
const int sy = 16 * row;
painter.drawPixmap(x * 14, y * 16, myCharset80, sx, sy, 7, 16);
painter.drawPixmap(xpixel, ypixel, text80Col, sx, sy, 7, 16);
}
{
BYTE ch2 = *(g_pTextBank0+offset);
const BYTE ch2 = *(g_pTextBank0+offset);
const int row = ch2 / 16;
const int column = ch2 % 16;
const int sx = 8 * column;
const int sy = 16 * row;
painter.drawPixmap(x * 14 + 7, y * 16, myCharset80, sx, sy, 7, 16);
painter.drawPixmap(xpixel + 7, ypixel, text80Col, sx, sy, 7, 16);
}
return true;
@ -100,7 +92,7 @@ bool Video::UpdateLoResCell(QPainter & painter, int x, int y, int xpixel, int yp
Q_UNUSED(xpixel)
Q_UNUSED(ypixel)
BYTE val = *(g_pTextBank0+offset);
const BYTE val = *(g_pTextBank0+offset);
Q_UNUSED(val)
@ -121,15 +113,21 @@ bool Video::UpdateDLoResCell(QPainter & painter, int x, int y, int xpixel, int y
bool Video::UpdateHiResCell(QPainter & painter, int x, int y, int xpixel, int ypixel, int offset)
{
Q_UNUSED(painter)
Q_UNUSED(x)
Q_UNUSED(y)
Q_UNUSED(xpixel)
Q_UNUSED(ypixel)
const BYTE * base = g_pHiresBank0 + offset;
const QPixmap & hires = myGraphicsCache->hires();
Q_UNUSED(base)
for (size_t i = 0; i < 8; ++i)
{
const int line = 0x0400 * i;
const BYTE value = *(base + line);
const int row = value & 0x7f;
painter.drawPixmap(xpixel, ypixel + i * 2, hires, 0, row * 2, 14, 2);
}
return true;
}
@ -148,10 +146,7 @@ bool Video::UpdateDHiResCell(QPainter & painter, int x, int y, int xpixel, int y
Video::Video(QWidget *parent) : VIDEO_BASECLASS(parent)
{
myCharset40.load(":/resources/CHARSET4.BMP");
halfScanLines(myCharset40);
myCharset80 = myCharset40.scaled(myCharset40.width() / 2, myCharset40.height());
myGraphicsCache.reset(new GraphicsCache());
}
void Video::paintEvent(QPaintEvent *)

View file

@ -2,10 +2,13 @@
#define VIDEO_H
#include <QOpenGLWidget>
#include <memory>
//#define VIDEO_BASECLASS QOpenGLWidget
#define VIDEO_BASECLASS QWidget
class GraphicsCache;
class Video : public VIDEO_BASECLASS
{
Q_OBJECT
@ -29,8 +32,7 @@ private:
bool UpdateHiResCell(QPainter & painter, int x, int y, int xpixel, int ypixel, int offset);
bool UpdateDHiResCell(QPainter & painter, int x, int y, int xpixel, int ypixel, int offset);
QPixmap myCharset40;
QPixmap myCharset80;
std::shared_ptr<const GraphicsCache> myGraphicsCache;
};
#endif // VIDEO_H