From 0a053e4ce4fa440172792e00ebfaa676b412c846 Mon Sep 17 00:00:00 2001 From: Walter van Niftrik Date: Sat, 27 Aug 2016 01:47:43 +0200 Subject: ADL: Add support for reading .xfd Atari disk images --- engines/adl/disk.cpp | 70 ++++++++++++++++++++++++++++++-------------------- engines/adl/disk.h | 20 +++++++++------ engines/adl/hires0.cpp | 2 +- engines/adl/hires2.cpp | 6 ++--- 4 files changed, 58 insertions(+), 40 deletions(-) (limited to 'engines') diff --git a/engines/adl/disk.cpp b/engines/adl/disk.cpp index 49e01f9d0f..6a5cf0b20c 100644 --- a/engines/adl/disk.cpp +++ b/engines/adl/disk.cpp @@ -28,15 +28,7 @@ namespace Adl { -#define TRACKS 35 -// The Apple II uses either 13- or 16-sector disks. We currently pad out -// 13-sector disks, so we set SECTORS_PER_TRACK to 16 here. -#define SECTORS_PER_TRACK 16 -#define BYTES_PER_SECTOR 256 -#define RAW_IMAGE_SIZE(S) (TRACKS * (S) * BYTES_PER_SECTOR) -#define NIB_IMAGE_SIZE (RAW_IMAGE_SIZE(13) * 2) - -static Common::SeekableReadStream *readImage_DSK(const Common::String &filename) { +static Common::SeekableReadStream *readImage(const Common::String &filename) { Common::File *f = new Common::File; if (!f->open(filename)) { @@ -44,9 +36,6 @@ static Common::SeekableReadStream *readImage_DSK(const Common::String &filename) return nullptr; } - if (f->size() != RAW_IMAGE_SIZE(16)) - error("Unrecognized DSK image '%s' of size %d bytes", filename.c_str(), f->size()); - return f; } @@ -63,7 +52,7 @@ static Common::SeekableReadStream *readImage_NIB(const Common::String &filename) if (!f.open(filename)) return nullptr; - if (f.size() != NIB_IMAGE_SIZE) + if (f.size() != 232960) error("Unrecognized NIB image '%s' of size %d bytes", filename.c_str(), f.size()); // starting at 0xaa, 32 is invalid (see below) @@ -73,7 +62,9 @@ static Common::SeekableReadStream *readImage_NIB(const Common::String &filename) // we always pad it out const uint sectorsPerTrack = 16; - byte *diskImage = (byte *)calloc(RAW_IMAGE_SIZE(sectorsPerTrack), 1); + const uint bytesPerSector = 256; + const uint imageSize = 35 * sectorsPerTrack * bytesPerSector; + byte *const diskImage = (byte *)calloc(imageSize, 1); bool sawAddress = false; uint8 volNo, track, sector; @@ -120,13 +111,13 @@ static Common::SeekableReadStream *readImage_NIB(const Common::String &filename) // We should always find the data field after an address field. // TODO: we ignore volNo? - byte *output = diskImage + (track * sectorsPerTrack + sector) * BYTES_PER_SECTOR; + byte *output = diskImage + (track * sectorsPerTrack + sector) * bytesPerSector; if (newStyle) { // We hardcode the DOS 3.3 mapping here. TODO: Do we also need raw/prodos? int raw2dos[16] = { 0, 7, 14, 6, 13, 5, 12, 4, 11, 3, 10, 2, 9, 1, 8, 15 }; sector = raw2dos[sector]; - output = diskImage + (track * sectorsPerTrack + sector) * BYTES_PER_SECTOR; + output = diskImage + (track * sectorsPerTrack + sector) * bytesPerSector; // 6-and-2 uses 342 on-disk bytes byte inbuffer[342]; @@ -216,36 +207,59 @@ static Common::SeekableReadStream *readImage_NIB(const Common::String &filename) } } - return new Common::MemoryReadStream(diskImage, RAW_IMAGE_SIZE(sectorsPerTrack), DisposeAfterUse::YES); + return new Common::MemoryReadStream(diskImage, imageSize, DisposeAfterUse::YES); } bool DiskImage::open(const Common::String &filename) { Common::String lcName(filename); lcName.toLowercase(); - if (lcName.hasSuffix(".dsk")) - _stream = readImage_DSK(filename); - else if (lcName.hasSuffix(".nib")) + if (lcName.hasSuffix(".dsk")) { + _stream = readImage(filename); + _tracks = 35; + _sectorsPerTrack = 16; + _bytesPerSector = 256; + } else if (lcName.hasSuffix(".nib")) { _stream = readImage_NIB(filename); + _tracks = 35; + _sectorsPerTrack = 16; + _bytesPerSector = 256; + } else if (lcName.hasSuffix(".xfd")) { + _stream = readImage(filename); + _tracks = 40; + _sectorsPerTrack = 18; + _bytesPerSector = 128; + } + + int expectedSize = _tracks * _sectorsPerTrack * _bytesPerSector; + + if (!_stream) + return false; + + if (_stream->size() != expectedSize) + error("Unrecognized disk image '%s' of size %d bytes (expected %d bytes)", filename.c_str(), _stream->size(), expectedSize); - return _stream != nullptr; + return true; } const DataBlockPtr DiskImage::getDataBlock(uint track, uint sector, uint offset, uint size) const { - return DataBlockPtr(new DiskImage::DataBlock(this, track, sector, offset, size, _mode13)); + return DataBlockPtr(new DiskImage::DataBlock(this, track, sector, offset, size, _sectorLimit)); } -Common::SeekableReadStream *DiskImage::createReadStream(uint track, uint sector, uint offset, uint size, uint sectorsPerTrackToRead) const { - const uint bytesToRead = size * BYTES_PER_SECTOR + BYTES_PER_SECTOR - offset; +Common::SeekableReadStream *DiskImage::createReadStream(uint track, uint sector, uint offset, uint size, uint sectorLimit) const { + const uint bytesToRead = size * _bytesPerSector + _bytesPerSector - offset; byte *const data = (byte *)malloc(bytesToRead); uint dataOffset = 0; - if (sector > sectorsPerTrackToRead - 1) - error("Sector %i is out of bounds for %i-sector reading", sector, sectorsPerTrackToRead); + if (sectorLimit == 0) + sectorLimit = _sectorsPerTrack; + + if (sector >= sectorLimit) + error("Sector %i is out of bounds for %i-sector reading", sector, sectorLimit); while (dataOffset < bytesToRead) { - uint bytesRemInTrack = (sectorsPerTrackToRead - 1 - sector) * BYTES_PER_SECTOR + BYTES_PER_SECTOR - offset; - _stream->seek((track * SECTORS_PER_TRACK + sector) * BYTES_PER_SECTOR + offset); + uint bytesRemInTrack = (sectorLimit - 1 - sector) * _bytesPerSector + _bytesPerSector - offset; + _stream->seek((track * _sectorsPerTrack + sector) * _bytesPerSector + offset); if (bytesToRead - dataOffset < bytesRemInTrack) bytesRemInTrack = bytesToRead - dataOffset; diff --git a/engines/adl/disk.h b/engines/adl/disk.h index 1041f0cebd..653d76ff10 100644 --- a/engines/adl/disk.h +++ b/engines/adl/disk.h @@ -74,7 +74,10 @@ class DiskImage { public: DiskImage() : _stream(nullptr), - _mode13(false) { } + _tracks(0), + _sectorsPerTrack(0), + _bytesPerSector(0), + _sectorLimit(0) { } ~DiskImage() { delete _stream; @@ -82,32 +85,33 @@ public: bool open(const Common::String &filename); const DataBlockPtr getDataBlock(uint track, uint sector, uint offset = 0, uint size = 0) const; - Common::SeekableReadStream *createReadStream(uint track, uint sector, uint offset = 0, uint size = 0, uint sectorsPerTrackToRead = 16) const; - void setMode13(bool enable) { _mode13 = enable; } + Common::SeekableReadStream *createReadStream(uint track, uint sector, uint offset = 0, uint size = 0, uint sectorsUsed = 0) const; + void setSectorLimit(uint sectorLimit) { _sectorLimit = sectorLimit; } // Maximum number of sectors to read per track before stepping protected: class DataBlock : public Adl::DataBlock { public: - DataBlock(const DiskImage *disk, uint track, uint sector, uint offset, uint size, bool mode13) : + DataBlock(const DiskImage *disk, uint track, uint sector, uint offset, uint size, uint sectorLimit) : _track(track), _sector(sector), _offset(offset), _size(size), - _mode13(mode13), + _sectorLimit(sectorLimit), _disk(disk) { } Common::SeekableReadStream *createReadStream() const { - return _disk->createReadStream(_track, _sector, _offset, _size, (_mode13 ? 13 : 16)); + return _disk->createReadStream(_track, _sector, _offset, _size, _sectorLimit); } private: uint _track, _sector, _offset, _size; - bool _mode13; + uint _sectorLimit; const DiskImage *_disk; }; Common::SeekableReadStream *_stream; - bool _mode13; // Older 13-sector format + uint _tracks, _sectorsPerTrack, _bytesPerSector; + uint _sectorLimit; }; // Data in plain files diff --git a/engines/adl/hires0.cpp b/engines/adl/hires0.cpp index a348779e89..875a06c73d 100644 --- a/engines/adl/hires0.cpp +++ b/engines/adl/hires0.cpp @@ -35,7 +35,7 @@ void HiRes0Engine::init() { if (!_disk->open(IDS_HR0_DISK_IMAGE)) error("Failed to open disk image '" IDS_HR0_DISK_IMAGE "'"); - _disk->setMode13(true); + _disk->setSectorLimit(13); StreamPtr stream(_disk->createReadStream(0x1f, 0x2, 0x00, 2)); diff --git a/engines/adl/hires2.cpp b/engines/adl/hires2.cpp index 14db237d82..d0e459c96c 100644 --- a/engines/adl/hires2.cpp +++ b/engines/adl/hires2.cpp @@ -37,7 +37,7 @@ void HiRes2Engine::runIntro() const { // This only works for the 16-sector re-release. The original // release is not supported at this time, because we don't have // access to it. - _disk->setMode13(false); + _disk->setSectorLimit(0); StreamPtr stream(_disk->createReadStream(0x00, 0xd, 0x17, 1)); _display->setMode(DISPLAY_MODE_TEXT); @@ -50,7 +50,7 @@ void HiRes2Engine::runIntro() const { _display->printString(str); delay(2000); - _disk->setMode13(true); + _disk->setSectorLimit(13); } void HiRes2Engine::init() { @@ -60,7 +60,7 @@ void HiRes2Engine::init() { if (!_disk->open(IDS_HR2_DISK_IMAGE)) error("Failed to open disk image '" IDS_HR2_DISK_IMAGE "'"); - _disk->setMode13(true); + _disk->setSectorLimit(13); StreamPtr stream(_disk->createReadStream(0x1f, 0x2, 0x00, 4)); -- cgit v1.2.3