diff options
| -rw-r--r-- | engines/adl/disk.cpp | 60 | ||||
| -rw-r--r-- | engines/adl/disk.h | 42 | 
2 files changed, 92 insertions, 10 deletions
| diff --git a/engines/adl/disk.cpp b/engines/adl/disk.cpp index b2746bcee7..5ee9b268ae 100644 --- a/engines/adl/disk.cpp +++ b/engines/adl/disk.cpp @@ -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; diff --git a/engines/adl/disk.h b/engines/adl/disk.h index a13c2eeb47..97b66a9a9e 100644 --- a/engines/adl/disk.h +++ b/engines/adl/disk.h @@ -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 | 
