Remove custon video processor in favour of AppleWin's.
Signed-off-by: Andrea Odetti <mariofutire@gmail.com>
This commit is contained in:
parent
d18269fb2d
commit
4792c2eeed
14 changed files with 54 additions and 640 deletions
|
@ -19,8 +19,6 @@ add_executable(qapple
|
||||||
audiogenerator.cpp
|
audiogenerator.cpp
|
||||||
loggingcategory.cpp
|
loggingcategory.cpp
|
||||||
|
|
||||||
graphics/graphicscache.cpp
|
|
||||||
|
|
||||||
qhexedit2/commands.cpp
|
qhexedit2/commands.cpp
|
||||||
qhexedit2/chunks.cpp
|
qhexedit2/chunks.cpp
|
||||||
qhexedit2/qhexedit.cpp
|
qhexedit2/qhexedit.cpp
|
||||||
|
|
|
@ -25,6 +25,11 @@ bool Emulator::saveScreen(const QString & filename) const
|
||||||
return video->getScreen().save(filename);
|
return video->getScreen().save(filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Emulator::displayLogo()
|
||||||
|
{
|
||||||
|
video->displayLogo();
|
||||||
|
}
|
||||||
|
|
||||||
void Emulator::setVideoSize(QMdiSubWindow * window, const QSize & size)
|
void Emulator::setVideoSize(QMdiSubWindow * window, const QSize & size)
|
||||||
{
|
{
|
||||||
window->showNormal();
|
window->showNormal();
|
||||||
|
|
|
@ -16,6 +16,7 @@ public:
|
||||||
void repaintVideo();
|
void repaintVideo();
|
||||||
|
|
||||||
bool saveScreen(const QString & filename) const;
|
bool saveScreen(const QString & filename) const;
|
||||||
|
void displayLogo();
|
||||||
|
|
||||||
void setZoom(QMdiSubWindow * window, const int x);
|
void setZoom(QMdiSubWindow * window, const int x);
|
||||||
void set43AspectRatio(QMdiSubWindow * window);
|
void set43AspectRatio(QMdiSubWindow * window);
|
||||||
|
|
|
@ -1,136 +0,0 @@
|
||||||
#include "graphics/graphicscache.h"
|
|
||||||
|
|
||||||
#include <QPainter>
|
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
|
|
||||||
void halfScanLines(QPaintDevice & charset, const QColor & black)
|
|
||||||
{
|
|
||||||
const int height = charset.height();
|
|
||||||
const int width = charset.width();
|
|
||||||
|
|
||||||
QPainter paint(&charset);
|
|
||||||
paint.setPen(black);
|
|
||||||
|
|
||||||
for (int i = 1; i < height; i += 2)
|
|
||||||
{
|
|
||||||
paint.drawLine(0, i, width - 1, i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GraphicsCache::Image_t buildHiResMono80()
|
|
||||||
{
|
|
||||||
const QColor black(Qt::black);
|
|
||||||
const QColor white(Qt::white);
|
|
||||||
|
|
||||||
GraphicsCache::Image_t hires(GraphicsCache::ScreenPainter_t::create(7, 128 * 2)); // 128 values 2 lines each
|
|
||||||
|
|
||||||
QPainter painter(&hires);
|
|
||||||
|
|
||||||
for (int i = 0; i < 128; ++i)
|
|
||||||
{
|
|
||||||
for (int j = 0; j < 7; ++j)
|
|
||||||
{
|
|
||||||
const QColor & color = (i & (1 << j)) ? white : black;
|
|
||||||
painter.fillRect(j, i * 2, 1, 2, color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return hires;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum LoResColor {
|
|
||||||
BLACK,
|
|
||||||
DEEP_RED,
|
|
||||||
DARK_BLUE,
|
|
||||||
MAGENTA,
|
|
||||||
DARK_GREEN,
|
|
||||||
DARK_GRAY,
|
|
||||||
BLUE,
|
|
||||||
LIGHT_BLUE,
|
|
||||||
BROWN,
|
|
||||||
ORANGE,
|
|
||||||
LIGHT_GRAY,
|
|
||||||
PINK,
|
|
||||||
GREEN,
|
|
||||||
YELLOW,
|
|
||||||
AQUA,
|
|
||||||
WHITE
|
|
||||||
};
|
|
||||||
|
|
||||||
#define SETFRAMECOLOR(c, r, g, b) colors[c].setRgb(r, g, b)
|
|
||||||
|
|
||||||
GraphicsCache::Image_t buildLoResColor80()
|
|
||||||
{
|
|
||||||
std::vector<QColor> colors(16);
|
|
||||||
|
|
||||||
SETFRAMECOLOR(BLACK, 0x00,0x00,0x00); // 0
|
|
||||||
SETFRAMECOLOR(DEEP_RED, 0x9D,0x09,0x66); // 0xD0,0x00,0x30 -> Linards Tweaked 0x9D,0x09,0x66
|
|
||||||
SETFRAMECOLOR(DARK_BLUE, 0x00,0x00,0x80); // 4 // not used
|
|
||||||
SETFRAMECOLOR(MAGENTA, 0xC7,0x34,0xFF); // FD Linards Tweaked 0xFF,0x00,0xFF -> 0xC7,0x34,0xFF
|
|
||||||
|
|
||||||
SETFRAMECOLOR(DARK_GREEN, 0x00,0x80,0x00); // 2 // not used
|
|
||||||
SETFRAMECOLOR(DARK_GRAY, 0x80,0x80,0x80); // F8
|
|
||||||
SETFRAMECOLOR(BLUE, 0x0D,0xA1,0xFF); // FC Linards Tweaked 0x00,0x00,0xFF -> 0x0D,0xA1,0xFF
|
|
||||||
SETFRAMECOLOR(LIGHT_BLUE, 0xAA,0xAA,0xFF); // 0x60,0xA0,0xFF -> Linards Tweaked 0xAA,0xAA,0xFF
|
|
||||||
|
|
||||||
SETFRAMECOLOR(BROWN, 0x55,0x55,0x00); // 0x80,0x50,0x00 -> Linards Tweaked 0x55,0x55,0x00
|
|
||||||
SETFRAMECOLOR(ORANGE, 0xF2,0x5E,0x00); // 0xFF,0x80,0x00 -> Linards Tweaked 0xF2,0x5E,0x00
|
|
||||||
SETFRAMECOLOR(LIGHT_GRAY, 0xC0,0xC0,0xC0); // 7 // GR: COLOR=10
|
|
||||||
SETFRAMECOLOR(PINK, 0xFF,0x89,0xE5); // 0xFF,0x90,0x80 -> Linards Tweaked 0xFF,0x89,0xE5
|
|
||||||
|
|
||||||
SETFRAMECOLOR(GREEN, 0x38,0xCB,0x00); // FA Linards Tweaked 0x00,0xFF,0x00 -> 0x38,0xCB,0x00
|
|
||||||
SETFRAMECOLOR(YELLOW, 0xD5,0xD5,0x1A); // FB Linards Tweaked 0xFF,0xFF,0x00 -> 0xD5,0xD5,0x1A
|
|
||||||
SETFRAMECOLOR(AQUA, 0x62,0xF6,0x99); // 0x40,0xFF,0x90 -> Linards Tweaked 0x62,0xF6,0x99
|
|
||||||
SETFRAMECOLOR(WHITE, 0xFF,0xFF,0xFF); // FF
|
|
||||||
|
|
||||||
|
|
||||||
GraphicsCache::Image_t lores(GraphicsCache::ScreenPainter_t::create(7, 256 * 16)); // 128 values 2 lines each
|
|
||||||
|
|
||||||
QPainter painter(&lores);
|
|
||||||
|
|
||||||
for (int i = 0; i < 256; ++i)
|
|
||||||
{
|
|
||||||
const int top = i & 0b1111;
|
|
||||||
const int bottom = (i >> 4) & 0b1111;
|
|
||||||
|
|
||||||
painter.fillRect(0, i * 16, 7, 8, colors[top]);
|
|
||||||
painter.fillRect(0, i * 16 + 8, 7, 8, colors[bottom]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return lores;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GraphicsCache::GraphicsCache()
|
|
||||||
{
|
|
||||||
const QColor black(Qt::black);
|
|
||||||
|
|
||||||
myCharset40.load(":/resources/CHARSET4.BMP");
|
|
||||||
GraphicsCache::ScreenPainter_t::convert(myCharset40);
|
|
||||||
|
|
||||||
halfScanLines(myCharset40, black);
|
|
||||||
|
|
||||||
myCharset80 = myCharset40.scaled(myCharset40.width() / 2, myCharset40.height());
|
|
||||||
// it was already half scan
|
|
||||||
|
|
||||||
myHiResMono80 = buildHiResMono80();
|
|
||||||
halfScanLines(myHiResMono80, black);
|
|
||||||
|
|
||||||
myHiResMono40 = myHiResMono80.scaled(myHiResMono80.width() * 2, myHiResMono80.height());
|
|
||||||
// it was already half scan
|
|
||||||
|
|
||||||
myLoResColor80 = buildLoResColor80();
|
|
||||||
halfScanLines(myLoResColor80, black);
|
|
||||||
|
|
||||||
myLoResColor40 = myLoResColor80.scaled(myLoResColor80.width() * 2, myLoResColor80.height());
|
|
||||||
// it was already half scan
|
|
||||||
}
|
|
||||||
|
|
||||||
GraphicsCache::Image_t GraphicsCache::createBlackScreenImage()
|
|
||||||
{
|
|
||||||
GraphicsCache::Image_t screen = GraphicsCache::ScreenPainter_t::create(40 * 7 * 2, 24 * 8 * 2);
|
|
||||||
screen.fill(Qt::black);
|
|
||||||
return screen;
|
|
||||||
}
|
|
|
@ -1,60 +0,0 @@
|
||||||
#ifndef GRAPHICSCACHE_H
|
|
||||||
#define GRAPHICSCACHE_H
|
|
||||||
|
|
||||||
#include <QPixmap>
|
|
||||||
#include <QImage>
|
|
||||||
|
|
||||||
#include "graphics/painters.h"
|
|
||||||
|
|
||||||
class GraphicsCache
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
GraphicsCache();
|
|
||||||
|
|
||||||
typedef FastPainter ScreenPainter_t;
|
|
||||||
typedef ScreenPainter_t::Source_t Image_t;
|
|
||||||
|
|
||||||
static Image_t createBlackScreenImage();
|
|
||||||
|
|
||||||
const Image_t & text40Col() const
|
|
||||||
{
|
|
||||||
return myCharset40;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Image_t & text80Col() const
|
|
||||||
{
|
|
||||||
return myCharset80;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Image_t & hires40() const
|
|
||||||
{
|
|
||||||
return myHiResMono40;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Image_t & hires80() const
|
|
||||||
{
|
|
||||||
return myHiResMono80;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Image_t & lores40() const
|
|
||||||
{
|
|
||||||
return myLoResColor40;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Image_t & lores80() const
|
|
||||||
{
|
|
||||||
return myLoResColor80;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Image_t myCharset40;
|
|
||||||
Image_t myCharset80;
|
|
||||||
|
|
||||||
Image_t myHiResMono40;
|
|
||||||
Image_t myHiResMono80;
|
|
||||||
|
|
||||||
Image_t myLoResColor40;
|
|
||||||
Image_t myLoResColor80;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // GRAPHICSCACHE_H
|
|
|
@ -1,115 +0,0 @@
|
||||||
#ifndef PAINTERS_H
|
|
||||||
#define PAINTERS_H
|
|
||||||
|
|
||||||
#include <QImage>
|
|
||||||
#include <QPixmap>
|
|
||||||
#include <QPainter>
|
|
||||||
|
|
||||||
inline void drawAny(QPainter & painter, const QPixmap & image)
|
|
||||||
{
|
|
||||||
painter.drawPixmap(0, 0, image);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void drawAny(QPainter & painter, const QImage & image)
|
|
||||||
{
|
|
||||||
painter.drawImage(0, 0, image);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline QPixmap toPixmap(const QPixmap & image)
|
|
||||||
{
|
|
||||||
return image;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline QPixmap toPixmap(const QImage & image)
|
|
||||||
{
|
|
||||||
return QPixmap::fromImage(image);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class FastPainter
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef QImage Source_t;
|
|
||||||
|
|
||||||
FastPainter(QImage * image)
|
|
||||||
: myImage(image)
|
|
||||||
{
|
|
||||||
myBits = myImage->bits();
|
|
||||||
myBytesPerLine = myImage->bytesPerLine();
|
|
||||||
|
|
||||||
const QPixelFormat format = myImage->pixelFormat();
|
|
||||||
myBytesPerPixel = format.bitsPerPixel() / 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
void draw(int x, int y, const QImage & source, int sx, int sy, int wx, int wy)
|
|
||||||
{
|
|
||||||
// this only works if the 2 images have the same format
|
|
||||||
const int destOffset = x * myBytesPerPixel;
|
|
||||||
const int sourceOffset = sx * myBytesPerPixel;
|
|
||||||
const int length = wx * myBytesPerPixel;
|
|
||||||
|
|
||||||
const int sourceBytesPerLine = source.bytesPerLine();
|
|
||||||
const uchar * sourceBits = source.bits();
|
|
||||||
|
|
||||||
for (int iy = 0; iy < wy; iy += 1)
|
|
||||||
{
|
|
||||||
const uchar * sourceLine = sourceBits + sourceBytesPerLine * (sy + iy);
|
|
||||||
uchar * destLine = myBits + myBytesPerLine * (y + iy);
|
|
||||||
memcpy(destLine + destOffset, sourceLine + sourceOffset, length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static QImage create(int width, int height)
|
|
||||||
{
|
|
||||||
return QImage(width, height, theFormat);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void convert(QImage & image)
|
|
||||||
{
|
|
||||||
image = image.convertToFormat(theFormat);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
static const QImage::Format theFormat = QImage::Format_RGB32;
|
|
||||||
|
|
||||||
QImage * myImage;
|
|
||||||
|
|
||||||
uchar * myBits;
|
|
||||||
int myBytesPerPixel;
|
|
||||||
int myBytesPerLine;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Painter : QPainter
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef QPixmap Source_t;
|
|
||||||
//typedef QImage Source_t;
|
|
||||||
|
|
||||||
Painter(QPaintDevice * image)
|
|
||||||
: QPainter(image)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void draw(int x, int y, const QImage & source, int sx, int sy, int wx, int wy)
|
|
||||||
{
|
|
||||||
drawImage(x, y, source, sx, sy, wx, wy);
|
|
||||||
}
|
|
||||||
|
|
||||||
void draw(int x, int y, const QPixmap & source, int sx, int sy, int wx, int wy)
|
|
||||||
{
|
|
||||||
drawPixmap(x, y, source, sx, sy, wx, wy);
|
|
||||||
}
|
|
||||||
|
|
||||||
static QPixmap create(int width, int height)
|
|
||||||
{
|
|
||||||
return QPixmap(width, height);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void convert(Source_t & image)
|
|
||||||
{
|
|
||||||
Q_UNUSED(image)
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // PAINTERS_H
|
|
|
@ -53,7 +53,7 @@ namespace
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void startEmulator(QWidget * window)
|
void startEmulator(QWidget * window, Emulator * emulator)
|
||||||
{
|
{
|
||||||
LoadConfiguration();
|
LoadConfiguration();
|
||||||
|
|
||||||
|
@ -86,6 +86,9 @@ namespace
|
||||||
|
|
||||||
MemInitialize();
|
MemInitialize();
|
||||||
VideoInitialize();
|
VideoInitialize();
|
||||||
|
|
||||||
|
emulator->displayLogo();
|
||||||
|
|
||||||
sg_Disk2Card.Reset();
|
sg_Disk2Card.Reset();
|
||||||
HD_Reset();
|
HD_Reset();
|
||||||
}
|
}
|
||||||
|
@ -204,7 +207,7 @@ QApple::QApple(QWidget *parent) :
|
||||||
|
|
||||||
on_actionPause_triggered();
|
on_actionPause_triggered();
|
||||||
initialiseEmulator();
|
initialiseEmulator();
|
||||||
startEmulator(myEmulatorWindow);
|
startEmulator(myEmulatorWindow, myEmulator);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QApple::closeEvent(QCloseEvent *)
|
void QApple::closeEvent(QCloseEvent *)
|
||||||
|
@ -331,7 +334,7 @@ void QApple::on_actionReboot_triggered()
|
||||||
{
|
{
|
||||||
emit endEmulator();
|
emit endEmulator();
|
||||||
stopEmulator();
|
stopEmulator();
|
||||||
startEmulator(myEmulatorWindow);
|
startEmulator(myEmulatorWindow, myEmulator);
|
||||||
myEmulatorWindow->setWindowTitle(QString::fromStdString(g_pAppTitle));
|
myEmulatorWindow->setWindowTitle(QString::fromStdString(g_pAppTitle));
|
||||||
myEmulator->updateVideo();
|
myEmulator->updateVideo();
|
||||||
restartTimeCounters();
|
restartTimeCounters();
|
||||||
|
|
|
@ -12,7 +12,6 @@ TEMPLATE = app
|
||||||
|
|
||||||
SOURCES += main.cpp\
|
SOURCES += main.cpp\
|
||||||
audiogenerator.cpp \
|
audiogenerator.cpp \
|
||||||
graphics/graphicscache.cpp \
|
|
||||||
loggingcategory.cpp \
|
loggingcategory.cpp \
|
||||||
qapple.cpp \
|
qapple.cpp \
|
||||||
qresources.cpp \
|
qresources.cpp \
|
||||||
|
@ -30,8 +29,6 @@ SOURCES += main.cpp\
|
||||||
HEADERS += qapple.h \
|
HEADERS += qapple.h \
|
||||||
audiogenerator.h \
|
audiogenerator.h \
|
||||||
emulator.h \
|
emulator.h \
|
||||||
graphics/graphicscache.h \
|
|
||||||
graphics/painters.h \
|
|
||||||
loggingcategory.h \
|
loggingcategory.h \
|
||||||
video.h \
|
video.h \
|
||||||
graphicscache.h \
|
graphicscache.h \
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
<file alias="resources/CHARSET82.BMP">resources/CHARSET82.bmp</file>
|
<file alias="resources/CHARSET82.BMP">resources/CHARSET82.bmp</file>
|
||||||
<file alias="resources/CHARSET8M.BMP">resources/CHARSET8M.bmp</file>
|
<file alias="resources/CHARSET8M.BMP">resources/CHARSET8M.bmp</file>
|
||||||
<file alias="resources/CHARSET8C.BMP">resources/CHARSET8C.bmp</file>
|
<file alias="resources/CHARSET8C.BMP">resources/CHARSET8C.bmp</file>
|
||||||
|
<file alias="resources/APPLEWINLOGO.BMP">resources/ApplewinLogo.bmp</file>
|
||||||
<file>resources/DISK2.rom</file>
|
<file>resources/DISK2.rom</file>
|
||||||
<file>resources/Hddrvr.bin</file>
|
<file>resources/Hddrvr.bin</file>
|
||||||
<file>resources/Parallel.rom</file>
|
<file>resources/Parallel.rom</file>
|
||||||
|
|
1
source/frontends/qapple/resources/ApplewinLogo.bmp
Symbolic link
1
source/frontends/qapple/resources/ApplewinLogo.bmp
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../../../../resource/ApplewinLogo.bmp
|
|
@ -3,228 +3,66 @@
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include <QKeyEvent>
|
#include <QKeyEvent>
|
||||||
|
|
||||||
#include "graphics/graphicscache.h"
|
|
||||||
|
|
||||||
#include "StdAfx.h"
|
#include "StdAfx.h"
|
||||||
#include "Video.h"
|
|
||||||
#include "Memory.h"
|
|
||||||
#include "linux/data.h"
|
#include "linux/data.h"
|
||||||
#include "MouseInterface.h"
|
#include "MouseInterface.h"
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
LPBYTE g_pTextBank1; // Aux
|
|
||||||
LPBYTE g_pTextBank0; // Main
|
|
||||||
LPBYTE g_pHiresBank1;
|
|
||||||
LPBYTE g_pHiresBank0;
|
|
||||||
|
|
||||||
#define SW_80COL (g_uVideoMode & VF_80COL)
|
|
||||||
#define SW_DHIRES (g_uVideoMode & VF_DHIRES)
|
|
||||||
#define SW_HIRES (g_uVideoMode & VF_HIRES)
|
|
||||||
#define SW_80STORE (g_uVideoMode & VF_80STORE)
|
|
||||||
#define SW_MIXED (g_uVideoMode & VF_MIXED)
|
|
||||||
#define SW_PAGE2 (g_uVideoMode & VF_PAGE2)
|
|
||||||
#define SW_TEXT (g_uVideoMode & VF_TEXT)
|
|
||||||
|
|
||||||
// bool g_bTextFlashState = false;
|
|
||||||
|
|
||||||
BYTE keyCode = 0;
|
BYTE keyCode = 0;
|
||||||
bool keyWaiting = false;
|
bool keyWaiting = false;
|
||||||
|
|
||||||
BYTE ROL_NIB(BYTE x)
|
|
||||||
{
|
|
||||||
return ((x << 1) & 0x0F) | ((x >> 3) & 0x01);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Video::Update40ColCell (ScreenPainter_t & painter, int x, int y, int xpixel, int ypixel, int offset)
|
|
||||||
{
|
|
||||||
Q_UNUSED(x)
|
|
||||||
Q_UNUSED(y)
|
|
||||||
|
|
||||||
const GraphicsCache::Image_t & text40Col = myGraphicsCache->text40Col();
|
|
||||||
|
|
||||||
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 * (base + row);
|
|
||||||
|
|
||||||
painter.draw(xpixel, ypixel, text40Col, sx, sy, 14, 16);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Video::Update80ColCell(ScreenPainter_t & painter, int x, int y, int xpixel, int ypixel, int offset)
|
|
||||||
{
|
|
||||||
Q_UNUSED(x)
|
|
||||||
Q_UNUSED(y)
|
|
||||||
|
|
||||||
const GraphicsCache::Image_t & text80Col = myGraphicsCache->text80Col();
|
|
||||||
|
|
||||||
const int base = g_nAltCharSetOffset ? 16 : 0;
|
|
||||||
|
|
||||||
{
|
|
||||||
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 + base);
|
|
||||||
painter.draw(xpixel, ypixel, text80Col, sx, sy, 7, 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
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 + base);
|
|
||||||
painter.draw(xpixel + 7, ypixel, text80Col, sx, sy, 7, 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Video::UpdateLoResCell(ScreenPainter_t & painter, int x, int y, int xpixel, int ypixel, int offset)
|
|
||||||
{
|
|
||||||
Q_UNUSED(x)
|
|
||||||
Q_UNUSED(y)
|
|
||||||
|
|
||||||
const GraphicsCache::Image_t & lores = myGraphicsCache->lores40();
|
|
||||||
|
|
||||||
const BYTE ch = *(g_pTextBank0 + offset);
|
|
||||||
|
|
||||||
const int sx = 0;
|
|
||||||
const int sy = ch * 16;
|
|
||||||
|
|
||||||
painter.draw(xpixel, ypixel, lores, sx, sy, 14, 16);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Video::UpdateDLoResCell(ScreenPainter_t & painter, int x, int y, int xpixel, int ypixel, int offset)
|
|
||||||
{
|
|
||||||
Q_UNUSED(x)
|
|
||||||
Q_UNUSED(y)
|
|
||||||
|
|
||||||
const GraphicsCache::Image_t & lores = myGraphicsCache->lores80();
|
|
||||||
|
|
||||||
{
|
|
||||||
BYTE ch = *(g_pTextBank1 + offset);
|
|
||||||
|
|
||||||
const BYTE ch_high = ch >> 4;
|
|
||||||
const BYTE ch_low = ch & 0x0F;
|
|
||||||
ch = (ROL_NIB(ch_high) << 4) | ROL_NIB(ch_low);
|
|
||||||
|
|
||||||
const int sx = 0;
|
|
||||||
const int sy = ch * 16;
|
|
||||||
|
|
||||||
painter.draw(xpixel, ypixel, lores, sx, sy, 7, 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
const BYTE ch = *(g_pTextBank0 + offset);
|
|
||||||
|
|
||||||
const int sx = 0;
|
|
||||||
const int sy = ch * 16;
|
|
||||||
|
|
||||||
painter.draw(xpixel + 7, ypixel, lores, sx, sy, 7, 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Video::UpdateHiResCell(ScreenPainter_t & painter, int x, int y, int xpixel, int ypixel, int offset)
|
|
||||||
{
|
|
||||||
Q_UNUSED(x)
|
|
||||||
Q_UNUSED(y)
|
|
||||||
|
|
||||||
const BYTE * base = g_pHiresBank0 + offset;
|
|
||||||
const GraphicsCache::Image_t & hires = myGraphicsCache->hires40();
|
|
||||||
|
|
||||||
for (size_t i = 0; i < 8; ++i)
|
|
||||||
{
|
|
||||||
const int line = 0x0400 * i;
|
|
||||||
const BYTE value = *(base + line);
|
|
||||||
|
|
||||||
const int row = value & 0x7f;
|
|
||||||
|
|
||||||
painter.draw(xpixel, ypixel + i * 2, hires, 0, row * 2, 14, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Video::UpdateDHiResCell(ScreenPainter_t & painter, int x, int y, int xpixel, int ypixel, int offset)
|
|
||||||
{
|
|
||||||
Q_UNUSED(x)
|
|
||||||
Q_UNUSED(y)
|
|
||||||
|
|
||||||
const GraphicsCache::Image_t & dhires = myGraphicsCache->hires80();
|
|
||||||
|
|
||||||
{
|
|
||||||
const BYTE * base = g_pHiresBank1 + offset;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < 8; ++i)
|
|
||||||
{
|
|
||||||
const int line = 0x0400 * i;
|
|
||||||
const BYTE value = *(base + line);
|
|
||||||
|
|
||||||
const int row = value & 0x7f;
|
|
||||||
|
|
||||||
painter.draw(xpixel, ypixel + i * 2, dhires, 0, row * 2, 7, 2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
const BYTE * base = g_pHiresBank0 + offset;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < 8; ++i)
|
|
||||||
{
|
|
||||||
const int line = 0x0400 * i;
|
|
||||||
const BYTE value = *(base + line);
|
|
||||||
|
|
||||||
const int row = value & 0x7f;
|
|
||||||
|
|
||||||
painter.draw(xpixel + 7, ypixel + i * 2, dhires, 0, row * 2, 7, 2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Video::Video(QWidget *parent) : VIDEO_BASECLASS(parent)
|
Video::Video(QWidget *parent) : VIDEO_BASECLASS(parent)
|
||||||
{
|
{
|
||||||
myGraphicsCache.reset(new GraphicsCache());
|
|
||||||
setMouseTracking(true);
|
setMouseTracking(true);
|
||||||
|
|
||||||
myOffscreen = GraphicsCache::createBlackScreenImage();
|
myLogo = QImage(":/resources/APPLEWINLOGO.BMP").mirrored(false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Video::paintEvent(QPaintEvent *)
|
QImage Video::getScreen() const
|
||||||
{
|
{
|
||||||
paintEventNTSC();
|
uint8_t * data;
|
||||||
}
|
|
||||||
|
|
||||||
void Video::paintEventNTSC()
|
|
||||||
{
|
|
||||||
const uint8_t * data;
|
|
||||||
int width;
|
int width;
|
||||||
int height;
|
int height;
|
||||||
int sx, sy;
|
int sx, sy;
|
||||||
int sw, sh;
|
int sw, sh;
|
||||||
|
|
||||||
getScreenData(data, width, height, sx, sy, sw, sh);
|
getScreenData(data, width, height, sx, sy, sw, sh);
|
||||||
|
QImage frameBuffer(data, width, height, QImage::Format_RGB32);
|
||||||
|
|
||||||
myFrameBuffer = QImage(data, width, height, QImage::Format_RGB32);
|
QImage screen = frameBuffer.copy(sx, sy, sw, sh);
|
||||||
|
|
||||||
|
return screen;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Video::displayLogo()
|
||||||
|
{
|
||||||
|
uint8_t * data;
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
int sx, sy;
|
||||||
|
int sw, sh;
|
||||||
|
|
||||||
|
getScreenData(data, width, height, sx, sy, sw, sh);
|
||||||
|
QImage frameBuffer(data, width, height, QImage::Format_RGB32);
|
||||||
|
|
||||||
|
QPainter painter(&frameBuffer);
|
||||||
|
painter.drawImage(sx, sy, myLogo);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Video::paintEvent(QPaintEvent *)
|
||||||
|
{
|
||||||
|
uint8_t * data;
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
int sx, sy;
|
||||||
|
int sw, sh;
|
||||||
|
|
||||||
|
getScreenData(data, width, height, sx, sy, sw, sh);
|
||||||
|
QImage frameBuffer(data, width, height, QImage::Format_RGB32);
|
||||||
|
|
||||||
const QSize actual = size();
|
const QSize actual = size();
|
||||||
const double scaleX = double(actual.width()) / sw;
|
const double scaleX = double(actual.width()) / sw;
|
||||||
|
@ -238,104 +76,7 @@ void Video::paintEventNTSC()
|
||||||
const QTransform transform(scaleX, 0.0, 0.0, -scaleY, 0.0, actual.height());
|
const QTransform transform(scaleX, 0.0, 0.0, -scaleY, 0.0, actual.height());
|
||||||
painter.setTransform(transform);
|
painter.setTransform(transform);
|
||||||
|
|
||||||
painter.drawImage(0, 0, myFrameBuffer, sx, sy, sw, sh);
|
painter.drawImage(0, 0, frameBuffer, sx, sy, sw, sh);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Video::paintEventInternal()
|
|
||||||
{
|
|
||||||
/* How to make this faster
|
|
||||||
* 1) Do not call Video::paint() with a scale != 1:1
|
|
||||||
* 2) For this reason we need to draw elsewhere
|
|
||||||
* 3) and finally scale the whole thing just once to the widget
|
|
||||||
* 4) QPixmap vs QImage: cant see the difference
|
|
||||||
* 5) QOpenGLWidget is 2x faster than QWidget but it has some flickering when resizing
|
|
||||||
*
|
|
||||||
* On my i5-4460 CPU @ 3.20GHz with x2 zoom
|
|
||||||
* TEXT: 4-5% CPU usage
|
|
||||||
* HGR: 6-7% CPU usage
|
|
||||||
*/
|
|
||||||
|
|
||||||
// first draw the image offscreen 1:1
|
|
||||||
{
|
|
||||||
ScreenPainter_t painter(&myOffscreen);
|
|
||||||
paint(painter);
|
|
||||||
}
|
|
||||||
|
|
||||||
const QSize min = myOffscreen.size();
|
|
||||||
const QSize actual = size();
|
|
||||||
const double sx = double(actual.width()) / double(min.width());
|
|
||||||
const double sy = double(actual.height()) / double(min.height());
|
|
||||||
|
|
||||||
// then paint it on the widget with scale
|
|
||||||
{
|
|
||||||
QPainter painter(this);
|
|
||||||
painter.scale(sx, sy);
|
|
||||||
drawAny(painter, myOffscreen);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GraphicsCache::Image_t Video::getScreen() const
|
|
||||||
{
|
|
||||||
return myOffscreen;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Video::paint(ScreenPainter_t & painter)
|
|
||||||
{
|
|
||||||
const int displaypage2 = (SW_PAGE2) == 0 ? 0 : 1;
|
|
||||||
|
|
||||||
g_pHiresBank1 = MemGetAuxPtr (0x2000 << displaypage2);
|
|
||||||
g_pHiresBank0 = MemGetMainPtr(0x2000 << displaypage2);
|
|
||||||
g_pTextBank1 = MemGetAuxPtr (0x400 << displaypage2);
|
|
||||||
g_pTextBank0 = MemGetMainPtr(0x400 << displaypage2);
|
|
||||||
|
|
||||||
typedef bool (Video::*VideoUpdateFuncPtr_t)(ScreenPainter_t&,int,int,int,int,int);
|
|
||||||
|
|
||||||
VideoUpdateFuncPtr_t update = SW_TEXT
|
|
||||||
? SW_80COL
|
|
||||||
? &Video::Update80ColCell
|
|
||||||
: &Video::Update40ColCell
|
|
||||||
: SW_HIRES
|
|
||||||
? (SW_DHIRES && SW_80COL)
|
|
||||||
? &Video::UpdateDHiResCell
|
|
||||||
: &Video::UpdateHiResCell
|
|
||||||
: (SW_DHIRES && SW_80COL)
|
|
||||||
? &Video::UpdateDLoResCell
|
|
||||||
: &Video::UpdateLoResCell;
|
|
||||||
|
|
||||||
int y = 0;
|
|
||||||
int ypixel = 0;
|
|
||||||
while (y < 20)
|
|
||||||
{
|
|
||||||
int offset = ((y & 7) << 7) + ((y >> 3) * 40);
|
|
||||||
int x = 0;
|
|
||||||
int xpixel = 0;
|
|
||||||
while (x < 40)
|
|
||||||
{
|
|
||||||
(this->*update)(painter, x, y, xpixel, ypixel, offset + x);
|
|
||||||
++x;
|
|
||||||
xpixel += 14;
|
|
||||||
}
|
|
||||||
++y;
|
|
||||||
ypixel += 16;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SW_MIXED)
|
|
||||||
update = SW_80COL ? &Video::Update80ColCell : &Video::Update40ColCell;
|
|
||||||
|
|
||||||
while (y < 24)
|
|
||||||
{
|
|
||||||
int offset = ((y & 7) << 7) + ((y >> 3) * 40);
|
|
||||||
int x = 0;
|
|
||||||
int xpixel = 0;
|
|
||||||
while (x < 40)
|
|
||||||
{
|
|
||||||
(this->*update)(painter, x, y, xpixel, ypixel, offset + x);
|
|
||||||
++x;
|
|
||||||
xpixel += 14;
|
|
||||||
}
|
|
||||||
++y;
|
|
||||||
ypixel += 16;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,9 +2,6 @@
|
||||||
#define VIDEO_H
|
#define VIDEO_H
|
||||||
|
|
||||||
#include <QOpenGLWidget>
|
#include <QOpenGLWidget>
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
#include "graphics/graphicscache.h"
|
|
||||||
|
|
||||||
#define VIDEO_BASECLASS QOpenGLWidget
|
#define VIDEO_BASECLASS QOpenGLWidget
|
||||||
//#define VIDEO_BASECLASS QWidget
|
//#define VIDEO_BASECLASS QWidget
|
||||||
|
@ -14,12 +11,10 @@ class Video : public VIDEO_BASECLASS
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
typedef GraphicsCache::ScreenPainter_t ScreenPainter_t;
|
|
||||||
typedef GraphicsCache::Image_t Image_t;
|
|
||||||
|
|
||||||
explicit Video(QWidget *parent = 0);
|
explicit Video(QWidget *parent = 0);
|
||||||
|
|
||||||
Image_t getScreen() const;
|
QImage getScreen() const;
|
||||||
|
void displayLogo();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
|
@ -34,24 +29,7 @@ protected:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
bool Update40ColCell(ScreenPainter_t & painter, int x, int y, int xpixel, int ypixel, int offset);
|
QImage myLogo;
|
||||||
bool Update80ColCell(ScreenPainter_t & painter, int x, int y, int xpixel, int ypixel, int offset);
|
|
||||||
bool UpdateLoResCell(ScreenPainter_t & painter, int x, int y, int xpixel, int ypixel, int offset);
|
|
||||||
bool UpdateDLoResCell(ScreenPainter_t & painter, int x, int y, int xpixel, int ypixel, int offset);
|
|
||||||
bool UpdateHiResCell(ScreenPainter_t & painter, int x, int y, int xpixel, int ypixel, int offset);
|
|
||||||
bool UpdateDHiResCell(ScreenPainter_t & painter, int x, int y, int xpixel, int ypixel, int offset);
|
|
||||||
|
|
||||||
// paint the whole screen
|
|
||||||
// no scale applied
|
|
||||||
void paint(ScreenPainter_t & painter);
|
|
||||||
|
|
||||||
void paintEventInternal();
|
|
||||||
void paintEventNTSC();
|
|
||||||
|
|
||||||
std::shared_ptr<const GraphicsCache> myGraphicsCache;
|
|
||||||
Image_t myOffscreen;
|
|
||||||
|
|
||||||
QImage myFrameBuffer;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // VIDEO_H
|
#endif // VIDEO_H
|
||||||
|
|
|
@ -4,4 +4,4 @@ void LoadConfiguration(void);
|
||||||
void CheckCpu();
|
void CheckCpu();
|
||||||
void SetWindowTitle();
|
void SetWindowTitle();
|
||||||
|
|
||||||
void getScreenData(const uint8_t * & data, int & width, int & height, int & sx, int & sy, int & sw, int & sh);
|
void getScreenData(uint8_t * & data, int & width, int & height, int & sx, int & sy, int & sw, int & sh);
|
||||||
|
|
|
@ -513,7 +513,7 @@ static void videoCreateDIBSection()
|
||||||
NTSC_VideoInit( g_pFramebufferbits );
|
NTSC_VideoInit( g_pFramebufferbits );
|
||||||
}
|
}
|
||||||
|
|
||||||
void getScreenData(const uint8_t * & data, int & width, int & height, int & sx, int & sy, int & sw, int & sh)
|
void getScreenData(uint8_t * & data, int & width, int & height, int & sx, int & sy, int & sw, int & sh)
|
||||||
{
|
{
|
||||||
data = g_pFramebufferbits;
|
data = g_pFramebufferbits;
|
||||||
width = GetFrameBufferWidth();
|
width = GetFrameBufferWidth();
|
||||||
|
|
Loading…
Add table
Reference in a new issue