From 0d40a0f264f9375eac212f9d0662b4491de182cc Mon Sep 17 00:00:00 2001 From: Mark Long Date: Wed, 20 Jan 2016 20:58:48 -0600 Subject: [PATCH] Added NTSC emulation for HiresViewWidget. --- AppleSAWS.pro | 9 +- src/applesoftfile/applesoftfile.h | 10 +- src/applesoftfile/applesoftline.cpp | 2 + src/applesoftfile/applesoftline.h | 17 ++ src/applesoftfile/applesofttoken.h | 2 - src/main.cpp | 33 +-- src/ui/catalogwidget.ui | 6 + src/ui/mainwindow.cxx | 2 +- src/ui/viewers/applesoftfileviewer.ui | 5 +- src/ui/viewers/hiresviewwidget.cxx | 307 ++++++++++++++++++++++++-- src/ui/viewers/hiresviewwidget.h | 37 ++++ 11 files changed, 364 insertions(+), 66 deletions(-) create mode 100644 src/applesoftfile/applesoftline.cpp create mode 100644 src/applesoftfile/applesoftline.h diff --git a/AppleSAWS.pro b/AppleSAWS.pro index 64ed5ab..94ec414 100644 --- a/AppleSAWS.pro +++ b/AppleSAWS.pro @@ -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 \ diff --git a/src/applesoftfile/applesoftfile.h b/src/applesoftfile/applesoftfile.h index b3378fc..94d1da8 100644 --- a/src/applesoftfile/applesoftfile.h +++ b/src/applesoftfile/applesoftfile.h @@ -6,17 +6,10 @@ #include #include +#include "applesoftline.h" #include "genericfile.h" #include "applesofttoken.h" -struct ApplesoftLine { - qint16 address; - quint16 next_address; - quint16 linenum; - QVector tokens; - // QString detokenized_line; -}; - class ApplesoftFile : public GenericFile { @@ -39,7 +32,6 @@ private: int m_data_end; quint16 m_length; QString m_filename; - // QList m_detokenized; friend class Retokenizer; }; diff --git a/src/applesoftfile/applesoftline.cpp b/src/applesoftfile/applesoftline.cpp new file mode 100644 index 0000000..00452ac --- /dev/null +++ b/src/applesoftfile/applesoftline.cpp @@ -0,0 +1,2 @@ +#include "applesoftline.h" + diff --git a/src/applesoftfile/applesoftline.h b/src/applesoftfile/applesoftline.h new file mode 100644 index 0000000..6badb4a --- /dev/null +++ b/src/applesoftfile/applesoftline.h @@ -0,0 +1,17 @@ +#ifndef APPLESOFTLINE_H +#define APPLESOFTLINE_H +#include +#include + +class ApplesoftToken; + +struct ApplesoftLine { + qint16 address; + quint16 next_address; + quint16 linenum; + QVector tokens; + // QString detokenized_line; +}; + + +#endif // APPLESOFTLINE_H diff --git a/src/applesoftfile/applesofttoken.h b/src/applesoftfile/applesofttoken.h index 6f16446..b0c54e4 100644 --- a/src/applesoftfile/applesofttoken.h +++ b/src/applesoftfile/applesofttoken.h @@ -1,7 +1,6 @@ #ifndef APPLESOFTTOKEN_H #define APPLESOFTTOKEN_H - #include #include #include @@ -49,7 +48,6 @@ public: UNDEFINED_COMMAND } CommandType; - ApplesoftToken(); ApplesoftToken(quint16 id); ApplesoftToken(quint16 id, QVariant payload); diff --git a/src/main.cpp b/src/main.cpp index 59cd445..3c86c21 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -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 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(); diff --git a/src/ui/catalogwidget.ui b/src/ui/catalogwidget.ui index 1e1ce85..22fab9c 100644 --- a/src/ui/catalogwidget.ui +++ b/src/ui/catalogwidget.ui @@ -10,6 +10,12 @@ 560 + + + Courier 10 Pitch + 10 + + Form diff --git a/src/ui/mainwindow.cxx b/src/ui/mainwindow.cxx index 2c5bd03..3cecd9e 100644 --- a/src/ui/mainwindow.cxx +++ b/src/ui/mainwindow.cxx @@ -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(); diff --git a/src/ui/viewers/applesoftfileviewer.ui b/src/ui/viewers/applesoftfileviewer.ui index fe0baaf..e291615 100644 --- a/src/ui/viewers/applesoftfileviewer.ui +++ b/src/ui/viewers/applesoftfileviewer.ui @@ -12,7 +12,8 @@ - Century Schoolbook L + Courier 10 Pitch + 10 @@ -23,7 +24,7 @@ - Source Code Pro + Courier 10 Pitch 10 diff --git a/src/ui/viewers/hiresviewwidget.cxx b/src/ui/viewers/hiresviewwidget.cxx index a08e5b4..86070e2 100644 --- a/src/ui/viewers/hiresviewwidget.cxx +++ b/src/ui/viewers/hiresviewwidget.cxx @@ -4,13 +4,21 @@ #include #include +#include + +#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 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; } diff --git a/src/ui/viewers/hiresviewwidget.h b/src/ui/viewers/hiresviewwidget.h index db32373..3b161d2 100644 --- a/src/ui/viewers/hiresviewwidget.h +++ b/src/ui/viewers/hiresviewwidget.h @@ -6,28 +6,65 @@ #include #include #include +#include + +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 *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); };