Added NTSC emulation for HiresViewWidget.

This commit is contained in:
Mark Long 2016-01-20 20:58:48 -06:00
parent 808cbc32c5
commit 0d40a0f264
11 changed files with 364 additions and 66 deletions

View File

@ -14,6 +14,9 @@ INCLUDEPATH += src/applesoftfile
INCLUDEPATH += src/binaryfile
INCLUDEPATH += src/ui
INCLUDEPATH += src/ui/viewers
INCLUDEPATH += src/imported
DEFINES += WS_VIDEO
SOURCES += \
src/main.cpp \
@ -33,7 +36,8 @@ SOURCES += \
src/ui/mainwindow.cxx \
src/ui/viewers/hiresviewwidget.cxx \
src/ui/viewers/applesoftfileviewer.cxx \
src/applesoftfile/applesoftformatter.cxx
src/applesoftfile/applesoftformatter.cxx \
src/applesoftfile/applesoftline.cpp
HEADERS += \
src/diskfiles/dos33/diskfile.h \
@ -53,7 +57,8 @@ HEADERS += \
src/ui/mainwindow.h \
src/ui/viewers/hiresviewwidget.h \
src/ui/viewers/applesoftfileviewer.h \
src/applesoftfile/applesoftformatter.h
src/applesoftfile/applesoftformatter.h \
src/applesoftfile/applesoftline.h
FORMS += \
src/ui/catalogwidget.ui \

View File

@ -6,17 +6,10 @@
#include <QMap>
#include <QVector>
#include "applesoftline.h"
#include "genericfile.h"
#include "applesofttoken.h"
struct ApplesoftLine {
qint16 address;
quint16 next_address;
quint16 linenum;
QVector<ApplesoftToken> tokens;
// QString detokenized_line;
};
class ApplesoftFile : public GenericFile
{
@ -39,7 +32,6 @@ private:
int m_data_end;
quint16 m_length;
QString m_filename;
// QList<ApplesoftLine> m_detokenized;
friend class Retokenizer;
};

View File

@ -0,0 +1,2 @@
#include "applesoftline.h"

View File

@ -0,0 +1,17 @@
#ifndef APPLESOFTLINE_H
#define APPLESOFTLINE_H
#include <Qt>
#include <QVector>
class ApplesoftToken;
struct ApplesoftLine {
qint16 address;
quint16 next_address;
quint16 linenum;
QVector<ApplesoftToken> tokens;
// QString detokenized_line;
};
#endif // APPLESOFTLINE_H

View File

@ -1,7 +1,6 @@
#ifndef APPLESOFTTOKEN_H
#define APPLESOFTTOKEN_H
#include <QString>
#include <QVariant>
#include <QMap>
@ -49,7 +48,6 @@ public:
UNDEFINED_COMMAND
} CommandType;
ApplesoftToken();
ApplesoftToken(quint16 id);
ApplesoftToken(quint16 id, QVariant payload);

View File

@ -9,38 +9,11 @@
int main(int argc, char** argv)
{
/*
// DiskFile df("/home/mlong/Desktop/dos.3.3.system.master.dsk");
DiskFile df("/home/mlong/Desktop/missing_ring_good.dsk");
df.getVTOC().dump();
QList<CatalogSector> sectors = df.getCatalogSectors();
FileDescriptiveEntry toLoad;
foreach (FileDescriptiveEntry fde, df.getAllFDEs()) {
fde.catalog();
if (fde.filename.printable().contains("ASM.DATA")) {
toLoad = fde;
}
}
QByteArray file = df.getFile(toLoad);
BinaryFile myfile;
myfile.setData(file);
myfile.dump();
//ApplesoftFile af(file);
//af.list();
*/
QApplication a(argc, argv);
MainWindow w;
w.loadDiskFile("/home/mlong/Desktop/missing_ring_good.dsk");
// w.loadDiskFile("/home/mlong/Desktop/dos.3.3.system.master.dsk");
w.loadDiskFile("/home/mlong2/missing_ring_good.dsk");
// w.loadDiskFile("/home/mlong2/dos.3.3.system.master.dsk");
// w.loadDiskFile("/home/mlong2/montezuma_etc.dsk");
w.show();
return a.exec();

View File

@ -10,6 +10,12 @@
<height>560</height>
</rect>
</property>
<property name="font">
<font>
<family>Courier 10 Pitch</family>
<pointsize>10</pointsize>
</font>
</property>
<property name="windowTitle">
<string>Form</string>
</property>

View File

@ -86,7 +86,7 @@ void MainWindow::handleDiskItemSelectedDefaultOpen(DiskFile *disk, FileDescripti
if (fde.lengthInSectors == 34)
{
HiresViewWidget *hvwma = new HiresViewWidget(0);
hvwma->resize(280,192);
QString title = QString("Image: %1").arg(AppleString(fde.filename).printable().trimmed());
hvwma->setWindowTitle(title);
hvwma->show();

View File

@ -12,7 +12,8 @@
</property>
<property name="font">
<font>
<family>Century Schoolbook L</family>
<family>Courier 10 Pitch</family>
<pointsize>10</pointsize>
</font>
</property>
<property name="windowTitle">
@ -23,7 +24,7 @@
<widget class="QTextBrowser" name="textArea">
<property name="font">
<font>
<family>Source Code Pro</family>
<family>Courier 10 Pitch</family>
<pointsize>10</pointsize>
</font>
</property>

View File

@ -4,13 +4,21 @@
#include <QDebug>
#include <QResizeEvent>
#include <math.h>
#define CYCLESTART (M_PI * 4.0 / 16.0)
HiresViewWidget::HiresViewWidget(QWidget *parent) :
QWidget(parent)
{
resize(561,384);
m_viewMode = Color2;
if (m_rowTable == 0) { makeOffsetTable(); }
qDebug() << "ctor";
m_pixmap = QPixmap(280,192);
m_pixmap = QPixmap(561,384);
qDebug() << "Pixmap size: " << m_pixmap.size();
QPainter painter(&m_pixmap);
painter.setBrush(Qt::black);
@ -43,37 +51,296 @@ void HiresViewWidget::setData(QByteArray data) {
qDebug() << "setData";
m_data = data;
QPainter pmpainter(&m_pixmap);
pmpainter.setPen(Qt::white);
pmpainter.setBrush(Qt::white);
for (int idx = 0; idx < m_data.size() ; idx++) {
int rowcol = findRowCol(idx);
if (m_viewMode == Monochrome)
{
pmpainter.setPen(Qt::white);
pmpainter.setBrush(Qt::white);
quint8 byte = m_data[idx];
for (int idx = 0; idx < m_data.size() ; idx++) {
int rowcol = findRowCol(idx);
// qDebug() << "idx: " << idx << (rowcol / 1000) << (rowcol % 1000);
int xoff = (rowcol / 10000) * 7;
int yoff = (rowcol % 10000);
quint8 byte = m_data[idx];
if (byte & 0x01) { pmpainter.drawPoint(xoff+0,yoff); }
if (byte & 0x02) { pmpainter.drawPoint(xoff+1,yoff); }
if (byte & 0x04) { pmpainter.drawPoint(xoff+2,yoff); }
if (byte & 0x08) { pmpainter.drawPoint(xoff+3,yoff); }
if (byte & 0x10) { pmpainter.drawPoint(xoff+4,yoff); }
if (byte & 0x20) { pmpainter.drawPoint(xoff+5,yoff); }
if (byte & 0x40) { pmpainter.drawPoint(xoff+6,yoff); }
// qDebug() << "idx: " << idx << (rowcol / 1000) << (rowcol % 1000);
int xoff = (rowcol / 10000) * 7 * 2;
int yoff = (rowcol % 10000) * 2;
if (idx >= (280*192)) break;
if (byte & 0x01) { pmpainter.drawRect(xoff+0,yoff,1,1); }
if (byte & 0x02) { pmpainter.drawRect(xoff+2,yoff,1,1); }
if (byte & 0x04) { pmpainter.drawRect(xoff+4,yoff,1,1); }
if (byte & 0x08) { pmpainter.drawRect(xoff+6,yoff,1,1); }
if (byte & 0x10) { pmpainter.drawRect(xoff+8,yoff,1,1); }
if (byte & 0x20) { pmpainter.drawRect(xoff+10,yoff,1,1); }
if (byte & 0x40) { pmpainter.drawRect(xoff+12,yoff,1,1); }
if (idx >= (280*192)) break;
}
} else if (m_viewMode == Color1) {
pmpainter.setPen(Qt::white);
pmpainter.setBrush(Qt::white);
for (int idx = 0; idx < m_data.size() ; idx++) {
int rowcol = findRowCol(idx);
quint8 byte = m_data[idx];
bool highBit = byte & 0x80;
QColor oddColor = highBit? QColor(orangeColor) : QColor(greenColor);
QColor evenColor = highBit? QColor(blueColor) : QColor(purpleColor);
int xoff = (rowcol / 10000) * 7;
int yoff = (rowcol % 10000)*2;
quint8 cOffset = 0;// highBit?1:0;
quint8 doubleScan = 0;
pmpainter.setPen(xoff & 0x01?oddColor:evenColor);
pmpainter.setBrush(xoff & 0x01?oddColor:evenColor);
if (byte & 0x01) { pmpainter.drawRect((cOffset+xoff*2)+0,yoff,1,doubleScan); }
pmpainter.setPen(xoff & 0x01?evenColor:oddColor);
pmpainter.setBrush(xoff & 0x01?evenColor:oddColor);
if (byte & 0x02) { pmpainter.drawRect((cOffset+xoff*2)+2,yoff,1,doubleScan); }
pmpainter.setPen(xoff & 0x01?oddColor:evenColor);
pmpainter.setBrush(xoff & 0x01?oddColor:evenColor);
if (byte & 0x04) { pmpainter.drawRect((cOffset+xoff*2)+4,yoff,1,doubleScan); }
pmpainter.setPen(xoff & 0x01?evenColor:oddColor);
pmpainter.setBrush(xoff & 0x01?evenColor:oddColor);
if (byte & 0x08) { pmpainter.drawRect((cOffset+xoff*2)+6,yoff,1,doubleScan); }
pmpainter.setPen(xoff & 0x01?oddColor:evenColor);
pmpainter.setBrush(xoff & 0x01?oddColor:evenColor);
if (byte & 0x10) { pmpainter.drawRect((cOffset+xoff*2)+8,yoff,1,doubleScan); }
pmpainter.setPen(xoff & 0x01?evenColor:oddColor);
pmpainter.setBrush(xoff & 0x01?evenColor:oddColor);
if (byte & 0x20) { pmpainter.drawRect((cOffset+xoff*2)+10,yoff,1,doubleScan); }
pmpainter.setPen(xoff & 0x01?oddColor:evenColor);
pmpainter.setBrush(xoff & 0x01?oddColor:evenColor);
if (byte & 0x40) { pmpainter.drawRect((cOffset+xoff*2)+12,yoff,cOffset?0:1,doubleScan); }
if (idx >= (280*192)) break;
}
} else if (m_viewMode == Color2) {
pmpainter.setPen(Qt::white);
pmpainter.setBrush(Qt::white);
quint8 chunkCount = 0;
// for (int idx = 0; idx < m_data.size() ; idx+=40) {
int idx = 0;
while (idx < m_data.size()) {
int rowcol = findRowCol(idx);
// int xoff = (rowcol / 10000) * 7;
int yoff = (rowcol % 10000);
QBitArray bits(561,false);
int bitoffset = 0;
bool lastbit = false;
for (int jdx = 0; jdx < 40; jdx++)
{
quint8 byte = m_data[idx++];
QBitArray dataBits = byteToBits(byte);
bool highBit = dataBits.at(0);
if (highBit) {
bits[bitoffset++] = lastbit;
}
for (int xdx = 1; xdx < 7; xdx++) {
bits[bitoffset++] = dataBits.at(xdx);
bits[bitoffset++] = dataBits.at(xdx);
}
lastbit = dataBits.at(7);
bits[bitoffset++] = dataBits.at(7);
if (!highBit) {
bits[bitoffset++] = dataBits.at(7);
}
}
drawNtscLine(pmpainter, yoff*2, bits);
// drawMonoLine(pmpainter, yoff*2, bits);
// for (int ddx = 0; ddx < bits.count(); ddx++) {
// if (bits.at(ddx)) { pmpainter.drawRect(ddx,yoff*2,0,1); }
// }
chunkCount++;
if (chunkCount == 3) {
chunkCount = 0;
idx+=8;
}
}
}
}
void HiresViewWidget::drawMonoLine(QPainter &painter, int lineNum, QBitArray data) {
for (int idx = 0; idx < data.count(); idx++) {
if (data.at(idx)) { painter.drawPoint(idx,lineNum); }
}
}
QColor HiresViewWidget::getColorFromBits(QBitArray bits, quint8 phase)
{
quint8 bitval = (bits[0] * 0x08) +
(bits[1] * 0x04) +
(bits[2] * 0x02) +
(bits[3] * 0x01);
phase %= 4;
//qDebug() << bits << phase;
if (bitval == 0) { return blackColor; }
if (bitval == 1 && phase == 0) return brownColor;
if (bitval == 2 && phase == 1) return brownColor;
if (bitval == 4 && phase == 2) return brownColor;
if (bitval == 8 && phase == 3) return brownColor;
if (bitval == 2 && phase == 0) return darkGreenColor;
if (bitval == 4 && phase == 1) return darkGreenColor;
if (bitval == 8 && phase == 2) return darkGreenColor;
if (bitval == 1 && phase == 3) return darkGreenColor;
if (bitval == 3 && phase == 0) return greenColor;
if (bitval == 6 && phase == 1) return greenColor;
if (bitval == 12 && phase == 2) return greenColor;
if (bitval == 9 && phase == 3) return greenColor;
if (bitval == 4 && phase == 0) return darkBlueColor;
if (bitval == 8 && phase == 1) return darkBlueColor;
if (bitval == 1 && phase == 2) return darkBlueColor;
if (bitval == 2 && phase == 3) return darkBlueColor;
if (bitval == 5 && phase == 0) return grayColor;
if (bitval == 10 && phase == 1) return grayColor;
if (bitval == 5 && phase == 2) return grayColor;
if (bitval == 10 && phase == 3) return grayColor;
if (bitval == 6 && phase == 0) return blueColor;
if (bitval == 12 && phase == 1) return blueColor;
if (bitval == 9 && phase == 2) return blueColor;
if (bitval == 3 && phase == 3) return blueColor;
if (bitval == 7 && phase == 0) return aquaColor;
if (bitval == 14 && phase == 1) return aquaColor;
if (bitval == 13 && phase == 2) return aquaColor;
if (bitval == 11 && phase == 3) return aquaColor;
if (bitval == 8 && phase == 0) return redColor;
if (bitval == 1 && phase == 1) return redColor;
if (bitval == 2 && phase == 2) return redColor;
if (bitval == 4 && phase == 3) return redColor;
if (bitval == 9 && phase == 0) return orangeColor;
if (bitval == 3 && phase == 1) return orangeColor;
if (bitval == 6 && phase == 2) return orangeColor;
if (bitval == 12 && phase == 3) return orangeColor;
if (bitval == 10 && phase == 0) return gray2Color;
if (bitval == 5 && phase == 1) return gray2Color;
if (bitval == 10 && phase == 2) return gray2Color;
if (bitval == 5 && phase == 3) return gray2Color;
if (bitval == 11 && phase == 0) return yellowColor;
if (bitval == 7 && phase == 1) return yellowColor;
if (bitval == 14 && phase == 2) return yellowColor;
if (bitval == 13 && phase == 3) return yellowColor;
if (bitval == 12 && phase == 0) return purpleColor;
if (bitval == 9 && phase == 1) return purpleColor;
if (bitval == 3 && phase == 2) return purpleColor;
if (bitval == 6 && phase == 3) return purpleColor;
if (bitval == 13 && phase == 0) return pinkColor;
if (bitval == 11 && phase == 1) return pinkColor;
if (bitval == 7 && phase == 2) return pinkColor;
if (bitval == 14 && phase == 3) return pinkColor;
if (bitval == 14 && phase == 0) return lightBlueColor;
if (bitval == 13 && phase == 1) return lightBlueColor;
if (bitval == 11 && phase == 2) return lightBlueColor;
if (bitval == 7 && phase == 3) return lightBlueColor;
return whiteColor;
}
void HiresViewWidget::drawNtscLine(QPainter &painter, int lineNum, QBitArray data) {
QVector<QColor> colors;
colors.resize(data.count()+4);
for (int idx = 0; idx < data.count(); idx++) {
QBitArray tmp(4);
tmp[0]=data.at(idx+0);
if (idx < data.count()-1) tmp[1]=data.at(idx+1); else tmp[1] = false;
if (idx < data.count()-2) tmp[2]=data.at(idx+2); else tmp[2] = false;
if (idx < data.count()-3) tmp[3]=data.at(idx+3); else tmp[3] = false;
colors[idx] = getColorFromBits(tmp,idx %4);
colors[idx+1] = getColorFromBits(tmp,idx %4);
colors[idx+2] = getColorFromBits(tmp,idx %4);
colors[idx+3] = getColorFromBits(tmp,idx %4);
}
for (int idx = 0; idx < colors.count(); idx++)
{
painter.setPen(colors.at(idx));
painter.setBrush(colors.at(idx));
painter.drawPoint(idx,lineNum);
}
}
QBitArray HiresViewWidget::byteToBits(quint8 byte) {
QBitArray bits(8);
bits.setBit(0,byte & 0x80);
bits.setBit(7,byte & 0x40);
bits.setBit(6,byte & 0x20);
bits.setBit(5,byte & 0x10);
bits.setBit(4,byte & 0x08);
bits.setBit(3,byte & 0x04);
bits.setBit(2,byte & 0x02);
bits.setBit(1,byte & 0x01);
return bits;
}
void HiresViewWidget::setMode(HiresViewWidget::ViewMode viewmode)
{
m_viewMode = viewmode;
update();
}
int HiresViewWidget::findRowCol(int offset) {
int retval = 0;
retval = (*m_rowTable)[offset];
// qDebug() << offset << " = " << row << col << retval;
return retval;
}

View File

@ -6,28 +6,65 @@
#include <QByteArray>
#include <QPair>
#include <QMap>
#include <QBitArray>
static const QColor blackColor = QColor(0,0,0);
static const QColor brownColor = QColor();
static const QColor darkGreenColor = QColor(96,114,3);
static const QColor greenColor = QColor(20,245,60);
static const QColor darkBlueColor = QColor(96,78,189);
static const QColor grayColor = QColor(156,156,156);
static const QColor blueColor = QColor(20,207,253);
static const QColor aquaColor = QColor(114,255,208);
static const QColor redColor = QColor(227,30,96);
static const QColor orangeColor = QColor(255,106,60);
static const QColor gray2Color = QColor(156,156,156);
static const QColor yellowColor = QColor(208,221,141);
static const QColor purpleColor = QColor(255,68,253);
static const QColor pinkColor = QColor(255,160,208);
static const QColor lightBlueColor = QColor(208,195,255);
static const QColor whiteColor = QColor(255,255,255);
class HiresViewWidget : public QWidget
{
Q_OBJECT
public:
enum ViewMode {
Monochrome,
Color1,
Color2
};
explicit HiresViewWidget(QWidget *parent = 0);
void paintEvent(QPaintEvent *event);
void resizeEvent(QResizeEvent *event);
static QBitArray byteToBits(quint8 byte);
signals:
public slots:
void setData(QByteArray data);
void setMode(ViewMode);
private:
QPixmap m_pixmap;
QByteArray m_data;
int findRowCol(int offset);
static QMap<int,int> *m_rowTable;
void makeOffsetTable();
ViewMode m_viewMode;
void drawNtscLine(QPainter &painter,int linenum, QBitArray data);
void drawMonoLine(QPainter &painter, int lineNum, QBitArray data);
QColor getColorFromBits(QBitArray bits, quint8 phase);
};