New work with diskimglib now stable
This commit is contained in:
parent
b093bf432a
commit
9e2320e051
2
ads
2
ads
|
@ -1 +1 @@
|
|||
Subproject commit 13853573ea51f9f0e682f7d005ca4443398512ae
|
||||
Subproject commit 6f8995cbd1b2999ba6ded903731eb4dd2a0af333
|
|
@ -1 +1 @@
|
|||
Subproject commit 7c637c4e6d2e0f7e0a60676bbda1bcd4618e1234
|
||||
Subproject commit 169a13206f4ff02a13cf22d3f3c2a5821a432686
|
|
@ -45,7 +45,7 @@ void ApplesoftFile::processData()
|
|||
}
|
||||
|
||||
m_length = dataWordAt(0);
|
||||
QByteArray tmp = rawData().asQByteArray().mid(2);
|
||||
QByteArray tmp = rawData().mid(2);
|
||||
|
||||
m_retokenizer->setData(tmp);
|
||||
m_retokenizer->parse();
|
||||
|
|
|
@ -28,7 +28,7 @@ BinaryFile::BinaryFile(Dos33DiskImage *image, FileDescriptiveEntry &fde)
|
|||
|
||||
void BinaryFile::setupData()
|
||||
{
|
||||
QByteArray data = rawData().asQByteArray();
|
||||
QByteArray data = rawData();
|
||||
|
||||
if (data.length() >= 4) {
|
||||
QByteArray metadata = data.left(4);
|
||||
|
|
|
@ -18,7 +18,9 @@
|
|||
|
||||
#include "asdiskdata.h"
|
||||
|
||||
ASDiskData::ASDiskData()
|
||||
#include <QDebug>
|
||||
|
||||
ASDiskData::ASDiskData(QObject *parent) : QObject(parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -28,39 +30,63 @@ ASDiskData::~ASDiskData()
|
|||
|
||||
}
|
||||
|
||||
void ASDiskData::setUseSectors(int numSectors, int numTracks)
|
||||
void ASDiskData::setUseSectors(int numTracks, int numSectors)
|
||||
{
|
||||
m_numsectors = numSectors;
|
||||
m_numtracks = numTracks;
|
||||
m_dataformat = DataFormat::Sectors;
|
||||
m_chunk_data.resize(m_numsectors * m_numtracks * 256); // Todo: magic number
|
||||
}
|
||||
|
||||
void ASDiskData::setUseBlocks(int numBlocks)
|
||||
{
|
||||
m_numblocks = numBlocks;
|
||||
m_dataformat = DataFormat::Blocks;
|
||||
m_chunk_data.resize(m_numblocks * 512);// Todo: magic number
|
||||
}
|
||||
|
||||
void ASDiskData::addSector(int track, int sector, QByteArray sectordata)
|
||||
{
|
||||
if (sectordata.length() != 256 || track >= m_numtracks || sector >= m_numsectors
|
||||
|| track < 0 || sector < 0)
|
||||
{
|
||||
qWarning("Invalid data in addSector.");
|
||||
return;
|
||||
}
|
||||
auto offset = tsToOffset(track,sector);
|
||||
m_chunks[offset] = sectordata;
|
||||
m_chunk_data.replace(offset*256,256,sectordata);
|
||||
}
|
||||
|
||||
void ASDiskData::addBlock(int number, QByteArray blockdata)
|
||||
{
|
||||
m_chunks[number] = blockdata;
|
||||
if (blockdata.length() != 512 || number >= m_numblocks || number < 0)
|
||||
{
|
||||
qWarning("Invalid data in addBlock.");
|
||||
return;
|
||||
};
|
||||
m_chunk_data.replace(number*512,512,blockdata);
|
||||
}
|
||||
|
||||
ASDiskData::SectorData &ASDiskData::getSector(int track, int sector)
|
||||
QByteArray ASDiskData::getSector(int track, int sector) const
|
||||
{
|
||||
auto offset = tsToOffset(track,sector);
|
||||
return m_chunks[offset];
|
||||
|
||||
if (offset >= m_chunk_data.size() / 256)
|
||||
{
|
||||
qWarning("Sector %d,%d out of bounds! Returning null data!",track,sector);
|
||||
return QByteArray();
|
||||
}
|
||||
return m_chunk_data.mid(offset*256,256);
|
||||
}
|
||||
|
||||
ASDiskData::BlockData &ASDiskData::getBlock(int blocknum)
|
||||
QByteArray ASDiskData::getBlock(int blocknum) const
|
||||
{
|
||||
return m_chunks[blocknum];
|
||||
if (blocknum >= m_chunk_data.size() / 256)
|
||||
{
|
||||
qWarning("Block %d out of bounds! Returning null data!",blocknum);
|
||||
return QByteArray();
|
||||
}
|
||||
return m_chunk_data.mid(blocknum*512,512);
|
||||
}
|
||||
|
||||
int ASDiskData::numTracks() const
|
||||
|
@ -119,8 +145,8 @@ QDataStream &ASDiskData::read(QDataStream &dataStream)
|
|||
dataStream >> m_fsname;
|
||||
m_metadata.clear();
|
||||
dataStream >> m_metadata;
|
||||
m_chunks.clear();
|
||||
dataStream >> m_chunks;
|
||||
m_chunk_data.clear();
|
||||
dataStream >> m_chunk_data;
|
||||
m_original_file_contents.clear();
|
||||
dataStream >> m_original_file_contents;
|
||||
}
|
||||
|
@ -147,7 +173,7 @@ QDataStream &ASDiskData::write(QDataStream &dataStream) const
|
|||
dataStream << m_fstype;
|
||||
dataStream << m_fsname;
|
||||
dataStream << m_metadata;
|
||||
dataStream << m_chunks;
|
||||
dataStream << m_chunk_data;
|
||||
dataStream << m_original_file_contents;
|
||||
|
||||
return dataStream;
|
||||
|
@ -159,9 +185,11 @@ void ASDiskData::setFSInfo(QString name, int fstypeval)
|
|||
m_fstype = fstypeval;
|
||||
}
|
||||
|
||||
int ASDiskData::tsToOffset(int track, int sector)
|
||||
int ASDiskData::tsToOffset(int track, int sector) const
|
||||
{
|
||||
return (track * m_numsectors) + sector;
|
||||
int val = (track * m_numsectors) + sector;
|
||||
//qDebug() << "TsToOffset: " << track << "," << sector << " = " << val;
|
||||
return val;
|
||||
}
|
||||
|
||||
QDataStream &operator<<(QDataStream &out, const ASDiskData &outObject)
|
||||
|
|
|
@ -20,32 +20,33 @@
|
|||
#define ASDISKDATA_H
|
||||
|
||||
#include <QString>
|
||||
#include <QMap>
|
||||
#include <QVector>
|
||||
#include <QVariant>
|
||||
#include <QDataStream>
|
||||
|
||||
class ASDiskData
|
||||
class ASDiskData : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
using AttributeMap = QMap<QString, QVariant>;
|
||||
using ChunkData = QByteArray;
|
||||
using DataMap = QMap<int,ChunkData>;
|
||||
|
||||
|
||||
public:
|
||||
using SectorData = QByteArray;
|
||||
using BlockData = QByteArray;
|
||||
// using SectorData = QByteArray;
|
||||
// using BlockData = QByteArray;
|
||||
|
||||
enum class DataFormat { Sectors, Blocks };
|
||||
|
||||
ASDiskData();
|
||||
ASDiskData(QObject *parent = nullptr);
|
||||
virtual ~ASDiskData();
|
||||
|
||||
QStringList attributeList() const { return m_metadata.keys(); }
|
||||
QVariant getAttribute(QString key) const;
|
||||
bool setAttribute(QString key, QVariant value);
|
||||
|
||||
void setUseSectors(int numSectors = 16, int numTracks = 35);
|
||||
void setUseSectors(int numTracks = 35, int numSectors = 16);
|
||||
void setUseBlocks(int numBlocks);
|
||||
void setDataFormat(DataFormat format) { m_dataformat = format; }
|
||||
|
||||
bool useSectors() const { return m_dataformat == DataFormat::Sectors; }
|
||||
bool useBlocks() const { return m_dataformat == DataFormat::Blocks; }
|
||||
|
@ -54,8 +55,8 @@ public:
|
|||
void addSector(int track, int sector, QByteArray sectordata);
|
||||
void addBlock(int number, QByteArray blockdata);
|
||||
|
||||
SectorData &getSector(int track, int sector);
|
||||
BlockData &getBlock(int blocknum);
|
||||
QByteArray getSector(int track, int sector) const;
|
||||
QByteArray getBlock(int blocknum) const;
|
||||
|
||||
int numTracks() const;
|
||||
int numSectorsPerTrack() const;
|
||||
|
@ -84,7 +85,7 @@ public:
|
|||
QDataStream &write(QDataStream &dataStream) const;
|
||||
|
||||
protected:
|
||||
int tsToOffset(int track, int sector);
|
||||
int tsToOffset(int track, int sector) const;
|
||||
|
||||
protected:
|
||||
QString m_filename { "[unknown]" };
|
||||
|
@ -102,9 +103,11 @@ protected:
|
|||
|
||||
AttributeMap m_metadata;
|
||||
|
||||
DataMap m_chunks;
|
||||
QByteArray m_chunk_data;
|
||||
|
||||
QByteArray m_original_file_contents;
|
||||
|
||||
QByteArray m_nulldata;
|
||||
};
|
||||
|
||||
QDataStream &operator<<(QDataStream &out, const ASDiskData &outData);
|
||||
|
|
|
@ -62,9 +62,11 @@ bool ASDiskImporter::importImage(QString filename, ASDiskData &into)
|
|||
int numsectors = image.GetNumSectPerTrack();\
|
||||
into.setNumSectorsPerTrack(numsectors);
|
||||
|
||||
|
||||
|
||||
if (image.ShowAsBlocks())
|
||||
{
|
||||
into.setDataFormat(ASDiskData::DataFormat::Blocks);
|
||||
into.setUseBlocks(numblocks);
|
||||
|
||||
char *buffer = new char[512]; // Todo: Remove magic number
|
||||
for (int idx = 0; idx < numblocks; idx++)
|
||||
|
@ -77,7 +79,7 @@ bool ASDiskImporter::importImage(QString filename, ASDiskData &into)
|
|||
}
|
||||
else
|
||||
{
|
||||
into.setDataFormat(ASDiskData::DataFormat::Sectors);
|
||||
into.setUseSectors(numtracks,numsectors);
|
||||
|
||||
char *buffer = new char[256]; // Todo: Remove magic number
|
||||
for (int track = 0; track < numtracks; track++)
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
#include "catalogsector.h"
|
||||
#include "sector.h"
|
||||
|
||||
CatalogSector::CatalogSector(Sector *data)
|
||||
CatalogSector::CatalogSector(QSharedPointer<const Sector> data)
|
||||
{
|
||||
m_data = data;
|
||||
|
||||
|
@ -42,13 +42,13 @@ CatalogSector::CatalogSector(Sector *data)
|
|||
{
|
||||
FileDescriptiveEntry fde = makeFDE(idx*0x23+0x0B);
|
||||
if (fde.firstTSListSector() != TSPair(0,0)) {
|
||||
// if (fde.firstTSListSector().isValid())
|
||||
if (fde.firstTSListSector().isValid())
|
||||
{
|
||||
m_fdes.append(fde);
|
||||
}
|
||||
// else qDebug() << "Not appending invalid TSPair.";
|
||||
else qDebug() << "Not appending invalid TSPair.";
|
||||
}
|
||||
// else { qWarning("fde.firstTSListSector() is 0,0"); }
|
||||
// else { qWarning("fde.firstTSListSector() is 0,0"); }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -33,11 +33,10 @@
|
|||
class Sector;
|
||||
|
||||
|
||||
|
||||
class CatalogSector
|
||||
{
|
||||
public:
|
||||
CatalogSector(Sector *sector);
|
||||
CatalogSector(QSharedPointer<const Sector> sector);
|
||||
|
||||
FileDescriptiveEntry getFDE(quint8 number) {
|
||||
if (m_fdes.length() == 0) { return FileDescriptiveEntry(); }
|
||||
|
@ -53,7 +52,7 @@ public:
|
|||
|
||||
void dumpFDEs();
|
||||
|
||||
Sector *getSector() const { return m_data; }
|
||||
QSharedPointer<const Sector> getSector() const { return m_data; }
|
||||
|
||||
FileDescriptiveEntry makeFDE(int offset);
|
||||
|
||||
|
@ -61,7 +60,7 @@ public:
|
|||
private:
|
||||
|
||||
private:
|
||||
Sector *m_data;
|
||||
QSharedPointer<const Sector> m_data;
|
||||
QList<FileDescriptiveEntry> m_fdes;
|
||||
TSPair m_next;
|
||||
};
|
||||
|
|
|
@ -35,120 +35,44 @@
|
|||
|
||||
Dos33DiskImage::Dos33DiskImage(QString filename)
|
||||
{
|
||||
m_disk_image = new RawDiskImage(filename);
|
||||
|
||||
m_disk_image = new ASDiskData();
|
||||
if (!filename.isEmpty())
|
||||
{
|
||||
read(filename);
|
||||
//TODO: Cross reference & dbl. check sec/track with VTOC
|
||||
}
|
||||
auto dummy_data = new SectorData;
|
||||
dummy_data->resize(256);
|
||||
m_dummy_sector.setData(dummy_data);
|
||||
}
|
||||
|
||||
Dos33DiskImage::Dos33DiskImage(RawDiskImage *rawImage)
|
||||
{
|
||||
m_disk_image = rawImage;
|
||||
//TODO: Cross reference & dbl. check sec/track with VTOC
|
||||
|
||||
}
|
||||
|
||||
Dos33DiskImage::~Dos33DiskImage()
|
||||
{
|
||||
// foreach (GenericFile *file, m_files)
|
||||
// {
|
||||
// delete file;
|
||||
// }
|
||||
delete m_disk_image;
|
||||
}
|
||||
|
||||
bool Dos33DiskImage::read(QString filename)
|
||||
{
|
||||
bool retval = m_disk_image->read(filename);
|
||||
ASDiskImporter importer;
|
||||
bool retval = importer.importImage(filename, *m_disk_image);
|
||||
|
||||
if (retval)
|
||||
{
|
||||
for (auto tracknum = 0; tracknum < m_disk_image->numTracks(); tracknum++)
|
||||
{
|
||||
for (auto secnum = 0; secnum < m_disk_image->sectorsPerTrack(); secnum++)
|
||||
{
|
||||
TSPair tmpts(tracknum,secnum);
|
||||
Sector newSec;
|
||||
SectorData * data = m_disk_image->sectorAt(tmpts);
|
||||
newSec.setData(data);
|
||||
newSec.setTrackSector(tmpts);
|
||||
m_contents[tmpts] = newSec;
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO: Cache sectors!!
|
||||
|
||||
return retval;
|
||||
|
||||
// m_fullImageName = filename;
|
||||
// m_imageName = QFileInfo(filename).fileName();
|
||||
// QFile infile(filename);
|
||||
// QCryptographicHash hash(QCryptographicHash::Md5);
|
||||
|
||||
// if (infile.open(QIODevice::ReadOnly))
|
||||
// {
|
||||
// QByteArray contents = infile.readAll();
|
||||
// int expectedsize = sectorsPerTrack() * tracks() * 256;
|
||||
// if (contents.size() != expectedsize)
|
||||
// {
|
||||
// if (contents.size() == 35*16*256) { m_sectors_per_track = 16; }
|
||||
// else if (contents.size() == 35*13*256) { m_sectors_per_track = 13; }
|
||||
// else qWarning() << QString("Size mismatch in file! Expected %1, got %2")
|
||||
// .arg(expectedsize)
|
||||
// .arg(contents.size());
|
||||
// }
|
||||
|
||||
// QDataStream qds(contents);
|
||||
// for (int track = 0; track < 35; track++)
|
||||
// {
|
||||
// for (int sector = 0; sector < m_sectors_per_track; sector++)
|
||||
// {
|
||||
// char buffer[256];
|
||||
// if (qds.readRawData(buffer,256) == 256)
|
||||
// {
|
||||
// TSPair tmpts(track,sector);
|
||||
// Sector newSec;
|
||||
// newSec.setTrackSector(tmpts);
|
||||
// newSec.setData(QByteArray(buffer,256));
|
||||
// m_contents[tmpts] = newSec;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// qDebug() << "Invalid sector read!";
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// hash.addData(contents);
|
||||
|
||||
// m_hash = hash.result();
|
||||
// // qDebug() << "Hash: " << m_hash;
|
||||
|
||||
// return true;
|
||||
// }
|
||||
// else
|
||||
// qDebug() << "Could not open file " << filename;
|
||||
// return false;
|
||||
}
|
||||
|
||||
Sector &Dos33DiskImage::getSector(TSPair ts) {
|
||||
if (m_contents.contains(ts))
|
||||
return m_contents[ts];
|
||||
else
|
||||
return m_dummy_sector;
|
||||
pSector Dos33DiskImage::getSector(TSPair ts) const {
|
||||
return getSector(ts.track(),ts.sector());
|
||||
}
|
||||
|
||||
Sector &Dos33DiskImage::getSector(int track, int sector) {
|
||||
return getSector(TSPair(track,sector));
|
||||
pSector Dos33DiskImage::getSector(int track, int sector) const {
|
||||
auto sectorData
|
||||
= m_disk_image->getSector(track,sector);
|
||||
qDebug() << "Dos33DiskImage::getSector("<<track<<","<<sector<<"); [SIZE = " << sectorData.size() << "]";
|
||||
auto val = QSharedPointer<Sector>(new Sector(sectorData, track, sector));
|
||||
val->dump();
|
||||
return val;
|
||||
}
|
||||
|
||||
VTOC Dos33DiskImage::getVTOC()
|
||||
VTOC Dos33DiskImage::getVTOC() const
|
||||
{
|
||||
return getSector(17,0).promoteToVTOC();
|
||||
return getSector(17,0)->promoteToVTOC();
|
||||
}
|
||||
|
||||
QList<CatalogSector> Dos33DiskImage::getCatalogSectors()
|
||||
|
@ -156,12 +80,15 @@ QList<CatalogSector> Dos33DiskImage::getCatalogSectors()
|
|||
QList<CatalogSector> retval;
|
||||
VTOC vtoc = getVTOC();
|
||||
TSPair ts = vtoc.firstCatalogSector();
|
||||
qDebug() << "First TSPair for catalogsectors is " << ts.track() << "," << ts.sector();
|
||||
|
||||
CatalogSector cs = getSector(ts).asCatalogSector();
|
||||
CatalogSector cs = getSector(ts)->asCatalogSector();
|
||||
retval.append(cs);
|
||||
while (cs.nextCatalogSector() != TSPair(0,0)) {
|
||||
ts = cs.nextCatalogSector();
|
||||
cs = getSector(ts).asCatalogSector();
|
||||
qDebug() << "Next TSPair for catalogsectors is " << ts.track() << "," << ts.sector();
|
||||
|
||||
cs = getSector(ts)->asCatalogSector();
|
||||
retval.append(cs);
|
||||
}
|
||||
|
||||
|
@ -183,7 +110,7 @@ GenericFile *Dos33DiskImage::getFile(FileDescriptiveEntry fde)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
TrackSectorList tsl = getSector(fde.firstTSListSector()).asTrackSectorList();
|
||||
TrackSectorList tsl = getSector(fde.firstTSListSector())->asTrackSectorList();
|
||||
if (!fde.firstTSListSector().isValid())
|
||||
{
|
||||
qWarning(" Not returning a file from invalid TSList!");
|
||||
|
@ -224,17 +151,17 @@ GenericFile *Dos33DiskImage::getFile(FileDescriptiveEntry fde)
|
|||
}
|
||||
|
||||
|
||||
ChunkByteList Dos33DiskImage::getDataFromTrackSectorList(TrackSectorList tsl)
|
||||
QByteArray Dos33DiskImage::getDataFromTrackSectorList(TrackSectorList tsl)
|
||||
{
|
||||
ChunkByteList retval;
|
||||
QByteArray retval;
|
||||
|
||||
|
||||
foreach(TSPair pair, tsl.getDataTSPairs())
|
||||
{
|
||||
if (pair.isValid())
|
||||
{
|
||||
Sector sec = getSector(pair);
|
||||
retval.appendChunk(sec.rawData());
|
||||
pSector sec = getSector(pair);
|
||||
retval.append(sec->rawData());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -244,22 +171,22 @@ ChunkByteList Dos33DiskImage::getDataFromTrackSectorList(TrackSectorList tsl)
|
|||
|
||||
auto next = tsl.getNextTSList();
|
||||
if (next.isValid() && next != TSPair(0,0)) {
|
||||
TrackSectorList nextTsl = getSector(tsl.getNextTSList()).asTrackSectorList();
|
||||
retval.appendChunkList(getDataFromTrackSectorList(nextTsl));
|
||||
TrackSectorList nextTsl = getSector(tsl.getNextTSList())->asTrackSectorList();
|
||||
retval.append(getDataFromTrackSectorList(nextTsl));
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
ChunkByteList Dos33DiskImage::getDataFromTSPairList(TSPairList list)
|
||||
QByteArray Dos33DiskImage::getDataFromTSPairList(TSPairList list)
|
||||
{
|
||||
ChunkByteList retval;
|
||||
QByteArray retval;
|
||||
foreach(TSPair pair, list)
|
||||
{
|
||||
if (pair.isValid())
|
||||
{
|
||||
Sector sec = getSector(pair);
|
||||
retval.appendChunk(sec.rawData());
|
||||
pSector sec = getSector(pair);
|
||||
retval.append(sec->rawData());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -32,9 +32,11 @@
|
|||
#include "vtoc.h"
|
||||
#include "tracksectorlist.h"
|
||||
|
||||
#include "rawdiskimage.h"
|
||||
#include "chunkbytelist.h"
|
||||
|
||||
#include "asdiskimporter.h"
|
||||
#include "asdiskdata.h"
|
||||
|
||||
|
||||
class GenericFile;
|
||||
|
||||
|
@ -44,48 +46,43 @@ class Dos33DiskImage
|
|||
{
|
||||
public:
|
||||
Dos33DiskImage(QString filename = "");
|
||||
Dos33DiskImage(RawDiskImage *rawImage);
|
||||
~Dos33DiskImage();
|
||||
|
||||
bool read(QString filename);
|
||||
|
||||
Sector &getSector(TSPair ts);
|
||||
Sector &getSector(int track, int sector);
|
||||
pSector getSector(TSPair ts) const;
|
||||
pSector getSector(int track, int sector) const;
|
||||
|
||||
VTOC getVTOC();
|
||||
VTOC getVTOC() const;
|
||||
|
||||
QList<CatalogSector> getCatalogSectors();
|
||||
|
||||
GenericFile *getFile(FileDescriptiveEntry fde);
|
||||
|
||||
ChunkByteList getDataFromTrackSectorList(TrackSectorList tsl);
|
||||
ChunkByteList getDataFromTSPairList(TSPairList list);
|
||||
QByteArray getDataFromTrackSectorList(TrackSectorList tsl);
|
||||
QByteArray getDataFromTSPairList(TSPairList list);
|
||||
|
||||
QList<FileDescriptiveEntry> getAllFDEs();
|
||||
|
||||
QByteArray fileHash() const { return m_hash; }
|
||||
|
||||
QString getDiskImageName() const { return m_disk_image->diskImageName(); }
|
||||
QString getFullDiskImageName() const { return m_disk_image->fullDiskImageName(); }
|
||||
QString getDiskImageName() const { return m_disk_image->filename(); }
|
||||
QString getFullDiskImageName() const { return m_disk_image->/*fullDiskImageName*/filename(); }
|
||||
QString getMetaDataPath() const;
|
||||
RawDiskImage *rawImage() const { return m_disk_image; }
|
||||
ASDiskData *rawImage() const { return m_disk_image; }
|
||||
|
||||
int sectorsPerTrack() const { return m_disk_image->sectorsPerTrack(); }
|
||||
int sectorsPerTrack() const { return m_disk_image->numSectorsPerTrack(); }
|
||||
int tracks() const { return m_disk_image->numTracks(); }
|
||||
|
||||
QList<GenericFile *> fileList();
|
||||
|
||||
private:
|
||||
|
||||
RawDiskImage *m_disk_image;
|
||||
ASDiskData *m_disk_image;
|
||||
|
||||
QMap<TSPair, Sector> m_contents;
|
||||
QMap<FileDescriptiveEntry, GenericFile *> m_files;
|
||||
QByteArray m_hash;
|
||||
|
||||
Sector m_dummy_sector; // Returned for non-existant sectors on disk
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif // DOS33DISKIMAGE_H
|
||||
|
|
|
@ -34,7 +34,6 @@ public:
|
|||
|
||||
protected:
|
||||
|
||||
|
||||
signals:
|
||||
void fileClicked(const FileDescriptiveEntry &fde);
|
||||
void fileRightClicked(const FileDescriptiveEntry &fde);
|
||||
|
@ -45,14 +44,11 @@ signals:
|
|||
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
|
||||
|
|
|
@ -19,8 +19,6 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
#include "dos33treeitem.h"
|
||||
#include "dos33diskimage.h"
|
||||
|
||||
|
@ -42,7 +40,6 @@ enum class Dos33ItemType {
|
|||
DiskImage
|
||||
};
|
||||
|
||||
|
||||
class Dos33ImageModel : public QStandardItemModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
@ -57,8 +54,6 @@ public:
|
|||
Dos33DiskImage *getDiskImage(QString name);
|
||||
Dos33DiskImage *removeDiskImage(QString name);
|
||||
|
||||
|
||||
|
||||
private:
|
||||
QIcon m_icon_A;
|
||||
QIcon m_icon_a;
|
||||
|
|
|
@ -19,8 +19,6 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
#include <QStandardItem>
|
||||
|
||||
class Dos33TreeItem : public QStandardItem
|
||||
|
|
|
@ -51,7 +51,7 @@ QByteArray GenericFile::data()
|
|||
{
|
||||
if (m_data_cache.size() == 0)
|
||||
{
|
||||
m_data_cache = rawData().asQByteArray();
|
||||
m_data_cache = rawData();
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -72,7 +72,7 @@ void GenericFile::resetToDefaultData()
|
|||
}
|
||||
|
||||
|
||||
ChunkByteList &GenericFile::rawData()
|
||||
QByteArray GenericFile::rawData()
|
||||
{
|
||||
if (!m_data_loaded)
|
||||
{
|
||||
|
@ -87,20 +87,13 @@ void GenericFile::updateFromFDE(FileDescriptiveEntry &fde)
|
|||
setLength(fde.lengthInSectors * m_diskfile->rawImage()->sectorSize());
|
||||
}
|
||||
|
||||
SectorData *GenericFile::peekFirstSector() const
|
||||
QByteArray GenericFile::peekFirstSector() const
|
||||
{
|
||||
SectorData *retval = nullptr;
|
||||
auto tsl = m_diskfile->getSector(m_fde.firstTSListSector())->asTrackSectorList();
|
||||
TSPairList pairs = tsl.getValidTSPairs();
|
||||
|
||||
return m_diskfile->getSector(pairs.first())->rawData();
|
||||
|
||||
if (m_diskfile)
|
||||
{
|
||||
auto tsl = m_diskfile->getSector(m_fde.firstTSListSector()).asTrackSectorList();
|
||||
TSPairList pairs = tsl.getValidTSPairs();
|
||||
if (pairs.size())
|
||||
{
|
||||
retval = m_diskfile->getSector(pairs.first()).rawData();
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
void GenericFile::initDataFromImage()
|
||||
|
@ -109,7 +102,7 @@ void GenericFile::initDataFromImage()
|
|||
{
|
||||
if (m_diskfile)
|
||||
{
|
||||
auto tsl = m_diskfile->getSector(m_fde.firstTSListSector()).asTrackSectorList();
|
||||
auto tsl = m_diskfile->getSector(m_fde.firstTSListSector())->asTrackSectorList();
|
||||
TSPairList pairs = tsl.getValidTSPairs();
|
||||
m_data_loaded = true;
|
||||
m_data = m_diskfile->getDataFromTSPairList(pairs);
|
||||
|
|
|
@ -55,7 +55,7 @@ public:
|
|||
|
||||
virtual quint8 rawDataAt(int offset) ;
|
||||
virtual quint16 rawDataWordAt(int offset);
|
||||
virtual ChunkByteList &rawData();
|
||||
virtual QByteArray rawData();
|
||||
|
||||
|
||||
[[deprecated("Only used for legacy purposes")]]
|
||||
|
@ -93,7 +93,7 @@ public:
|
|||
void initDataFromImage();
|
||||
|
||||
protected:
|
||||
SectorData *peekFirstSector() const;
|
||||
QByteArray peekFirstSector() const;
|
||||
|
||||
private:
|
||||
Dos33DiskImage * m_diskfile;
|
||||
|
@ -106,7 +106,7 @@ private:
|
|||
bool m_locked;
|
||||
|
||||
QString m_filename;
|
||||
ChunkByteList m_data;
|
||||
QByteArray m_data;
|
||||
|
||||
bool m_data_loaded;
|
||||
|
||||
|
|
|
@ -21,18 +21,19 @@
|
|||
#include <QString>
|
||||
#include <QDebug>
|
||||
|
||||
quint8 Sector::operator[](uint offset) const {
|
||||
if (offset > 255) {
|
||||
offset = 255;
|
||||
}
|
||||
if ((int) offset >= m_raw_data->size()) return 0;
|
||||
//quint8 Sector::operator[](uint offset) const {
|
||||
// if (offset > 255) {
|
||||
// offset = 255;
|
||||
// }
|
||||
// if ((int) offset >= m_raw_data.size()) return 0;
|
||||
|
||||
return m_raw_data->at(offset);
|
||||
}
|
||||
// return m_raw_data.at(offset);
|
||||
//}
|
||||
|
||||
|
||||
void Sector::dump() {
|
||||
void Sector::dump() const {
|
||||
qDebug() << "Dumping Track " << track() << "Sector " << sector() << " ...";
|
||||
qDebug() << " RawData size: " << m_raw_data.size();
|
||||
for (int jdx = 0; jdx < 16; jdx++)
|
||||
{
|
||||
QString line;
|
||||
|
@ -41,8 +42,8 @@ void Sector::dump() {
|
|||
for (int idx = 0; idx < 16; idx++)
|
||||
{
|
||||
int offset = (jdx*16) + idx;
|
||||
quint8 val = m_raw_data->at(offset);
|
||||
line += QString("%1 ").arg(uint16ToHex(val));
|
||||
quint8 val = m_raw_data.at(offset);
|
||||
line += QString("%1 ").arg(uint8ToHex(val));
|
||||
if (idx == 7) line += " ";
|
||||
}
|
||||
line = line.toUpper();
|
||||
|
@ -50,7 +51,7 @@ void Sector::dump() {
|
|||
for (int idx = 0; idx < 16; idx++)
|
||||
{
|
||||
int offset = (jdx*16) + idx;
|
||||
quint8 val = m_raw_data->at(offset);
|
||||
quint8 val = m_raw_data.at(offset);
|
||||
if (val > 127) { val -= 128; }
|
||||
QChar ch(val);
|
||||
line += QString("%1").arg(ch.isPrint()?ch:'.');
|
||||
|
|
|
@ -1,14 +1,3 @@
|
|||
#ifndef SECTOR_H
|
||||
#define SECTOR_H
|
||||
|
||||
#include <QByteArray>
|
||||
|
||||
#include "rawdiskimage.h"
|
||||
|
||||
#include "vtoc.h"
|
||||
#include "catalogsector.h"
|
||||
#include "tracksectorlist.h"
|
||||
|
||||
/*****************************************************************************
|
||||
* AppleSAWS - The Apple Software Analysis WorkShop *
|
||||
* Copyright (C) 2015-2021 Mark D. Long *
|
||||
|
@ -27,68 +16,78 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef SECTOR_H
|
||||
#define SECTOR_H
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QSharedPointer>
|
||||
//#include "rawdiskimage.h"
|
||||
|
||||
class Sector
|
||||
#include "vtoc.h"
|
||||
#include "catalogsector.h"
|
||||
#include "tracksectorlist.h"
|
||||
|
||||
#include "asdiskdata.h"
|
||||
|
||||
class Sector;
|
||||
|
||||
using pSector = QSharedPointer<Sector>;
|
||||
|
||||
class Sector : public QEnableSharedFromThis<Sector>
|
||||
{
|
||||
public:
|
||||
|
||||
Sector(SectorData *data = nullptr) {
|
||||
setData(data);
|
||||
m_track = 255;
|
||||
m_sector = 255;
|
||||
}
|
||||
|
||||
void setData(SectorData *data)
|
||||
Sector(QByteArray &data, int track, int sector )
|
||||
{
|
||||
m_raw_data = data;
|
||||
qDebug() << "Sector ctor: Datasize: " << data.size() << " t/s: " << track << "," << sector;
|
||||
m_track = track;
|
||||
m_sector = sector;
|
||||
m_raw_data = data;
|
||||
m_raw_data.append(12);
|
||||
m_raw_data.chop(1);
|
||||
if (m_raw_data.size() != 256)
|
||||
{
|
||||
qWarning() << "Setting sector with invalid sized data! [Size = " << data.size() << "]";
|
||||
}
|
||||
}
|
||||
|
||||
VTOC promoteToVTOC() {
|
||||
return VTOC(this);
|
||||
~Sector() { qDebug() << "Sector dtor for " << m_track << "," << m_sector; }
|
||||
|
||||
VTOC promoteToVTOC() const {
|
||||
return VTOC(sharedFromThis());
|
||||
}
|
||||
|
||||
CatalogSector asCatalogSector() {
|
||||
return CatalogSector(this);
|
||||
CatalogSector asCatalogSector() const {
|
||||
return CatalogSector(sharedFromThis());
|
||||
}
|
||||
|
||||
TrackSectorList asTrackSectorList() {
|
||||
return TrackSectorList(this);
|
||||
TrackSectorList asTrackSectorList() const {
|
||||
return TrackSectorList(sharedFromThis());
|
||||
}
|
||||
|
||||
int sector() { return m_sector; }
|
||||
int track() { return m_track; }
|
||||
int sector() const { return m_sector; }
|
||||
int track() const { return m_track; }
|
||||
|
||||
void setTrackSector(int track, int sector) {
|
||||
setTrack(track);
|
||||
setSector(sector);
|
||||
quint8 at(int offset) const {
|
||||
if (offset >= m_raw_data.size()) {
|
||||
|
||||
qWarning() << "sector::at() offset = " << offset
|
||||
<< ". m_raw_data.size() == " << m_raw_data.size();
|
||||
}
|
||||
|
||||
return m_raw_data.at(offset);
|
||||
}
|
||||
|
||||
void setTrackSector(TSPair ts)
|
||||
{
|
||||
setTrackSector(ts.track(),ts.sector());
|
||||
}
|
||||
void dump() const;
|
||||
|
||||
void setTrack(int track) { m_track = track; }
|
||||
void setSector(int sector) { m_sector = sector; }
|
||||
|
||||
quint8 operator[](uint offset) const;
|
||||
quint8 at(int offset) {
|
||||
if (offset >= m_raw_data->size()) return 0;
|
||||
|
||||
return m_raw_data->at(offset);
|
||||
}
|
||||
|
||||
void dump();
|
||||
|
||||
SectorData *rawData() { return m_raw_data; }
|
||||
QByteArray rawData() { return m_raw_data; }
|
||||
|
||||
private:
|
||||
// QByteArray m_data;
|
||||
int m_track;
|
||||
int m_sector;
|
||||
|
||||
SectorData *m_raw_data;
|
||||
QByteArray m_raw_data;
|
||||
};
|
||||
|
||||
|
||||
#endif // SECTOR_H
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
#include "sector.h"
|
||||
|
||||
TrackSectorList::TrackSectorList(Sector *data)
|
||||
TrackSectorList::TrackSectorList(QSharedPointer<const Sector> data)
|
||||
{
|
||||
m_data = data;
|
||||
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
|
||||
#include "tspair.h"
|
||||
|
||||
#include <QSharedPointer>
|
||||
|
||||
class Sector;
|
||||
|
||||
using TSPairList = QList<TSPair>;
|
||||
|
@ -30,7 +32,7 @@ using TSPairList = QList<TSPair>;
|
|||
class TrackSectorList
|
||||
{
|
||||
public:
|
||||
TrackSectorList(Sector *data);
|
||||
TrackSectorList(QSharedPointer<const Sector> data);
|
||||
|
||||
TSPair getNextTSList() const { return m_next_tslist; }
|
||||
bool isNextTSListValid() const;
|
||||
|
@ -47,7 +49,7 @@ private:
|
|||
TSPair m_sector_offset;
|
||||
TSPairList m_ts_pairs_for_data;
|
||||
|
||||
Sector *m_data;
|
||||
QSharedPointer<const Sector> m_data;
|
||||
};
|
||||
|
||||
#endif // TRACKSECTORLIST_H
|
||||
|
|
|
@ -24,35 +24,54 @@
|
|||
#include "sector.h"
|
||||
#include "util.h"
|
||||
|
||||
VTOC::VTOC(Sector *data)
|
||||
VTOC::VTOC(QSharedPointer<const Sector> data)
|
||||
{
|
||||
m_data = data;
|
||||
m_first_catalog_sector = TSPair(m_data->at(0x01), m_data->at(0x02));
|
||||
m_dos_version = m_data->at(0x03);
|
||||
m_volnum = m_data->at(0x06);
|
||||
m_max_ts_pairs = m_data->at(0x27);
|
||||
m_last_track_alloc = m_data->at(0x30);
|
||||
m_dir_of_alloc= m_data->at(0x31);
|
||||
m_tracks_per_disk = m_data->at(0x34);
|
||||
m_sec_per_track = m_data->at(0x35);
|
||||
m_byte_per_sec = makeWord(m_data->at(0x36),
|
||||
m_data->at(0x37));
|
||||
|
||||
}
|
||||
|
||||
TSPair VTOC::firstCatalogSector() {
|
||||
TSPair VTOC::firstCatalogSector() const {
|
||||
|
||||
|
||||
// return TSPair(0x11,0x0f); // Force to look at the normal location
|
||||
|
||||
return TSPair(m_data->at(0x01), m_data->at(0x02));
|
||||
// return TSPair(m_data->at(0x01), m_data->at(0x02));
|
||||
return m_first_catalog_sector;
|
||||
}
|
||||
|
||||
quint8 VTOC::dosVersion() {
|
||||
return m_data->at(0x03);
|
||||
return m_dos_version;
|
||||
//return m_data->at(0x03);
|
||||
}
|
||||
|
||||
quint8 VTOC::volumeNumber() {
|
||||
return m_data->at(0x06);
|
||||
return m_volnum;
|
||||
//return m_data->at(0x06);
|
||||
}
|
||||
|
||||
quint8 VTOC::maxTSPairs() {
|
||||
return m_data->at(0x27);
|
||||
//return m_data->at(0x27);
|
||||
return m_max_ts_pairs;
|
||||
}
|
||||
|
||||
quint8 VTOC::lastTrackAllocated() {
|
||||
return m_data->at(0x30);
|
||||
return m_last_track_alloc;
|
||||
//return m_data->at(0x30);
|
||||
}
|
||||
|
||||
qint8 VTOC::directionOfAllocation() {
|
||||
return m_data->at(0x31);
|
||||
return m_dir_of_alloc;
|
||||
//return m_data->at(0x31);
|
||||
}
|
||||
|
||||
quint8 VTOC::tracksPerDisk() {
|
||||
|
@ -60,12 +79,14 @@ quint8 VTOC::tracksPerDisk() {
|
|||
}
|
||||
|
||||
quint8 VTOC::sectorsPerTrack() {
|
||||
return m_data->at(0x35);
|
||||
return m_sec_per_track;
|
||||
//return m_data->at(0x35);
|
||||
}
|
||||
|
||||
qint16 VTOC::bytesPerSector() {
|
||||
return makeWord(m_data->at(0x36),
|
||||
m_data->at(0x37));
|
||||
return m_byte_per_sec;
|
||||
// return makeWord(m_data->at(0x36),
|
||||
// m_data->at(0x37));
|
||||
}
|
||||
|
||||
bool VTOC::isSectorInUse(TSPair ts) const {
|
||||
|
|
|
@ -26,15 +26,18 @@
|
|||
#include "tspair.h"
|
||||
|
||||
class Sector;
|
||||
|
||||
|
||||
|
||||
class QString;
|
||||
|
||||
class VTOC
|
||||
{
|
||||
public:
|
||||
VTOC(Sector *data);
|
||||
VTOC(QSharedPointer<const Sector> data);
|
||||
|
||||
void dump();
|
||||
TSPair firstCatalogSector();
|
||||
TSPair firstCatalogSector() const;
|
||||
quint8 dosVersion();
|
||||
quint8 volumeNumber();
|
||||
quint8 maxTSPairs();
|
||||
|
@ -53,7 +56,18 @@ public:
|
|||
private:
|
||||
QString buildUseString(quint8 track);
|
||||
|
||||
Sector *m_data;
|
||||
QSharedPointer<const Sector> m_data;
|
||||
|
||||
TSPair m_first_catalog_sector;
|
||||
quint8 m_dos_version;
|
||||
quint8 m_volnum;
|
||||
quint8 m_max_ts_pairs;
|
||||
quint8 m_last_track_alloc;
|
||||
qint8 m_dir_of_alloc;
|
||||
quint8 m_tracks_per_disk;
|
||||
quint8 m_sec_per_track;
|
||||
quint16 m_byte_per_sec;
|
||||
|
||||
};
|
||||
|
||||
#endif // VTOC_H
|
||||
|
|
|
@ -1,214 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* AppleSAWS - The Apple Software Analysis WorkShop *
|
||||
* Copyright (C) 2015-2021 Mark D. Long *
|
||||
* *
|
||||
* This program is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||
*****************************************************************************/
|
||||
|
||||
#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;
|
||||
}
|
|
@ -1,123 +0,0 @@
|
|||
#ifndef RAWDISKIMAGE_H
|
||||
#define RAWDISKIMAGE_H
|
||||
|
||||
/*****************************************************************************
|
||||
* AppleSAWS - The Apple Software Analysis WorkShop *
|
||||
* Copyright (C) 2015-2021 Mark D. Long *
|
||||
* *
|
||||
* This program is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
#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
|
|
@ -31,6 +31,7 @@ public:
|
|||
TSPair(int trackval, int secval) { m_track=trackval; m_sector = secval; }
|
||||
TSPair(QPair<int,int> pair) { m_track = pair.first; m_sector = pair.second;}
|
||||
|
||||
|
||||
void setTrack(int tracknum)
|
||||
{
|
||||
if (tracknum > 34 && tracknum != 0xff) {
|
||||
|
|
|
@ -34,7 +34,7 @@ QByteArray IntBasicFile::detokenize()
|
|||
// uint = unsigned int
|
||||
// quint8 = unsigned char
|
||||
// ==========================================================================
|
||||
return dumpBufferAsIntBasicFile(rawData().asQByteArray());
|
||||
return dumpBufferAsIntBasicFile(rawData());
|
||||
}
|
||||
|
||||
|
||||
|
@ -152,9 +152,10 @@ QByteArray IntBasicFile::dumpBufferAsIntBasicFile(QByteArray origdata)
|
|||
|
||||
QByteArray retval;
|
||||
|
||||
QVector<quint8> data;
|
||||
QList<quint8> data;
|
||||
QByteArray data0 = origdata;
|
||||
|
||||
if (origdata.size() == 0) return retval;
|
||||
|
||||
foreach (quint8 value, origdata)
|
||||
{
|
||||
|
|
15
src/main.cpp
15
src/main.cpp
|
@ -29,8 +29,23 @@
|
|||
#include "applesoftfile.h"
|
||||
#include "startupdialog.h"
|
||||
|
||||
//#include <QByteArray>
|
||||
//#include "sector.h"
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
// QByteArray ba(256,0xff);
|
||||
// Sector s(ba,1,2);
|
||||
// s.dump();
|
||||
// Sector t(s);
|
||||
// t.dump();
|
||||
|
||||
//qDebug () << "S at 1: " << s.at(1);
|
||||
//qDebug () << "T at 1: " << s.at(1);
|
||||
//qDebug () << "S at 2: " << s.at(2);
|
||||
//qDebug () << "T at 2: " << s.at(2);
|
||||
// return 0;
|
||||
|
||||
QApplication a(argc, argv);
|
||||
|
||||
QCoreApplication::setOrganizationName("LydianScaleSoftware");
|
||||
|
|
|
@ -31,16 +31,17 @@ INCLUDEPATH += ./memory
|
|||
INCLUDEPATH += ./memory/roles
|
||||
INCLUDEPATH += ./sequence
|
||||
INCLUDEPATH += ./ui/central
|
||||
INCLUDEPATH += ./diskfiles/diskstore
|
||||
|
||||
INCLUDEPATH += ../ads/src/
|
||||
|
||||
INCLUDEPATH += ../cpress/ciderpress/diskimg/
|
||||
|
||||
|
||||
DEFINES += WS_VIDEO
|
||||
|
||||
SOURCES += \
|
||||
./diskfiles/dos33/dos33disktreeview.cpp \
|
||||
./diskfiles/rawdiskimage.cpp \
|
||||
./intbasic/IntBasicFile.cxx \
|
||||
./main.cpp \
|
||||
./diskfiles/dos33/dos33diskimage.cxx \
|
||||
|
@ -132,7 +133,6 @@ HEADERS += \
|
|||
./diskfiles/tspair.h \
|
||||
./diskfiles/dos33/dos33imagemodel.h\
|
||||
./diskfiles/dos33/dos33treeitem.h\
|
||||
./diskfiles/rawdiskimage.h \
|
||||
./intbasic/IntBasicFile.h \
|
||||
./memory/attributedmemory.h \
|
||||
./memory/memorycell.h \
|
||||
|
@ -205,7 +205,8 @@ HEADERS += \
|
|||
diskfiles/cpressfile.h \
|
||||
diskfiles/diskstore/asdiskdata.h \
|
||||
diskfiles/diskstore/asdiskimporter.h \
|
||||
diskfiles/diskstore/asdiskstore.h
|
||||
diskfiles/diskstore/asdiskstore.h \
|
||||
util/referencelist.h
|
||||
|
||||
FORMS += \
|
||||
./sequence/sequenceviewer.ui \
|
||||
|
|
|
@ -230,7 +230,7 @@ void DiskExplorer::handleShowSectorData(QByteArray /*data*/, int track, int sect
|
|||
}
|
||||
}
|
||||
auto sec = m_disk->getSector(track,sector);
|
||||
m_vws->setSector(&sec, viewer);
|
||||
m_vws->setSector(sec, viewer);
|
||||
}
|
||||
|
||||
void DiskExplorer::showLoadDialog(bool parentToThis)
|
||||
|
|
|
@ -170,10 +170,10 @@ void DiskExplorerMapWidget::handleButtonCheck(int track, int sector, bool checke
|
|||
|
||||
if (checked)
|
||||
{
|
||||
Sector sec = m_disk->getSector(track,sector);
|
||||
QByteArray *data = sec.rawData();
|
||||
emit showSectorData(*data,track,sector,QVariant((int) m_roles[TSPair(track,sector)]));
|
||||
emit showSector(&sec,track,sector,m_roles[TSPair(track,sector)]);
|
||||
pSector sec = m_disk->getSector(track,sector);
|
||||
const QByteArray data = sec->rawData();
|
||||
emit showSectorData(data,track,sector,QVariant((int) m_roles[TSPair(track,sector)]));
|
||||
emit showSector(sec,track,sector,m_roles[TSPair(track,sector)]);
|
||||
|
||||
m_trackSectorLabel->setText(
|
||||
QString("Track: %1 Sector: %2 (%3)")
|
||||
|
@ -338,6 +338,8 @@ void DiskExplorerMapWidget::defineRoles(TSPair vtoc)
|
|||
m_numbers.clear();
|
||||
m_roles.clear();
|
||||
|
||||
qDebug() << "in defineRoles with vtoc at : " << vtoc.track() << "," << vtoc.sector();
|
||||
|
||||
int buttonNumber = 0;
|
||||
|
||||
for (auto track = 0; track < m_numtracks; track++)
|
||||
|
@ -380,14 +382,19 @@ void DiskExplorerMapWidget::defineRoles(TSPair vtoc)
|
|||
void DiskExplorerMapWidget::mapCatalogSectors(int &buttonNumber)
|
||||
{
|
||||
int catSectorCount = 0;
|
||||
foreach (CatalogSector cs, m_disk->getCatalogSectors())
|
||||
foreach (auto cs, m_disk->getCatalogSectors())
|
||||
{
|
||||
TSPair ts(cs.sectorLocation());
|
||||
qDebug() << "Processing buttons for catalog sectors";
|
||||
TSPair ts = cs.sectorLocation();
|
||||
qDebug() << "Sector location: " << ts.track() << "," << ts.sector();
|
||||
if (setButtonRole(ts,DiskSectorRole::CatalogSector))
|
||||
{
|
||||
QString desc = QString("Catalog Sector #%1").arg(++catSectorCount);
|
||||
qDebug() << "Desc: " << desc;
|
||||
setDescription(ts,desc);
|
||||
setButtonNumber(ts,buttonNumber++);
|
||||
// qDebug() << "Setting button number " << buttonNumber-1
|
||||
// << " at " << ts.track() << "," << ts.sector();
|
||||
|
||||
int fdeNum = 0;
|
||||
foreach (FileDescriptiveEntry fde, cs.getFDEs())
|
||||
|
@ -444,7 +451,7 @@ void DiskExplorerMapWidget::mapTSListSector(TSPair location,
|
|||
return;
|
||||
}
|
||||
|
||||
Sector *s = &(m_disk->getSector(location));
|
||||
pSector s = m_disk->getSector(location);
|
||||
TrackSectorList tsl(s);
|
||||
|
||||
if (setButtonRole(location,DiskSectorRole::TSList))
|
||||
|
@ -608,7 +615,7 @@ void DiskExplorerMapWidget::mapButtonsFromRoles()
|
|||
|
||||
void DiskExplorerMapWidget::checkForUsedButUnknown(TSPair vtoc)
|
||||
{
|
||||
auto vtocsector = m_disk->getSector(vtoc).promoteToVTOC();
|
||||
auto vtocsector = m_disk->getSector(vtoc)->promoteToVTOC();
|
||||
|
||||
for (auto track = 0; track < m_numtracks; track++)
|
||||
{
|
||||
|
|
|
@ -180,7 +180,7 @@ public:
|
|||
|
||||
signals:
|
||||
void showSectorData(QByteArray data, int track, int sector, QVariant metadata);
|
||||
void showSector(Sector *sec, int track, int sector, DiskSectorRole role);
|
||||
void showSector(pSector sec, int track, int sector, DiskSectorRole role);
|
||||
|
||||
public slots:
|
||||
void handleButtonCheck(int track, int sector, bool checked);
|
||||
|
|
|
@ -48,7 +48,7 @@ CatalogSectorView::~CatalogSectorView()
|
|||
delete ui;
|
||||
}
|
||||
|
||||
void CatalogSectorView::setSector(Sector *sec)
|
||||
void CatalogSectorView::setSector(QSharedPointer<Sector>sec)
|
||||
{
|
||||
|
||||
m_sector = sec;
|
||||
|
|
|
@ -37,12 +37,12 @@ public:
|
|||
explicit CatalogSectorView(QWidget *parent = nullptr);
|
||||
~CatalogSectorView();
|
||||
|
||||
void setSector(Sector *sec);
|
||||
void setSector(QSharedPointer<Sector> sec);
|
||||
|
||||
private:
|
||||
Ui::CatalogSectorView *ui;
|
||||
|
||||
Sector *m_sector;
|
||||
QSharedPointer<Sector> m_sector;
|
||||
};
|
||||
|
||||
#endif // CATALOGSECTORVIEW_H
|
||||
|
|
|
@ -24,7 +24,7 @@ TSListView::TSListView(QWidget *parent) : QTextBrowser(parent)
|
|||
|
||||
}
|
||||
|
||||
void TSListView::setSector(Sector *sec)
|
||||
void TSListView::setSector(pSector sec)
|
||||
{
|
||||
m_sector = sec;
|
||||
if (sec)
|
||||
|
|
|
@ -31,12 +31,12 @@ class TSListView : public QTextBrowser
|
|||
public:
|
||||
explicit TSListView(QWidget *parent = nullptr);
|
||||
|
||||
void setSector(Sector *sec);
|
||||
void setSector(QSharedPointer<Sector> sec);
|
||||
|
||||
signals:
|
||||
|
||||
private:
|
||||
Sector *m_sector;
|
||||
QSharedPointer<Sector> m_sector;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -29,11 +29,11 @@ ViewWidgetStack::ViewWidgetStack(QWidget *parent) : QTabWidget(parent)
|
|||
setSector(nullptr);
|
||||
}
|
||||
|
||||
void ViewWidgetStack::setSector(Sector *sec, PreferredViewer viewer)
|
||||
void ViewWidgetStack::setSector(QSharedPointer<Sector> sec, PreferredViewer viewer)
|
||||
{
|
||||
if (sec)
|
||||
{
|
||||
m_hdv->setRawData(*(sec->rawData()));
|
||||
m_hdv->setRawData(sec->rawData());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -79,7 +79,7 @@ void ViewWidgetStack::makeWidgets()
|
|||
setCurrentWidget(m_hdv);
|
||||
}
|
||||
|
||||
void ViewWidgetStack::handleShowSectorData(Sector *data, int /*track*/,
|
||||
void ViewWidgetStack::handleShowSectorData(pSector data, int /*track*/,
|
||||
int /*sector*/, DiskSectorRole role)
|
||||
{
|
||||
ViewWidgetStack::PreferredViewer viewer =
|
||||
|
|
|
@ -47,9 +47,9 @@ public:
|
|||
explicit ViewWidgetStack(QWidget *parent = nullptr);
|
||||
|
||||
public slots:
|
||||
void setSector(Sector *sec, PreferredViewer viewer = PreferredViewer::DontCare);
|
||||
void setSector(QSharedPointer<Sector> sec, PreferredViewer viewer = PreferredViewer::DontCare);
|
||||
|
||||
void handleShowSectorData(Sector *data, int track, int sector, DiskSectorRole role);
|
||||
void handleShowSectorData(QSharedPointer<Sector> data, int track, int sector, DiskSectorRole role);
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ VTOCView::~VTOCView()
|
|||
{
|
||||
delete ui;
|
||||
}
|
||||
void VTOCView::setSector(Sector *sec)
|
||||
void VTOCView::setSector(QSharedPointer<const Sector> sec)
|
||||
{
|
||||
m_sector = sec;
|
||||
|
||||
|
|
|
@ -37,12 +37,12 @@ public:
|
|||
explicit VTOCView(QWidget *parent = nullptr);
|
||||
~VTOCView();
|
||||
|
||||
void setSector(Sector *sec);
|
||||
void setSector(QSharedPointer<const Sector> sec);
|
||||
|
||||
|
||||
private:
|
||||
Ui::VTOCView *ui;
|
||||
Sector *m_sector;
|
||||
QSharedPointer<const Sector> m_sector;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -1,88 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* AppleSAWS - The Apple Software Analysis WorkShop *
|
||||
* Copyright (C) 2015-2021 Mark D. Long *
|
||||
* *
|
||||
* This program is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||
*****************************************************************************/
|
||||
|
||||
#include "chunkbytelist.h"
|
||||
|
||||
ChunkByteList::ChunkByteList()
|
||||
{
|
||||
m_preamble_size = 0;
|
||||
}
|
||||
|
||||
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 - preambleLength();
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
return preambleData(i + preambleLength());
|
||||
}
|
||||
|
||||
char ChunkByteList::operator[](int i) const
|
||||
{
|
||||
return at(i);
|
||||
}
|
||||
|
||||
|
|
@ -1,87 +0,0 @@
|
|||
#ifndef CHUNKBYTELIST_H
|
||||
#define CHUNKBYTELIST_H
|
||||
|
||||
/*****************************************************************************
|
||||
* AppleSAWS - The Apple Software Analysis WorkShop *
|
||||
* Copyright (C) 2015-2021 Mark D. Long *
|
||||
* *
|
||||
* This program is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||
*****************************************************************************/
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QList>
|
||||
|
||||
#include <QSharedPointer>
|
||||
|
||||
class ChunkByteList
|
||||
{
|
||||
public:
|
||||
ChunkByteList();
|
||||
|
||||
ChunkByteList &appendChunk(QByteArray *chunk);
|
||||
ChunkByteList &appendChunkList(ChunkByteList other);
|
||||
|
||||
void setPreambleLength(int bytes) { m_preamble_size = bytes; };
|
||||
int preambleLength() const { return m_preamble_size; };
|
||||
|
||||
int count() const;
|
||||
int size() const;
|
||||
int length() const;
|
||||
|
||||
char preambleData(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;
|
||||
}
|
||||
|
||||
int actualSize() const { return count() + preambleLength(); }
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
explicit operator QByteArray() { return asQByteArray(); }
|
||||
|
||||
private:
|
||||
QList<QByteArray *> m_chunk_list;
|
||||
int m_preamble_size;
|
||||
};
|
||||
|
||||
|
||||
#endif // CHUNKBYTELIST_H
|
|
@ -0,0 +1,409 @@
|
|||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* ReferenceList.h *
|
||||
* *
|
||||
* Copyright 2014 Tory Gaurnier <tory.gaurnier@linuxmail.org> *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License as published by *
|
||||
* the Free Software Foundation; version 3. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
|
||||
#ifndef REFERENCELIST_HPP
|
||||
#define REFERENCELIST_HPP
|
||||
|
||||
|
||||
#include <QDataStream>
|
||||
#include <QDebug>
|
||||
#include <QList>
|
||||
|
||||
|
||||
/**
|
||||
* class ReferenceList
|
||||
*
|
||||
* Uses QList under the hood to store pointers, on the surface recieves and returns nothing but the
|
||||
* references.
|
||||
*
|
||||
* NOTE: Any method that calls it's QList<T*> counterpart with parameter T, T must not be const, if
|
||||
* it is then QList<T*> would have to be QList<const T *const> instead.
|
||||
*/
|
||||
template<class T>
|
||||
class ReferenceList : public QList<T*> {
|
||||
public:
|
||||
// Forward declare iterators
|
||||
class const_iterator;
|
||||
class iterator;
|
||||
|
||||
// Set iterators as friends
|
||||
friend class const_iterator;
|
||||
friend class iterator;
|
||||
|
||||
|
||||
ReferenceList() {}
|
||||
ReferenceList(const QList<T*> &other) : QList<T*>(other) { }
|
||||
ReferenceList(const ReferenceList<T> &other) : QList<T*>(other) { }
|
||||
ReferenceList(ReferenceList<T> &&other) : QList<T*>(std::move(other)) { }
|
||||
~ReferenceList() {}
|
||||
|
||||
void append(T &value) {
|
||||
QList<T*>::append(&value);
|
||||
}
|
||||
|
||||
void append(const ReferenceList<T> other) {
|
||||
QList<T*>::append(other);
|
||||
}
|
||||
|
||||
const T & at(int i) const {
|
||||
return *QList<T*>::at(i);
|
||||
}
|
||||
|
||||
T & back() {
|
||||
return *QList<T*>::back();
|
||||
}
|
||||
|
||||
const T & back() const {
|
||||
return *QList<T*>::back();
|
||||
}
|
||||
|
||||
iterator begin() {
|
||||
return iterator(iterator(QList<T*>::begin()));
|
||||
}
|
||||
|
||||
const_iterator begin() const {
|
||||
return const_iterator(QList<T*>::begin());
|
||||
}
|
||||
|
||||
const_iterator cbegin() const {
|
||||
return const_iterator(QList<T*>::cbegin());
|
||||
}
|
||||
|
||||
const_iterator cend() const {
|
||||
return const_iterator(QList<T*>::cend());
|
||||
}
|
||||
|
||||
void clear() {
|
||||
QList<T*>::clear();
|
||||
}
|
||||
|
||||
const_iterator constBegin() const {
|
||||
return const_iterator(QList<T*>::constBegin());
|
||||
}
|
||||
|
||||
const_iterator constEnd() const {
|
||||
return const_iterator(QList<T*>::constEnd());
|
||||
}
|
||||
|
||||
bool contains(T &value) const {
|
||||
return QList<T*>::contains(&value);
|
||||
}
|
||||
|
||||
int count(T &value) const {
|
||||
return QList<T*>::count(&value);
|
||||
}
|
||||
|
||||
int count() const {
|
||||
return QList<T*>::count();
|
||||
}
|
||||
|
||||
bool empty() const {
|
||||
return QList<T*>::empty();
|
||||
}
|
||||
|
||||
iterator end() {
|
||||
return iterator(QList<T*>::end());
|
||||
}
|
||||
|
||||
const_iterator end() const {
|
||||
return const_iterator(QList<T*>::end());
|
||||
}
|
||||
|
||||
bool endsWith(T &value) const {
|
||||
return QList<T*>::endsWith(&value);
|
||||
}
|
||||
|
||||
iterator erase(iterator pos) {
|
||||
return iterator(QList<T*>::erase(pos));
|
||||
}
|
||||
|
||||
iterator erase(iterator begin, iterator end) {
|
||||
return iterator(QList<T*>::erase(begin, end));
|
||||
|
||||
}
|
||||
|
||||
T & first() {
|
||||
return *QList<T*>::first();
|
||||
}
|
||||
|
||||
const T & first() const {
|
||||
return *QList<T*>::first();
|
||||
}
|
||||
|
||||
/**
|
||||
* Inherited "from" methods are unsupported.
|
||||
*/
|
||||
static ReferenceList<T> fromSet(const QSet<T> & set) = delete;
|
||||
static ReferenceList<T> fromStdList(const std::list<T> & list) = delete;
|
||||
static ReferenceList<T> fromVector(const QVector<T> & vector) = delete;
|
||||
|
||||
T & front() {
|
||||
return *QList<T*>::front();
|
||||
}
|
||||
|
||||
const T & front() const {
|
||||
return *QList<T*>::front();
|
||||
}
|
||||
|
||||
int indexOf(T &value, int from = 0) const {
|
||||
return QList<T*>::indexOf(&value, from);
|
||||
}
|
||||
|
||||
void insert(int i, T &value) {
|
||||
QList<T*>::insert(i, &value);
|
||||
}
|
||||
|
||||
iterator insert(iterator before, T &value) {
|
||||
return iterator(QList<T*>::insert(before, &value));
|
||||
}
|
||||
|
||||
bool isEmpty() const {
|
||||
return QList<T*>::isEmpty();
|
||||
}
|
||||
|
||||
T & last() {
|
||||
return *QList<T*>::last();
|
||||
}
|
||||
|
||||
const T & last() const {
|
||||
return *QList<T*>::last();
|
||||
}
|
||||
|
||||
int lastIndexOf(T &value, int from = -1) const {
|
||||
return QList<T*>::lastIndexOf(&value, from);
|
||||
}
|
||||
|
||||
int length() const {
|
||||
return QList<T*>::length();
|
||||
}
|
||||
|
||||
ReferenceList<T> mid(int pos, int length = -1) const {
|
||||
return ReferenceList<T>(QList<T*>::mid(pos, length));
|
||||
}
|
||||
|
||||
void move(int from, int to) {
|
||||
QList<T*>::move(from, to);
|
||||
}
|
||||
|
||||
void pop_back() {
|
||||
QList<T*>::pop_back();
|
||||
}
|
||||
|
||||
void pop_front() {
|
||||
QList<T*>::pop_front();
|
||||
}
|
||||
|
||||
void prepend(T &value) {
|
||||
QList<T*>::prepend(&value);
|
||||
}
|
||||
|
||||
void push_back(T &value) {
|
||||
QList<T*>::push_back(&value);
|
||||
}
|
||||
|
||||
void push_front(T &value) {
|
||||
QList<T*>::push_front(&value);
|
||||
}
|
||||
|
||||
int removeAll(T &value) {
|
||||
return QList<T*>::removeAll(&value);
|
||||
}
|
||||
|
||||
void removeAt(int i) {
|
||||
QList<T*>::removeAt(i);
|
||||
}
|
||||
|
||||
void removeFirst() {
|
||||
QList<T*>::removeFirst();
|
||||
}
|
||||
|
||||
void removeLast() {
|
||||
QList<T*>::removeLast();
|
||||
}
|
||||
|
||||
bool removeOne(T &value) {
|
||||
return QList<T*>::removeOne(&value);
|
||||
}
|
||||
|
||||
void replace(int i, T &value) {
|
||||
QList<T*>::replace(i, &value);
|
||||
}
|
||||
|
||||
void reserve(int alloc) {
|
||||
QList<T*>::reserve(alloc);
|
||||
}
|
||||
|
||||
int size() const {
|
||||
return QList<T*>::size();
|
||||
}
|
||||
|
||||
bool startsWith(T &value) const {
|
||||
return QList<T*>::startsWith(&value);
|
||||
}
|
||||
|
||||
void swap(ReferenceList<T> &other) {
|
||||
QList<T*>::swap(other);
|
||||
}
|
||||
|
||||
void swap(int i, int j) {
|
||||
QList<T*>::swap(i, j);
|
||||
}
|
||||
|
||||
T & takeAt(int i) {
|
||||
return *QList<T*>::takeAt(i);
|
||||
}
|
||||
|
||||
T & takeFirst() {
|
||||
return *QList<T*>::takeFirst();
|
||||
}
|
||||
|
||||
T & takeLast() {
|
||||
return *QList<T*>::takeLast();
|
||||
}
|
||||
|
||||
/**
|
||||
* Inherited "to" methods are not supported.
|
||||
*/
|
||||
QSet<T> toSet() const = delete;
|
||||
std::list<T> toStdList() const = delete;
|
||||
QVector<T> toVector() const = delete;
|
||||
|
||||
T & value(int i) const {
|
||||
return *QList<T*>::value(i);
|
||||
}
|
||||
|
||||
T & value(int i, T &default_value) const {
|
||||
return *QList<T*>::value(i, &default_value);
|
||||
}
|
||||
|
||||
bool operator!=(const ReferenceList<T> &other) const {
|
||||
return QList<T*>::operator!=(other);
|
||||
}
|
||||
|
||||
ReferenceList<T> operator+(const ReferenceList<T> &other) const {
|
||||
return ReferenceList<T>(QList<T*>::operator+(other));
|
||||
}
|
||||
|
||||
ReferenceList<T> & operator+=(const ReferenceList<T> &other) {
|
||||
QList<T*>::operator+=(other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
ReferenceList<T> & operator+=(T &value) {
|
||||
QList<T*>::operator+=(&value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
ReferenceList<T> & operator<<(const ReferenceList<T> &other) {
|
||||
QList<T*>::operator<<(other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
ReferenceList<T> & operator<<(T &value) {
|
||||
QList<T*>::operator<<(&value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
ReferenceList<T> & operator=(ReferenceList<T> &other) {
|
||||
QList<T*>::operator=(other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
ReferenceList & operator=(ReferenceList<T> &&other) {
|
||||
QList<T*>::operator=(std::move(other));
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(const ReferenceList<T> &other) const {
|
||||
return QList<T*>::operator==(other);
|
||||
}
|
||||
|
||||
T & operator[](int i) {
|
||||
return *QList<T*>::operator[](i);
|
||||
}
|
||||
|
||||
const T & operator[](int i) const {
|
||||
return *QList<T*>::operator[](i);
|
||||
}
|
||||
|
||||
|
||||
class iterator : public QList<T*>::iterator {
|
||||
public:
|
||||
iterator() { }
|
||||
iterator(const typename QList<T*>::iterator &other)
|
||||
: QList<T*>::iterator(other) { }
|
||||
iterator(const iterator &other) : QList<T*>::iterator(other) { }
|
||||
T & operator*() const { return *QList<T*>::iterator::operator*(); }
|
||||
T * operator->() const { return *QList<T*>::iterator::operator->(); }
|
||||
T & operator[](int j) const { return *QList<T*>::iterator::operator[](j); }
|
||||
};
|
||||
|
||||
class const_iterator : public QList<T*>::const_iterator {
|
||||
public:
|
||||
const_iterator() { }
|
||||
const_iterator(const typename QList<T*>::const_iterator &other)
|
||||
: QList<T*>::const_iterator(other) { }
|
||||
const_iterator(const const_iterator &other)
|
||||
: QList<T*>::const_iterator(other) { }
|
||||
const_iterator(const iterator &other)
|
||||
: QList<T*>::const_iterator(other) { }
|
||||
T & operator*() const { return *QList<T*>::const_iterator::operator*(); }
|
||||
T * operator->() const { return *QList<T*>::const_iterator::operator->(); }
|
||||
T & operator[](int j) const { return *QList<T*>::const_iterator::operator[](j); }
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Implement QDebug << operator so that it will print out values rather than pointer addresses (do
|
||||
* to it implicitly converting to QList<T*>).
|
||||
*/
|
||||
template <class T>
|
||||
QDebug operator<<(QDebug debug, const ReferenceList<T> &list) {
|
||||
debug.nospace() << '(';
|
||||
for(typename QList<T>::size_type i = 0; i < list.count(); ++i) {
|
||||
if(i) debug << ", ";
|
||||
debug << list.at(i);
|
||||
}
|
||||
|
||||
debug << ')';
|
||||
|
||||
return debug.space();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* QDataStream << ReferenceList<T> should have same output as the QDataStream << QList<T>.
|
||||
*/
|
||||
template<class T>
|
||||
QDataStream & operator<<(QDataStream &out, const ReferenceList<T>& list) {
|
||||
out << quint32(list.size());
|
||||
for(int i = 0; i < list.size(); ++i) out << list.at(i);
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Make sure QDataStream >> is not callable, there is no scenario where it would be useful with a
|
||||
* ReferenceList.
|
||||
*/
|
||||
template<class T>
|
||||
QDataStream & operator>>(QDataStream &out, const ReferenceList<T>& list) = delete;
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue