Updated diskfile stuff

This commit is contained in:
Mark Long 2021-02-11 10:12:30 -06:00
parent 6303dd1228
commit 756cff8657
22 changed files with 565 additions and 219 deletions

View File

@ -3,7 +3,6 @@
CatalogSector::CatalogSector(Sector *data)
{
// qDebug() << "### Start CatalogSector ctor";
m_data = data;
m_next = TSPair(0,0);
@ -12,22 +11,19 @@ CatalogSector::CatalogSector(Sector *data)
if (next.isValid() && next.track() == 17)
{
next.dump();
// qDebug("Next track sector is valid.");
// next.dump();
m_next = next;
}
else
{
qWarning() << "Track sector " << next.track() << "," << next.sector() << "is invalid! Not adding to catalog.";
m_next.dump();
// qWarning() << "Track sector " << next.track() << "," << next.sector() << "is invalid! Not adding to catalog.";
// m_next.dump();
}
//m_next.setTrack(m_data->rawData()[0x01]);
//m_next.setSector(m_data->rawData()[0x02]);
for (int idx = 0; idx<7; idx++)
{
FileDescriptiveEntry fde = makeFDE(idx*0x23+0x0B);
if (fde.firstTSListSector() != TSPair(0,0)) {
if (fde.firstTSListSector() != TSPair(0,0)) {
if (fde.firstTSListSector().isValid())
{
m_fdes.append(fde);
@ -36,7 +32,6 @@ CatalogSector::CatalogSector(Sector *data)
}
// else { qWarning("fde.firstTSListSector() is 0,0"); }
}
// qDebug() << "### End CatalogSector ctor";
}
void CatalogSector::dumpFDEs() {
@ -53,12 +48,14 @@ void CatalogSector::dumpFDEs() {
FileDescriptiveEntry CatalogSector::makeFDE(int offset)
{
FileDescriptiveEntry fde;
fde.firstTSListSector().setTrack(m_data->rawData()[offset + 0x00]);
fde.firstTSListSector().setSector(m_data->rawData()[offset + 0x01]);
fde.fileTypeAndFlags = m_data->rawData()[offset + 0x02];
TSPair first(m_data->rawData()[offset + 0x00],m_data->rawData()[offset + 0x01]);
fde.setFirstTSListSector(first);
fde.lengthInSectors = makeWord( m_data->rawData()[offset + 0x21],
m_data->rawData()[offset + 0x22]);
fde.fileTypeFlags = m_data->rawData()[offset + 0x02];
if (fde.lengthInSectors > 16*35)
{
fde.lengthInSectors = -1;
@ -70,11 +67,12 @@ FileDescriptiveEntry CatalogSector::makeFDE(int offset)
if (fde.firstTSListSector().track() == 0xFF)
{
//TODO: Double check this stuff. applevision.dsk is a good example.
qDebug() << "File" << fde.filename.printable() << "is deleted";
fde.deleted = true;
qDebug() << fde.filename;
fde.firstTSListSector().setTrack(m_data->rawData()[offset + 0x20]);
TSPair first = fde.firstTSListSector();
first.setTrack(m_data->rawData()[offset + 0x20]);
fde.setFirstTSListSector(first);
qDebug() << " New track: " << (quint8) fde.firstTSListSector().track();
qDebug() << " Sector: " << fde.firstTSListSector().sector();
}

View File

@ -5,6 +5,7 @@
#include <QByteArray>
#include <QDebug>
#include "tspair.h"
#include "util.h"
#include "applestring.h"
#include "filedescriptiveentry.h"

View File

@ -1,4 +1,4 @@
#include "diskfile.h"
#include "dos33diskimage.h"
#include <QFile>
#include <QDataStream>
@ -7,13 +7,14 @@
#include <QDir>
#include "tracksectorlist.h"
#include "genericfile.h"
#include "applesoftfile.h"
#include "binaryfile.h"
#include "IntBasicFile.h"
#include "relocatablefile.h"
#include "textfile.h"
DiskFile::DiskFile(QString filename)
Dos33DiskImage::Dos33DiskImage(QString filename)
{
if (!filename.isEmpty())
{
@ -21,7 +22,7 @@ DiskFile::DiskFile(QString filename)
}
}
DiskFile::~DiskFile()
Dos33DiskImage::~Dos33DiskImage()
{
foreach (GenericFile *file, m_files)
{
@ -29,7 +30,7 @@ DiskFile::~DiskFile()
}
}
bool DiskFile::read(QString filename)
bool Dos33DiskImage::read(QString filename)
{
m_fullImageName = filename;
m_imageName = QFileInfo(filename).fileName();
@ -48,6 +49,16 @@ bool DiskFile::read(QString filename)
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++)
{
@ -56,11 +67,11 @@ bool DiskFile::read(QString filename)
char buffer[256];
if (qds.readRawData(buffer,256) == 256)
{
// qDebug() << "Track " << track << " Sector " << sector;
Sector sec;
sec.setTrackSector(track,sector);
sec.setData(QByteArray(buffer,256));
m_contents[track][sector] = sec;
TSPair tmpts(track,sector);
Sector newSec;
newSec.setTrackSector(tmpts);
newSec.setData(QByteArray(buffer,256));
m_contents[tmpts] = newSec;
}
else
{
@ -72,7 +83,7 @@ bool DiskFile::read(QString filename)
hash.addData(contents);
m_hash = hash.result();
// qDebug() << "Hash: " << m_hash;
// qDebug() << "Hash: " << m_hash;
return true;
}
@ -81,32 +92,32 @@ bool DiskFile::read(QString filename)
return false;
}
VTOC DiskFile::getVTOC()
VTOC Dos33DiskImage::getVTOC()
{
return getSector(17,0).promoteToVTOC();
}
QList<CatalogSector> DiskFile::getCatalogSectors()
QList<CatalogSector> Dos33DiskImage::getCatalogSectors()
{
// qDebug() << "### Start getCatalogSector";
// qDebug() << "### Start getCatalogSector";
QList<CatalogSector> retval;
VTOC vtoc = getVTOC();
TSPair ts = vtoc.firstCatalogSector();
CatalogSector cs = getSector(ts).promoteToCatalogSector();
CatalogSector cs = getSector(ts).asCatalogSector();
retval.append(cs);
while (cs.nextCatalogSector() != TSPair(0,0)) {
ts = cs.nextCatalogSector();
cs = getSector(ts).promoteToCatalogSector();
cs = getSector(ts).asCatalogSector();
retval.append(cs);
}
// qDebug() << "### End getCatalogSector";
// qDebug() << "### End getCatalogSector";
return retval;
}
GenericFile *DiskFile::getFile(FileDescriptiveEntry fde)
GenericFile *Dos33DiskImage::getFile(FileDescriptiveEntry fde)
{
GenericFile *retval = 0;
if (m_files.contains(fde))
@ -115,38 +126,38 @@ GenericFile *DiskFile::getFile(FileDescriptiveEntry fde)
}
else
{
if (!fde.firstTSListSector().isValid())
{
qWarning(" Not returning a file from invalid TSList!");
return nullptr;
}
TrackSectorList tsl = getSector(fde.firstTSListSector()).promoteToTrackSectorList();
TrackSectorList tsl = getSector(fde.firstTSListSector()).asTrackSectorList();
if (!fde.firstTSListSector().isValid())
{
qWarning(" Not returning a file from invalid TSList!");
return nullptr;
}
QByteArray data = getDataFromTrackSectorList(tsl);
setFileType(fde.fileType());
if (fde.fileType() == "A")
if (fileType() == "A")
{
retval = new ApplesoftFile(data);
}
else if (fde.fileType() == "B")
else if (fileType() == "B")
{
retval = new BinaryFile(data);
}
else if (fde.fileType() == "R")
else if (fileType() == "R")
{
retval = new RelocatableFile(data);
}
else if ((fde.fileType() == "T"))
else if ((fileType() == "T"))
{
retval = new TextFile(data);
}
else if ((fde.fileType() == "I"))
else if ((fileType() == "I"))
{
retval = new IntBasicFile(data);
}
@ -154,6 +165,7 @@ GenericFile *DiskFile::getFile(FileDescriptiveEntry fde)
{
retval = new GenericFile(data);
}
m_files[fde] = retval;
}
if (retval) { retval->setDiskFile(this); }
@ -161,7 +173,7 @@ GenericFile *DiskFile::getFile(FileDescriptiveEntry fde)
}
QByteArray DiskFile::getDataFromTrackSectorList(TrackSectorList tsl)
QByteArray Dos33DiskImage::getDataFromTrackSectorList(TrackSectorList tsl)
{
QByteArray retval;
@ -169,8 +181,8 @@ QByteArray DiskFile::getDataFromTrackSectorList(TrackSectorList tsl)
{
if (pair.isValid())
{
Sector sec = getSector(pair);
retval.append(sec.rawData());
Sector sec = getSector(pair);
retval.append(sec.rawData());
}
else
{
@ -180,16 +192,16 @@ QByteArray DiskFile::getDataFromTrackSectorList(TrackSectorList tsl)
auto next = tsl.getNextTSList();
if (next.isValid() && next != TSPair(0,0)) {
TrackSectorList nextTsl = getSector(tsl.getNextTSList()).promoteToTrackSectorList();
TrackSectorList nextTsl = getSector(tsl.getNextTSList()).asTrackSectorList();
retval.append(getDataFromTrackSectorList(nextTsl));
}
return retval;
}
QList<FileDescriptiveEntry> DiskFile::getAllFDEs()
QList<FileDescriptiveEntry> Dos33DiskImage::getAllFDEs()
{
// qDebug() << "### Start getAllFDEs";
// qDebug() << "### Start getAllFDEs";
QList<FileDescriptiveEntry> retval;
QList<CatalogSector> sectors = getCatalogSectors();
@ -199,11 +211,11 @@ QList<FileDescriptiveEntry> DiskFile::getAllFDEs()
QList<FileDescriptiveEntry> fdes = cs.getFDEs();
retval.append(fdes);
}
// qDebug() << "### End getAllFDEs";
// qDebug() << "### End getAllFDEs";
return retval;
}
QString DiskFile::getMetaDataPath() const {
QString Dos33DiskImage::getMetaDataPath() const {
QString path = QString("%1.metadata/").arg(getFullDiskImageName());
QDir dir(path);

View File

@ -1,59 +1,68 @@
#ifndef DISKFILE_H
#define DISKFILE_H
#include <Qt>
#include <QMap>
#include <QString>
#include <QDebug>
#include <QCryptographicHash>
#include "util.h"
#include "sector.h"
#include "vtoc.h"
class GenericFile;
class DiskFile
{
public:
DiskFile(QString filename = "");
~DiskFile();
bool read(QString filename);
Sector &getSector(TSPair ts) { return getSector(ts.track(), ts.sector()); }
Sector &getSector(int track, int sector) {
return m_contents[track][sector];
}
VTOC getVTOC();
QList<CatalogSector> getCatalogSectors();
GenericFile *getFile(FileDescriptiveEntry fde);
QByteArray 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 getMetaDataPath() const;
private:
QMap< int, QMap< int, Sector> > m_contents;
QMap<FileDescriptiveEntry,GenericFile *> m_files;
QByteArray m_hash;
QString m_imageName;
QString m_fullImageName;
quint8 m_sectors_per_track;
};
#endif // DISKFILE_H
#ifndef DOS33DISKIMAGE_H
#define DOS33DISKIMAGE_H
#include <Qt>
#include <QMap>
#include <QString>
#include <QDebug>
#include <QCryptographicHash>
#include "util.h"
#include "sector.h"
#include "vtoc.h"
class GenericFile;
class Dos33DiskImage
{
public:
Dos33DiskImage(QString filename = "");
~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);
}
VTOC getVTOC();
QList<CatalogSector> getCatalogSectors();
GenericFile *getFile(FileDescriptiveEntry fde);
QByteArray 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 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; }
private:
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;
};
#endif // DOS33DISKIMAGE_H

View File

@ -0,0 +1,95 @@
#include "dos33imagemodel.h"
#include <QIcon>
#include "tspair.h"
Dos33ImageModel::Dos33ImageModel(QObject *parent) : QStandardItemModel(parent)
{
setHorizontalHeaderLabels({"Disk Images"});
m_icon_A = QIcon(":/A_YELLOW.png");
m_icon_a = QIcon(":/A_GREY.png");
m_icon_B = QIcon(":/B_GREEN.png");
m_icon_b = QIcon(":/B_GREY.png");
m_icon_R = QIcon(":/R_MAGENTA.png");
m_icon_S = QIcon(":/S_ORANGE.png");
m_icon_T = QIcon(":/T_CYAN.png");
m_icon_I = QIcon(":/I_RED.png");
m_icon_disk = QIcon(":/disk.png");
}
Dos33ImageModel::~Dos33ImageModel()
{
}
bool Dos33ImageModel::addDiskImage(Dos33DiskImage *image, QString name)
{
if (!image) { return false; }
if (name.isEmpty()) { name = image->getDiskImageName(); }
if (m_images.contains(name)) { return false; }
auto diskImageItem = new Dos33TreeItem(name);
invisibleRootItem()->appendRow(diskImageItem);
foreach (auto sector, image->getCatalogSectors())
{
foreach (auto fde, sector.getFDEs())
{
if (!fde.deleted)
{
QString fn = AppleString(fde.filename).appleFontPrintable();
QString type = fde.fileType();
QIcon icon;
if (type == "A") { icon = m_icon_A; }
else if (type == "B") { icon = m_icon_B; }
else if (type == "T") { icon = m_icon_T; }
else if (type == "R") { icon = m_icon_R; }
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; }
auto item = new Dos33TreeItem(icon,fn);
QVariant data;
data.setValue(fde.firstTSListSector());
item->setData(data);
item->setToolTip(QString("%1 Block(s)").arg(fde.lengthInSectors));
diskImageItem->appendRow(item);
}
}
}
auto sectors = new Dos33TreeItem("Track/Sector");
diskImageItem->appendRow(sectors);
for (int track = 0; track < image->tracks(); track++)
{
auto trk = new Dos33TreeItem(m_icon_disk, QString("Track %1").arg(track));
sectors->appendRow(trk);
for (int sector = 0; sector < image->sectorsPerTrack(); sector++)
{
auto sec = new Dos33TreeItem(m_icon_disk, QString("Sector %1").arg(sector));
trk->appendRow(sec);
}
}
return true;
}
Dos33DiskImage *Dos33ImageModel::getDiskImage(QString name)
{
return nullptr;
}
Dos33DiskImage *Dos33ImageModel::removeDiskImage(QString name)
{
return nullptr;
}

View File

@ -0,0 +1,42 @@
#ifndef DOS33IMAGEMODEL_H
#define DOS33IMAGEMODEL_H
#include "dos33treeitem.h"
#include "dos33diskimage.h"
#include <QStandardItemModel>
#include <QObject>
#include <QIcon>
class Dos33ImageModel : public QStandardItemModel
{
Q_OBJECT
using ImageMap = QMap<QString, Dos33DiskImage *>;
public:
Dos33ImageModel(QObject *parent = nullptr);
~Dos33ImageModel();
bool addDiskImage(Dos33DiskImage *image, QString name = "");
Dos33DiskImage *getDiskImage(QString name);
Dos33DiskImage *removeDiskImage(QString name);
private:
QIcon m_icon_A;
QIcon m_icon_a;
QIcon m_icon_B;
QIcon m_icon_b;
QIcon m_icon_I;
QIcon m_icon_R;
QIcon m_icon_S;
QIcon m_icon_T;
QIcon m_icon_disk;
ImageMap m_images;
};
#endif // DOS33IMAGEMODEL_H

View File

@ -0,0 +1,18 @@
#include "dos33treeitem.h"
Dos33TreeItem::Dos33TreeItem() : QStandardItem()
{
setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
}
Dos33TreeItem::Dos33TreeItem(const QIcon &icon, const QString &text)
: QStandardItem(icon,text)
{
setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
}
Dos33TreeItem::Dos33TreeItem(const QString &text) : QStandardItem(text)
{
setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
}

View File

@ -0,0 +1,20 @@
#ifndef DOS33TREEITEM_H
#define DOS33TREEITEM_H
#include <QStandardItem>
class Dos33TreeItem : public QStandardItem
{
public:
Dos33TreeItem();
Dos33TreeItem(const QIcon &icon, const QString &text);
Dos33TreeItem(const QString &text);
~Dos33TreeItem() { }
private:
Dos33TreeItem(int rows, int columns = 1) : QStandardItem(rows,columns) { }
};
#endif // DOS33TREEITEM_H

View File

@ -1,18 +1,18 @@
#ifndef FILEDESCRIPTIVEENTRY_H
#define FILEDESCRIPTIVEENTRY_H
#include "util.h"
#include "tspair.h"
#include <QDebug>
#include "applestring.h"
struct FileDescriptiveEntry {
int fileTypeAndFlags;
quint8 fileTypeFlags;
AppleString filename;
quint16 lengthInSectors;
bool deleted;
FileDescriptiveEntry() {
fileTypeAndFlags = 0;
fileTypeFlags = 0;
lengthInSectors = 0;
deleted = false;
}
@ -22,23 +22,23 @@ struct FileDescriptiveEntry {
}
QString fileType() {
if (fileTypeAndFlags & DOSIntegerBasicFile) { return "I"; }
if (fileTypeAndFlags & DOSApplesoftBasicFile) { return "A"; }
if (fileTypeAndFlags & DOSRelocatableFile) { return "R"; }
if (fileTypeAndFlags & DOSRawBinaryFile) { return "B"; }
if (fileTypeAndFlags & DOSTypeSFile) { return "S"; }
if (fileTypeAndFlags & DOSTypeAFile) { return "a"; }
if (fileTypeAndFlags & DOSTypeBFile) { return "b"; }
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";
}
bool isLocked() { return (fileTypeAndFlags & DOSIsLocked); }
bool isLocked() { return (fileTypeFlags & (quint8) FileTypeFlag::IsLockedFlag); }
void dump() {
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)fileTypeAndFlags) << "(" << fileType() << "," << (isLocked()?"Locked":"Unlocked") << ")";
qDebug() << "File Type and Flags: " << QString::number((quint8) fileTypeFlags) << "(" << fileType() << "," << (isLocked()?"Locked":"Unlocked") << ")";
qDebug() << "Filename: " << filename.printable();
qDebug() << "Length in Sectors: " << lengthInSectors;
}
@ -62,7 +62,7 @@ struct FileDescriptiveEntry {
m_firstTSListSector = TSPair(0,0);
}
}
TSPair &firstTSListSector() { return m_firstTSListSector; }
TSPair firstTSListSector() const { return m_firstTSListSector; }
private:
TSPair m_firstTSListSector;

View File

@ -15,3 +15,17 @@ void GenericFile::setData(QByteArray data)
m_data = data;
m_length = data.size();
}
QString GenericFile::getFileType() const
{
if (m_file_type == "A" || m_file_type == "B" || m_file_type == "T" ||
m_file_type == "I" || m_file_type == "R" || m_file_type == "S" ||
m_file_type == "a" || m_file_type == "b")
{
return m_file_type;
}
else
{
return "?";
}
}

View File

@ -1,7 +1,7 @@
#ifndef GENERICFILE_H
#define GENERICFILE_H
#include "diskfile.h"
#include "dos33diskimage.h"
#include <QByteArray>
#include <QString>
@ -27,15 +27,21 @@ public:
virtual void setLength(quint16 length) { m_length = length; }
virtual quint16 length() const { return m_length; }
DiskFile *diskFile() const { return m_diskfile; }
void setDiskFile(DiskFile *diskfile) { m_diskfile = diskfile; }
Dos33DiskImage *diskFile() const { return m_diskfile; }
void setDiskFile(Dos33DiskImage *diskfile) { m_diskfile = diskfile; }
void setFileType(QString type) { m_file_type = type; }
QString getFileType() const;
protected:
QByteArray m_data;
QString m_filename;
quint16 m_address;
qint16 m_length;
DiskFile * m_diskfile;
Dos33DiskImage * m_diskfile;
QString m_file_type;
};

View File

@ -22,12 +22,13 @@ void Sector::dump() {
for (int jdx = 0; jdx < 16; jdx++)
{
QString line;
line += QString("%1 (%2): ").arg(jdx*16,2,16,QChar('0')).arg(jdx*16,3,10,QChar(' '));
line += QString("%1 (%2): ")
.arg(uint16ToHex(jdx*16)).arg(jdx*16,3,10,QChar(' '));
for (int idx = 0; idx < 16; idx++)
{
int offset = (jdx*16) + idx;
quint8 val = m_data[offset];
line += QString("%1 ").arg(val,2,16,QChar('0'));
line += QString("%1 ").arg(uint16ToHex(val));
if (idx == 7) line += " ";
}
line = line.toUpper();

View File

@ -21,11 +21,11 @@ public:
return VTOC(this);
}
CatalogSector promoteToCatalogSector() {
CatalogSector asCatalogSector() {
return CatalogSector(this);
}
TrackSectorList promoteToTrackSectorList() {
TrackSectorList asTrackSectorList() {
return TrackSectorList(this);
}
@ -37,6 +37,11 @@ public:
setSector(sector);
}
void setTrackSector(TSPair ts)
{
setTrackSector(ts.track(),ts.sector());
}
void setTrack(int track) { m_track = track; }
void setSector(int sector) { m_sector = sector; }

View File

@ -22,3 +22,25 @@ TrackSectorList::TrackSectorList(Sector *data)
}
}
}
bool TrackSectorList::isNextTSListValid() const
{
return getNextTSList().isValid();
}
bool TrackSectorList::isSectorOffsetValid() const
{
return getSectorOffset().isValid();
}
QList<TSPair> TrackSectorList::getValidTSPairs() const
{
QList<TSPair> retval;
foreach (auto item, m_ts_pairs_for_data)
{
if (item.isValid()) { retval.append(item); }
}
return retval;
}

View File

@ -1,7 +1,7 @@
#ifndef TRACKSECTORLIST_H
#define TRACKSECTORLIST_H
#include "util.h"
#include "tspair.h"
class Sector;
@ -11,12 +11,16 @@ public:
TrackSectorList(Sector *data);
TSPair getNextTSList() const { return m_next_tslist; }
TSPair getSectorOffset() const { return m_sector_offset; }
bool isNextTSListValid() const;
TSPair getSectorOffset() const { return m_sector_offset; }
bool isSectorOffsetValid() const;
QList<TSPair> getDataTSPairs() const { return m_ts_pairs_for_data; }
QList<TSPair> getValidTSPairs() const;
QList<TSPair> getDataTSPairs() { return m_ts_pairs_for_data; }
private:
TSPair m_next_tslist;
TSPair m_sector_offset;
QList<TSPair> m_ts_pairs_for_data;

View File

@ -0,0 +1 @@
#include "tspair.h"

View File

@ -0,0 +1,71 @@
#ifndef TSPAIR_H
#define TSPAIR_H
#include <Qt>
#include <QDebug>
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;}
void setTrack(quint8 tracknum)
{
if (tracknum > 34 && tracknum != 0xff) {
qWarning("Setting a track with value %d (> 34 and not 256).",tracknum);
}
m_track = tracknum;
}
void setSector(quint8 secnum)
{
if (secnum > 15 && m_track != 0xff) {
qWarning("Setting a sector with value %d (> 15) on track %d.",
secnum, m_track);
}
m_sector = secnum;
}
bool isValid() const
{
auto retval= (m_track != 0xff && m_track < 35) && m_sector < 16;
return retval; }
quint8 track() const { return m_track; }
quint8 sector() const { return m_sector; }
bool operator==(const TSPair &other) const {
if (other.track() == track() && other.sector() == sector()) return true;
return false;
}
bool operator!=(const TSPair &other) const {
return !(operator==(other));
}
bool operator<(const TSPair &other) const {
if (m_track == other.track())
{
return (m_sector < other.sector());
}
else
{
return (m_track < other.track());
}
}
QPair<quint8,quint8> toQPair() { return QPair<quint8,quint8>(track(),sector()); }
void dump() const {
qDebug() << "TSPair: track: " << track() << " sector: " << sector();
}
private:
quint8 m_track;
quint8 m_sector;
};
Q_DECLARE_METATYPE(TSPair);
#endif // TSPAIR_H

View File

@ -49,7 +49,7 @@ qint16 VTOC::bytesPerSector() {
m_data->rawData()[0x37]);
}
bool VTOC::isSectorInUse(TSPair ts) {
bool VTOC::isSectorInUse(TSPair ts) const {
quint8 track = ts.track();
quint8 sec = ts.sector();
quint8 baseaddr = (track * 4) + 0x38;
@ -62,6 +62,42 @@ bool VTOC::isSectorInUse(TSPair ts) {
return !(word & bitpos);
}
QList<TSPair> VTOC::sectorsInUse() const
{
QList<TSPair> retval;
for (int track = 0; track < 35; track++)
{
for (int sector = 0; sector < 16; sector++)
{
TSPair ts(track,sector);
if (isSectorInUse(ts))
{
retval.append(ts);
}
}
}
return retval;
}
QList<TSPair> VTOC::sectorsNotInUse() const
{
QList<TSPair> retval;
for (int track = 0; track < 35; track++)
{
for (int sector = 0; sector < 16; sector++)
{
TSPair ts(track,sector);
if (!isSectorInUse(ts))
{
retval.append(ts);
}
}
}
return retval;
}
void VTOC::dump()
{
/*

View File

@ -3,6 +3,8 @@
#include <Qt>
#include "util.h"
#include "tspair.h"
class Sector;
class QString;
@ -22,7 +24,10 @@ public:
quint8 tracksPerDisk();
quint8 sectorsPerDisk();
qint16 bytesPerSector();
bool isSectorInUse(TSPair ts);
bool isSectorInUse(TSPair ts) const;
QList<TSPair> sectorsInUse() const;
QList<TSPair> sectorsNotInUse() const;
private:
QString buildUseString(quint8 track);

View File

@ -7,10 +7,16 @@ QString AppleString::printable() const
QString retval;
foreach (quint8 ch, *this) {
retval.append(AppleChar::printable(ch));
// if (ch > 0x80)
// retval.append(QChar(ch-0x80));
// else
// retval.append(QChar(ch));
}
return retval;
}
QString AppleString::appleFontPrintable() const
{
QString retval;
foreach (quint8 ch, *this) {
retval.append(AppleChar::getAppleFontChar(ch));
}
return retval;
}
@ -30,28 +36,28 @@ QChar AppleChar::printable(quint8 val)
{
quint8 newval;
switch (getTextSet(val)) {
case SetInvUC:
case TextSet::SetInvUC:
newval = val+0x40;
break;
case SetInvSp:
case TextSet::SetInvSp:
newval = val;
break;
case SetFlUC:
case TextSet::SetFlUC:
newval = val;
break;
case SetFlSp:
case TextSet::SetFlSp:
newval = val-0x40;
break;
case SetNormUC:
case TextSet::SetNormUC:
newval = val-0x40;
break;
case SetNormSp:
case TextSet::SetNormSp:
newval = val-0x80;
break;
case SetNormAltUC:
case TextSet::SetNormAltUC:
newval = val-0x80;
break;
case SetNormLC:
case TextSet::SetNormLC:
default:
newval = val-0x80;
break;
@ -61,22 +67,22 @@ QChar AppleChar::printable(quint8 val)
TextAttribute AppleChar::getAttribute(quint8 val)
{
if (val <= 0x3f) { return Inverse; }
if (val <= 0x7f) { return Flash; }
if (val <= 0xbf) { return NormalLow; }
if (val <= 0xdf) { return NormalHigh; }
return NormalHigh;
if (val <= 0x3f) { return TextAttribute::Inverse; }
if (val <= 0x7f) { return TextAttribute::Flash; }
if (val <= 0xbf) { return TextAttribute::NormalLow; }
if (val <= 0xdf) { return TextAttribute::NormalHigh; }
return TextAttribute::NormalHigh;
}
TextSet AppleChar::getTextSet(quint8 val) {
if (val < 0x20) { return SetInvUC; }
if (val < 0x40) { return SetInvSp; }
if (val < 0x60) { return SetFlUC; }
if (val < 0x80) { return SetFlSp; }
if (val < 0xA0) { return SetNormUC; }
if (val < 0xC0) { return SetNormSp; }
if (val < 0xE0) { return SetNormAltUC; }
return SetNormLC;
if (val < 0x20) { return TextSet::SetInvUC; }
if (val < 0x40) { return TextSet::SetInvSp; }
if (val < 0x60) { return TextSet::SetFlUC; }
if (val < 0x80) { return TextSet::SetFlSp; }
if (val < 0xA0) { return TextSet::SetNormUC; }
if (val < 0xC0) { return TextSet::SetNormSp; }
if (val < 0xE0) { return TextSet::SetNormAltUC; }
return TextSet::SetNormLC;
}
QString AppleChar::getHtmlString(quint8 val)
@ -86,11 +92,33 @@ QString AppleChar::getHtmlString(quint8 val)
htmlstring = htmlstring.toHtmlEscaped();
QString retval;
if (attribute == Inverse) { retval = QString("<font color=\"blue\"><b>%1</b></font>").arg(htmlstring); }
else if (attribute == Flash) { retval = QString("<font color=\"green\"><b><i>%1</i></b></font>").arg(htmlstring);}
else if (attribute == NormalLow) { retval = QString("<font color=\"red\"><i>%1</i></font>").arg(htmlstring);}
if (attribute == TextAttribute::Inverse) { retval = QString("<font color=\"blue\"><b>%1</b></font>").arg(htmlstring); }
else if (attribute == TextAttribute::Flash) { retval = QString("<font color=\"green\"><b><i>%1</i></b></font>").arg(htmlstring);}
else if (attribute == TextAttribute::NormalLow) { retval = QString("<font color=\"red\"><i>%1</i></font>").arg(htmlstring);}
else { retval = QString("%1").arg(htmlstring);}
return retval;
}
QChar AppleChar::getAppleFontChar(quint8 val)
{
if (getAttribute(val) == TextAttribute::Inverse)
{
return QChar(printable(val).unicode() + 0xe100);
}
else if (getAttribute(val) == TextAttribute::Flash)
{
return QChar(printable(val).unicode() + 0xe100);
}
else if (val >= 0x80 && val < 0xA0)
{
return QChar(val - 0x80 + 0xe800);
}
else
{
return printable(val);
}
}

View File

@ -22,7 +22,7 @@ public:
static TextSet getTextSet(quint8 val) ;
static QChar printable(quint8 val) ;
static QString getHtmlString(quint8 val);
static QChar getAppleFontChar(quint8 val);
private:
quint8 m_val;
@ -32,6 +32,7 @@ class AppleString : public QByteArray {
public:
void setData(const QByteArray &data) { insert(0,data); }
QString printable() const;
QString appleFontPrintable() const;
QVector<TextAttribute> attributes() const;
};

View File

@ -8,26 +8,26 @@
#include <QFont>
#include <QSettings>
typedef enum {
DOSTextFile = 0x00,
DOSIntegerBasicFile = 0x01,
DOSApplesoftBasicFile = 0x02,
DOSRawBinaryFile = 0x04,
DOSTypeSFile = 0x08,
DOSRelocatableFile = 0x10,
DOSTypeAFile = 0x20,
DOSTypeBFile= 0x40,
DOSIsLocked = 0x80
} FileTypeFlag;
enum class FileTypeFlag : quint8 {
Text = 0x00,
Integer = 0x01,
Applesoft = 0x02,
Binary = 0x04,
TypeS = 0x08,
Relocatable = 0x10,
TypeA = 0x20,
TypeB= 0x40,
IsLockedFlag = 0x80
};
typedef enum {
enum class TextAttribute {
Inverse = 0x00, // 0x00 -- 0x3F
Flash = 0x01, // 0x40 -- 0x7F
NormalLow = 0x02, // 0x80 -- 0xBF
NormalHigh = 0x04 // 0xC0 -- 0xFF
} TextAttribute;
};
typedef enum {
enum class TextSet {
SetInvUC = 0x00,
SetInvSp = 0x20,
SetFlUC = 0x40,
@ -36,52 +36,9 @@ typedef enum {
SetNormSp = 0xA0,
SetNormAltUC = 0xC0,
SetNormLC = 0xE0
} TextSet;
struct TSPair {
TSPair() { m_track = m_sector = 0; }
TSPair(quint8 trackval, quint8 secval) { m_track=trackval; m_sector = secval; }
void setTrack(quint8 tracknum)
{
// Q_ASSERT(tracknum < 35);
if (tracknum > 34 && tracknum != 0xff) { qWarning("Setting a track with value %d (> 34 and not 256).",tracknum); }
m_track = tracknum;
}
void setSector(quint8 secnum)
{
//Q_ASSERT(secnum < 16);
if (secnum > 15 && m_track != 0xff) { qWarning("Setting a sector with value %d (> 15) on track %d.",secnum, m_track); }
m_sector = secnum;
}
bool isValid()
{
auto retval= (m_track != 0xff && m_track < 35) && m_sector < 16;
// qDebug() << "TSPair " << track() << "," << sector() << " is " << (retval?"":"not ") << "valid";
return retval; }
quint8 track() const { return m_track; }
quint8 sector() const { return m_sector; }
bool operator==(const TSPair &other) {
if (other.track() == track() && other.sector() == sector()) return true;
return false;
}
bool operator!=(const TSPair &other) {
return !(operator==(other));
}
void dump() const {
//qDebug() << "TSPair: track: " << track() << " sector: " << sector();
}
private:
quint8 m_track;
quint8 m_sector;
};
inline QString uint8ToHex(quint8 val) {
QString retval = QString("%1").arg(val,2,16,QChar('0')).toUpper();
return retval;