mirror of
https://github.com/markdavidlong/AppleSAWS.git
synced 2024-06-25 18:29:49 +00:00
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
|
DEFINES += WS_VIDEO
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
|
src/diskfiles/dos33/dos33disktreeview.cpp \
|
||||||
|
src/diskfiles/rawdiskimage.cpp \
|
||||||
src/intbasic/IntBasicFile.cxx \
|
src/intbasic/IntBasicFile.cxx \
|
||||||
src/main.cpp \
|
src/main.cpp \
|
||||||
src/diskfiles/dos33/dos33diskimage.cxx \
|
src/diskfiles/dos33/dos33diskimage.cxx \
|
||||||
|
@ -45,7 +47,7 @@ SOURCES += \
|
||||||
src/diskfiles/dos33/tracksectorlist.cxx \
|
src/diskfiles/dos33/tracksectorlist.cxx \
|
||||||
src/diskfiles/dos33/filedescriptiveentry.cxx \
|
src/diskfiles/dos33/filedescriptiveentry.cxx \
|
||||||
src/diskfiles/dos33/genericfile.cxx \
|
src/diskfiles/dos33/genericfile.cxx \
|
||||||
src/diskfiles/dos33/tspair.cpp \
|
src/diskfiles/tspair.cpp \
|
||||||
src/diskfiles/dos33/dos33imagemodel.cpp \
|
src/diskfiles/dos33/dos33imagemodel.cpp \
|
||||||
src/diskfiles/dos33/dos33treeitem.cpp \
|
src/diskfiles/dos33/dos33treeitem.cpp \
|
||||||
src/memory/attributedmemory.cpp \
|
src/memory/attributedmemory.cpp \
|
||||||
|
@ -101,20 +103,23 @@ SOURCES += \
|
||||||
src/applesoftfile/ApplesoftRetokenizer.cpp \
|
src/applesoftfile/ApplesoftRetokenizer.cpp \
|
||||||
src/internals/JumpLineManager.cpp \
|
src/internals/JumpLineManager.cpp \
|
||||||
src/ui/widgets/FlowLineTextBrowser.cpp \
|
src/ui/widgets/FlowLineTextBrowser.cpp \
|
||||||
|
src/util/chunkbytelist.cpp \
|
||||||
src/util/opcodes.cpp
|
src/util/opcodes.cpp
|
||||||
|
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
src/diskfiles/dos33/dos33diskimage.h \
|
src/diskfiles/dos33/dos33diskimage.h \
|
||||||
|
src/diskfiles/dos33/dos33disktreeview.h \
|
||||||
src/diskfiles/dos33/sector.h \
|
src/diskfiles/dos33/sector.h \
|
||||||
src/diskfiles/dos33/vtoc.h \
|
src/diskfiles/dos33/vtoc.h \
|
||||||
src/diskfiles/dos33/catalogsector.h \
|
src/diskfiles/dos33/catalogsector.h \
|
||||||
src/diskfiles/dos33/tracksectorlist.h \
|
src/diskfiles/dos33/tracksectorlist.h \
|
||||||
src/diskfiles/dos33/filedescriptiveentry.h \
|
src/diskfiles/dos33/filedescriptiveentry.h \
|
||||||
src/diskfiles/dos33/genericfile.h \
|
src/diskfiles/dos33/genericfile.h \
|
||||||
src/diskfiles/dos33/tspair.h \
|
src/diskfiles/tspair.h \
|
||||||
src/diskfiles/dos33/dos33imagemodel.h\
|
src/diskfiles/dos33/dos33imagemodel.h\
|
||||||
src/diskfiles/dos33/dos33treeitem.h\
|
src/diskfiles/dos33/dos33treeitem.h\
|
||||||
|
src/diskfiles/rawdiskimage.h \
|
||||||
src/intbasic/IntBasicFile.h \
|
src/intbasic/IntBasicFile.h \
|
||||||
src/memory/attributedmemory.h \
|
src/memory/attributedmemory.h \
|
||||||
src/memory/memorycell.h \
|
src/memory/memorycell.h \
|
||||||
|
@ -134,6 +139,7 @@ HEADERS += \
|
||||||
src/ui/startupdialog.h \
|
src/ui/startupdialog.h \
|
||||||
src/ui/viewers/intbasicfileviewer.h \
|
src/ui/viewers/intbasicfileviewer.h \
|
||||||
src/ui/widgets/notesdialog.h \
|
src/ui/widgets/notesdialog.h \
|
||||||
|
src/util/chunkbytelist.h \
|
||||||
src/util/opcodes.h \
|
src/util/opcodes.h \
|
||||||
src/util/util.h \
|
src/util/util.h \
|
||||||
src/util/applestring.h \
|
src/util/applestring.h \
|
||||||
|
|
|
@ -11,42 +11,29 @@ ApplesoftFile::ApplesoftFile(QByteArray data) : GenericFile(data)
|
||||||
m_retokenizer = Q_NULLPTR;
|
m_retokenizer = Q_NULLPTR;
|
||||||
m_data_end = data.length();
|
m_data_end = data.length();
|
||||||
|
|
||||||
if (!data.isEmpty())
|
|
||||||
{
|
|
||||||
setData(data);
|
|
||||||
}
|
|
||||||
setAddress(0x801);
|
setAddress(0x801);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ApplesoftFile::setData(QByteArray data)
|
void ApplesoftFile::processData()
|
||||||
{
|
{
|
||||||
if (!m_retokenizer)
|
if (!m_retokenizer)
|
||||||
{
|
{
|
||||||
m_retokenizer = new ApplesoftRetokenizer();
|
m_retokenizer = new ApplesoftRetokenizer();
|
||||||
}
|
}
|
||||||
|
|
||||||
GenericFile::setData(data);
|
m_length = dataWordAt(0);
|
||||||
|
setIgnoreOffset(2);
|
||||||
|
|
||||||
quint8 addlo = m_data.at(0);
|
m_retokenizer->setData(data());
|
||||||
quint8 addhi = m_data.at(1);
|
|
||||||
m_length = makeWord(addlo,addhi);
|
|
||||||
m_data.remove(0,2);
|
|
||||||
|
|
||||||
m_retokenizer->setData(m_data);
|
|
||||||
m_retokenizer->parse();
|
m_retokenizer->parse();
|
||||||
m_data_end = m_retokenizer->getEndOfDataOffset();
|
m_data_end = m_retokenizer->getEndOfDataOffset();
|
||||||
m_lines = m_retokenizer->getRetokenizedLines();
|
m_lines = m_retokenizer->getRetokenizedLines();
|
||||||
|
|
||||||
m_flowTargets = m_retokenizer->getFlowTargets();
|
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 ApplesoftFile::extraDataHexValues() {
|
||||||
QStringList retval;
|
QStringList retval;
|
||||||
|
@ -72,7 +59,7 @@ QStringList ApplesoftFile::extraDataHexValues() {
|
||||||
|
|
||||||
QByteArray ApplesoftFile::extraData()
|
QByteArray ApplesoftFile::extraData()
|
||||||
{
|
{
|
||||||
return m_data.mid(m_data_end);
|
return data().mid(m_data_end);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -14,20 +14,22 @@
|
||||||
|
|
||||||
class ApplesoftFile : public GenericFile
|
class ApplesoftFile : public GenericFile
|
||||||
{
|
{
|
||||||
|
friend class Dos33DiskImage;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ApplesoftFile(QByteArray data = QByteArray());
|
|
||||||
void setData(QByteArray data);
|
|
||||||
QByteArray extraData();
|
QByteArray extraData();
|
||||||
QStringList extraDataHexValues();
|
QStringList extraDataHexValues();
|
||||||
|
|
||||||
QVector<ApplesoftLine> getLines() const { return m_lines; }
|
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:
|
private:
|
||||||
|
ApplesoftFile(QByteArray data = QByteArray());
|
||||||
QVector<ApplesoftLine> m_lines;
|
QVector<ApplesoftLine> m_lines;
|
||||||
int m_data_end;
|
int m_data_end;
|
||||||
quint16 m_length;
|
quint16 m_length;
|
||||||
|
|
|
@ -4,8 +4,6 @@
|
||||||
|
|
||||||
BinaryFile::BinaryFile(QByteArray data) : GenericFile(data)
|
BinaryFile::BinaryFile(QByteArray data) : GenericFile(data)
|
||||||
{
|
{
|
||||||
m_length = 0;
|
|
||||||
|
|
||||||
if (!data.isEmpty()) {
|
if (!data.isEmpty()) {
|
||||||
setData(data);
|
setData(data);
|
||||||
}
|
}
|
||||||
|
@ -15,9 +13,9 @@ void BinaryFile::setData(QByteArray data)
|
||||||
{
|
{
|
||||||
if (data.length() >= 4) {
|
if (data.length() >= 4) {
|
||||||
QByteArray metadata = data.left(4);
|
QByteArray metadata = data.left(4);
|
||||||
m_data = data.mid(4);
|
GenericFile::setData(data.mid(4));
|
||||||
setAddress(makeWord(metadata[0],metadata[1]));
|
setAddress(makeWord(metadata[0],metadata[1]));
|
||||||
m_length = makeWord(metadata[2],metadata[3]);
|
setLength(makeWord(metadata[2],metadata[3]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,7 +23,5 @@ void BinaryFile::dump()
|
||||||
{
|
{
|
||||||
qDebug() << QString("Address: %1 Length: %2")
|
qDebug() << QString("Address: %1 Length: %2")
|
||||||
.arg((quint16) address(),4,16,QChar('0'))
|
.arg((quint16) address(),4,16,QChar('0'))
|
||||||
.arg(m_length,4,16,QChar('0')).toUpper();
|
.arg(length(),4,16,QChar('0')).toUpper();
|
||||||
qDebug() << QString("Data Length Recorded: %1")
|
|
||||||
.arg(m_data.length(),4,16,QChar('0')).toUpper();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,15 +5,15 @@
|
||||||
|
|
||||||
class BinaryFile : public GenericFile
|
class BinaryFile : public GenericFile
|
||||||
{
|
{
|
||||||
public:
|
friend class Dos33DiskImage;
|
||||||
BinaryFile(QByteArray data = QByteArray());
|
|
||||||
void setData(QByteArray data) override;
|
|
||||||
|
|
||||||
virtual quint16 length() const override { return m_length; }
|
public:
|
||||||
|
|
||||||
void dump();
|
void dump();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
BinaryFile(QByteArray data = QByteArray());
|
||||||
|
void setData(QByteArray data) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // BINARYFILE_H
|
#endif // BINARYFILE_H
|
||||||
|
|
|
@ -7,7 +7,7 @@ CatalogSector::CatalogSector(Sector *data)
|
||||||
|
|
||||||
m_next = TSPair(0,0);
|
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)
|
if (next.isValid() && next.track() == 17)
|
||||||
{
|
{
|
||||||
|
@ -48,13 +48,13 @@ void CatalogSector::dumpFDEs() {
|
||||||
FileDescriptiveEntry CatalogSector::makeFDE(int offset)
|
FileDescriptiveEntry CatalogSector::makeFDE(int offset)
|
||||||
{
|
{
|
||||||
FileDescriptiveEntry fde;
|
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.setFirstTSListSector(first);
|
||||||
|
|
||||||
fde.lengthInSectors = makeWord( m_data->rawData()[offset + 0x21],
|
fde.lengthInSectors = makeWord(m_data->at(offset + 0x21),
|
||||||
m_data->rawData()[offset + 0x22]);
|
m_data->at(offset + 0x22));
|
||||||
|
|
||||||
fde.fileTypeFlags = m_data->rawData()[offset + 0x02];
|
fde.fileTypeFlags = m_data->at(offset + 0x02);
|
||||||
|
|
||||||
if (fde.lengthInSectors > 16*35)
|
if (fde.lengthInSectors > 16*35)
|
||||||
{
|
{
|
||||||
|
@ -62,7 +62,7 @@ FileDescriptiveEntry CatalogSector::makeFDE(int offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int idx = 0x03; idx <= 0x20; idx++) {
|
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)
|
if (fde.firstTSListSector().track() == 0xFF)
|
||||||
|
@ -71,7 +71,7 @@ FileDescriptiveEntry CatalogSector::makeFDE(int offset)
|
||||||
fde.deleted = true;
|
fde.deleted = true;
|
||||||
qDebug() << fde.filename;
|
qDebug() << fde.filename;
|
||||||
TSPair first = fde.firstTSListSector();
|
TSPair first = fde.firstTSListSector();
|
||||||
first.setTrack(m_data->rawData()[offset + 0x20]);
|
first.setTrack(m_data->at(offset + 0x20));
|
||||||
fde.setFirstTSListSector(first);
|
fde.setFirstTSListSector(first);
|
||||||
qDebug() << " New track: " << (quint8) fde.firstTSListSector().track();
|
qDebug() << " New track: " << (quint8) fde.firstTSListSector().track();
|
||||||
qDebug() << " Sector: " << fde.firstTSListSector().sector();
|
qDebug() << " Sector: " << fde.firstTSListSector().sector();
|
||||||
|
|
|
@ -16,80 +16,104 @@
|
||||||
|
|
||||||
Dos33DiskImage::Dos33DiskImage(QString filename)
|
Dos33DiskImage::Dos33DiskImage(QString filename)
|
||||||
{
|
{
|
||||||
|
m_disk_image = new RawDiskImage(filename);
|
||||||
|
|
||||||
if (!filename.isEmpty())
|
if (!filename.isEmpty())
|
||||||
{
|
{
|
||||||
read(filename);
|
read(filename);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Dos33DiskImage::Dos33DiskImage(RawDiskImage *rawImage)
|
||||||
|
{
|
||||||
|
m_disk_image = rawImage;
|
||||||
|
}
|
||||||
|
|
||||||
Dos33DiskImage::~Dos33DiskImage()
|
Dos33DiskImage::~Dos33DiskImage()
|
||||||
{
|
{
|
||||||
foreach (GenericFile *file, m_files)
|
// foreach (GenericFile *file, m_files)
|
||||||
{
|
// {
|
||||||
delete file;
|
// delete file;
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Dos33DiskImage::read(QString filename)
|
bool Dos33DiskImage::read(QString filename)
|
||||||
{
|
{
|
||||||
m_fullImageName = filename;
|
bool retval = m_disk_image->read(filename);
|
||||||
m_imageName = QFileInfo(filename).fileName();
|
|
||||||
if (m_imageName.toUpper().contains(".D13"))
|
|
||||||
{
|
|
||||||
m_sectors_per_track = 13;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_sectors_per_track = 16;
|
|
||||||
}
|
|
||||||
|
|
||||||
QFile infile(filename);
|
if (retval)
|
||||||
QCryptographicHash hash(QCryptographicHash::Md5);
|
|
||||||
|
|
||||||
if (infile.open(QIODevice::ReadOnly))
|
|
||||||
{
|
{
|
||||||
QByteArray contents = infile.readAll();
|
for (auto tracknum = 0; tracknum < m_disk_image->numTracks(); tracknum++)
|
||||||
int expectedsize = sectorsPerTrack() * tracks() * 256;
|
|
||||||
if (contents.size() != expectedsize)
|
|
||||||
{
|
{
|
||||||
if (contents.size() == 35*16*256) { m_sectors_per_track = 16; }
|
for (auto secnum = 0; secnum < m_disk_image->sectorsPerTrack(); secnum++)
|
||||||
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];
|
TSPair tmpts(tracknum,secnum);
|
||||||
if (qds.readRawData(buffer,256) == 256)
|
Sector newSec;
|
||||||
{
|
SectorData * data = m_disk_image->sectorAt(tmpts);
|
||||||
TSPair tmpts(track,sector);
|
newSec.setData(data);
|
||||||
Sector newSec;
|
newSec.setTrackSector(tmpts);
|
||||||
newSec.setTrackSector(tmpts);
|
m_contents[tmpts] = newSec;
|
||||||
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 retval;
|
||||||
return false;
|
|
||||||
|
// 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()
|
VTOC Dos33DiskImage::getVTOC()
|
||||||
|
@ -99,8 +123,6 @@ VTOC Dos33DiskImage::getVTOC()
|
||||||
|
|
||||||
QList<CatalogSector> Dos33DiskImage::getCatalogSectors()
|
QList<CatalogSector> Dos33DiskImage::getCatalogSectors()
|
||||||
{
|
{
|
||||||
// qDebug() << "### Start getCatalogSector";
|
|
||||||
|
|
||||||
QList<CatalogSector> retval;
|
QList<CatalogSector> retval;
|
||||||
VTOC vtoc = getVTOC();
|
VTOC vtoc = getVTOC();
|
||||||
TSPair ts = vtoc.firstCatalogSector();
|
TSPair ts = vtoc.firstCatalogSector();
|
||||||
|
@ -112,7 +134,6 @@ QList<CatalogSector> Dos33DiskImage::getCatalogSectors()
|
||||||
cs = getSector(ts).asCatalogSector();
|
cs = getSector(ts).asCatalogSector();
|
||||||
retval.append(cs);
|
retval.append(cs);
|
||||||
}
|
}
|
||||||
// qDebug() << "### End getCatalogSector";
|
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
@ -138,30 +159,31 @@ GenericFile *Dos33DiskImage::getFile(FileDescriptiveEntry fde)
|
||||||
qWarning(" Not returning a file from invalid TSList!");
|
qWarning(" Not returning a file from invalid TSList!");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
QByteArray data = getDataFromTrackSectorList(tsl);
|
|
||||||
setFileType(fde.fileType());
|
|
||||||
|
|
||||||
if (fileType() == "A")
|
ChunkByteList data = getDataFromTrackSectorList(tsl);
|
||||||
{
|
setFileType(fde.fileTypeIdentifier());
|
||||||
retval = new ApplesoftFile(data);
|
|
||||||
}
|
// if (fileType() == "A")
|
||||||
else if (fileType() == "B")
|
// {
|
||||||
{
|
// retval = new ApplesoftFile(data);
|
||||||
retval = new BinaryFile(data);
|
// }
|
||||||
}
|
// else if (fileType() == "B")
|
||||||
else if (fileType() == "R")
|
// {
|
||||||
{
|
// retval = new BinaryFile(data);
|
||||||
retval = new RelocatableFile(data);
|
// }
|
||||||
}
|
// else if (fileType() == "R")
|
||||||
else if ((fileType() == "T"))
|
// {
|
||||||
{
|
// retval = new RelocatableFile(data);
|
||||||
retval = new TextFile(data);
|
// }
|
||||||
}
|
// else if ((fileType() == "T"))
|
||||||
else if ((fileType() == "I"))
|
// {
|
||||||
{
|
// retval = new TextFile(data);
|
||||||
retval = new IntBasicFile(data);
|
// }
|
||||||
}
|
// else if ((fileType() == "I"))
|
||||||
else
|
// {
|
||||||
|
// retval = new IntBasicFile(data);
|
||||||
|
// }
|
||||||
|
// else
|
||||||
{
|
{
|
||||||
retval = new GenericFile(data);
|
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())
|
foreach(TSPair pair, tsl.getDataTSPairs())
|
||||||
{
|
{
|
||||||
if (pair.isValid())
|
if (pair.isValid())
|
||||||
{
|
{
|
||||||
Sector sec = getSector(pair);
|
Sector sec = getSector(pair);
|
||||||
retval.append(sec.rawData());
|
retval.appendChunk(sec.rawData());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -193,7 +215,7 @@ QByteArray Dos33DiskImage::getDataFromTrackSectorList(TrackSectorList tsl)
|
||||||
auto next = tsl.getNextTSList();
|
auto next = tsl.getNextTSList();
|
||||||
if (next.isValid() && next != TSPair(0,0)) {
|
if (next.isValid() && next != TSPair(0,0)) {
|
||||||
TrackSectorList nextTsl = getSector(tsl.getNextTSList()).asTrackSectorList();
|
TrackSectorList nextTsl = getSector(tsl.getNextTSList()).asTrackSectorList();
|
||||||
retval.append(getDataFromTrackSectorList(nextTsl));
|
retval.appendChunkList(getDataFromTrackSectorList(nextTsl));
|
||||||
}
|
}
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -201,7 +223,6 @@ QByteArray Dos33DiskImage::getDataFromTrackSectorList(TrackSectorList tsl)
|
||||||
|
|
||||||
QList<FileDescriptiveEntry> Dos33DiskImage::getAllFDEs()
|
QList<FileDescriptiveEntry> Dos33DiskImage::getAllFDEs()
|
||||||
{
|
{
|
||||||
// qDebug() << "### Start getAllFDEs";
|
|
||||||
QList<FileDescriptiveEntry> retval;
|
QList<FileDescriptiveEntry> retval;
|
||||||
|
|
||||||
QList<CatalogSector> sectors = getCatalogSectors();
|
QList<CatalogSector> sectors = getCatalogSectors();
|
||||||
|
@ -211,7 +232,6 @@ QList<FileDescriptiveEntry> Dos33DiskImage::getAllFDEs()
|
||||||
QList<FileDescriptiveEntry> fdes = cs.getFDEs();
|
QList<FileDescriptiveEntry> fdes = cs.getFDEs();
|
||||||
retval.append(fdes);
|
retval.append(fdes);
|
||||||
}
|
}
|
||||||
// qDebug() << "### End getAllFDEs";
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -224,3 +244,8 @@ QString Dos33DiskImage::getMetaDataPath() const {
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FileList Dos33DiskImage::fileList()
|
||||||
|
{
|
||||||
|
return { };
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,22 +11,25 @@
|
||||||
#include "sector.h"
|
#include "sector.h"
|
||||||
#include "vtoc.h"
|
#include "vtoc.h"
|
||||||
|
|
||||||
|
#include "rawdiskimage.h"
|
||||||
|
#include "chunkbytelist.h"
|
||||||
|
|
||||||
|
|
||||||
class GenericFile;
|
class GenericFile;
|
||||||
|
|
||||||
|
using FileList = QList<GenericFile *>;
|
||||||
|
|
||||||
class Dos33DiskImage
|
class Dos33DiskImage
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Dos33DiskImage(QString filename = "");
|
Dos33DiskImage(QString filename = "");
|
||||||
|
Dos33DiskImage(RawDiskImage *rawImage);
|
||||||
~Dos33DiskImage();
|
~Dos33DiskImage();
|
||||||
|
|
||||||
bool read(QString filename);
|
bool read(QString filename);
|
||||||
|
|
||||||
Sector &getSector(TSPair ts) { return m_contents[ts]; }
|
Sector &getSector(TSPair ts);
|
||||||
|
Sector &getSector(int track, int sector);
|
||||||
Sector &getSector(int track, int sector) {
|
|
||||||
TSPair ts(track,sector);
|
|
||||||
return getSector(ts);
|
|
||||||
}
|
|
||||||
|
|
||||||
VTOC getVTOC();
|
VTOC getVTOC();
|
||||||
|
|
||||||
|
@ -34,34 +37,36 @@ public:
|
||||||
|
|
||||||
GenericFile *getFile(FileDescriptiveEntry fde);
|
GenericFile *getFile(FileDescriptiveEntry fde);
|
||||||
|
|
||||||
QByteArray getDataFromTrackSectorList(TrackSectorList tsl);
|
ChunkByteList getDataFromTrackSectorList(TrackSectorList tsl);
|
||||||
|
|
||||||
QList<FileDescriptiveEntry> getAllFDEs();
|
QList<FileDescriptiveEntry> getAllFDEs();
|
||||||
|
|
||||||
QByteArray fileHash() const { return m_hash; }
|
QByteArray fileHash() const { return m_hash; }
|
||||||
|
|
||||||
QString getDiskImageName() const { return m_imageName; }
|
QString getDiskImageName() const { return m_disk_image->diskImageName(); }
|
||||||
QString getFullDiskImageName() const { return m_fullImageName; }
|
QString getFullDiskImageName() const { return m_disk_image->fullDiskImageName(); }
|
||||||
QString getMetaDataPath() const;
|
QString getMetaDataPath() const;
|
||||||
|
|
||||||
QString fileType() const { return m_fileType; }
|
QString fileType() const { return m_fileType; }
|
||||||
void setFileType(QString type) { m_fileType = type; }
|
void setFileType(QString type) { m_fileType = type; }
|
||||||
|
|
||||||
quint8 sectorsPerTrack() const { return m_sectors_per_track; }
|
int sectorsPerTrack() const { return m_disk_image->sectorsPerTrack(); }
|
||||||
quint8 tracks() const { return 35; }
|
int tracks() const { return m_disk_image->numTracks(); }
|
||||||
|
|
||||||
|
QList<GenericFile *> fileList();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
RawDiskImage *m_disk_image;
|
||||||
|
|
||||||
QMap<TSPair, Sector> m_contents;
|
QMap<TSPair, Sector> m_contents;
|
||||||
QMap<FileDescriptiveEntry, GenericFile *> m_files;
|
QMap<FileDescriptiveEntry, GenericFile *> m_files;
|
||||||
QByteArray m_hash;
|
QByteArray m_hash;
|
||||||
|
|
||||||
QString m_imageName;
|
|
||||||
QString m_fullImageName;
|
|
||||||
|
|
||||||
QString m_fileType;
|
QString m_fileType;
|
||||||
|
|
||||||
quint8 m_sectors_per_track;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
32
src/diskfiles/dos33/dos33disktreeview.cpp
Normal file
32
src/diskfiles/dos33/dos33disktreeview.cpp
Normal file
|
@ -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)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
38
src/diskfiles/dos33/dos33disktreeview.h
Normal file
38
src/diskfiles/dos33/dos33disktreeview.h
Normal file
|
@ -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)
|
if (!fde.deleted)
|
||||||
{
|
{
|
||||||
QString fn = AppleString(fde.filename).appleFontPrintable();
|
QString fn = AppleString(fde.filename).appleFontPrintable();
|
||||||
QString type = fde.fileType();
|
QString type = fde.fileTypeIdentifier();
|
||||||
|
|
||||||
QIcon icon;
|
QIcon icon;
|
||||||
if (type == "A") { icon = m_icon_A; }
|
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 == "I") { icon = m_icon_I; }
|
||||||
else if (type == "a") { icon = m_icon_a; }
|
else if (type == "a") { icon = m_icon_a; }
|
||||||
else if (type == "b") { icon = m_icon_b; }
|
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);
|
auto item = new Dos33TreeItem(icon,fn);
|
||||||
|
|
||||||
|
|
||||||
QVariant data;
|
QVariant typevar = (int) Dos33ItemType::File;
|
||||||
data.setValue(fde.firstTSListSector());
|
item->setData(typevar, (int) Dos33TreeRole::ItemType);
|
||||||
item->setData(data);
|
|
||||||
|
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));
|
item->setToolTip(QString("%1 Block(s)").arg(fde.lengthInSectors));
|
||||||
diskImageItem->appendRow(item);
|
diskImageItem->appendRow(item);
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,20 @@
|
||||||
|
|
||||||
#include <QIcon>
|
#include <QIcon>
|
||||||
|
|
||||||
|
enum class Dos33TreeRole {
|
||||||
|
ItemType = Qt::UserRole,
|
||||||
|
GetTSPair,
|
||||||
|
GetFDE,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class Dos33ItemType {
|
||||||
|
Unknown,
|
||||||
|
Sector,
|
||||||
|
File,
|
||||||
|
DiskImage
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class Dos33ImageModel : public QStandardItemModel
|
class Dos33ImageModel : public QStandardItemModel
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
|
@ -21,15 +21,15 @@ struct FileDescriptiveEntry {
|
||||||
return f1.filename < filename;
|
return f1.filename < filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString fileType() {
|
QString fileTypeIdentifier() {
|
||||||
if (fileTypeFlags & (quint8) FileTypeFlag::Integer) { return "I"; }
|
if (fileTypeFlags & (quint8) FileTypeFlag::Integer) { return "I"; }
|
||||||
if (fileTypeFlags & (quint8) FileTypeFlag::Applesoft) { return "A"; }
|
else if (fileTypeFlags & (quint8) FileTypeFlag::Applesoft) { return "A"; }
|
||||||
if (fileTypeFlags & (quint8) FileTypeFlag::Relocatable) { return "R"; }
|
else if (fileTypeFlags & (quint8) FileTypeFlag::Relocatable) { return "R"; }
|
||||||
if (fileTypeFlags & (quint8) FileTypeFlag::Binary) { return "B"; }
|
else if (fileTypeFlags & (quint8) FileTypeFlag::Binary) { return "B"; }
|
||||||
if (fileTypeFlags & (quint8) FileTypeFlag::TypeS) { return "S"; }
|
else if (fileTypeFlags & (quint8) FileTypeFlag::TypeS) { return "S"; }
|
||||||
if (fileTypeFlags & (quint8) FileTypeFlag::TypeA) { return "a"; }
|
else if (fileTypeFlags & (quint8) FileTypeFlag::TypeA) { return "a"; }
|
||||||
if (fileTypeFlags & (quint8) FileTypeFlag::TypeB) { return "b"; }
|
else if (fileTypeFlags & (quint8) FileTypeFlag::TypeB) { return "b"; }
|
||||||
return "T";
|
else return "T";
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isLocked() { return (fileTypeFlags & (quint8) FileTypeFlag::IsLockedFlag); }
|
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()
|
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();
|
<< " 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() << "Filename: " << filename.printable();
|
||||||
qDebug() << "Length in Sectors: " << lengthInSectors;
|
qDebug() << "Length in Sectors: " << lengthInSectors;
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,7 @@ struct FileDescriptiveEntry {
|
||||||
void catalog() {
|
void catalog() {
|
||||||
QString output = QString("%1 %2 %3 %4").arg(QString(isLocked()?"*":" "))
|
QString output = QString("%1 %2 %3 %4").arg(QString(isLocked()?"*":" "))
|
||||||
.arg(lengthInSectors,3,10,QChar('0'))
|
.arg(lengthInSectors,3,10,QChar('0'))
|
||||||
.arg(fileType())
|
.arg(fileTypeIdentifier())
|
||||||
.arg(filename.printable().trimmed());
|
.arg(filename.printable().trimmed());
|
||||||
qDebug() << output;
|
qDebug() << output;
|
||||||
}
|
}
|
||||||
|
@ -68,5 +68,5 @@ private:
|
||||||
TSPair m_firstTSListSector;
|
TSPair m_firstTSListSector;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
Q_DECLARE_METATYPE(FileDescriptiveEntry);
|
||||||
#endif // FILEDESCRIPTIVEENTRY_H
|
#endif // FILEDESCRIPTIVEENTRY_H
|
||||||
|
|
|
@ -2,20 +2,40 @@
|
||||||
|
|
||||||
GenericFile::GenericFile(QByteArray data)
|
GenericFile::GenericFile(QByteArray data)
|
||||||
{
|
{
|
||||||
|
m_data_loaded = false;
|
||||||
m_diskfile = 0;
|
m_diskfile = 0;
|
||||||
if (!data.isEmpty()) {
|
if (!data.isEmpty()) {
|
||||||
setData(data);
|
setData(data);
|
||||||
|
m_data_loaded = true;
|
||||||
}
|
}
|
||||||
m_address = 0x00;
|
m_address = 0x00;
|
||||||
m_length = 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)
|
void GenericFile::setData(QByteArray data)
|
||||||
{
|
{
|
||||||
|
m_data_loaded = true;
|
||||||
m_data = data;
|
m_data = data;
|
||||||
m_length = data.size();
|
m_length = data.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
QString GenericFile::getFileType() const
|
QString GenericFile::getFileType() const
|
||||||
{
|
{
|
||||||
if (m_file_type == "A" || m_file_type == "B" || m_file_type == "T" ||
|
if (m_file_type == "A" || m_file_type == "B" || m_file_type == "T" ||
|
||||||
|
@ -29,3 +49,10 @@ QString GenericFile::getFileType() const
|
||||||
return "?";
|
return "?";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
quint16 GenericFile::dataWordAt(int offset) const
|
||||||
|
{
|
||||||
|
return makeWord(dataAt(offset),dataAt(offset+1));
|
||||||
|
}
|
||||||
|
|
|
@ -9,23 +9,22 @@
|
||||||
|
|
||||||
class GenericFile
|
class GenericFile
|
||||||
{
|
{
|
||||||
|
friend class Dos33DiskImage;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GenericFile(QByteArray data = QByteArray());
|
|
||||||
virtual ~GenericFile() { }
|
virtual ~GenericFile() { }
|
||||||
|
|
||||||
virtual void setData(QByteArray data);
|
virtual QByteArray data() { return m_data.mid(m_ignore_offset); }
|
||||||
virtual QByteArray data() { return m_data; }
|
quint8 dataAt(int offset) const;
|
||||||
|
quint16 dataWordAt(int offset) const;
|
||||||
|
|
||||||
void setFilename(QString filename) { m_filename = filename; }
|
virtual void setFilename(QString filename) { m_filename = filename; }
|
||||||
QString filename() const { return m_filename; }
|
QString filename() const { return m_filename; }
|
||||||
|
|
||||||
virtual void setAddress(quint16 location) { m_address = location; }
|
virtual void setAddress(quint16 location) { m_address = location; }
|
||||||
virtual quint16 address() { return m_address; }
|
virtual quint16 address() { return m_address; }
|
||||||
|
|
||||||
virtual QByteArray rawData() { return m_data; }
|
virtual int length() const { return m_length; }
|
||||||
|
|
||||||
virtual void setLength(quint16 length) { m_length = length; }
|
|
||||||
virtual quint16 length() const { return m_length; }
|
|
||||||
|
|
||||||
Dos33DiskImage *diskFile() const { return m_diskfile; }
|
Dos33DiskImage *diskFile() const { return m_diskfile; }
|
||||||
void setDiskFile(Dos33DiskImage *diskfile) { m_diskfile = diskfile; }
|
void setDiskFile(Dos33DiskImage *diskfile) { m_diskfile = diskfile; }
|
||||||
|
@ -33,13 +32,27 @@ public:
|
||||||
void setFileType(QString type) { m_file_type = type; }
|
void setFileType(QString type) { m_file_type = type; }
|
||||||
QString getFileType() const;
|
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;
|
QByteArray m_data;
|
||||||
QString m_filename;
|
QString m_filename;
|
||||||
quint16 m_address;
|
quint16 m_address;
|
||||||
qint16 m_length;
|
qint16 m_length;
|
||||||
Dos33DiskImage * m_diskfile;
|
Dos33DiskImage * m_diskfile;
|
||||||
|
bool m_data_loaded;
|
||||||
|
TSPairList m_ts_pairs;
|
||||||
|
|
||||||
QString m_file_type;
|
QString m_file_type;
|
||||||
|
|
||||||
|
|
|
@ -3,19 +3,13 @@
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
QByteRef Sector::operator[](uint offset) {
|
quint8 Sector::operator[](uint offset) const {
|
||||||
if (offset > 255) {
|
if (offset > 255) {
|
||||||
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() {
|
void Sector::dump() {
|
||||||
qDebug() << "Dumping Track " << track() << "Sector " << sector() << " ...";
|
qDebug() << "Dumping Track " << track() << "Sector " << sector() << " ...";
|
||||||
|
@ -27,7 +21,7 @@ void Sector::dump() {
|
||||||
for (int idx = 0; idx < 16; idx++)
|
for (int idx = 0; idx < 16; idx++)
|
||||||
{
|
{
|
||||||
int offset = (jdx*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));
|
line += QString("%1 ").arg(uint16ToHex(val));
|
||||||
if (idx == 7) line += " ";
|
if (idx == 7) line += " ";
|
||||||
}
|
}
|
||||||
|
@ -36,7 +30,7 @@ void Sector::dump() {
|
||||||
for (int idx = 0; idx < 16; idx++)
|
for (int idx = 0; idx < 16; idx++)
|
||||||
{
|
{
|
||||||
int offset = (jdx*16) + idx;
|
int offset = (jdx*16) + idx;
|
||||||
quint8 val = m_data[offset];
|
quint8 val = m_raw_data->at(offset);
|
||||||
if (val > 127) { val -= 128; }
|
if (val > 127) { val -= 128; }
|
||||||
QChar ch(val);
|
QChar ch(val);
|
||||||
line += QString("%1").arg(ch.isPrint()?ch:'.');
|
line += QString("%1").arg(ch.isPrint()?ch:'.');
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
|
|
||||||
#include <QByteArray>
|
#include <QByteArray>
|
||||||
|
|
||||||
|
#include "rawdiskimage.h"
|
||||||
|
|
||||||
#include "vtoc.h"
|
#include "vtoc.h"
|
||||||
#include "catalogsector.h"
|
#include "catalogsector.h"
|
||||||
#include "tracksectorlist.h"
|
#include "tracksectorlist.h"
|
||||||
|
@ -11,12 +13,18 @@ class Sector
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Sector() {
|
Sector(SectorData *data = nullptr) {
|
||||||
m_data.resize(256);
|
// m_data.resize(256);
|
||||||
|
setData(data);
|
||||||
m_track = 255;
|
m_track = 255;
|
||||||
m_sector = 255;
|
m_sector = 255;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setData(SectorData *data)
|
||||||
|
{
|
||||||
|
m_raw_data = data;
|
||||||
|
}
|
||||||
|
|
||||||
VTOC promoteToVTOC() {
|
VTOC promoteToVTOC() {
|
||||||
return VTOC(this);
|
return VTOC(this);
|
||||||
}
|
}
|
||||||
|
@ -45,18 +53,19 @@ public:
|
||||||
void setTrack(int track) { m_track = track; }
|
void setTrack(int track) { m_track = track; }
|
||||||
void setSector(int sector) { m_sector = sector; }
|
void setSector(int sector) { m_sector = sector; }
|
||||||
|
|
||||||
QByteRef operator[](uint offset);
|
quint8 operator[](uint offset) const;
|
||||||
|
quint8 at(int offset) { return m_raw_data->at(offset); }
|
||||||
bool setData(QByteArray data);
|
|
||||||
|
|
||||||
void dump();
|
void dump();
|
||||||
|
|
||||||
QByteArray rawData() { return m_data; }
|
SectorData *rawData() { return m_raw_data; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QByteArray m_data;
|
// QByteArray m_data;
|
||||||
int m_track;
|
int m_track;
|
||||||
int m_sector;
|
int m_sector;
|
||||||
|
|
||||||
|
SectorData *m_raw_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SECTOR_H
|
#endif // SECTOR_H
|
||||||
|
|
|
@ -6,15 +6,15 @@ TrackSectorList::TrackSectorList(Sector *data)
|
||||||
{
|
{
|
||||||
m_data = data;
|
m_data = data;
|
||||||
|
|
||||||
m_next_tslist.setTrack(m_data->rawData()[0x01]);
|
m_next_tslist.setTrack(m_data->at(0x01));
|
||||||
m_next_tslist.setSector(m_data->rawData()[0x02]);
|
m_next_tslist.setSector(m_data->at(0x02));
|
||||||
|
|
||||||
m_sector_offset.setTrack(m_data->rawData()[0x05]);
|
m_sector_offset.setTrack(m_data->at(0x05));
|
||||||
m_sector_offset.setSector(m_data->rawData()[0x06]);
|
m_sector_offset.setSector(m_data->at(0x06));
|
||||||
|
|
||||||
for (int idx = 0x0C; idx < 0xff; idx+=2)
|
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()) {
|
if (ts == TSPair(0,0) && ts.isValid()) {
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
|
|
||||||
class Sector;
|
class Sector;
|
||||||
|
|
||||||
|
using TSPairList = QList<TSPair>;
|
||||||
|
|
||||||
class TrackSectorList
|
class TrackSectorList
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -16,14 +18,14 @@ public:
|
||||||
TSPair getSectorOffset() const { return m_sector_offset; }
|
TSPair getSectorOffset() const { return m_sector_offset; }
|
||||||
bool isSectorOffsetValid() const;
|
bool isSectorOffsetValid() const;
|
||||||
|
|
||||||
QList<TSPair> getDataTSPairs() const { return m_ts_pairs_for_data; }
|
TSPairList getDataTSPairs() const { return m_ts_pairs_for_data; }
|
||||||
QList<TSPair> getValidTSPairs() const;
|
TSPairList getValidTSPairs() const;
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TSPair m_next_tslist;
|
TSPair m_next_tslist;
|
||||||
TSPair m_sector_offset;
|
TSPair m_sector_offset;
|
||||||
QList<TSPair> m_ts_pairs_for_data;
|
TSPairList m_ts_pairs_for_data;
|
||||||
|
|
||||||
Sector *m_data;
|
Sector *m_data;
|
||||||
};
|
};
|
||||||
|
|
|
@ -13,40 +13,40 @@ VTOC::VTOC(Sector *data)
|
||||||
|
|
||||||
TSPair VTOC::firstCatalogSector() {
|
TSPair VTOC::firstCatalogSector() {
|
||||||
// return TSPair(0x11,0x0f); // Force to look at the normal location
|
// 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() {
|
quint8 VTOC::dosVersion() {
|
||||||
return m_data->rawData()[0x03];
|
return m_data->at(0x03);
|
||||||
}
|
}
|
||||||
|
|
||||||
quint8 VTOC::volumeNumber() {
|
quint8 VTOC::volumeNumber() {
|
||||||
return m_data->rawData()[0x06];
|
return m_data->at(0x06);
|
||||||
}
|
}
|
||||||
|
|
||||||
quint8 VTOC::maxTSPairs() {
|
quint8 VTOC::maxTSPairs() {
|
||||||
return m_data->rawData()[0x27];
|
return m_data->at(0x27);
|
||||||
}
|
}
|
||||||
|
|
||||||
quint8 VTOC::lastTrackAllocated() {
|
quint8 VTOC::lastTrackAllocated() {
|
||||||
return m_data->rawData()[0x30];
|
return m_data->at(0x30);
|
||||||
}
|
}
|
||||||
|
|
||||||
qint8 VTOC::directionOfAllocation() {
|
qint8 VTOC::directionOfAllocation() {
|
||||||
return m_data->rawData()[0x31];
|
return m_data->at(0x31);
|
||||||
}
|
}
|
||||||
|
|
||||||
quint8 VTOC::tracksPerDisk() {
|
quint8 VTOC::tracksPerDisk() {
|
||||||
return m_data->rawData()[0x34];
|
return m_data->at(0x34);
|
||||||
}
|
}
|
||||||
|
|
||||||
quint8 VTOC::sectorsPerDisk() {
|
quint8 VTOC::sectorsPerDisk() {
|
||||||
return m_data->rawData()[0x35];
|
return m_data->at(0x35);
|
||||||
}
|
}
|
||||||
|
|
||||||
qint16 VTOC::bytesPerSector() {
|
qint16 VTOC::bytesPerSector() {
|
||||||
return makeWord(m_data->rawData()[0x36],
|
return makeWord(m_data->at(0x36),
|
||||||
m_data->rawData()[0x37]);
|
m_data->at(0x37));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VTOC::isSectorInUse(TSPair ts) const {
|
bool VTOC::isSectorInUse(TSPair ts) const {
|
||||||
|
@ -55,8 +55,8 @@ bool VTOC::isSectorInUse(TSPair ts) const {
|
||||||
quint8 baseaddr = (track * 4) + 0x38;
|
quint8 baseaddr = (track * 4) + 0x38;
|
||||||
|
|
||||||
//quint16 word = (((quint16) m_data->rawData()[baseaddr]) *256) + (quint8) m_data->rawData()[baseaddr+1];
|
//quint16 word = (((quint16) m_data->rawData()[baseaddr]) *256) + (quint8) m_data->rawData()[baseaddr+1];
|
||||||
quint16 word = makeWord(m_data->rawData()[baseaddr+1],
|
quint16 word = makeWord(m_data->at(baseaddr+1),
|
||||||
m_data->rawData()[baseaddr]);
|
m_data->at(baseaddr));
|
||||||
quint16 bitpos = (quint16) 0x01 << (quint16) sec;
|
quint16 bitpos = (quint16) 0x01 << (quint16) sec;
|
||||||
|
|
||||||
return !(word & bitpos);
|
return !(word & bitpos);
|
||||||
|
@ -119,7 +119,7 @@ void VTOC::dump()
|
||||||
qDebug() << " Number sectors per disk: " << QString::number(sectorsPerDisk());
|
qDebug() << " Number sectors per disk: " << QString::number(sectorsPerDisk());
|
||||||
qDebug() << " Number bytes/sector: " << QString::number(bytesPerSector());
|
qDebug() << " Number bytes/sector: " << QString::number(bytesPerSector());
|
||||||
qDebug() << " Track Usage (.=free, 0-F=used):";
|
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);
|
qDebug() << " " << QString("Track %1:").arg((int) track,2,10,QChar('0')) << buildUseString(track);
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,17 +14,18 @@ class VTOC
|
||||||
public:
|
public:
|
||||||
VTOC(Sector *data);
|
VTOC(Sector *data);
|
||||||
|
|
||||||
void dump();
|
void dump();
|
||||||
TSPair firstCatalogSector();
|
TSPair firstCatalogSector();
|
||||||
quint8 dosVersion();
|
quint8 dosVersion();
|
||||||
quint8 volumeNumber();
|
quint8 volumeNumber();
|
||||||
quint8 maxTSPairs();
|
quint8 maxTSPairs();
|
||||||
quint8 lastTrackAllocated();
|
quint8 lastTrackAllocated();
|
||||||
qint8 directionOfAllocation();
|
qint8 directionOfAllocation();
|
||||||
quint8 tracksPerDisk();
|
quint8 tracksPerDisk();
|
||||||
quint8 sectorsPerDisk();
|
quint8 sectorsPerDisk();
|
||||||
qint16 bytesPerSector();
|
qint16 bytesPerSector();
|
||||||
bool isSectorInUse(TSPair ts) const;
|
|
||||||
|
bool isSectorInUse(TSPair ts) const;
|
||||||
|
|
||||||
QList<TSPair> sectorsInUse() const;
|
QList<TSPair> sectorsInUse() const;
|
||||||
QList<TSPair> sectorsNotInUse() const;
|
QList<TSPair> sectorsNotInUse() const;
|
||||||
|
|
194
src/diskfiles/rawdiskimage.cpp
Normal file
194
src/diskfiles/rawdiskimage.cpp
Normal file
|
@ -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;
|
||||||
|
}
|
103
src/diskfiles/rawdiskimage.h
Normal file
103
src/diskfiles/rawdiskimage.h
Normal file
|
@ -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:
|
public:
|
||||||
TSPair() { m_track = m_sector = 0; }
|
TSPair() { m_track = m_sector = 0; }
|
||||||
TSPair(quint8 trackval, quint8 secval) { m_track=trackval; m_sector = secval; }
|
TSPair(int trackval, int secval) { m_track=trackval; m_sector = secval; }
|
||||||
TSPair(QPair<quint8,quint8> pair) { m_track = pair.first; m_sector = pair.second;}
|
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) {
|
if (tracknum > 34 && tracknum != 0xff) {
|
||||||
qWarning("Setting a track with value %d (> 34 and not 256).",tracknum);
|
qWarning("Setting a track with value %d (> 34 and not 256).",tracknum);
|
||||||
|
@ -34,8 +34,8 @@ public:
|
||||||
|
|
||||||
return retval; }
|
return retval; }
|
||||||
|
|
||||||
quint8 track() const { return m_track; }
|
int track() const { return m_track; }
|
||||||
quint8 sector() const { return m_sector; }
|
int sector() const { return m_sector; }
|
||||||
|
|
||||||
bool operator==(const TSPair &other) const {
|
bool operator==(const TSPair &other) const {
|
||||||
if (other.track() == track() && other.sector() == sector()) return true;
|
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 {
|
void dump() const {
|
||||||
qDebug() << "TSPair: track: " << track() << " sector: " << sector();
|
qDebug() << "TSPair: track: " << track() << " sector: " << sector();
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
quint8 m_track;
|
int m_track;
|
||||||
quint8 m_sector;
|
int m_sector;
|
||||||
};
|
};
|
||||||
Q_DECLARE_METATYPE(TSPair);
|
Q_DECLARE_METATYPE(TSPair);
|
||||||
|
|
|
@ -6,11 +6,13 @@
|
||||||
|
|
||||||
class IntBasicFile : public GenericFile
|
class IntBasicFile : public GenericFile
|
||||||
{
|
{
|
||||||
public:
|
friend class Dos33DiskImage;
|
||||||
IntBasicFile(QByteArray data = QByteArray());
|
|
||||||
|
|
||||||
|
public:
|
||||||
QByteArray detokenize();
|
QByteArray detokenize();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
IntBasicFile(QByteArray data = QByteArray());
|
||||||
quint16 get16(quint8 v1, quint8 v2);
|
quint16 get16(quint8 v1, quint8 v2);
|
||||||
QByteArray dumpBufferAsIntBasicFile(QByteArray origdata);
|
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 -----------------------------------------------------------
|
/* QDarkStyleSheet -----------------------------------------------------------
|
||||||
|
|
||||||
This is the main style sheet, the palette has nine colors.
|
This is the main style sheet, the palette has nine colors.
|
||||||
|
@ -1010,7 +1002,7 @@ QPushButton {
|
||||||
padding: 3px;
|
padding: 3px;
|
||||||
outline: none;
|
outline: none;
|
||||||
/* Issue #194 - Special case of QPushButton inside dialogs, for better UI */
|
/* Issue #194 - Special case of QPushButton inside dialogs, for better UI */
|
||||||
min-width: 80px;
|
min-width: 80px;
|
||||||
}
|
}
|
||||||
|
|
||||||
QPushButton:disabled {
|
QPushButton:disabled {
|
||||||
|
@ -2187,3 +2179,13 @@ background-color: #32414B;
|
||||||
color: #aaa;
|
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()";
|
// qDebug() << "setData()";
|
||||||
if (data.length() >= 6) {
|
if (length() >= 6) {
|
||||||
m_starting_ram_address = makeWord(m_data[0],m_data[1]);
|
m_starting_ram_address = dataWordAt(0);
|
||||||
m_ram_image_length = makeWord(m_data[2],m_data[3]);
|
m_ram_image_length = dataWordAt(2);
|
||||||
m_code_image_length = makeWord(m_data[4],m_data[5]);
|
m_code_image_length = dataWordAt(4);
|
||||||
|
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
|
|
||||||
for (int idx = 6; idx < m_code_image_length+6; idx++) {
|
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);
|
m_binary_code_image.append(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,14 +33,12 @@ void RelocatableFile::setData(QByteArray data)
|
||||||
// << uint8ToHex(m_data[offset+2])
|
// << uint8ToHex(m_data[offset+2])
|
||||||
// << uint8ToHex(m_data[offset+3]);
|
// << uint8ToHex(m_data[offset+3]);
|
||||||
|
|
||||||
RelocatableDictItem rdi = RelocatableDictItem(m_data[offset],m_data[offset+1],
|
RelocatableDictItem rdi = RelocatableDictItem(
|
||||||
m_data[offset+2],m_data[offset+3]);
|
dataAt(offset),dataAt(offset+1),
|
||||||
|
dataAt(offset+2),dataAt(offset+3));
|
||||||
m_relocatable_dict.append(rdi);
|
m_relocatable_dict.append(rdi);
|
||||||
if (rdi.isEndOfRLD()) { break; }
|
if (rdi.isEndOfRLD()) { break; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -77,12 +77,10 @@ private:
|
||||||
|
|
||||||
class RelocatableFile : public GenericFile
|
class RelocatableFile : public GenericFile
|
||||||
{
|
{
|
||||||
|
friend class Dos33DiskImage;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
RelocatableFile(QByteArray data = QByteArray());
|
|
||||||
void setData(QByteArray data);
|
|
||||||
|
|
||||||
virtual quint16 length() { return m_data.length(); }
|
|
||||||
|
|
||||||
void dump();
|
void dump();
|
||||||
|
|
||||||
|
@ -95,6 +93,9 @@ public:
|
||||||
QStringList decodeRelocatableDict();
|
QStringList decodeRelocatableDict();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
RelocatableFile(QByteArray data = QByteArray());
|
||||||
|
void setData(QByteArray data);
|
||||||
|
|
||||||
quint16 m_starting_ram_address;
|
quint16 m_starting_ram_address;
|
||||||
quint16 m_ram_image_length;
|
quint16 m_ram_image_length;
|
||||||
quint16 m_code_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()
|
void TextFile::dump()
|
||||||
{
|
{
|
||||||
|
|
|
@ -5,13 +5,14 @@
|
||||||
|
|
||||||
class TextFile : public GenericFile
|
class TextFile : public GenericFile
|
||||||
{
|
{
|
||||||
|
friend class Dos33DiskImage;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TextFile(QByteArray data = QByteArray());
|
|
||||||
void setData(QByteArray data);
|
|
||||||
|
|
||||||
void dump();
|
void dump();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
TextFile(QByteArray data = QByteArray());
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // TEXTFILE_H
|
#endif // TEXTFILE_H
|
||||||
|
|
|
@ -42,7 +42,7 @@ QString CatalogWidget::createToolTip(FileDescriptiveEntry &fde) {
|
||||||
QString retval;
|
QString retval;
|
||||||
retval += AppleString(fde.filename).printable().trimmed() +
|
retval += AppleString(fde.filename).printable().trimmed() +
|
||||||
(fde.deleted?"(Deleted)":"") + "\n";
|
(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")
|
retval += QString("Sectors: %1 (%2 bytes)\n")
|
||||||
.arg(fde.lengthInSectors)
|
.arg(fde.lengthInSectors)
|
||||||
.arg(fde.lengthInSectors*256);
|
.arg(fde.lengthInSectors*256);
|
||||||
|
@ -54,12 +54,12 @@ QString CatalogWidget::createToolTip(FileDescriptiveEntry &fde) {
|
||||||
.arg(address);
|
.arg(address);
|
||||||
if (dynamic_cast<BinaryFile*>(file)) {
|
if (dynamic_cast<BinaryFile*>(file)) {
|
||||||
BinaryFile *binfile = 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'))
|
retval += QString("Length: $%1 (%2)\n").arg((quint16) (length),4,16,QChar('0'))
|
||||||
.arg(length);
|
.arg(length);
|
||||||
} else if (dynamic_cast<ApplesoftFile*>(file)) {
|
} else if (dynamic_cast<ApplesoftFile*>(file)) {
|
||||||
ApplesoftFile *asfile = 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'))
|
retval += QString("Length: $%1 (%2)\n").arg((quint16) (length),4,16,QChar('0'))
|
||||||
.arg(length);
|
.arg(length);
|
||||||
quint16 uabytes = asfile->extraData().length();
|
quint16 uabytes = asfile->extraData().length();
|
||||||
|
@ -87,7 +87,7 @@ void CatalogWidget::processNewlyLoadedDisk(QString diskfilename, Dos33DiskImage
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
foreach(FileDescriptiveEntry fde, m_disk->getAllFDEs()) {
|
foreach(FileDescriptiveEntry fde, m_disk->getAllFDEs()) {
|
||||||
// qDebug() << " Processing FDE# " << idx;
|
// qDebug() << " Processing FDE# " << idx;
|
||||||
QString filetype = fde.fileType();
|
QString filetype = fde.fileTypeIdentifier();
|
||||||
QString filename = AppleString(fde.filename).printable().trimmed();
|
QString filename = AppleString(fde.filename).printable().trimmed();
|
||||||
quint16 size = fde.lengthInSectors;
|
quint16 size = fde.lengthInSectors;
|
||||||
bool locked = fde.isLocked();
|
bool locked = fde.isLocked();
|
||||||
|
|
|
@ -3,8 +3,9 @@
|
||||||
|
|
||||||
#include "dos33diskimage.h"
|
#include "dos33diskimage.h"
|
||||||
#include "dos33imagemodel.h"
|
#include "dos33imagemodel.h"
|
||||||
|
#include "dos33disktreeview.h"
|
||||||
#include "sequencetoolbox.h"
|
#include "sequencetoolbox.h"
|
||||||
|
#include "DiskExplorerMapWidget.h"
|
||||||
|
|
||||||
#include <QTreeView>
|
#include <QTreeView>
|
||||||
#include <QAction>
|
#include <QAction>
|
||||||
|
@ -15,6 +16,9 @@
|
||||||
#include <QDockWidget>
|
#include <QDockWidget>
|
||||||
#include <QGridLayout>
|
#include <QGridLayout>
|
||||||
#include <QStatusBar>
|
#include <QStatusBar>
|
||||||
|
#include <QStackedWidget>
|
||||||
|
#include <QScrollArea>
|
||||||
|
|
||||||
|
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
|
|
||||||
|
@ -36,8 +40,8 @@ CentralAppWindow::CentralAppWindow(QWidget *parent) : QMainWindow(parent)
|
||||||
initToolBars();
|
initToolBars();
|
||||||
initDockWidgets();
|
initDockWidgets();
|
||||||
initStatusBar();
|
initStatusBar();
|
||||||
|
initCentralWidget();
|
||||||
|
|
||||||
setCentralWidget(new SequenceViewer());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CentralAppWindow::createActions()
|
void CentralAppWindow::createActions()
|
||||||
|
@ -74,14 +78,13 @@ void CentralAppWindow::initToolBars()
|
||||||
void CentralAppWindow::initDockWidgets()
|
void CentralAppWindow::initDockWidgets()
|
||||||
{
|
{
|
||||||
QDockWidget *container = new QDockWidget(this);
|
QDockWidget *container = new QDockWidget(this);
|
||||||
// container->setLayout(new QGridLayout());
|
|
||||||
container->setMinimumWidth(200);
|
container->setMinimumWidth(200);
|
||||||
container->setFeatures(QDockWidget::DockWidgetMovable);
|
container->setFeatures(QDockWidget::DockWidgetMovable);
|
||||||
|
|
||||||
m_project_area = new QWidget(container);
|
m_project_area = new QWidget(container);
|
||||||
m_project_area->setMinimumSize(300,200);
|
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->setFont(QFont("Pr Number 3", 12));
|
||||||
m_directory_area->setMinimumSize(300,200);
|
m_directory_area->setMinimumSize(300,200);
|
||||||
|
|
||||||
|
@ -114,7 +117,7 @@ void CentralAppWindow::initDockWidgets()
|
||||||
QDockWidget *stb = new QDockWidget(this);
|
QDockWidget *stb = new QDockWidget(this);
|
||||||
stb->setMinimumWidth(200);
|
stb->setMinimumWidth(200);
|
||||||
stb->setFeatures(QDockWidget::DockWidgetMovable);
|
stb->setFeatures(QDockWidget::DockWidgetMovable);
|
||||||
stb->setLayout(new QGridLayout());
|
// stb->setLayout(new QGridLayout());
|
||||||
|
|
||||||
m_toolbox = new SequenceToolBox(this);
|
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 QAction;
|
||||||
class QStatusBar;
|
class QStatusBar;
|
||||||
class SequenceToolBox;
|
class SequenceToolBox;
|
||||||
|
class QStackedWidget;
|
||||||
|
|
||||||
class CentralAppWindow : public QMainWindow
|
class CentralAppWindow : public QMainWindow
|
||||||
{
|
{
|
||||||
|
@ -22,6 +23,7 @@ private:
|
||||||
void initStatusBar();
|
void initStatusBar();
|
||||||
void initToolBars();
|
void initToolBars();
|
||||||
void initDockWidgets();
|
void initDockWidgets();
|
||||||
|
void initCentralWidget();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QAction *m_quitAction;
|
QAction *m_quitAction;
|
||||||
|
@ -32,6 +34,8 @@ private:
|
||||||
QStatusBar *m_status_bar;
|
QStatusBar *m_status_bar;
|
||||||
|
|
||||||
SequenceToolBox *m_toolbox;
|
SequenceToolBox *m_toolbox;
|
||||||
|
|
||||||
|
QStackedWidget *m_central_stack;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CENTRALAPPWINDOW_H
|
#endif // CENTRALAPPWINDOW_H
|
||||||
|
|
|
@ -36,7 +36,7 @@ DiskExplorer::~DiskExplorer()
|
||||||
void DiskExplorer::initUi()
|
void DiskExplorer::initUi()
|
||||||
{
|
{
|
||||||
QMenuBar *menuBar = new QMenuBar(this);
|
QMenuBar *menuBar = new QMenuBar(this);
|
||||||
setMenuBar(menuBar);
|
setMenuBar(menuBar);
|
||||||
QMenu *menu = new QMenu(tr("&File"),this);
|
QMenu *menu = new QMenu(tr("&File"),this);
|
||||||
menuBar->addMenu(menu);
|
menuBar->addMenu(menu);
|
||||||
|
|
||||||
|
@ -100,7 +100,7 @@ void DiskExplorer::initUi()
|
||||||
// if (!m_notesDialog) m_notesDialog = new NotesDialog(this);
|
// if (!m_notesDialog) m_notesDialog = new NotesDialog(this);
|
||||||
// connect(action_Notes, &QAction::triggered, m_notesDialog, &NotesDialog::show);
|
// 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 = new QGridLayout();
|
||||||
m_gridLayout->setVerticalSpacing(4);
|
m_gridLayout->setVerticalSpacing(4);
|
||||||
m_gridLayout->setHorizontalSpacing(4);
|
m_gridLayout->setHorizontalSpacing(4);
|
||||||
|
@ -125,7 +125,12 @@ void DiskExplorer::initUi()
|
||||||
m_key = m_demw->makeKeyWidget();
|
m_key = m_demw->makeKeyWidget();
|
||||||
m_gridLayout->addWidget(m_key,1,1);
|
m_gridLayout->addWidget(m_key,1,1);
|
||||||
m_gridLayout->addWidget(m_frame,1,2);
|
m_gridLayout->addWidget(m_frame,1,2);
|
||||||
|
|
||||||
this->setCentralWidget(widget);
|
this->setCentralWidget(widget);
|
||||||
|
// auto lo = new QGridLayout();
|
||||||
|
// this->setLayout(lo);
|
||||||
|
// lo->addWidget(widget);
|
||||||
|
|
||||||
|
|
||||||
connect(m_cw, &CatalogWidget::openWithDefaultViewer,
|
connect(m_cw, &CatalogWidget::openWithDefaultViewer,
|
||||||
this, &DiskExplorer::handleDiskItemSelectedDefaultOpen);
|
this, &DiskExplorer::handleDiskItemSelectedDefaultOpen);
|
||||||
|
|
|
@ -25,8 +25,9 @@ DiskExplorerMapWidget::DiskExplorerMapWidget(int numtracks, int numsectors, QWid
|
||||||
setWindowTitle("Disk Explorer");
|
setWindowTitle("Disk Explorer");
|
||||||
|
|
||||||
QGridLayout *gridlayout = new QGridLayout(this);
|
QGridLayout *gridlayout = new QGridLayout(this);
|
||||||
gridlayout->setSizeConstraint(QLayout::SetFixedSize);
|
// gridlayout->setSizeConstraint(QLayout::SetFixedSize);
|
||||||
gridlayout->setHorizontalSpacing(2);
|
gridlayout->setSizeConstraint(QLayout::SetMinimumSize);
|
||||||
|
gridlayout->setHorizontalSpacing(1);
|
||||||
gridlayout->setVerticalSpacing(1);
|
gridlayout->setVerticalSpacing(1);
|
||||||
|
|
||||||
initColors();
|
initColors();
|
||||||
|
@ -37,7 +38,7 @@ DiskExplorerMapWidget::DiskExplorerMapWidget(int numtracks, int numsectors, QWid
|
||||||
gridlayout->addWidget(tracklabel,0,0,1,m_numtracks+1,Qt::AlignHCenter);
|
gridlayout->addWidget(tracklabel,0,0,1,m_numtracks+1,Qt::AlignHCenter);
|
||||||
for (int track= 0; track < numtracks; track++)
|
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);
|
label->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
|
||||||
gridlayout->addWidget(label,1,track+1);
|
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(tb,sec+2,track+1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
gridlayout->addWidget(new QLabel("Stretchy Row"),18,0,1,5);
|
||||||
|
gridlayout->setRowStretch(18,900);
|
||||||
|
|
||||||
|
|
||||||
makeStatusWidget();
|
makeStatusWidget();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DiskExplorerMapWidget::makeStatusWidget()
|
void DiskExplorerMapWidget::makeStatusWidget()
|
||||||
{
|
{
|
||||||
QWidget *statusWidget = new QWidget(this);
|
QWidget *statusWidget = new QWidget;
|
||||||
QHBoxLayout *hbl = new QHBoxLayout();
|
QHBoxLayout *hbl = new QHBoxLayout();
|
||||||
statusWidget->setLayout(hbl);
|
statusWidget->setLayout(hbl);
|
||||||
|
|
||||||
|
@ -125,8 +129,8 @@ void DiskExplorerMapWidget::handleButtonCheck(int track, int sector, bool checke
|
||||||
if (checked)
|
if (checked)
|
||||||
{
|
{
|
||||||
Sector sec = m_disk->getSector(track,sector);
|
Sector sec = m_disk->getSector(track,sector);
|
||||||
QByteArray data = sec.rawData();
|
QByteArray *data = sec.rawData();
|
||||||
emit showSectorData(data,track,sector,QVariant());
|
emit showSectorData(*data,track,sector,QVariant());
|
||||||
m_trackSectorLabel->setText(
|
m_trackSectorLabel->setText(
|
||||||
QString("Track: %1 Sector: %2 (%3)")
|
QString("Track: %1 Sector: %2 (%3)")
|
||||||
.arg(track)
|
.arg(track)
|
||||||
|
@ -215,7 +219,7 @@ QLabel *DiskExplorerMapWidget::makeKeyLabel(QWidget *parent, QString name, QColo
|
||||||
QGroupBox *DiskExplorerMapWidget::makeKeyWidget()
|
QGroupBox *DiskExplorerMapWidget::makeKeyWidget()
|
||||||
{
|
{
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
QGroupBox *groupbox= new QGroupBox(this);
|
QGroupBox *groupbox= new QGroupBox();
|
||||||
groupbox->setTitle("Key");
|
groupbox->setTitle("Key");
|
||||||
QGridLayout *layout = new QGridLayout();
|
QGridLayout *layout = new QGridLayout();
|
||||||
layout->setVerticalSpacing(0);
|
layout->setVerticalSpacing(0);
|
||||||
|
@ -354,15 +358,15 @@ void DiskExplorerMapWidget::mapDiskToButtons()
|
||||||
m_sectorDescriptions.insert(DETSPair(tr,se),description);
|
m_sectorDescriptions.insert(DETSPair(tr,se),description);
|
||||||
|
|
||||||
QColor color;
|
QColor color;
|
||||||
if (fde.fileType() == "I") color = m_intBasicFileColor;
|
if (fde.fileTypeIdentifier() == "I") color = m_intBasicFileColor;
|
||||||
else if (fde.fileType() == "A") color = m_applesoftFileColor;
|
else if (fde.fileTypeIdentifier() == "A") color = m_applesoftFileColor;
|
||||||
else if (fde.fileType() == "R") color = m_reloFileColor;
|
else if (fde.fileTypeIdentifier() == "R") color = m_reloFileColor;
|
||||||
else if (fde.fileType() == "B") color = m_binaryFileColor;
|
else if (fde.fileTypeIdentifier() == "B") color = m_binaryFileColor;
|
||||||
else if (fde.fileType() == "S") color = m_typeSFileColor;
|
else if (fde.fileTypeIdentifier() == "S") color = m_typeSFileColor;
|
||||||
else if (fde.fileType() == "T") color = m_textFileColor;
|
else if (fde.fileTypeIdentifier() == "T") color = m_textFileColor;
|
||||||
else if (fde.fileType() == "a") color = m_typeAFileColor;
|
else if (fde.fileTypeIdentifier() == "a") color = m_typeAFileColor;
|
||||||
else if (fde.fileType() == "b") color = m_typeBFileColor;
|
else if (fde.fileTypeIdentifier() == "b") color = m_typeBFileColor;
|
||||||
else qDebug() << "Unknown file type: " << fde.fileType();
|
else qDebug() << "Unknown file type: " << fde.fileTypeIdentifier();
|
||||||
buttonAt(tr,se)->setBgColor(color);
|
buttonAt(tr,se)->setBgColor(color);
|
||||||
setButtonText(tr,se,QString("%1").arg(idx));
|
setButtonText(tr,se,QString("%1").arg(idx));
|
||||||
qDebug() << "Button" << idx << "=" << tr << "," << se << " " << fde.filename.printable();
|
qDebug() << "Button" << idx << "=" << tr << "," << se << " " << fde.filename.printable();
|
||||||
|
|
|
@ -8,29 +8,37 @@
|
||||||
#include <QColor>
|
#include <QColor>
|
||||||
#include <QGroupBox>
|
#include <QGroupBox>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
|
#include <QToolButton>
|
||||||
|
|
||||||
|
|
||||||
#include "dos33diskimage.h"
|
#include "dos33diskimage.h"
|
||||||
|
|
||||||
|
|
||||||
class DEButton : public QPushButton
|
class DEButton : public QToolButton
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
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);
|
setTrack(track);
|
||||||
setSector(sec);
|
setSector(sec);
|
||||||
connect(this, &DEButton::clicked, this, &DEButton::handleClick);
|
connect(this, &DEButton::clicked, this, &DEButton::handleClick);
|
||||||
m_isHighlighted = false;
|
m_isHighlighted = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setTrack(int track) { m_track = track; }
|
void setTrack(int track) { m_track = track; }
|
||||||
void setSector(int sector) { m_sector = sector; }
|
void setSector(int sector) { m_sector = sector; }
|
||||||
|
|
||||||
int track() const { return m_track; }
|
int track() const { return m_track; }
|
||||||
int sector() const { return m_sector; }
|
int sector() const { return m_sector; }
|
||||||
|
|
||||||
void clearBgColor() { m_backgroundColor = ""; setText(""); setStyleSheet(makeStyleSheet());}
|
void clearBgColor() {
|
||||||
|
m_backgroundColor = "";
|
||||||
|
setText("");
|
||||||
|
setStyleSheet(makeStyleSheet());
|
||||||
|
}
|
||||||
|
|
||||||
void setBgColor(QColor color) {
|
void setBgColor(QColor color) {
|
||||||
m_fgColor = determineFgColor(color).name();
|
m_fgColor = determineFgColor(color).name();
|
||||||
|
@ -40,9 +48,18 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
bool highlighted() const { return m_isHighlighted; }
|
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(); }
|
void resetToDefault() { clearBgColor(); reset(); }
|
||||||
|
|
||||||
|
@ -59,28 +76,41 @@ signals:
|
||||||
void checked(int track, int sec,bool );
|
void checked(int track, int sec,bool );
|
||||||
|
|
||||||
private slots:
|
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); }
|
QSize sizeHint() const Q_DECL_OVERRIDE { return QSize(24,24); }
|
||||||
bool hasHeightForWidth() const Q_DECL_OVERRIDE { return true; }
|
bool hasHeightForWidth() const Q_DECL_OVERRIDE { return true; }
|
||||||
int heightForWidth(int width) const Q_DECL_OVERRIDE { return width; }
|
int heightForWidth(int width) const Q_DECL_OVERRIDE { return width; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
QString makeStyleSheet() const {
|
QString makeStyleSheet() const {
|
||||||
return QString(" QPushButton { font: 10px; border-width: 1px; color: %1; background-color: %2} "
|
return QString("DEButton { "
|
||||||
" QPushButton:checked { font: bold italic 11px; } "
|
" font: 10px; "
|
||||||
) .arg(m_fgColor)
|
" border-width: 1px; "
|
||||||
|
" color: %1; "
|
||||||
|
" background-color: %2 "
|
||||||
|
"} "
|
||||||
|
" "
|
||||||
|
"DEButton:checked { "
|
||||||
|
" font: bold italic 11px; "
|
||||||
|
"}"
|
||||||
|
).arg(m_fgColor)
|
||||||
.arg(m_backgroundColor);
|
.arg(m_backgroundColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
int m_track;
|
int m_track;
|
||||||
int m_sector;
|
int m_sector;
|
||||||
|
|
||||||
bool m_isHighlighted;
|
bool m_isHighlighted;
|
||||||
|
|
||||||
QString m_fgColor;
|
QString m_fgColor;
|
||||||
QString m_backgroundColor;
|
QString m_backgroundColor;
|
||||||
QString m_hlColor;
|
QString m_hlColor;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
80
src/util/chunkbytelist.cpp
Normal file
80
src/util/chunkbytelist.cpp
Normal file
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
43
src/util/chunkbytelist.h
Normal file
43
src/util/chunkbytelist.h
Normal file
|
@ -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) {
|
inline QString uint8ToHex(quint8 val) {
|
||||||
QString retval = QString("%1").arg(val,2,16,QChar('0')).toUpper();
|
QString retval = QString("%1").arg(val,2,16,QChar('0')).toUpper();
|
||||||
return retval;
|
return retval;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user