mirror of
https://github.com/markdavidlong/AppleSAWS.git
synced 2024-06-17 07:29:28 +00:00
215 lines
6.3 KiB
C++
215 lines
6.3 KiB
C++
/*****************************************************************************
|
|
* 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;
|
|
}
|