Refactoring RawDiskImage out of Dos33DiskImage
This commit is contained in:
parent
20165005c2
commit
14301d7083
|
@ -36,6 +36,8 @@ INCLUDEPATH += src/ui/central
|
|||
DEFINES += WS_VIDEO
|
||||
|
||||
SOURCES += \
|
||||
src/diskfiles/dos33/dos33disktreeview.cpp \
|
||||
src/diskfiles/rawdiskimage.cpp \
|
||||
src/intbasic/IntBasicFile.cxx \
|
||||
src/main.cpp \
|
||||
src/diskfiles/dos33/dos33diskimage.cxx \
|
||||
|
@ -45,7 +47,7 @@ SOURCES += \
|
|||
src/diskfiles/dos33/tracksectorlist.cxx \
|
||||
src/diskfiles/dos33/filedescriptiveentry.cxx \
|
||||
src/diskfiles/dos33/genericfile.cxx \
|
||||
src/diskfiles/dos33/tspair.cpp \
|
||||
src/diskfiles/tspair.cpp \
|
||||
src/diskfiles/dos33/dos33imagemodel.cpp \
|
||||
src/diskfiles/dos33/dos33treeitem.cpp \
|
||||
src/memory/attributedmemory.cpp \
|
||||
|
@ -101,20 +103,23 @@ SOURCES += \
|
|||
src/applesoftfile/ApplesoftRetokenizer.cpp \
|
||||
src/internals/JumpLineManager.cpp \
|
||||
src/ui/widgets/FlowLineTextBrowser.cpp \
|
||||
src/util/chunkbytelist.cpp \
|
||||
src/util/opcodes.cpp
|
||||
|
||||
|
||||
HEADERS += \
|
||||
src/diskfiles/dos33/dos33diskimage.h \
|
||||
src/diskfiles/dos33/dos33disktreeview.h \
|
||||
src/diskfiles/dos33/sector.h \
|
||||
src/diskfiles/dos33/vtoc.h \
|
||||
src/diskfiles/dos33/catalogsector.h \
|
||||
src/diskfiles/dos33/tracksectorlist.h \
|
||||
src/diskfiles/dos33/filedescriptiveentry.h \
|
||||
src/diskfiles/dos33/genericfile.h \
|
||||
src/diskfiles/dos33/tspair.h \
|
||||
src/diskfiles/tspair.h \
|
||||
src/diskfiles/dos33/dos33imagemodel.h\
|
||||
src/diskfiles/dos33/dos33treeitem.h\
|
||||
src/diskfiles/rawdiskimage.h \
|
||||
src/intbasic/IntBasicFile.h \
|
||||
src/memory/attributedmemory.h \
|
||||
src/memory/memorycell.h \
|
||||
|
@ -134,6 +139,7 @@ HEADERS += \
|
|||
src/ui/startupdialog.h \
|
||||
src/ui/viewers/intbasicfileviewer.h \
|
||||
src/ui/widgets/notesdialog.h \
|
||||
src/util/chunkbytelist.h \
|
||||
src/util/opcodes.h \
|
||||
src/util/util.h \
|
||||
src/util/applestring.h \
|
||||
|
|
|
@ -11,42 +11,29 @@ ApplesoftFile::ApplesoftFile(QByteArray data) : GenericFile(data)
|
|||
m_retokenizer = Q_NULLPTR;
|
||||
m_data_end = data.length();
|
||||
|
||||
if (!data.isEmpty())
|
||||
{
|
||||
setData(data);
|
||||
}
|
||||
setAddress(0x801);
|
||||
}
|
||||
|
||||
void ApplesoftFile::setData(QByteArray data)
|
||||
void ApplesoftFile::processData()
|
||||
{
|
||||
if (!m_retokenizer)
|
||||
{
|
||||
m_retokenizer = new ApplesoftRetokenizer();
|
||||
}
|
||||
|
||||
GenericFile::setData(data);
|
||||
m_length = dataWordAt(0);
|
||||
setIgnoreOffset(2);
|
||||
|
||||
quint8 addlo = m_data.at(0);
|
||||
quint8 addhi = m_data.at(1);
|
||||
m_length = makeWord(addlo,addhi);
|
||||
m_data.remove(0,2);
|
||||
|
||||
m_retokenizer->setData(m_data);
|
||||
m_retokenizer->setData(data());
|
||||
m_retokenizer->parse();
|
||||
m_data_end = m_retokenizer->getEndOfDataOffset();
|
||||
m_lines = m_retokenizer->getRetokenizedLines();
|
||||
|
||||
m_flowTargets = m_retokenizer->getFlowTargets();
|
||||
|
||||
}
|
||||
|
||||
QByteArray ApplesoftFile::rawData() {
|
||||
QByteArray retval;
|
||||
retval.append(m_length % 255);
|
||||
retval.append(m_length / 255);
|
||||
retval.append(m_data);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
QStringList ApplesoftFile::extraDataHexValues() {
|
||||
QStringList retval;
|
||||
|
@ -72,7 +59,7 @@ QStringList ApplesoftFile::extraDataHexValues() {
|
|||
|
||||
QByteArray ApplesoftFile::extraData()
|
||||
{
|
||||
return m_data.mid(m_data_end);
|
||||
return data().mid(m_data_end);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -14,20 +14,22 @@
|
|||
|
||||
class ApplesoftFile : public GenericFile
|
||||
{
|
||||
friend class Dos33DiskImage;
|
||||
|
||||
public:
|
||||
ApplesoftFile(QByteArray data = QByteArray());
|
||||
void setData(QByteArray data);
|
||||
QByteArray extraData();
|
||||
QStringList extraDataHexValues();
|
||||
|
||||
QVector<ApplesoftLine> getLines() const { return m_lines; }
|
||||
|
||||
quint16 length() const { return m_length; }
|
||||
int length() const override { return m_length; }
|
||||
|
||||
QByteArray rawData();
|
||||
|
||||
protected:
|
||||
void processData();
|
||||
|
||||
private:
|
||||
|
||||
ApplesoftFile(QByteArray data = QByteArray());
|
||||
QVector<ApplesoftLine> m_lines;
|
||||
int m_data_end;
|
||||
quint16 m_length;
|
||||
|
|
|
@ -4,8 +4,6 @@
|
|||
|
||||
BinaryFile::BinaryFile(QByteArray data) : GenericFile(data)
|
||||
{
|
||||
m_length = 0;
|
||||
|
||||
if (!data.isEmpty()) {
|
||||
setData(data);
|
||||
}
|
||||
|
@ -15,17 +13,15 @@ void BinaryFile::setData(QByteArray data)
|
|||
{
|
||||
if (data.length() >= 4) {
|
||||
QByteArray metadata = data.left(4);
|
||||
m_data = data.mid(4);
|
||||
GenericFile::setData(data.mid(4));
|
||||
setAddress(makeWord(metadata[0],metadata[1]));
|
||||
m_length = makeWord(metadata[2],metadata[3]);
|
||||
}
|
||||
setLength(makeWord(metadata[2],metadata[3]));
|
||||
}
|
||||
}
|
||||
|
||||
void BinaryFile::dump()
|
||||
{
|
||||
qDebug() << QString("Address: %1 Length: %2")
|
||||
.arg((quint16) address(),4,16,QChar('0'))
|
||||
.arg(m_length,4,16,QChar('0')).toUpper();
|
||||
qDebug() << QString("Data Length Recorded: %1")
|
||||
.arg(m_data.length(),4,16,QChar('0')).toUpper();
|
||||
.arg(length(),4,16,QChar('0')).toUpper();
|
||||
}
|
||||
|
|
|
@ -5,15 +5,15 @@
|
|||
|
||||
class BinaryFile : public GenericFile
|
||||
{
|
||||
public:
|
||||
BinaryFile(QByteArray data = QByteArray());
|
||||
void setData(QByteArray data) override;
|
||||
friend class Dos33DiskImage;
|
||||
|
||||
virtual quint16 length() const override { return m_length; }
|
||||
public:
|
||||
|
||||
void dump();
|
||||
|
||||
protected:
|
||||
BinaryFile(QByteArray data = QByteArray());
|
||||
void setData(QByteArray data) override;
|
||||
};
|
||||
|
||||
#endif // BINARYFILE_H
|
||||
|
|
|
@ -7,7 +7,7 @@ CatalogSector::CatalogSector(Sector *data)
|
|||
|
||||
m_next = TSPair(0,0);
|
||||
|
||||
TSPair next(m_data->rawData()[0x01],m_data->rawData()[0x02]);
|
||||
TSPair next(m_data->at(0x01),m_data->at(0x02));
|
||||
|
||||
if (next.isValid() && next.track() == 17)
|
||||
{
|
||||
|
@ -48,13 +48,13 @@ void CatalogSector::dumpFDEs() {
|
|||
FileDescriptiveEntry CatalogSector::makeFDE(int offset)
|
||||
{
|
||||
FileDescriptiveEntry fde;
|
||||
TSPair first(m_data->rawData()[offset + 0x00],m_data->rawData()[offset + 0x01]);
|
||||
TSPair first(m_data->at(offset + 0x00),m_data->at(offset + 0x01));
|
||||
fde.setFirstTSListSector(first);
|
||||
|
||||
fde.lengthInSectors = makeWord( m_data->rawData()[offset + 0x21],
|
||||
m_data->rawData()[offset + 0x22]);
|
||||
fde.lengthInSectors = makeWord(m_data->at(offset + 0x21),
|
||||
m_data->at(offset + 0x22));
|
||||
|
||||
fde.fileTypeFlags = m_data->rawData()[offset + 0x02];
|
||||
fde.fileTypeFlags = m_data->at(offset + 0x02);
|
||||
|
||||
if (fde.lengthInSectors > 16*35)
|
||||
{
|
||||
|
@ -62,7 +62,7 @@ FileDescriptiveEntry CatalogSector::makeFDE(int offset)
|
|||
}
|
||||
|
||||
for (int idx = 0x03; idx <= 0x20; idx++) {
|
||||
fde.filename.append(m_data->rawData()[idx+offset]);
|
||||
fde.filename.append(m_data->at(idx+offset));
|
||||
}
|
||||
|
||||
if (fde.firstTSListSector().track() == 0xFF)
|
||||
|
@ -71,7 +71,7 @@ FileDescriptiveEntry CatalogSector::makeFDE(int offset)
|
|||
fde.deleted = true;
|
||||
qDebug() << fde.filename;
|
||||
TSPair first = fde.firstTSListSector();
|
||||
first.setTrack(m_data->rawData()[offset + 0x20]);
|
||||
first.setTrack(m_data->at(offset + 0x20));
|
||||
fde.setFirstTSListSector(first);
|
||||
qDebug() << " New track: " << (quint8) fde.firstTSListSector().track();
|
||||
qDebug() << " Sector: " << fde.firstTSListSector().sector();
|
||||
|
|
|
@ -16,80 +16,104 @@
|
|||
|
||||
Dos33DiskImage::Dos33DiskImage(QString filename)
|
||||
{
|
||||
m_disk_image = new RawDiskImage(filename);
|
||||
|
||||
if (!filename.isEmpty())
|
||||
{
|
||||
read(filename);
|
||||
}
|
||||
}
|
||||
|
||||
Dos33DiskImage::Dos33DiskImage(RawDiskImage *rawImage)
|
||||
{
|
||||
m_disk_image = rawImage;
|
||||
}
|
||||
|
||||
Dos33DiskImage::~Dos33DiskImage()
|
||||
{
|
||||
foreach (GenericFile *file, m_files)
|
||||
{
|
||||
delete file;
|
||||
}
|
||||
// foreach (GenericFile *file, m_files)
|
||||
// {
|
||||
// delete file;
|
||||
// }
|
||||
}
|
||||
|
||||
bool Dos33DiskImage::read(QString filename)
|
||||
{
|
||||
m_fullImageName = filename;
|
||||
m_imageName = QFileInfo(filename).fileName();
|
||||
if (m_imageName.toUpper().contains(".D13"))
|
||||
{
|
||||
m_sectors_per_track = 13;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_sectors_per_track = 16;
|
||||
}
|
||||
bool retval = m_disk_image->read(filename);
|
||||
|
||||
QFile infile(filename);
|
||||
QCryptographicHash hash(QCryptographicHash::Md5);
|
||||
|
||||
if (infile.open(QIODevice::ReadOnly))
|
||||
if (retval)
|
||||
{
|
||||
QByteArray contents = infile.readAll();
|
||||
int expectedsize = sectorsPerTrack() * tracks() * 256;
|
||||
if (contents.size() != expectedsize)
|
||||
for (auto tracknum = 0; tracknum < m_disk_image->numTracks(); tracknum++)
|
||||
{
|
||||
if (contents.size() == 35*16*256) { m_sectors_per_track = 16; }
|
||||
else if (contents.size() == 35*13*256) { m_sectors_per_track = 13; }
|
||||
else qWarning() << QString("Size mismatch in file! Expected %1, got %2")
|
||||
.arg(expectedsize)
|
||||
.arg(contents.size());
|
||||
}
|
||||
|
||||
QDataStream qds(contents);
|
||||
for (int track = 0; track < 35; track++)
|
||||
{
|
||||
for (int sector = 0; sector < m_sectors_per_track; sector++)
|
||||
for (auto secnum = 0; secnum < m_disk_image->sectorsPerTrack(); secnum++)
|
||||
{
|
||||
char buffer[256];
|
||||
if (qds.readRawData(buffer,256) == 256)
|
||||
{
|
||||
TSPair tmpts(track,sector);
|
||||
Sector newSec;
|
||||
newSec.setTrackSector(tmpts);
|
||||
newSec.setData(QByteArray(buffer,256));
|
||||
m_contents[tmpts] = newSec;
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "Invalid sector read!";
|
||||
return false;
|
||||
}
|
||||
TSPair tmpts(tracknum,secnum);
|
||||
Sector newSec;
|
||||
SectorData * data = m_disk_image->sectorAt(tmpts);
|
||||
newSec.setData(data);
|
||||
newSec.setTrackSector(tmpts);
|
||||
m_contents[tmpts] = newSec;
|
||||
}
|
||||
}
|
||||
hash.addData(contents);
|
||||
|
||||
m_hash = hash.result();
|
||||
// qDebug() << "Hash: " << m_hash;
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
qDebug() << "Could not open file " << filename;
|
||||
return false;
|
||||
|
||||
return retval;
|
||||
|
||||
// m_fullImageName = filename;
|
||||
// m_imageName = QFileInfo(filename).fileName();
|
||||
// QFile infile(filename);
|
||||
// QCryptographicHash hash(QCryptographicHash::Md5);
|
||||
|
||||
// if (infile.open(QIODevice::ReadOnly))
|
||||
// {
|
||||
// QByteArray contents = infile.readAll();
|
||||
// int expectedsize = sectorsPerTrack() * tracks() * 256;
|
||||
// if (contents.size() != expectedsize)
|
||||
// {
|
||||
// if (contents.size() == 35*16*256) { m_sectors_per_track = 16; }
|
||||
// else if (contents.size() == 35*13*256) { m_sectors_per_track = 13; }
|
||||
// else qWarning() << QString("Size mismatch in file! Expected %1, got %2")
|
||||
// .arg(expectedsize)
|
||||
// .arg(contents.size());
|
||||
// }
|
||||
|
||||
// QDataStream qds(contents);
|
||||
// for (int track = 0; track < 35; track++)
|
||||
// {
|
||||
// for (int sector = 0; sector < m_sectors_per_track; sector++)
|
||||
// {
|
||||
// char buffer[256];
|
||||
// if (qds.readRawData(buffer,256) == 256)
|
||||
// {
|
||||
// TSPair tmpts(track,sector);
|
||||
// Sector newSec;
|
||||
// newSec.setTrackSector(tmpts);
|
||||
// newSec.setData(QByteArray(buffer,256));
|
||||
// m_contents[tmpts] = newSec;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// qDebug() << "Invalid sector read!";
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// hash.addData(contents);
|
||||
|
||||
// m_hash = hash.result();
|
||||
// // qDebug() << "Hash: " << m_hash;
|
||||
|
||||
// return true;
|
||||
// }
|
||||
// else
|
||||
// qDebug() << "Could not open file " << filename;
|
||||
// return false;
|
||||
}
|
||||
|
||||
Sector &Dos33DiskImage::getSector(TSPair ts) { return m_contents[ts]; }
|
||||
|
||||
Sector &Dos33DiskImage::getSector(int track, int sector) {
|
||||
return getSector(TSPair(track,sector));
|
||||
}
|
||||
|
||||
VTOC Dos33DiskImage::getVTOC()
|
||||
|
@ -99,8 +123,6 @@ VTOC Dos33DiskImage::getVTOC()
|
|||
|
||||
QList<CatalogSector> Dos33DiskImage::getCatalogSectors()
|
||||
{
|
||||
// qDebug() << "### Start getCatalogSector";
|
||||
|
||||
QList<CatalogSector> retval;
|
||||
VTOC vtoc = getVTOC();
|
||||
TSPair ts = vtoc.firstCatalogSector();
|
||||
|
@ -112,7 +134,6 @@ QList<CatalogSector> Dos33DiskImage::getCatalogSectors()
|
|||
cs = getSector(ts).asCatalogSector();
|
||||
retval.append(cs);
|
||||
}
|
||||
// qDebug() << "### End getCatalogSector";
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
@ -138,30 +159,31 @@ GenericFile *Dos33DiskImage::getFile(FileDescriptiveEntry fde)
|
|||
qWarning(" Not returning a file from invalid TSList!");
|
||||
return nullptr;
|
||||
}
|
||||
QByteArray data = getDataFromTrackSectorList(tsl);
|
||||
setFileType(fde.fileType());
|
||||
|
||||
if (fileType() == "A")
|
||||
{
|
||||
retval = new ApplesoftFile(data);
|
||||
}
|
||||
else if (fileType() == "B")
|
||||
{
|
||||
retval = new BinaryFile(data);
|
||||
}
|
||||
else if (fileType() == "R")
|
||||
{
|
||||
retval = new RelocatableFile(data);
|
||||
}
|
||||
else if ((fileType() == "T"))
|
||||
{
|
||||
retval = new TextFile(data);
|
||||
}
|
||||
else if ((fileType() == "I"))
|
||||
{
|
||||
retval = new IntBasicFile(data);
|
||||
}
|
||||
else
|
||||
ChunkByteList data = getDataFromTrackSectorList(tsl);
|
||||
setFileType(fde.fileTypeIdentifier());
|
||||
|
||||
// if (fileType() == "A")
|
||||
// {
|
||||
// retval = new ApplesoftFile(data);
|
||||
// }
|
||||
// else if (fileType() == "B")
|
||||
// {
|
||||
// retval = new BinaryFile(data);
|
||||
// }
|
||||
// else if (fileType() == "R")
|
||||
// {
|
||||
// retval = new RelocatableFile(data);
|
||||
// }
|
||||
// else if ((fileType() == "T"))
|
||||
// {
|
||||
// retval = new TextFile(data);
|
||||
// }
|
||||
// else if ((fileType() == "I"))
|
||||
// {
|
||||
// retval = new IntBasicFile(data);
|
||||
// }
|
||||
// else
|
||||
{
|
||||
retval = new GenericFile(data);
|
||||
}
|
||||
|
@ -173,16 +195,16 @@ GenericFile *Dos33DiskImage::getFile(FileDescriptiveEntry fde)
|
|||
}
|
||||
|
||||
|
||||
QByteArray Dos33DiskImage::getDataFromTrackSectorList(TrackSectorList tsl)
|
||||
ChunkByteList Dos33DiskImage::getDataFromTrackSectorList(TrackSectorList tsl)
|
||||
{
|
||||
QByteArray retval;
|
||||
ChunkByteList retval;
|
||||
|
||||
foreach(TSPair pair, tsl.getDataTSPairs())
|
||||
{
|
||||
if (pair.isValid())
|
||||
{
|
||||
Sector sec = getSector(pair);
|
||||
retval.append(sec.rawData());
|
||||
retval.appendChunk(sec.rawData());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -193,7 +215,7 @@ QByteArray Dos33DiskImage::getDataFromTrackSectorList(TrackSectorList tsl)
|
|||
auto next = tsl.getNextTSList();
|
||||
if (next.isValid() && next != TSPair(0,0)) {
|
||||
TrackSectorList nextTsl = getSector(tsl.getNextTSList()).asTrackSectorList();
|
||||
retval.append(getDataFromTrackSectorList(nextTsl));
|
||||
retval.appendChunkList(getDataFromTrackSectorList(nextTsl));
|
||||
}
|
||||
|
||||
return retval;
|
||||
|
@ -201,7 +223,6 @@ QByteArray Dos33DiskImage::getDataFromTrackSectorList(TrackSectorList tsl)
|
|||
|
||||
QList<FileDescriptiveEntry> Dos33DiskImage::getAllFDEs()
|
||||
{
|
||||
// qDebug() << "### Start getAllFDEs";
|
||||
QList<FileDescriptiveEntry> retval;
|
||||
|
||||
QList<CatalogSector> sectors = getCatalogSectors();
|
||||
|
@ -211,7 +232,6 @@ QList<FileDescriptiveEntry> Dos33DiskImage::getAllFDEs()
|
|||
QList<FileDescriptiveEntry> fdes = cs.getFDEs();
|
||||
retval.append(fdes);
|
||||
}
|
||||
// qDebug() << "### End getAllFDEs";
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
@ -224,3 +244,8 @@ QString Dos33DiskImage::getMetaDataPath() const {
|
|||
return path;
|
||||
}
|
||||
|
||||
FileList Dos33DiskImage::fileList()
|
||||
{
|
||||
return { };
|
||||
}
|
||||
|
||||
|
|
|
@ -11,22 +11,25 @@
|
|||
#include "sector.h"
|
||||
#include "vtoc.h"
|
||||
|
||||
#include "rawdiskimage.h"
|
||||
#include "chunkbytelist.h"
|
||||
|
||||
|
||||
class GenericFile;
|
||||
|
||||
using FileList = QList<GenericFile *>;
|
||||
|
||||
class Dos33DiskImage
|
||||
{
|
||||
public:
|
||||
Dos33DiskImage(QString filename = "");
|
||||
Dos33DiskImage(RawDiskImage *rawImage);
|
||||
~Dos33DiskImage();
|
||||
|
||||
bool read(QString filename);
|
||||
|
||||
Sector &getSector(TSPair ts) { return m_contents[ts]; }
|
||||
|
||||
Sector &getSector(int track, int sector) {
|
||||
TSPair ts(track,sector);
|
||||
return getSector(ts);
|
||||
}
|
||||
Sector &getSector(TSPair ts);
|
||||
Sector &getSector(int track, int sector);
|
||||
|
||||
VTOC getVTOC();
|
||||
|
||||
|
@ -34,34 +37,36 @@ public:
|
|||
|
||||
GenericFile *getFile(FileDescriptiveEntry fde);
|
||||
|
||||
QByteArray getDataFromTrackSectorList(TrackSectorList tsl);
|
||||
ChunkByteList getDataFromTrackSectorList(TrackSectorList tsl);
|
||||
|
||||
QList<FileDescriptiveEntry> getAllFDEs();
|
||||
|
||||
QByteArray fileHash() const { return m_hash; }
|
||||
|
||||
QString getDiskImageName() const { return m_imageName; }
|
||||
QString getFullDiskImageName() const { return m_fullImageName; }
|
||||
QString getDiskImageName() const { return m_disk_image->diskImageName(); }
|
||||
QString getFullDiskImageName() const { return m_disk_image->fullDiskImageName(); }
|
||||
QString getMetaDataPath() const;
|
||||
|
||||
QString fileType() const { return m_fileType; }
|
||||
void setFileType(QString type) { m_fileType = type; }
|
||||
|
||||
quint8 sectorsPerTrack() const { return m_sectors_per_track; }
|
||||
quint8 tracks() const { return 35; }
|
||||
int sectorsPerTrack() const { return m_disk_image->sectorsPerTrack(); }
|
||||
int tracks() const { return m_disk_image->numTracks(); }
|
||||
|
||||
QList<GenericFile *> fileList();
|
||||
|
||||
|
||||
|
||||
private:
|
||||
|
||||
RawDiskImage *m_disk_image;
|
||||
|
||||
QMap<TSPair, Sector> m_contents;
|
||||
QMap<FileDescriptiveEntry, GenericFile *> m_files;
|
||||
QByteArray m_hash;
|
||||
|
||||
QString m_imageName;
|
||||
QString m_fullImageName;
|
||||
|
||||
QString m_fileType;
|
||||
|
||||
quint8 m_sectors_per_track;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
#include "dos33disktreeview.h"
|
||||
|
||||
#include <QGuiApplication>
|
||||
|
||||
Dos33DiskTreeView::Dos33DiskTreeView(QWidget *parent) : QTreeView(parent)
|
||||
{
|
||||
connect(this, &Dos33DiskTreeView::clicked,
|
||||
this, &Dos33DiskTreeView::handleClick);
|
||||
connect(this, &Dos33DiskTreeView::pressed,
|
||||
this, &Dos33DiskTreeView::handlePress);
|
||||
connect(this, &Dos33DiskTreeView::doubleClicked,
|
||||
this, &Dos33DiskTreeView::handleDoubleClick);
|
||||
|
||||
}
|
||||
|
||||
void Dos33DiskTreeView::handleClick(const QModelIndex &/*index*/)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Dos33DiskTreeView::handleDoubleClick(const QModelIndex &/*index*/)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Dos33DiskTreeView::handlePress(const QModelIndex &/*index*/)
|
||||
{
|
||||
if (QGuiApplication::mouseButtons() & Qt::RightButton)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
#ifndef DOS33DISKTREEVIEW_H
|
||||
#define DOS33DISKTREEVIEW_H
|
||||
|
||||
#include <QTreeView>
|
||||
#include <QWidget>
|
||||
|
||||
#include "filedescriptiveentry.h"
|
||||
|
||||
class Dos33DiskTreeView : public QTreeView
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
Dos33DiskTreeView(QWidget *parent = nullptr);
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
signals:
|
||||
void fileClicked(const FileDescriptiveEntry &fde);
|
||||
void fileRightClicked(const FileDescriptiveEntry &fde);
|
||||
void fileDoubleClicked(const FileDescriptiveEntry &fde);
|
||||
void diskClicked(QString name);
|
||||
void diskRightClicked(QString name);
|
||||
void sectorClicked(TSPair ts);
|
||||
void sectorRightClicked(TSPair ts);
|
||||
void sectorDoubleClicked(TSPair ts);
|
||||
|
||||
|
||||
private slots:
|
||||
void handleClick(const QModelIndex &index);
|
||||
void handleDoubleClick(const QModelIndex &index);
|
||||
void handlePress(const QModelIndex &index);
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif // DOS33DISKTREEVIEW_H
|
|
@ -43,7 +43,7 @@ bool Dos33ImageModel::addDiskImage(Dos33DiskImage *image, QString name)
|
|||
if (!fde.deleted)
|
||||
{
|
||||
QString fn = AppleString(fde.filename).appleFontPrintable();
|
||||
QString type = fde.fileType();
|
||||
QString type = fde.fileTypeIdentifier();
|
||||
|
||||
QIcon icon;
|
||||
if (type == "A") { icon = m_icon_A; }
|
||||
|
@ -53,14 +53,23 @@ bool Dos33ImageModel::addDiskImage(Dos33DiskImage *image, QString name)
|
|||
else if (type == "I") { icon = m_icon_I; }
|
||||
else if (type == "a") { icon = m_icon_a; }
|
||||
else if (type == "b") { icon = m_icon_b; }
|
||||
else { icon = m_icon_S; }
|
||||
else if (type == "S") { icon = m_icon_S; }
|
||||
|
||||
auto item = new Dos33TreeItem(icon,fn);
|
||||
|
||||
|
||||
QVariant data;
|
||||
data.setValue(fde.firstTSListSector());
|
||||
item->setData(data);
|
||||
QVariant typevar = (int) Dos33ItemType::File;
|
||||
item->setData(typevar, (int) Dos33TreeRole::ItemType);
|
||||
|
||||
QVariant datavar;
|
||||
datavar.setValue(fde.firstTSListSector());
|
||||
item->setData(datavar, (int) Dos33TreeRole::GetTSPair);
|
||||
|
||||
QVariant fdevar;
|
||||
fdevar.setValue(fde);
|
||||
item->setData(fdevar, (int) Dos33TreeRole::GetFDE);
|
||||
|
||||
|
||||
item->setToolTip(QString("%1 Block(s)").arg(fde.lengthInSectors));
|
||||
diskImageItem->appendRow(item);
|
||||
}
|
||||
|
|
|
@ -9,6 +9,20 @@
|
|||
|
||||
#include <QIcon>
|
||||
|
||||
enum class Dos33TreeRole {
|
||||
ItemType = Qt::UserRole,
|
||||
GetTSPair,
|
||||
GetFDE,
|
||||
};
|
||||
|
||||
enum class Dos33ItemType {
|
||||
Unknown,
|
||||
Sector,
|
||||
File,
|
||||
DiskImage
|
||||
};
|
||||
|
||||
|
||||
class Dos33ImageModel : public QStandardItemModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
|
|
@ -21,15 +21,15 @@ struct FileDescriptiveEntry {
|
|||
return f1.filename < filename;
|
||||
}
|
||||
|
||||
QString fileType() {
|
||||
if (fileTypeFlags & (quint8) FileTypeFlag::Integer) { return "I"; }
|
||||
if (fileTypeFlags & (quint8) FileTypeFlag::Applesoft) { return "A"; }
|
||||
if (fileTypeFlags & (quint8) FileTypeFlag::Relocatable) { return "R"; }
|
||||
if (fileTypeFlags & (quint8) FileTypeFlag::Binary) { return "B"; }
|
||||
if (fileTypeFlags & (quint8) FileTypeFlag::TypeS) { return "S"; }
|
||||
if (fileTypeFlags & (quint8) FileTypeFlag::TypeA) { return "a"; }
|
||||
if (fileTypeFlags & (quint8) FileTypeFlag::TypeB) { return "b"; }
|
||||
return "T";
|
||||
QString fileTypeIdentifier() {
|
||||
if (fileTypeFlags & (quint8) FileTypeFlag::Integer) { return "I"; }
|
||||
else if (fileTypeFlags & (quint8) FileTypeFlag::Applesoft) { return "A"; }
|
||||
else if (fileTypeFlags & (quint8) FileTypeFlag::Relocatable) { return "R"; }
|
||||
else if (fileTypeFlags & (quint8) FileTypeFlag::Binary) { return "B"; }
|
||||
else if (fileTypeFlags & (quint8) FileTypeFlag::TypeS) { return "S"; }
|
||||
else if (fileTypeFlags & (quint8) FileTypeFlag::TypeA) { return "a"; }
|
||||
else if (fileTypeFlags & (quint8) FileTypeFlag::TypeB) { return "b"; }
|
||||
else return "T";
|
||||
}
|
||||
|
||||
bool isLocked() { return (fileTypeFlags & (quint8) FileTypeFlag::IsLockedFlag); }
|
||||
|
@ -38,7 +38,7 @@ struct FileDescriptiveEntry {
|
|||
|
||||
qDebug() << "First TS List Sector: Track: " << QString("%1").arg(firstTSListSector().track(),2,16,QChar('0')).toUpper()
|
||||
<< " Sector: " << QString("%1").arg(firstTSListSector().sector(),2,16,QChar('0')).toUpper();
|
||||
qDebug() << "File Type and Flags: " << QString::number((quint8) fileTypeFlags) << "(" << fileType() << "," << (isLocked()?"Locked":"Unlocked") << ")";
|
||||
qDebug() << "File Type and Flags: " << QString::number((quint8) fileTypeFlags) << "(" << fileTypeIdentifier() << "," << (isLocked()?"Locked":"Unlocked") << ")";
|
||||
qDebug() << "Filename: " << filename.printable();
|
||||
qDebug() << "Length in Sectors: " << lengthInSectors;
|
||||
}
|
||||
|
@ -46,7 +46,7 @@ struct FileDescriptiveEntry {
|
|||
void catalog() {
|
||||
QString output = QString("%1 %2 %3 %4").arg(QString(isLocked()?"*":" "))
|
||||
.arg(lengthInSectors,3,10,QChar('0'))
|
||||
.arg(fileType())
|
||||
.arg(fileTypeIdentifier())
|
||||
.arg(filename.printable().trimmed());
|
||||
qDebug() << output;
|
||||
}
|
||||
|
@ -68,5 +68,5 @@ private:
|
|||
TSPair m_firstTSListSector;
|
||||
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(FileDescriptiveEntry);
|
||||
#endif // FILEDESCRIPTIVEENTRY_H
|
||||
|
|
|
@ -2,20 +2,40 @@
|
|||
|
||||
GenericFile::GenericFile(QByteArray data)
|
||||
{
|
||||
m_data_loaded = false;
|
||||
m_diskfile = 0;
|
||||
if (!data.isEmpty()) {
|
||||
setData(data);
|
||||
m_data_loaded = true;
|
||||
}
|
||||
m_address = 0x00;
|
||||
m_length = 0x00;
|
||||
m_ignore_offset = 0;
|
||||
}
|
||||
|
||||
GenericFile::GenericFile(Dos33DiskImage *image, TSPairList pairs)
|
||||
{
|
||||
m_diskfile = image;
|
||||
m_ts_pairs = pairs;
|
||||
m_length = 0x00;
|
||||
m_address = 0x00;
|
||||
m_ignore_offset = 0;
|
||||
m_data_loaded = false;
|
||||
}
|
||||
|
||||
quint8 GenericFile::dataAt(int offset) const
|
||||
{
|
||||
return m_data[offset ];
|
||||
}
|
||||
|
||||
void GenericFile::setData(QByteArray data)
|
||||
{
|
||||
m_data_loaded = true;
|
||||
m_data = data;
|
||||
m_length = data.size();
|
||||
}
|
||||
|
||||
|
||||
QString GenericFile::getFileType() const
|
||||
{
|
||||
if (m_file_type == "A" || m_file_type == "B" || m_file_type == "T" ||
|
||||
|
@ -29,3 +49,10 @@ QString GenericFile::getFileType() const
|
|||
return "?";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
quint16 GenericFile::dataWordAt(int offset) const
|
||||
{
|
||||
return makeWord(dataAt(offset),dataAt(offset+1));
|
||||
}
|
||||
|
|
|
@ -9,23 +9,22 @@
|
|||
|
||||
class GenericFile
|
||||
{
|
||||
friend class Dos33DiskImage;
|
||||
|
||||
public:
|
||||
GenericFile(QByteArray data = QByteArray());
|
||||
virtual ~GenericFile() { }
|
||||
|
||||
virtual void setData(QByteArray data);
|
||||
virtual QByteArray data() { return m_data; }
|
||||
|
||||
void setFilename(QString filename) { m_filename = filename; }
|
||||
virtual QByteArray data() { return m_data.mid(m_ignore_offset); }
|
||||
quint8 dataAt(int offset) const;
|
||||
quint16 dataWordAt(int offset) const;
|
||||
|
||||
virtual void setFilename(QString filename) { m_filename = filename; }
|
||||
QString filename() const { return m_filename; }
|
||||
|
||||
virtual void setAddress(quint16 location) { m_address = location; }
|
||||
virtual quint16 address() { return m_address; }
|
||||
|
||||
virtual QByteArray rawData() { return m_data; }
|
||||
|
||||
virtual void setLength(quint16 length) { m_length = length; }
|
||||
virtual quint16 length() const { return m_length; }
|
||||
virtual int length() const { return m_length; }
|
||||
|
||||
Dos33DiskImage *diskFile() const { return m_diskfile; }
|
||||
void setDiskFile(Dos33DiskImage *diskfile) { m_diskfile = diskfile; }
|
||||
|
@ -33,13 +32,27 @@ public:
|
|||
void setFileType(QString type) { m_file_type = type; }
|
||||
QString getFileType() const;
|
||||
|
||||
protected:
|
||||
QByteArray rawData() const { return m_data; }
|
||||
|
||||
void setIgnoreOffset(int offset) { m_ignore_offset = offset; }
|
||||
int ignoreOffset() const { return m_ignore_offset; }
|
||||
|
||||
protected:
|
||||
GenericFile(Dos33DiskImage *image, QList<TSPair> pairs);
|
||||
|
||||
GenericFile(QByteArray data = QByteArray());
|
||||
virtual void setLength(quint16 length) { m_length = length; }
|
||||
virtual void setData(QByteArray data);
|
||||
|
||||
private:
|
||||
int m_ignore_offset;
|
||||
QByteArray m_data;
|
||||
QString m_filename;
|
||||
quint16 m_address;
|
||||
qint16 m_length;
|
||||
Dos33DiskImage * m_diskfile;
|
||||
bool m_data_loaded;
|
||||
TSPairList m_ts_pairs;
|
||||
|
||||
QString m_file_type;
|
||||
|
||||
|
|
|
@ -3,19 +3,13 @@
|
|||
#include <QString>
|
||||
#include <QDebug>
|
||||
|
||||
QByteRef Sector::operator[](uint offset) {
|
||||
quint8 Sector::operator[](uint offset) const {
|
||||
if (offset > 255) {
|
||||
offset = 255;
|
||||
}
|
||||
return m_data[offset];
|
||||
return m_raw_data->at(offset);
|
||||
}
|
||||
|
||||
bool Sector::setData(QByteArray data) {
|
||||
if (data.length() != 256) return false;
|
||||
|
||||
m_data = data;
|
||||
return true;
|
||||
}
|
||||
|
||||
void Sector::dump() {
|
||||
qDebug() << "Dumping Track " << track() << "Sector " << sector() << " ...";
|
||||
|
@ -27,7 +21,7 @@ void Sector::dump() {
|
|||
for (int idx = 0; idx < 16; idx++)
|
||||
{
|
||||
int offset = (jdx*16) + idx;
|
||||
quint8 val = m_data[offset];
|
||||
quint8 val = m_raw_data->at(offset);
|
||||
line += QString("%1 ").arg(uint16ToHex(val));
|
||||
if (idx == 7) line += " ";
|
||||
}
|
||||
|
@ -36,7 +30,7 @@ void Sector::dump() {
|
|||
for (int idx = 0; idx < 16; idx++)
|
||||
{
|
||||
int offset = (jdx*16) + idx;
|
||||
quint8 val = m_data[offset];
|
||||
quint8 val = m_raw_data->at(offset);
|
||||
if (val > 127) { val -= 128; }
|
||||
QChar ch(val);
|
||||
line += QString("%1").arg(ch.isPrint()?ch:'.');
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
#include <QByteArray>
|
||||
|
||||
#include "rawdiskimage.h"
|
||||
|
||||
#include "vtoc.h"
|
||||
#include "catalogsector.h"
|
||||
#include "tracksectorlist.h"
|
||||
|
@ -11,12 +13,18 @@ class Sector
|
|||
{
|
||||
public:
|
||||
|
||||
Sector() {
|
||||
m_data.resize(256);
|
||||
Sector(SectorData *data = nullptr) {
|
||||
// m_data.resize(256);
|
||||
setData(data);
|
||||
m_track = 255;
|
||||
m_sector = 255;
|
||||
}
|
||||
|
||||
void setData(SectorData *data)
|
||||
{
|
||||
m_raw_data = data;
|
||||
}
|
||||
|
||||
VTOC promoteToVTOC() {
|
||||
return VTOC(this);
|
||||
}
|
||||
|
@ -45,18 +53,19 @@ public:
|
|||
void setTrack(int track) { m_track = track; }
|
||||
void setSector(int sector) { m_sector = sector; }
|
||||
|
||||
QByteRef operator[](uint offset);
|
||||
|
||||
bool setData(QByteArray data);
|
||||
quint8 operator[](uint offset) const;
|
||||
quint8 at(int offset) { return m_raw_data->at(offset); }
|
||||
|
||||
void dump();
|
||||
|
||||
QByteArray rawData() { return m_data; }
|
||||
SectorData *rawData() { return m_raw_data; }
|
||||
|
||||
private:
|
||||
QByteArray m_data;
|
||||
// QByteArray m_data;
|
||||
int m_track;
|
||||
int m_sector;
|
||||
|
||||
SectorData *m_raw_data;
|
||||
};
|
||||
|
||||
#endif // SECTOR_H
|
||||
|
|
|
@ -6,15 +6,15 @@ TrackSectorList::TrackSectorList(Sector *data)
|
|||
{
|
||||
m_data = data;
|
||||
|
||||
m_next_tslist.setTrack(m_data->rawData()[0x01]);
|
||||
m_next_tslist.setSector(m_data->rawData()[0x02]);
|
||||
m_next_tslist.setTrack(m_data->at(0x01));
|
||||
m_next_tslist.setSector(m_data->at(0x02));
|
||||
|
||||
m_sector_offset.setTrack(m_data->rawData()[0x05]);
|
||||
m_sector_offset.setSector(m_data->rawData()[0x06]);
|
||||
m_sector_offset.setTrack(m_data->at(0x05));
|
||||
m_sector_offset.setSector(m_data->at(0x06));
|
||||
|
||||
for (int idx = 0x0C; idx < 0xff; idx+=2)
|
||||
{
|
||||
TSPair ts(m_data->rawData()[idx],m_data->rawData()[idx+1]);
|
||||
TSPair ts(m_data->at(idx),m_data->at(idx+1));
|
||||
if (ts == TSPair(0,0) && ts.isValid()) {
|
||||
break;
|
||||
} else {
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
|
||||
class Sector;
|
||||
|
||||
using TSPairList = QList<TSPair>;
|
||||
|
||||
class TrackSectorList
|
||||
{
|
||||
public:
|
||||
|
@ -16,14 +18,14 @@ public:
|
|||
TSPair getSectorOffset() const { return m_sector_offset; }
|
||||
bool isSectorOffsetValid() const;
|
||||
|
||||
QList<TSPair> getDataTSPairs() const { return m_ts_pairs_for_data; }
|
||||
QList<TSPair> getValidTSPairs() const;
|
||||
TSPairList getDataTSPairs() const { return m_ts_pairs_for_data; }
|
||||
TSPairList getValidTSPairs() const;
|
||||
|
||||
|
||||
private:
|
||||
TSPair m_next_tslist;
|
||||
TSPair m_sector_offset;
|
||||
QList<TSPair> m_ts_pairs_for_data;
|
||||
TSPairList m_ts_pairs_for_data;
|
||||
|
||||
Sector *m_data;
|
||||
};
|
||||
|
|
|
@ -13,40 +13,40 @@ VTOC::VTOC(Sector *data)
|
|||
|
||||
TSPair VTOC::firstCatalogSector() {
|
||||
// return TSPair(0x11,0x0f); // Force to look at the normal location
|
||||
return TSPair(m_data->rawData()[0x01], m_data->rawData()[0x02]);
|
||||
return TSPair(m_data->at(0x01), m_data->at(0x02));
|
||||
}
|
||||
|
||||
quint8 VTOC::dosVersion() {
|
||||
return m_data->rawData()[0x03];
|
||||
return m_data->at(0x03);
|
||||
}
|
||||
|
||||
quint8 VTOC::volumeNumber() {
|
||||
return m_data->rawData()[0x06];
|
||||
return m_data->at(0x06);
|
||||
}
|
||||
|
||||
quint8 VTOC::maxTSPairs() {
|
||||
return m_data->rawData()[0x27];
|
||||
return m_data->at(0x27);
|
||||
}
|
||||
|
||||
quint8 VTOC::lastTrackAllocated() {
|
||||
return m_data->rawData()[0x30];
|
||||
return m_data->at(0x30);
|
||||
}
|
||||
|
||||
qint8 VTOC::directionOfAllocation() {
|
||||
return m_data->rawData()[0x31];
|
||||
return m_data->at(0x31);
|
||||
}
|
||||
|
||||
quint8 VTOC::tracksPerDisk() {
|
||||
return m_data->rawData()[0x34];
|
||||
return m_data->at(0x34);
|
||||
}
|
||||
|
||||
quint8 VTOC::sectorsPerDisk() {
|
||||
return m_data->rawData()[0x35];
|
||||
return m_data->at(0x35);
|
||||
}
|
||||
|
||||
qint16 VTOC::bytesPerSector() {
|
||||
return makeWord(m_data->rawData()[0x36],
|
||||
m_data->rawData()[0x37]);
|
||||
return makeWord(m_data->at(0x36),
|
||||
m_data->at(0x37));
|
||||
}
|
||||
|
||||
bool VTOC::isSectorInUse(TSPair ts) const {
|
||||
|
@ -55,8 +55,8 @@ bool VTOC::isSectorInUse(TSPair ts) const {
|
|||
quint8 baseaddr = (track * 4) + 0x38;
|
||||
|
||||
//quint16 word = (((quint16) m_data->rawData()[baseaddr]) *256) + (quint8) m_data->rawData()[baseaddr+1];
|
||||
quint16 word = makeWord(m_data->rawData()[baseaddr+1],
|
||||
m_data->rawData()[baseaddr]);
|
||||
quint16 word = makeWord(m_data->at(baseaddr+1),
|
||||
m_data->at(baseaddr));
|
||||
quint16 bitpos = (quint16) 0x01 << (quint16) sec;
|
||||
|
||||
return !(word & bitpos);
|
||||
|
@ -119,7 +119,7 @@ void VTOC::dump()
|
|||
qDebug() << " Number sectors per disk: " << QString::number(sectorsPerDisk());
|
||||
qDebug() << " Number bytes/sector: " << QString::number(bytesPerSector());
|
||||
qDebug() << " Track Usage (.=free, 0-F=used):";
|
||||
for (quint8 track = 0; track < m_data->rawData()[0x34];track++)
|
||||
for (quint8 track = 0; track < m_data->at(0x34);track++)
|
||||
{
|
||||
qDebug() << " " << QString("Track %1:").arg((int) track,2,10,QChar('0')) << buildUseString(track);
|
||||
}
|
||||
|
|
|
@ -14,17 +14,18 @@ class VTOC
|
|||
public:
|
||||
VTOC(Sector *data);
|
||||
|
||||
void dump();
|
||||
void dump();
|
||||
TSPair firstCatalogSector();
|
||||
quint8 dosVersion();
|
||||
quint8 volumeNumber();
|
||||
quint8 maxTSPairs();
|
||||
quint8 lastTrackAllocated();
|
||||
qint8 directionOfAllocation();
|
||||
qint8 directionOfAllocation();
|
||||
quint8 tracksPerDisk();
|
||||
quint8 sectorsPerDisk();
|
||||
qint16 bytesPerSector();
|
||||
bool isSectorInUse(TSPair ts) const;
|
||||
|
||||
bool isSectorInUse(TSPair ts) const;
|
||||
|
||||
QList<TSPair> sectorsInUse() const;
|
||||
QList<TSPair> sectorsNotInUse() const;
|
||||
|
|
|
@ -0,0 +1,194 @@
|
|||
#include "rawdiskimage.h"
|
||||
|
||||
#include <QFileInfo>
|
||||
#include <QFile>
|
||||
#include <QCryptographicHash>
|
||||
#include <QDataStream>
|
||||
|
||||
RawDiskImage::RawDiskImage(QString name)
|
||||
{
|
||||
setCustomOrderMap0(dosOrderMap());
|
||||
setCustomOrderMap1(prodosOrderMap());
|
||||
|
||||
// Set everything up assuming a 140k DOS image as a default for now
|
||||
|
||||
m_track_count = 35;
|
||||
m_sector_size = 256;
|
||||
m_sectors_per_track = 16;
|
||||
m_sector_order = SectorOrder::Dos33;
|
||||
m_empty_image = true;
|
||||
|
||||
if (!name.isEmpty())
|
||||
{
|
||||
read(name);
|
||||
}
|
||||
}
|
||||
|
||||
RawDiskImage::~RawDiskImage()
|
||||
{
|
||||
foreach (auto track, m_tracks)
|
||||
{
|
||||
while (track.count())
|
||||
{
|
||||
auto sectorblock = track.takeFirst();
|
||||
delete sectorblock;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool RawDiskImage::read(QString filename)
|
||||
{
|
||||
if (!isEmpty()) return false; // Don't reread a disk!
|
||||
|
||||
m_full_filename = filename;
|
||||
m_filename = QFileInfo(filename).fileName();
|
||||
|
||||
if (m_filename.toUpper().contains(".D13"))
|
||||
{
|
||||
setSectorsPerTrack(13);
|
||||
}
|
||||
else
|
||||
{
|
||||
setSectorsPerTrack(16);
|
||||
}
|
||||
|
||||
QFile infile(filename);
|
||||
QCryptographicHash hash(QCryptographicHash::Md5);
|
||||
|
||||
|
||||
if (infile.open(QIODevice::ReadOnly))
|
||||
{
|
||||
QByteArray contents = infile.readAll();
|
||||
int expectedsize = sectorsPerTrack() * numTracks() * 256;
|
||||
if (contents.size() != expectedsize)
|
||||
{
|
||||
if (contents.size() == 35*16*256) { m_sectors_per_track = 16; }
|
||||
else if (contents.size() == 35*13*256) { m_sectors_per_track = 13; }
|
||||
else qWarning() << QString("Size mismatch in file! Expected %1, got %2")
|
||||
.arg(expectedsize)
|
||||
.arg(contents.size());
|
||||
}
|
||||
|
||||
QDataStream qds(contents);
|
||||
for (int track = 0; track < numTracks(); track++)
|
||||
{
|
||||
TrackData td;
|
||||
for (int sector = 0; sector < m_sectors_per_track; sector++)
|
||||
{
|
||||
char buffer[256];
|
||||
if (qds.readRawData(buffer,sectorSize()) == sectorSize())
|
||||
{
|
||||
TSPair tmpts(track,sector);
|
||||
SectorData *newSec = new SectorData();
|
||||
*newSec = QByteArray(buffer,sectorSize());
|
||||
td.append(newSec);
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "Invalid sector read!";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
m_tracks.append(td);
|
||||
}
|
||||
hash.addData(contents);
|
||||
|
||||
m_hash = hash.result();
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "Could not open file " << filename;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool RawDiskImage::isEmpty() const { return m_empty_image; }
|
||||
|
||||
HashValue RawDiskImage::hash() const { return m_hash; }
|
||||
|
||||
QString RawDiskImage::diskImageName() const { return m_filename; }
|
||||
|
||||
QString RawDiskImage::fullDiskImageName() const { return m_full_filename; }
|
||||
|
||||
void RawDiskImage::setNumTracks(int count) { m_track_count = count; }
|
||||
|
||||
int RawDiskImage::numTracks() const { return m_track_count; }
|
||||
|
||||
bool RawDiskImage::hasSectors() const {return true; }
|
||||
|
||||
int RawDiskImage::sectorSize() const { return m_sector_size; }
|
||||
|
||||
void RawDiskImage::setSectorSize(int size) { m_sector_size = size; }
|
||||
|
||||
void RawDiskImage::setSectorsPerTrack(int spt) { m_sectors_per_track = spt; }
|
||||
|
||||
int RawDiskImage::sectorsPerTrack() const { return m_sectors_per_track; }
|
||||
|
||||
void RawDiskImage::setSectorOrder(SectorOrder order) { m_sector_order = order; }
|
||||
|
||||
SectorOrder RawDiskImage::sectorOrder() const { return m_sector_order; }
|
||||
|
||||
bool RawDiskImage::reorderSectorsTo(SectorOrder)
|
||||
{
|
||||
//TODO: Handle Reordering
|
||||
return false;
|
||||
}
|
||||
|
||||
SectorData *RawDiskImage::sectorAt(int track, int sector)
|
||||
{
|
||||
if (track >= numTracks() || sector >= sectorsPerTrack())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return m_tracks[track][sector];
|
||||
}
|
||||
|
||||
SectorData *RawDiskImage::sectorAt(TSPair ts)
|
||||
{
|
||||
return sectorAt(ts.track(),ts.sector());
|
||||
}
|
||||
|
||||
SectorOrderMap RawDiskImage::dosOrderMap() const {
|
||||
return QByteArrayLiteral("\x0\xD\xB\x9\x7\x5\x3\x1\xE\xC\xA\x8\x6\x4\x2\xF");
|
||||
}
|
||||
|
||||
SectorOrderMap RawDiskImage::prodosOrderMap() const {
|
||||
return QByteArrayLiteral("\x0\x8\x1\x9\x2\xA\x3\xB\x4\xC\x5\xD\x6\xE\x7\xF");
|
||||
}
|
||||
|
||||
SectorOrderMap RawDiskImage::pascalOrderMap() const {
|
||||
return QByteArrayLiteral("\x0\x2\x4\x6\x8\xA\xC\xE\x1\x3\x5\x7x9xBxDxF");
|
||||
}
|
||||
|
||||
SectorOrderMap RawDiskImage::cpmOrderMap() const {
|
||||
return QByteArrayLiteral("\x0\x3\x6\x9\xC\xF\x2\x5\x8\xB\xE\x1\x4\x7\xA\xD");
|
||||
}
|
||||
|
||||
SectorOrderMap RawDiskImage::customOrderMap0() const { return m_custom_order_map_0; }
|
||||
|
||||
SectorOrderMap RawDiskImage::customOrderMap1() const { return m_custom_order_map_0; }
|
||||
|
||||
bool RawDiskImage::setCustomOrderMap0(SectorOrderMap map)
|
||||
{
|
||||
if (map.count() < m_sectors_per_track)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_custom_order_map_0 = map.left(m_sectors_per_track);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RawDiskImage::setCustomOrderMap1(SectorOrderMap map)
|
||||
{
|
||||
if (map.count() < m_sectors_per_track)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_custom_order_map_1 = map.left(m_sectors_per_track);
|
||||
return true;
|
||||
}
|
|
@ -0,0 +1,103 @@
|
|||
#ifndef RAWDISKIMAGE_H
|
||||
#define RAWDISKIMAGE_H
|
||||
|
||||
#include "tspair.h"
|
||||
|
||||
#include <QString>
|
||||
#include <QByteArray>
|
||||
#include <QVector>
|
||||
|
||||
using SectorOrderMap = QByteArray;
|
||||
|
||||
using SectorData = QByteArray;
|
||||
//PRODOS using BlockData = QByteArray;
|
||||
//PRODOS using BlockPair = QPair<TSPair, TSPair>;
|
||||
using TrackData = QList<SectorData*>;
|
||||
using TrackList = QList<TrackData>;
|
||||
|
||||
using HashValue = QByteArray;
|
||||
|
||||
|
||||
enum class SectorOrder
|
||||
{
|
||||
Unknown = 0,
|
||||
Dos33 = 0,
|
||||
ProDos,
|
||||
Pascal,
|
||||
CPM,
|
||||
Custom1,
|
||||
Custom2
|
||||
};
|
||||
|
||||
|
||||
class RawDiskImage
|
||||
{
|
||||
public:
|
||||
|
||||
RawDiskImage(QString filename = QString());
|
||||
~RawDiskImage();
|
||||
bool read(QString filename);
|
||||
|
||||
bool isEmpty() const;
|
||||
|
||||
HashValue hash() const;
|
||||
|
||||
QString diskImageName() const;
|
||||
QString fullDiskImageName() const;
|
||||
|
||||
void setNumTracks(int count);
|
||||
int numTracks() const;
|
||||
|
||||
bool hasSectors() const;
|
||||
int sectorSize() const;
|
||||
void setSectorSize(int size);
|
||||
void setSectorsPerTrack(int spt);
|
||||
int sectorsPerTrack() const;
|
||||
|
||||
//PRODOS bool hasBlocks();
|
||||
//PRODOS int blockSize();
|
||||
//PRODOS int blocksPerTrack();
|
||||
|
||||
void setSectorOrder(SectorOrder order);
|
||||
SectorOrder sectorOrder() const;
|
||||
|
||||
bool reorderSectorsTo(SectorOrder newOrder);
|
||||
|
||||
SectorData *sectorAt(int track, int sector);
|
||||
SectorData *sectorAt(TSPair ts);
|
||||
|
||||
inline SectorOrderMap dosOrderMap() const;;
|
||||
inline SectorOrderMap prodosOrderMap() const;
|
||||
inline SectorOrderMap pascalOrderMap() const;
|
||||
inline SectorOrderMap cpmOrderMap() const;
|
||||
|
||||
SectorOrderMap customOrderMap0() const;
|
||||
SectorOrderMap customOrderMap1() const;
|
||||
|
||||
bool setCustomOrderMap0(SectorOrderMap map);
|
||||
bool setCustomOrderMap1(SectorOrderMap map);
|
||||
|
||||
private:
|
||||
//PRODOS BlockPair mapBlockToTS(int blocknum);
|
||||
|
||||
private:
|
||||
TrackList m_tracks;
|
||||
|
||||
bool m_empty_image;
|
||||
|
||||
int m_sector_size;
|
||||
int m_sectors_per_track;
|
||||
int m_track_count;
|
||||
|
||||
QString m_full_filename;
|
||||
QString m_filename;
|
||||
|
||||
SectorOrder m_sector_order;
|
||||
|
||||
SectorOrderMap m_custom_order_map_0;
|
||||
SectorOrderMap m_custom_order_map_1;
|
||||
|
||||
HashValue m_hash;
|
||||
};
|
||||
|
||||
#endif // RAWDISKIMAGE_H
|
|
@ -8,10 +8,10 @@ class TSPair
|
|||
{
|
||||
public:
|
||||
TSPair() { m_track = m_sector = 0; }
|
||||
TSPair(quint8 trackval, quint8 secval) { m_track=trackval; m_sector = secval; }
|
||||
TSPair(QPair<quint8,quint8> pair) { m_track = pair.first; m_sector = pair.second;}
|
||||
TSPair(int trackval, int secval) { m_track=trackval; m_sector = secval; }
|
||||
TSPair(QPair<int,int> pair) { m_track = pair.first; m_sector = pair.second;}
|
||||
|
||||
void setTrack(quint8 tracknum)
|
||||
void setTrack(int tracknum)
|
||||
{
|
||||
if (tracknum > 34 && tracknum != 0xff) {
|
||||
qWarning("Setting a track with value %d (> 34 and not 256).",tracknum);
|
||||
|
@ -34,8 +34,8 @@ public:
|
|||
|
||||
return retval; }
|
||||
|
||||
quint8 track() const { return m_track; }
|
||||
quint8 sector() const { return m_sector; }
|
||||
int track() const { return m_track; }
|
||||
int sector() const { return m_sector; }
|
||||
|
||||
bool operator==(const TSPair &other) const {
|
||||
if (other.track() == track() && other.sector() == sector()) return true;
|
||||
|
@ -57,14 +57,14 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
QPair<quint8,quint8> toQPair() { return QPair<quint8,quint8>(track(),sector()); }
|
||||
QPair<int,int> toQPair() { return QPair<quint8,quint8>(track(),sector()); }
|
||||
|
||||
void dump() const {
|
||||
qDebug() << "TSPair: track: " << track() << " sector: " << sector();
|
||||
}
|
||||
private:
|
||||
quint8 m_track;
|
||||
quint8 m_sector;
|
||||
int m_track;
|
||||
int m_sector;
|
||||
};
|
||||
Q_DECLARE_METATYPE(TSPair);
|
||||
|
|
@ -6,11 +6,13 @@
|
|||
|
||||
class IntBasicFile : public GenericFile
|
||||
{
|
||||
public:
|
||||
IntBasicFile(QByteArray data = QByteArray());
|
||||
friend class Dos33DiskImage;
|
||||
|
||||
public:
|
||||
QByteArray detokenize();
|
||||
|
||||
private:
|
||||
IntBasicFile(QByteArray data = QByteArray());
|
||||
quint16 get16(quint8 v1, quint8 v2);
|
||||
QByteArray dumpBufferAsIntBasicFile(QByteArray origdata);
|
||||
};
|
||||
|
|
|
@ -1,12 +1,4 @@
|
|||
/* ---------------------------------------------------------------------------
|
||||
|
||||
Created by the qtsass compiler v0.1.1
|
||||
|
||||
The definitions are in the "qdarkstyle.qss._styles.scss" module
|
||||
|
||||
WARNING! All changes made in this file will be lost!
|
||||
|
||||
--------------------------------------------------------------------------- */
|
||||
/* QDarkStyleSheet -----------------------------------------------------------
|
||||
|
||||
This is the main style sheet, the palette has nine colors.
|
||||
|
@ -1010,7 +1002,7 @@ QPushButton {
|
|||
padding: 3px;
|
||||
outline: none;
|
||||
/* Issue #194 - Special case of QPushButton inside dialogs, for better UI */
|
||||
min-width: 80px;
|
||||
min-width: 80px;
|
||||
}
|
||||
|
||||
QPushButton:disabled {
|
||||
|
@ -2187,3 +2179,13 @@ background-color: #32414B;
|
|||
color: #aaa;
|
||||
}
|
||||
|
||||
|
||||
DEButton {
|
||||
background-color: #505F69;
|
||||
border: 1px solid #32414B;
|
||||
color: #F0F0F0;
|
||||
border-radius: 4px;
|
||||
padding: 2px;
|
||||
outline: none;
|
||||
min-width: 10px;
|
||||
}
|
||||
|
|
|
@ -10,18 +10,18 @@ RelocatableFile::RelocatableFile(QByteArray data) : GenericFile(data)
|
|||
}
|
||||
}
|
||||
|
||||
void RelocatableFile::setData(QByteArray data)
|
||||
void RelocatableFile::setData(QByteArray /*data*/)
|
||||
{
|
||||
// qDebug() << "setData()";
|
||||
if (data.length() >= 6) {
|
||||
m_starting_ram_address = makeWord(m_data[0],m_data[1]);
|
||||
m_ram_image_length = makeWord(m_data[2],m_data[3]);
|
||||
m_code_image_length = makeWord(m_data[4],m_data[5]);
|
||||
if (length() >= 6) {
|
||||
m_starting_ram_address = dataWordAt(0);
|
||||
m_ram_image_length = dataWordAt(2);
|
||||
m_code_image_length = dataWordAt(4);
|
||||
|
||||
int offset = 0;
|
||||
|
||||
for (int idx = 6; idx < m_code_image_length+6; idx++) {
|
||||
quint8 val = m_data[idx];
|
||||
quint8 val = dataAt(idx);
|
||||
m_binary_code_image.append(val);
|
||||
}
|
||||
|
||||
|
@ -33,14 +33,12 @@ void RelocatableFile::setData(QByteArray data)
|
|||
// << 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]);
|
||||
RelocatableDictItem rdi = RelocatableDictItem(
|
||||
dataAt(offset),dataAt(offset+1),
|
||||
dataAt(offset+2),dataAt(offset+3));
|
||||
m_relocatable_dict.append(rdi);
|
||||
if (rdi.isEndOfRLD()) { break; }
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -77,12 +77,10 @@ private:
|
|||
|
||||
class RelocatableFile : public GenericFile
|
||||
{
|
||||
friend class Dos33DiskImage;
|
||||
|
||||
public:
|
||||
|
||||
RelocatableFile(QByteArray data = QByteArray());
|
||||
void setData(QByteArray data);
|
||||
|
||||
virtual quint16 length() { return m_data.length(); }
|
||||
|
||||
void dump();
|
||||
|
||||
|
@ -95,6 +93,9 @@ public:
|
|||
QStringList decodeRelocatableDict();
|
||||
|
||||
protected:
|
||||
RelocatableFile(QByteArray data = QByteArray());
|
||||
void setData(QByteArray data);
|
||||
|
||||
quint16 m_starting_ram_address;
|
||||
quint16 m_ram_image_length;
|
||||
quint16 m_code_image_length;
|
||||
|
|
|
@ -8,10 +8,6 @@ TextFile::TextFile(QByteArray data) : GenericFile(data)
|
|||
}
|
||||
}
|
||||
|
||||
void TextFile::setData(QByteArray data)
|
||||
{
|
||||
m_data = data;
|
||||
}
|
||||
|
||||
void TextFile::dump()
|
||||
{
|
||||
|
|
|
@ -5,13 +5,14 @@
|
|||
|
||||
class TextFile : public GenericFile
|
||||
{
|
||||
friend class Dos33DiskImage;
|
||||
|
||||
public:
|
||||
TextFile(QByteArray data = QByteArray());
|
||||
void setData(QByteArray data);
|
||||
|
||||
void dump();
|
||||
|
||||
protected:
|
||||
TextFile(QByteArray data = QByteArray());
|
||||
};
|
||||
|
||||
#endif // TEXTFILE_H
|
||||
|
|
|
@ -42,7 +42,7 @@ QString CatalogWidget::createToolTip(FileDescriptiveEntry &fde) {
|
|||
QString retval;
|
||||
retval += AppleString(fde.filename).printable().trimmed() +
|
||||
(fde.deleted?"(Deleted)":"") + "\n";
|
||||
retval += QString("Type: %1\n").arg(fde.fileType());
|
||||
retval += QString("Type: %1\n").arg(fde.fileTypeIdentifier());
|
||||
retval += QString("Sectors: %1 (%2 bytes)\n")
|
||||
.arg(fde.lengthInSectors)
|
||||
.arg(fde.lengthInSectors*256);
|
||||
|
@ -54,12 +54,12 @@ QString CatalogWidget::createToolTip(FileDescriptiveEntry &fde) {
|
|||
.arg(address);
|
||||
if (dynamic_cast<BinaryFile*>(file)) {
|
||||
BinaryFile *binfile = dynamic_cast<BinaryFile*>(file);
|
||||
quint16 length = binfile->length();
|
||||
auto length = binfile->length();
|
||||
retval += QString("Length: $%1 (%2)\n").arg((quint16) (length),4,16,QChar('0'))
|
||||
.arg(length);
|
||||
} else if (dynamic_cast<ApplesoftFile*>(file)) {
|
||||
ApplesoftFile *asfile = dynamic_cast<ApplesoftFile*>(file);
|
||||
quint16 length = asfile->length();
|
||||
auto length = asfile->length();
|
||||
retval += QString("Length: $%1 (%2)\n").arg((quint16) (length),4,16,QChar('0'))
|
||||
.arg(length);
|
||||
quint16 uabytes = asfile->extraData().length();
|
||||
|
@ -87,7 +87,7 @@ void CatalogWidget::processNewlyLoadedDisk(QString diskfilename, Dos33DiskImage
|
|||
int idx = 0;
|
||||
foreach(FileDescriptiveEntry fde, m_disk->getAllFDEs()) {
|
||||
// qDebug() << " Processing FDE# " << idx;
|
||||
QString filetype = fde.fileType();
|
||||
QString filetype = fde.fileTypeIdentifier();
|
||||
QString filename = AppleString(fde.filename).printable().trimmed();
|
||||
quint16 size = fde.lengthInSectors;
|
||||
bool locked = fde.isLocked();
|
||||
|
|
|
@ -3,8 +3,9 @@
|
|||
|
||||
#include "dos33diskimage.h"
|
||||
#include "dos33imagemodel.h"
|
||||
|
||||
#include "dos33disktreeview.h"
|
||||
#include "sequencetoolbox.h"
|
||||
#include "DiskExplorerMapWidget.h"
|
||||
|
||||
#include <QTreeView>
|
||||
#include <QAction>
|
||||
|
@ -15,6 +16,9 @@
|
|||
#include <QDockWidget>
|
||||
#include <QGridLayout>
|
||||
#include <QStatusBar>
|
||||
#include <QStackedWidget>
|
||||
#include <QScrollArea>
|
||||
|
||||
|
||||
#include <QFile>
|
||||
|
||||
|
@ -36,8 +40,8 @@ CentralAppWindow::CentralAppWindow(QWidget *parent) : QMainWindow(parent)
|
|||
initToolBars();
|
||||
initDockWidgets();
|
||||
initStatusBar();
|
||||
initCentralWidget();
|
||||
|
||||
setCentralWidget(new SequenceViewer());
|
||||
}
|
||||
|
||||
void CentralAppWindow::createActions()
|
||||
|
@ -74,14 +78,13 @@ void CentralAppWindow::initToolBars()
|
|||
void CentralAppWindow::initDockWidgets()
|
||||
{
|
||||
QDockWidget *container = new QDockWidget(this);
|
||||
// container->setLayout(new QGridLayout());
|
||||
container->setMinimumWidth(200);
|
||||
container->setFeatures(QDockWidget::DockWidgetMovable);
|
||||
|
||||
m_project_area = new QWidget(container);
|
||||
m_project_area->setMinimumSize(300,200);
|
||||
|
||||
m_directory_area = new QTreeView(container);
|
||||
m_directory_area = new Dos33DiskTreeView(container);
|
||||
m_directory_area->setFont(QFont("Pr Number 3", 12));
|
||||
m_directory_area->setMinimumSize(300,200);
|
||||
|
||||
|
@ -114,7 +117,7 @@ void CentralAppWindow::initDockWidgets()
|
|||
QDockWidget *stb = new QDockWidget(this);
|
||||
stb->setMinimumWidth(200);
|
||||
stb->setFeatures(QDockWidget::DockWidgetMovable);
|
||||
stb->setLayout(new QGridLayout());
|
||||
// stb->setLayout(new QGridLayout());
|
||||
|
||||
m_toolbox = new SequenceToolBox(this);
|
||||
|
||||
|
@ -124,3 +127,20 @@ void CentralAppWindow::initDockWidgets()
|
|||
|
||||
|
||||
}
|
||||
|
||||
void CentralAppWindow::initCentralWidget()
|
||||
{
|
||||
m_central_stack = new QStackedWidget(this);
|
||||
QScrollArea *sa = new QScrollArea(m_central_stack);
|
||||
sa->setWidgetResizable(true);
|
||||
m_central_stack->addWidget(sa);
|
||||
|
||||
setCentralWidget(m_central_stack);
|
||||
|
||||
Dos33DiskImage *img = new Dos33DiskImage("c:/develop/git/AppleSAWS/disk-images/ApplesoftToolkit.dsk");
|
||||
auto dew = new DiskExplorerMapWidget(img->tracks(),img->sectorsPerTrack());
|
||||
dew->setDisk(img);
|
||||
sa->setWidget(dew);
|
||||
// m_central_stack->addWidget(dew);
|
||||
//new SequenceViewer()
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ class QTreeView;
|
|||
class QAction;
|
||||
class QStatusBar;
|
||||
class SequenceToolBox;
|
||||
class QStackedWidget;
|
||||
|
||||
class CentralAppWindow : public QMainWindow
|
||||
{
|
||||
|
@ -22,6 +23,7 @@ private:
|
|||
void initStatusBar();
|
||||
void initToolBars();
|
||||
void initDockWidgets();
|
||||
void initCentralWidget();
|
||||
|
||||
private:
|
||||
QAction *m_quitAction;
|
||||
|
@ -32,6 +34,8 @@ private:
|
|||
QStatusBar *m_status_bar;
|
||||
|
||||
SequenceToolBox *m_toolbox;
|
||||
|
||||
QStackedWidget *m_central_stack;
|
||||
};
|
||||
|
||||
#endif // CENTRALAPPWINDOW_H
|
||||
|
|
|
@ -36,7 +36,7 @@ DiskExplorer::~DiskExplorer()
|
|||
void DiskExplorer::initUi()
|
||||
{
|
||||
QMenuBar *menuBar = new QMenuBar(this);
|
||||
setMenuBar(menuBar);
|
||||
setMenuBar(menuBar);
|
||||
QMenu *menu = new QMenu(tr("&File"),this);
|
||||
menuBar->addMenu(menu);
|
||||
|
||||
|
@ -100,7 +100,7 @@ void DiskExplorer::initUi()
|
|||
// if (!m_notesDialog) m_notesDialog = new NotesDialog(this);
|
||||
// connect(action_Notes, &QAction::triggered, m_notesDialog, &NotesDialog::show);
|
||||
|
||||
QWidget *widget = new QWidget(0);
|
||||
QWidget *widget = new QWidget(nullptr);
|
||||
m_gridLayout = new QGridLayout();
|
||||
m_gridLayout->setVerticalSpacing(4);
|
||||
m_gridLayout->setHorizontalSpacing(4);
|
||||
|
@ -125,7 +125,12 @@ void DiskExplorer::initUi()
|
|||
m_key = m_demw->makeKeyWidget();
|
||||
m_gridLayout->addWidget(m_key,1,1);
|
||||
m_gridLayout->addWidget(m_frame,1,2);
|
||||
|
||||
this->setCentralWidget(widget);
|
||||
// auto lo = new QGridLayout();
|
||||
// this->setLayout(lo);
|
||||
// lo->addWidget(widget);
|
||||
|
||||
|
||||
connect(m_cw, &CatalogWidget::openWithDefaultViewer,
|
||||
this, &DiskExplorer::handleDiskItemSelectedDefaultOpen);
|
||||
|
|
|
@ -25,8 +25,9 @@ DiskExplorerMapWidget::DiskExplorerMapWidget(int numtracks, int numsectors, QWid
|
|||
setWindowTitle("Disk Explorer");
|
||||
|
||||
QGridLayout *gridlayout = new QGridLayout(this);
|
||||
gridlayout->setSizeConstraint(QLayout::SetFixedSize);
|
||||
gridlayout->setHorizontalSpacing(2);
|
||||
// gridlayout->setSizeConstraint(QLayout::SetFixedSize);
|
||||
gridlayout->setSizeConstraint(QLayout::SetMinimumSize);
|
||||
gridlayout->setHorizontalSpacing(1);
|
||||
gridlayout->setVerticalSpacing(1);
|
||||
|
||||
initColors();
|
||||
|
@ -37,7 +38,7 @@ DiskExplorerMapWidget::DiskExplorerMapWidget(int numtracks, int numsectors, QWid
|
|||
gridlayout->addWidget(tracklabel,0,0,1,m_numtracks+1,Qt::AlignHCenter);
|
||||
for (int track= 0; track < numtracks; track++)
|
||||
{
|
||||
QLabel *label = new QLabel(QString("%1").arg(track));
|
||||
QLabel *label = new QLabel(QString("%1").arg(track,2,10,QChar('0')));
|
||||
label->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
|
||||
gridlayout->addWidget(label,1,track+1);
|
||||
}
|
||||
|
@ -64,13 +65,16 @@ DiskExplorerMapWidget::DiskExplorerMapWidget(int numtracks, int numsectors, QWid
|
|||
gridlayout->addWidget(tb,sec+2,track+1);
|
||||
}
|
||||
}
|
||||
gridlayout->addWidget(new QLabel("Stretchy Row"),18,0,1,5);
|
||||
gridlayout->setRowStretch(18,900);
|
||||
|
||||
|
||||
makeStatusWidget();
|
||||
}
|
||||
|
||||
void DiskExplorerMapWidget::makeStatusWidget()
|
||||
{
|
||||
QWidget *statusWidget = new QWidget(this);
|
||||
QWidget *statusWidget = new QWidget;
|
||||
QHBoxLayout *hbl = new QHBoxLayout();
|
||||
statusWidget->setLayout(hbl);
|
||||
|
||||
|
@ -125,8 +129,8 @@ void DiskExplorerMapWidget::handleButtonCheck(int track, int sector, bool checke
|
|||
if (checked)
|
||||
{
|
||||
Sector sec = m_disk->getSector(track,sector);
|
||||
QByteArray data = sec.rawData();
|
||||
emit showSectorData(data,track,sector,QVariant());
|
||||
QByteArray *data = sec.rawData();
|
||||
emit showSectorData(*data,track,sector,QVariant());
|
||||
m_trackSectorLabel->setText(
|
||||
QString("Track: %1 Sector: %2 (%3)")
|
||||
.arg(track)
|
||||
|
@ -215,7 +219,7 @@ QLabel *DiskExplorerMapWidget::makeKeyLabel(QWidget *parent, QString name, QColo
|
|||
QGroupBox *DiskExplorerMapWidget::makeKeyWidget()
|
||||
{
|
||||
int idx = 0;
|
||||
QGroupBox *groupbox= new QGroupBox(this);
|
||||
QGroupBox *groupbox= new QGroupBox();
|
||||
groupbox->setTitle("Key");
|
||||
QGridLayout *layout = new QGridLayout();
|
||||
layout->setVerticalSpacing(0);
|
||||
|
@ -354,15 +358,15 @@ void DiskExplorerMapWidget::mapDiskToButtons()
|
|||
m_sectorDescriptions.insert(DETSPair(tr,se),description);
|
||||
|
||||
QColor color;
|
||||
if (fde.fileType() == "I") color = m_intBasicFileColor;
|
||||
else if (fde.fileType() == "A") color = m_applesoftFileColor;
|
||||
else if (fde.fileType() == "R") color = m_reloFileColor;
|
||||
else if (fde.fileType() == "B") color = m_binaryFileColor;
|
||||
else if (fde.fileType() == "S") color = m_typeSFileColor;
|
||||
else if (fde.fileType() == "T") color = m_textFileColor;
|
||||
else if (fde.fileType() == "a") color = m_typeAFileColor;
|
||||
else if (fde.fileType() == "b") color = m_typeBFileColor;
|
||||
else qDebug() << "Unknown file type: " << fde.fileType();
|
||||
if (fde.fileTypeIdentifier() == "I") color = m_intBasicFileColor;
|
||||
else if (fde.fileTypeIdentifier() == "A") color = m_applesoftFileColor;
|
||||
else if (fde.fileTypeIdentifier() == "R") color = m_reloFileColor;
|
||||
else if (fde.fileTypeIdentifier() == "B") color = m_binaryFileColor;
|
||||
else if (fde.fileTypeIdentifier() == "S") color = m_typeSFileColor;
|
||||
else if (fde.fileTypeIdentifier() == "T") color = m_textFileColor;
|
||||
else if (fde.fileTypeIdentifier() == "a") color = m_typeAFileColor;
|
||||
else if (fde.fileTypeIdentifier() == "b") color = m_typeBFileColor;
|
||||
else qDebug() << "Unknown file type: " << fde.fileTypeIdentifier();
|
||||
buttonAt(tr,se)->setBgColor(color);
|
||||
setButtonText(tr,se,QString("%1").arg(idx));
|
||||
qDebug() << "Button" << idx << "=" << tr << "," << se << " " << fde.filename.printable();
|
||||
|
|
|
@ -8,29 +8,37 @@
|
|||
#include <QColor>
|
||||
#include <QGroupBox>
|
||||
#include <QLabel>
|
||||
#include <QToolButton>
|
||||
|
||||
|
||||
#include "dos33diskimage.h"
|
||||
|
||||
|
||||
class DEButton : public QPushButton
|
||||
class DEButton : public QToolButton
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
DEButton(QWidget *parent,int track = -1, int sec = -1) : QPushButton(parent)
|
||||
|
||||
DEButton(QWidget *parent,int track = -1, int sec = -1) : QToolButton(parent)
|
||||
{
|
||||
setTrack(track);
|
||||
setSector(sec);
|
||||
connect(this, &DEButton::clicked, this, &DEButton::handleClick);
|
||||
m_isHighlighted = false;
|
||||
}
|
||||
|
||||
void setTrack(int track) { m_track = track; }
|
||||
void setSector(int sector) { m_sector = sector; }
|
||||
|
||||
int track() const { return m_track; }
|
||||
int sector() const { return m_sector; }
|
||||
|
||||
void clearBgColor() { m_backgroundColor = ""; setText(""); setStyleSheet(makeStyleSheet());}
|
||||
void clearBgColor() {
|
||||
m_backgroundColor = "";
|
||||
setText("");
|
||||
setStyleSheet(makeStyleSheet());
|
||||
}
|
||||
|
||||
void setBgColor(QColor color) {
|
||||
m_fgColor = determineFgColor(color).name();
|
||||
|
@ -40,9 +48,18 @@ public:
|
|||
}
|
||||
|
||||
bool highlighted() const { return m_isHighlighted; }
|
||||
void setHighlighted(bool highlighted) { m_isHighlighted = highlighted;setStyleSheet(makeStyleSheet()); }
|
||||
|
||||
void reset() { setHighlighted(false); setChecked(false); makeStyleSheet(); qDebug() << "Reset";}
|
||||
void setHighlighted(bool highlighted) {
|
||||
m_isHighlighted = highlighted;
|
||||
setStyleSheet(makeStyleSheet());
|
||||
}
|
||||
|
||||
void reset() {
|
||||
setHighlighted(false);
|
||||
setChecked(false);
|
||||
makeStyleSheet();
|
||||
qDebug() << "Reset";
|
||||
}
|
||||
|
||||
void resetToDefault() { clearBgColor(); reset(); }
|
||||
|
||||
|
@ -59,28 +76,41 @@ signals:
|
|||
void checked(int track, int sec,bool );
|
||||
|
||||
private slots:
|
||||
void handleClick(bool isChecked) { emit checked(m_track,m_sector,isChecked); }
|
||||
void handleClick(bool isChecked) {
|
||||
emit checked(m_track,m_sector,isChecked);
|
||||
}
|
||||
|
||||
QSize minimumSizeHint() const Q_DECL_OVERRIDE { return QSize(24,24); }
|
||||
QSize minimumSizeHint() const Q_DECL_OVERRIDE { return QSize(12,12); }
|
||||
QSize sizeHint() const Q_DECL_OVERRIDE { return QSize(24,24); }
|
||||
bool hasHeightForWidth() const Q_DECL_OVERRIDE { return true; }
|
||||
int heightForWidth(int width) const Q_DECL_OVERRIDE { return width; }
|
||||
|
||||
private:
|
||||
|
||||
QString makeStyleSheet() const {
|
||||
return QString(" QPushButton { font: 10px; border-width: 1px; color: %1; background-color: %2} "
|
||||
" QPushButton:checked { font: bold italic 11px; } "
|
||||
) .arg(m_fgColor)
|
||||
return QString("DEButton { "
|
||||
" font: 10px; "
|
||||
" border-width: 1px; "
|
||||
" color: %1; "
|
||||
" background-color: %2 "
|
||||
"} "
|
||||
" "
|
||||
"DEButton:checked { "
|
||||
" font: bold italic 11px; "
|
||||
"}"
|
||||
).arg(m_fgColor)
|
||||
.arg(m_backgroundColor);
|
||||
}
|
||||
|
||||
int m_track;
|
||||
int m_sector;
|
||||
|
||||
bool m_isHighlighted;
|
||||
|
||||
QString m_fgColor;
|
||||
QString m_backgroundColor;
|
||||
QString m_hlColor;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
#include "chunkbytelist.h"
|
||||
|
||||
ChunkByteList::ChunkByteList() { }
|
||||
|
||||
ChunkByteList &ChunkByteList::appendChunk(QByteArray *chunk)
|
||||
{
|
||||
if (chunk)
|
||||
{
|
||||
m_chunk_list.append(chunk);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
ChunkByteList &ChunkByteList::appendChunkList(ChunkByteList other)
|
||||
{
|
||||
if (&other != this)
|
||||
{
|
||||
for (auto count = 0; count < other.numChunks(); count++)
|
||||
{
|
||||
m_chunk_list.append(other.getChunk(count));
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
int ChunkByteList::count() const
|
||||
{
|
||||
int size = 0;
|
||||
foreach (auto chunk, m_chunk_list)
|
||||
{
|
||||
size += chunk->size();
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
int ChunkByteList::size() const
|
||||
{
|
||||
return count();
|
||||
}
|
||||
|
||||
int ChunkByteList::length() const
|
||||
{
|
||||
return count();
|
||||
}
|
||||
|
||||
bool ChunkByteList::isEmpty() const
|
||||
{
|
||||
if (m_chunk_list.size() == 0) return true;
|
||||
|
||||
foreach (auto chunk, m_chunk_list)
|
||||
{
|
||||
if (!chunk->isEmpty()) return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
char ChunkByteList::at(int i) const
|
||||
{
|
||||
int offset = 0;
|
||||
foreach (auto chunk, m_chunk_list)
|
||||
{
|
||||
int upperbound = offset + chunk->size();
|
||||
if (i < upperbound)
|
||||
{
|
||||
return chunk->at(i-offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
offset += chunk->size();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
char ChunkByteList::operator[](int i) const
|
||||
{
|
||||
return at(i);
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
#ifndef CHUNKBYTELIST_H
|
||||
#define CHUNKBYTELIST_H
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QList>
|
||||
|
||||
class ChunkByteList
|
||||
{
|
||||
public:
|
||||
ChunkByteList();
|
||||
|
||||
ChunkByteList &appendChunk(QByteArray *chunk);
|
||||
ChunkByteList &appendChunkList(ChunkByteList other);
|
||||
|
||||
int count() const;
|
||||
int size() const;
|
||||
int length() const;
|
||||
|
||||
bool isEmpty() const;
|
||||
|
||||
char at(int i) const;
|
||||
char operator[](int i) const;
|
||||
|
||||
int numChunks() const { return m_chunk_list.size(); }
|
||||
QByteArray *getChunk(int chunk) const { return m_chunk_list[chunk]; }
|
||||
|
||||
QByteArray asQByteArray() const {
|
||||
QByteArray retval;
|
||||
foreach (auto chunk, m_chunk_list)
|
||||
{
|
||||
retval.append(*chunk);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
operator QByteArray() { return asQByteArray(); }
|
||||
|
||||
private:
|
||||
QList<QByteArray *> m_chunk_list;
|
||||
};
|
||||
|
||||
|
||||
#endif // CHUNKBYTELIST_H
|
|
@ -39,6 +39,8 @@ enum class TextSet {
|
|||
};
|
||||
|
||||
|
||||
|
||||
|
||||
inline QString uint8ToHex(quint8 val) {
|
||||
QString retval = QString("%1").arg(val,2,16,QChar('0')).toUpper();
|
||||
return retval;
|
||||
|
|
Loading…
Reference in New Issue