mirror of
https://github.com/libretro/scummvm.git
synced 2025-01-20 17:03:05 +00:00
ADL: Add support for Serenia data blocks
This commit is contained in:
parent
14bfe02b81
commit
e937838b91
@ -30,6 +30,59 @@
|
||||
|
||||
namespace Adl {
|
||||
|
||||
void DataBlock_PC::read(Common::SeekableReadStream &stream, byte *const dataPtr, const uint32 size) const {
|
||||
uint32 ofs = 0;
|
||||
|
||||
while (ofs < size) {
|
||||
const uint bps = _disk->getBytesPerSector();
|
||||
uint bytesToRead = bps - ((_offset + stream.pos()) % bps);
|
||||
|
||||
if (bytesToRead == bps) {
|
||||
stream.readByte(); // Skip volume byte
|
||||
--bytesToRead;
|
||||
}
|
||||
|
||||
if (bytesToRead > size - ofs)
|
||||
bytesToRead = size - ofs;
|
||||
|
||||
if (stream.read(dataPtr + ofs, bytesToRead) < bytesToRead)
|
||||
error("Failed to read data block");
|
||||
|
||||
ofs += bytesToRead;
|
||||
}
|
||||
}
|
||||
|
||||
Common::SeekableReadStream *DataBlock_PC::createReadStream() const {
|
||||
const uint bps = _disk->getBytesPerSector();
|
||||
uint sectors = 0;
|
||||
|
||||
// Every data sector starts with a volume byte that we need to skip,
|
||||
// so we need to take that into account during our computations here
|
||||
if (_offset == bps - 1)
|
||||
sectors = 1;
|
||||
|
||||
StreamPtr diskStream(_disk->createReadStream(_track, _sector, _offset, sectors));
|
||||
|
||||
byte sizeBuf[2];
|
||||
read(*diskStream, sizeBuf, 2);
|
||||
|
||||
uint16 blockSize = READ_LE_UINT16(sizeBuf);
|
||||
sectors = 0;
|
||||
|
||||
const uint16 remSize = _disk->getBytesPerSector() - MAX<uint>(_offset, 1);
|
||||
|
||||
if (blockSize + 2 > remSize)
|
||||
sectors = (blockSize + 2 - remSize - 1) / (_disk->getBytesPerSector() - 1) + 1;
|
||||
|
||||
diskStream.reset(_disk->createReadStream(_track, _sector, _offset, sectors));
|
||||
read(*diskStream, sizeBuf, 2);
|
||||
|
||||
byte *buf = static_cast<byte *>(malloc(blockSize));
|
||||
read(*diskStream, buf, blockSize);
|
||||
|
||||
return new Common::MemoryReadStream(buf, blockSize, DisposeAfterUse::YES);
|
||||
}
|
||||
|
||||
const uint trackLen = 256 * 26;
|
||||
|
||||
static bool detectDOS33_NIB(Common::SeekableReadStream &f) {
|
||||
@ -309,6 +362,7 @@ bool DiskImage::open(const Common::String &filename) {
|
||||
_tracks = 40;
|
||||
_sectorsPerTrack = 8;
|
||||
_bytesPerSector = 512;
|
||||
_firstSector = 1;
|
||||
_stream = f;
|
||||
}
|
||||
|
||||
@ -335,8 +389,10 @@ Common::SeekableReadStream *DiskImage::createReadStream(uint track, uint sector,
|
||||
if (sectorLimit == 0)
|
||||
sectorLimit = _sectorsPerTrack;
|
||||
|
||||
if (sector >= sectorLimit)
|
||||
error("Sector %i is out of bounds for %i-sector reading", sector, sectorLimit);
|
||||
if (sector < _firstSector || sector >= sectorLimit + _firstSector)
|
||||
error("Sector %u is out of bounds for %u-sector %u-based reading", sector, sectorLimit, _firstSector);
|
||||
|
||||
sector -= _firstSector;
|
||||
|
||||
while (dataOffset < bytesToRead) {
|
||||
uint bytesRemInTrack = (sectorLimit - 1 - sector) * _bytesPerSector + _bytesPerSector - offset;
|
||||
|
@ -62,7 +62,7 @@ protected:
|
||||
_filename(filename),
|
||||
_offset(offset) { }
|
||||
|
||||
Common::SeekableReadStream *createReadStream() const {
|
||||
Common::SeekableReadStream *createReadStream() const override {
|
||||
return _files->createReadStream(_filename, _offset);
|
||||
}
|
||||
|
||||
@ -80,7 +80,8 @@ public:
|
||||
_tracks(0),
|
||||
_sectorsPerTrack(0),
|
||||
_bytesPerSector(0),
|
||||
_sectorLimit(0) { }
|
||||
_sectorLimit(0),
|
||||
_firstSector(0) { }
|
||||
|
||||
~DiskImage() {
|
||||
delete _stream;
|
||||
@ -105,7 +106,7 @@ protected:
|
||||
_sectorLimit(sectorLimit),
|
||||
_disk(disk) { }
|
||||
|
||||
Common::SeekableReadStream *createReadStream() const {
|
||||
Common::SeekableReadStream *createReadStream() const override {
|
||||
return _disk->createReadStream(_track, _sector, _offset, _size, _sectorLimit);
|
||||
}
|
||||
|
||||
@ -116,15 +117,15 @@ protected:
|
||||
};
|
||||
|
||||
Common::SeekableReadStream *_stream;
|
||||
uint _tracks, _sectorsPerTrack, _bytesPerSector;
|
||||
uint _tracks, _sectorsPerTrack, _bytesPerSector, _firstSector;
|
||||
uint _sectorLimit;
|
||||
};
|
||||
|
||||
// Data in plain files
|
||||
class Files_Plain : public Files {
|
||||
public:
|
||||
const DataBlockPtr getDataBlock(const Common::String &filename, uint offset = 0) const;
|
||||
Common::SeekableReadStream *createReadStream(const Common::String &filename, uint offset = 0) const;
|
||||
const DataBlockPtr getDataBlock(const Common::String &filename, uint offset = 0) const override;
|
||||
Common::SeekableReadStream *createReadStream(const Common::String &filename, uint offset = 0) const override;
|
||||
};
|
||||
|
||||
// Data in files contained in Apple DOS 3.3 disk image
|
||||
@ -134,8 +135,8 @@ public:
|
||||
~Files_AppleDOS();
|
||||
|
||||
bool open(const Common::String &filename, uint trackVTOC = 17);
|
||||
const DataBlockPtr getDataBlock(const Common::String &filename, uint offset = 0) const;
|
||||
Common::SeekableReadStream *createReadStream(const Common::String &filename, uint offset = 0) const;
|
||||
const DataBlockPtr getDataBlock(const Common::String &filename, uint offset = 0) const override;
|
||||
Common::SeekableReadStream *createReadStream(const Common::String &filename, uint offset = 0) const override;
|
||||
|
||||
private:
|
||||
enum FileType {
|
||||
@ -169,6 +170,31 @@ private:
|
||||
Common::HashMap<Common::String, TOCEntry> _toc;
|
||||
};
|
||||
|
||||
// On the Apple II, sector headers contain a disk volume number. This number
|
||||
// is used by ADL multi-disk games. The PC port has the disk volume number
|
||||
// as the first data byte of every sector that contains game data. We need
|
||||
// to skip this number as we read in the data. Additionally, the data is now
|
||||
// prefixed with an uint16 containing the data size.
|
||||
class DataBlock_PC : public DataBlock {
|
||||
public:
|
||||
DataBlock_PC(DiskImage *disk, byte track, byte sector, uint16 offset = 0) :
|
||||
_disk(disk),
|
||||
_track(track),
|
||||
_sector(sector),
|
||||
_offset(offset) { }
|
||||
|
||||
virtual ~DataBlock_PC() { }
|
||||
|
||||
Common::SeekableReadStream *createReadStream() const override;
|
||||
|
||||
private:
|
||||
void read(Common::SeekableReadStream &stream, byte *const dataPtr, const uint32 size) const;
|
||||
|
||||
DiskImage *_disk;
|
||||
byte _track, _sector;
|
||||
uint16 _offset;
|
||||
};
|
||||
|
||||
} // End of namespace Adl
|
||||
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user