From 919cf5b6eb10918825b03c194f82195b8f3c00d1 Mon Sep 17 00:00:00 2001 From: Mark Long Date: Fri, 26 Feb 2016 15:06:48 -0600 Subject: [PATCH] Added text/hex viewer for hex files --- AppleSAWS.pro | 8 +- src/diskfiles/dos33/diskfile.cxx | 11 ++- src/relocatablefile/relocatablefile.cxx | 71 ++++++++++++++++ src/relocatablefile/relocatablefile.h | 106 ++++++++++++++++++++++++ src/textfile/textfile.cxx | 18 ++++ src/textfile/textfile.h | 17 ++++ src/ui/mainwindow.cxx | 11 +++ src/ui/viewers/hexdumpviewer.ui | 2 +- src/ui/viewers/texthexdumpviewer.cpp | 95 +++++++++++++++++++++ src/ui/viewers/texthexdumpviewer.h | 36 ++++++++ src/ui/viewers/texthexdumpviewer.ui | 31 +++++++ src/util/applestring.cxx | 6 +- src/util/applestring.h | 1 + 13 files changed, 406 insertions(+), 7 deletions(-) create mode 100644 src/relocatablefile/relocatablefile.cxx create mode 100644 src/relocatablefile/relocatablefile.h create mode 100644 src/textfile/textfile.cxx create mode 100644 src/textfile/textfile.h create mode 100644 src/ui/viewers/texthexdumpviewer.cpp create mode 100644 src/ui/viewers/texthexdumpviewer.h create mode 100644 src/ui/viewers/texthexdumpviewer.ui diff --git a/AppleSAWS.pro b/AppleSAWS.pro index 74ce02f..599881f 100644 --- a/AppleSAWS.pro +++ b/AppleSAWS.pro @@ -14,6 +14,7 @@ INCLUDEPATH += src/diskfiles/dos33 INCLUDEPATH += src/util INCLUDEPATH += src/applesoftfile INCLUDEPATH += src/binaryfile +INCLUDEPATH += src/textfile INCLUDEPATH += src/ui/viewers INCLUDEPATH += src/imported INCLUDEPATH += src/internals @@ -35,6 +36,7 @@ SOURCES += \ src/applesoftfile/applesofttoken.cxx \ src/binaryfile/disassembler.cxx \ src/binaryfile/binaryfile.cxx \ + src/textfile/textfile.cxx \ src/ui/catalogwidget.cxx \ src/ui/mainwindow.cxx \ src/ui/viewers/hiresviewwidget.cxx \ @@ -44,6 +46,7 @@ SOURCES += \ src/internals/memory.cxx \ src/ui/viewers/disassemblerviewer.cpp \ src/ui/viewers/hexdumpviewer.cpp \ + src/ui/viewers/texthexdumpviewer.cpp \ src/relocatablefile/relocatablefile.cxx HEADERS += \ @@ -60,6 +63,7 @@ HEADERS += \ src/applesoftfile/applesofttoken.h \ src/binaryfile/disassembler.h \ src/binaryfile/binaryfile.h \ + src/textfile/textfile.h \ src/ui/catalogwidget.h \ src/ui/mainwindow.h \ src/ui/viewers/hiresviewwidget.h \ @@ -69,6 +73,7 @@ HEADERS += \ src/internals/memory.h \ src/ui/viewers/disassemblerviewer.h \ src/ui/viewers/hexdumpviewer.h \ + src/ui/viewers/texthexdumpviewer.h \ src/relocatablefile/relocatablefile.h FORMS += \ @@ -76,4 +81,5 @@ FORMS += \ src/ui/mainwindow.ui \ src/ui/viewers/applesoftfileviewer.ui \ src/ui/viewers/disassemblerviewer.ui \ - src/ui/viewers/hexdumpviewer.ui + src/ui/viewers/hexdumpviewer.ui \ + src/ui/viewers/texthexdumpviewer.ui diff --git a/src/diskfiles/dos33/diskfile.cxx b/src/diskfiles/dos33/diskfile.cxx index 61c79f4..4a637f1 100644 --- a/src/diskfiles/dos33/diskfile.cxx +++ b/src/diskfiles/dos33/diskfile.cxx @@ -8,6 +8,7 @@ #include "applesoftfile.h" #include "binaryfile.h" #include "relocatablefile.h" +#include "textfile.h" DiskFile::DiskFile(QString filename) { @@ -91,18 +92,22 @@ GenericFile *DiskFile::getFile(FileDescriptiveEntry fde) TrackSectorList tsl = getSector(fde.firstTSListSector).promoteToTrackSectorList(); QByteArray data = getDataFromTrackSectorList(tsl); - if (fde.fileTypeAndFlags & DOSApplesoftBasicFile) + if (fde.fileType() == "A") { retval = new ApplesoftFile(data); } - else if (fde.fileTypeAndFlags & DOSRawBinaryFile) + else if (fde.fileType() == "B") { retval = new BinaryFile(data); } - else if (fde.fileTypeAndFlags & DOSRelocatableFile) + else if (fde.fileType() == "R") { retval = new RelocatableFile(data); } + else if ((fde.fileType() == "T")) + { + retval = new TextFile(data); + } else { retval = new GenericFile(data); diff --git a/src/relocatablefile/relocatablefile.cxx b/src/relocatablefile/relocatablefile.cxx new file mode 100644 index 0000000..06e486d --- /dev/null +++ b/src/relocatablefile/relocatablefile.cxx @@ -0,0 +1,71 @@ +#include +#include "relocatablefile.h" +#include "util.h" + +RelocatableFile::RelocatableFile(QByteArray data) : GenericFile(data) +{ + // qDebug() << "Relocatable file ctor"; + if (!data.isEmpty()) { + setData(data); + } +} + +void RelocatableFile::setData(QByteArray data) +{ + // qDebug() << "setData()"; + if (data.length() >= 6) { + m_starting_ram_address = (quint8) m_data[0] + ((quint8) m_data[1] * 256); + m_ram_image_length = (quint8) m_data[2] + ((quint8) m_data[3] * 256); + m_code_image_length = (quint8) m_data[4] + ((quint8) m_data[5] * 256); + + int offset = 0; + + for (int idx = 6; idx < m_code_image_length+6; idx++) { + quint8 val = m_data[idx]; + m_binary_code_image.append(val); + } + + for (int N = 0; N < (m_code_image_length/4); N++) { + offset = m_code_image_length+ 6 +(N*4); + +// qDebug() << "N: " << N << uint8ToHex(m_data[offset]) +// << uint8ToHex(m_data[offset+1]) +// << uint8ToHex(m_data[offset+2]) +// << uint8ToHex(m_data[offset+3]); + + RelocatableDictItem rdi = RelocatableDictItem(m_data[offset],m_data[offset+1], + m_data[offset+2],m_data[offset+3]); + m_relocatable_dict.append(rdi); + if (rdi.isEndOfRLD()) { break; } + } + + + + } +} + +void RelocatableFile::dump() +{ + qDebug() << "\nTotalLength: " << length(); + qDebug() << "Starting Ram Address: " << (quint16) m_starting_ram_address << uint16ToHex(m_starting_ram_address); + qDebug() << "Length of Ram Image: " << (quint16) m_ram_image_length << uint16ToHex(m_ram_image_length); + qDebug() << "Length of Code Image: " << (quint16) m_code_image_length << uint16ToHex(m_code_image_length); + + int itemIdx = 0; + foreach (RelocatableDictItem item, m_relocatable_dict) { + Byte4ReturnType b4rt = item.getByte4(); + QString typestr; + if (b4rt.first == ESDSymbol) { typestr = "ESDSymbol"; } + else if (b4rt.first == ByteHi) { typestr = "Hi Byte"; } + else { typestr = "Lo Byte"; } + quint16 fo = item.getFieldOffset(); + qDebug() << " Item #" << itemIdx++ + << "Field Offset: " << uint16ToHex(fo) + << "FieldSize: " << ((item.getFieldSize()==RFS2Byte)?"2-Byte":"1-Byte") + << typestr << uint8ToHex(b4rt.second) + << ((item.isNotEndOfRLD())?"NotEndOfRLD":"EndOfRLD") + << " " << ((item.isExtern())?"Extern":"Not Extern"); + } + + +} diff --git a/src/relocatablefile/relocatablefile.h b/src/relocatablefile/relocatablefile.h new file mode 100644 index 0000000..b697af9 --- /dev/null +++ b/src/relocatablefile/relocatablefile.h @@ -0,0 +1,106 @@ +#ifndef RELOCATABLEFILE_H +#define RELOCATABLEFILE_H + +#include +#include + +#include "genericfile.h" + + +typedef enum { RFS1Byte, RFS2Byte } FieldSize; +typedef enum { ULIsHighByte, ULIsLowByte } WordUpperLower; +typedef enum { LowHi, HiLow } Endianness; +typedef enum { ByteLo, ByteHi, ESDSymbol } Byte4Type; + +typedef QPair Byte4ReturnType; + +class RelocatableDictItem { +public: + RelocatableDictItem() {init(0,0,0,0); } + RelocatableDictItem(quint8 rld, quint8 fo_low, quint8 fo_hi, quint8 lbsym) { + init(rld,fo_low, fo_hi,lbsym); + } + RelocatableDictItem(quint8 rld, quint16 fo, quint8 lbsym) { + init(rld,fo,lbsym); + } + + void init(quint8 rld, quint8 fo_low, quint8 fo_hi, quint8 lbsym) { + m_rld_flag = rld; + m_halfword_or_sym_num = lbsym; + m_field_offset = (quint8) fo_low + ((quint8) fo_hi * 256); + } + + void init(quint8 rld, quint16 fo, quint8 lbsym) { + m_rld_flag = rld; + m_halfword_or_sym_num = lbsym; + m_field_offset = fo; + } + + FieldSize getFieldSize() { return (m_rld_flag & 0x80)?RFS2Byte:RFS1Byte; } + WordUpperLower getWordBytePos() { return (m_rld_flag & 0x40)?ULIsHighByte:ULIsLowByte; } + Endianness getEndianness() { return (m_rld_flag & 0x20)?HiLow:LowHi; } + bool isExtern() { return (m_rld_flag & 0x10); } + bool isNotEndOfRLD() { return (m_rld_flag & 0x01); } + bool isEndOfRLD() { return !(m_rld_flag & 0x01); } + + Byte4ReturnType getByte4() { + Byte4ReturnType retval; + + if (isExtern()) { + retval.first = ESDSymbol; + } else if (getWordBytePos() == ULIsHighByte) { + retval.first = ByteHi; + } else { + retval.first = ByteLo; + } + + retval.second = m_halfword_or_sym_num; + + return retval; + } + + quint16 getFieldOffset() { return m_field_offset; } + + quint8 getRLDFlag() { return m_rld_flag; } + quint8 getRawHalfWordOrSymNum() { return m_halfword_or_sym_num; } + +private: + + quint8 m_rld_flag; + quint16 m_field_offset; + quint8 m_halfword_or_sym_num; + +}; + + + +class RelocatableFile : public GenericFile +{ +public: + + RelocatableFile(QByteArray data = QByteArray()); + void setData(QByteArray data); + + quint16 length() { return m_data.length(); } + + void dump(); + + QByteArray getBinaryCodeImage() { return m_binary_code_image; } + QList getRelocatableDict() { return m_relocatable_dict; } + + quint16 address() { return m_starting_ram_address; } + quint16 codeImageLength() { return m_code_image_length; } + +protected: + quint16 m_starting_ram_address; + quint16 m_ram_image_length; + quint16 m_code_image_length; + + QByteArray m_binary_code_image; + + QList m_relocatable_dict; + + +}; + +#endif diff --git a/src/textfile/textfile.cxx b/src/textfile/textfile.cxx new file mode 100644 index 0000000..7aaa458 --- /dev/null +++ b/src/textfile/textfile.cxx @@ -0,0 +1,18 @@ +#include +#include "textfile.h" + +TextFile::TextFile(QByteArray data) : GenericFile(data) +{ + if (!data.isEmpty()) { + setData(data); + } +} + +void TextFile::setData(QByteArray data) +{ + m_data = data; +} + +void TextFile::dump() +{ +} diff --git a/src/textfile/textfile.h b/src/textfile/textfile.h new file mode 100644 index 0000000..35f24fc --- /dev/null +++ b/src/textfile/textfile.h @@ -0,0 +1,17 @@ +#ifndef TEXTFILE_H +#define TEXTFILE_H + +#include "genericfile.h" + +class TextFile : public GenericFile +{ +public: + TextFile(QByteArray data = QByteArray()); + void setData(QByteArray data); + + void dump(); + +protected: +}; + +#endif // TEXTFILE_H diff --git a/src/ui/mainwindow.cxx b/src/ui/mainwindow.cxx index 754108a..3941dd4 100644 --- a/src/ui/mainwindow.cxx +++ b/src/ui/mainwindow.cxx @@ -4,10 +4,13 @@ #include "hiresviewwidget.h" #include "applesoftfileviewer.h" #include "applesoftfile.h" +#include "textfile.h" #include "memory.h" #include "disassembler.h" #include "disassemblerviewer.h" #include "hexdumpviewer.h" +#include "texthexdumpviewer.h" + #include "relocatablefile.h" #include @@ -142,6 +145,14 @@ void MainWindow::handleDiskItemSelectedDefaultOpen(DiskFile *disk, FileDescripti abf->setFilename(AppleString(fde.filename).printable().trimmed()); openInApplesoftFileViewer(abf); } + else if (dynamic_cast(file)) + { + TextFile *tf = dynamic_cast(file); + tf->setFilename(AppleString(fde.filename).printable().trimmed()); + TextHexDumpViewer *thdv = new TextHexDumpViewer(); + thdv->setFile(tf); + thdv->show(); + } else if (dynamic_cast(file)) { RelocatableFile *rf = dynamic_cast(file); diff --git a/src/ui/viewers/hexdumpviewer.ui b/src/ui/viewers/hexdumpviewer.ui index e0fd51d..c3c5df2 100644 --- a/src/ui/viewers/hexdumpviewer.ui +++ b/src/ui/viewers/hexdumpviewer.ui @@ -18,7 +18,7 @@ - Courier + Courier 10 Pitch 12 diff --git a/src/ui/viewers/texthexdumpviewer.cpp b/src/ui/viewers/texthexdumpviewer.cpp new file mode 100644 index 0000000..c17643a --- /dev/null +++ b/src/ui/viewers/texthexdumpviewer.cpp @@ -0,0 +1,95 @@ +#include "texthexdumpviewer.h" +#include "ui_texthexdumpviewer.h" +#include "applestring.h" + +#include +#include + +TextHexDumpViewer::TextHexDumpViewer(QWidget *parent) : + QWidget(parent), + ui(new Ui::TextHexDumpViewer) +{ + ui->setupUi(this); + m_offset = 0; + + QString title = QString("Text/Hex File Viewer"); + setWindowTitle(title); +} + +TextHexDumpViewer::~TextHexDumpViewer() +{ + delete ui; +} + +QString TextHexDumpViewer::makeHexStr(QByteArray data) +{ + QString retval; + for (int idx = 0; idx < data.length(); idx++) + { + retval += QString(" %1").arg((quint8) data[idx],2,16,QChar('0')); + } + retval.remove(0,1); + + return retval; +} + +QString TextHexDumpViewer::makeTextStr(QByteArray data) +{ + AppleString as; + as.setData(data); + + QString retval = as.printable(); + + retval.replace(QChar(0x7f),QChar(0x25a9)); + + for (int idx = 0; idx <= 0x1f; idx++) { + retval.replace(QChar(idx),QChar(idx+0x2400)); + } + + return retval; +} + +void TextHexDumpViewer::setFile(GenericFile *file, quint16 offset) +{ + m_offset = offset; + QByteArray data = file->data(); + + QString title = QString("Text/Hex File Viewer: %1").arg(file->filename()); + setWindowTitle(title); + + QStringList outputlines; + + + QVector chunks; + + QByteArray tmpval = data; + + while (tmpval.count()) { + QByteArray tmpchunk = tmpval.left(16); + tmpval.remove(0,16); + chunks.append(tmpchunk); + } + + quint16 addr = 0; + foreach (QByteArray chunk, chunks) { + QString hexstr = makeHexStr(chunk); +// chunk.replace(0,'.'); + QString textstr = makeTextStr(chunk); + QString line = QString("%1: %2 %3").arg(addr,4,16,QChar('0')).arg(hexstr).arg(textstr); + + addr += 16; + outputlines.append(line); + } + + setData(qPrintable(outputlines.join("\n").toUpper())); +} + +void TextHexDumpViewer::setData(QByteArray data) +{ + ui->textArea->setText(data); +} + +void TextHexDumpViewer::setText(QString text) +{ + ui->textArea->setHtml(text); +} diff --git a/src/ui/viewers/texthexdumpviewer.h b/src/ui/viewers/texthexdumpviewer.h new file mode 100644 index 0000000..8267739 --- /dev/null +++ b/src/ui/viewers/texthexdumpviewer.h @@ -0,0 +1,36 @@ +#ifndef TEXTHEXDUMPVIEWER_H +#define TEXTHEXDUMPVIEWER_H + +#include "genericfile.h" + +#include +#include +#include + + +namespace Ui { +class TextHexDumpViewer; +} + +class TextHexDumpViewer : public QWidget +{ + Q_OBJECT + +public: + explicit TextHexDumpViewer(QWidget *parent = 0); + ~TextHexDumpViewer(); + + void setFile(GenericFile *file, quint16 offset = 0); + void setData(QByteArray data); + void setText(QString text); + +protected: + QString makeTextStr(QByteArray data); + QString makeHexStr(QByteArray data); +private: + Ui::TextHexDumpViewer *ui; + + quint16 m_offset; +}; + +#endif // TEXTHEXDUMPVIEWER_H diff --git a/src/ui/viewers/texthexdumpviewer.ui b/src/ui/viewers/texthexdumpviewer.ui new file mode 100644 index 0000000..15375ea --- /dev/null +++ b/src/ui/viewers/texthexdumpviewer.ui @@ -0,0 +1,31 @@ + + + TextHexDumpViewer + + + + 0 + 0 + 836 + 540 + + + + Form + + + + + + + Courier + 12 + + + + + + + + + diff --git a/src/util/applestring.cxx b/src/util/applestring.cxx index 776bd16..2125676 100644 --- a/src/util/applestring.cxx +++ b/src/util/applestring.cxx @@ -6,7 +6,10 @@ QString AppleString::printable() const { QString retval; foreach (quint8 ch, *this) { - retval.append(AppleChar(ch).printable()); + if (ch > 0x80) + retval.append(QChar(ch-0x80)); + else + retval.append(QChar(ch)); } return retval; } @@ -22,7 +25,6 @@ QVector AppleString::attributes() const } - QChar AppleChar::printable() const { quint8 newval; diff --git a/src/util/applestring.h b/src/util/applestring.h index 5ac6090..6eee388 100644 --- a/src/util/applestring.h +++ b/src/util/applestring.h @@ -24,6 +24,7 @@ private: class AppleString : public QByteArray { public: + void setData(const QByteArray &data) { insert(0,data); } QString printable() const; QVector attributes() const;