[Scummvm-git-logs] scummvm master -> 4cfb93c227f916a059c3000cbdde800967777854

waltervn walter at vanniftrik-it.nl
Sat Jun 10 17:17:44 CEST 2017


This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
4cfb93c227 ADL: Add loading of hires4 game data


Commit: 4cfb93c227f916a059c3000cbdde800967777854
    https://github.com/scummvm/scummvm/commit/4cfb93c227f916a059c3000cbdde800967777854
Author: Walter van Niftrik (walter at scummvm.org)
Date: 2017-06-10T17:07:17+02:00

Commit Message:
ADL: Add loading of hires4 game data

Changed paths:
    engines/adl/disk.h
    engines/adl/hires4.cpp


diff --git a/engines/adl/disk.h b/engines/adl/disk.h
index 4c0df83..6126ef5 100644
--- a/engines/adl/disk.h
+++ b/engines/adl/disk.h
@@ -87,6 +87,8 @@ public:
 	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 sectorsUsed = 0) const;
 	void setSectorLimit(uint sectorLimit) { _sectorLimit = sectorLimit; } // Maximum number of sectors to read per track before stepping
+	uint getBytesPerSector() const { return _bytesPerSector; }
+	uint getSectorsPerTrack() const { return _sectorsPerTrack; }
 
 protected:
 	class DataBlock : public Adl::DataBlock {
diff --git a/engines/adl/hires4.cpp b/engines/adl/hires4.cpp
index a76b424..bfa37c3 100644
--- a/engines/adl/hires4.cpp
+++ b/engines/adl/hires4.cpp
@@ -26,6 +26,7 @@
 #include "common/file.h"
 #include "common/stream.h"
 #include "common/events.h"
+#include "common/memstream.h"
 
 #include "adl/adl_v3.h"
 #include "adl/detection.h"
@@ -52,13 +53,16 @@ namespace Adl {
 class HiRes4Engine : public AdlEngine_v3 {
 public:
 	HiRes4Engine(OSystem *syst, const AdlGameDescription *gd) :
-			AdlEngine_v3(syst, gd) { }
+			AdlEngine_v3(syst, gd),
+			_boot(nullptr) { }
+	~HiRes4Engine();
 
 private:
 	// AdlEngine
 	void runIntro();
 	void init();
 	void initGameState();
+	void loadRoom(byte roomNr);
 
 	void putSpace(uint x, uint y) const;
 	void drawChar(byte c, Common::SeekableReadStream &shapeTable, Common::Point &pos) const;
@@ -71,8 +75,60 @@ private:
 	void runIntroLoading(Common::SeekableReadStream &adventure);
 
 	static const uint kClock = 1022727; // Apple II CPU clock rate
+
+	DiskImage *_boot;
 };
 
+// TODO: It might be worth replacing this with a more generic variant that
+// can be used in both hires4 and hires6
+static Common::MemoryReadStream *readSkewedSectors(DiskImage *disk, byte track, byte sector, byte count) {
+	const uint bytesPerSector = disk->getBytesPerSector();
+	const uint sectorsPerTrack = disk->getSectorsPerTrack();
+	const uint bufSize = count * bytesPerSector;
+	byte *const buf = (byte *)malloc(bufSize);
+	byte *p = buf;
+
+	while (count-- != 0) {
+		StreamPtr stream(disk->createReadStream(track, sector));
+		stream->read(p, bytesPerSector);
+
+		if (stream->err() || stream->eos())
+			error("Error loading from disk image");
+
+		p += bytesPerSector;
+		sector += 5;
+		sector %= sectorsPerTrack;
+		if (sector == 0)
+			++track;
+	}
+
+	return new Common::MemoryReadStream(buf, bufSize, DisposeAfterUse::YES);
+}
+
+static Common::MemoryReadStream *decodeData(Common::SeekableReadStream &stream, const uint startOffset, uint endOffset, const byte xorVal) {
+	assert(stream.size() >= 0);
+
+	uint streamSize(stream.size());
+
+	if (endOffset > streamSize)
+		endOffset = streamSize;
+
+	byte *const buf = (byte *)malloc(streamSize);
+	stream.read(buf, streamSize);
+
+	if (stream.err() || stream.eos())
+		error("Failed to read data for decoding");
+
+	for (uint i = startOffset; i < endOffset; ++i)
+		buf[i] ^= xorVal;
+
+	return new Common::MemoryReadStream(buf, streamSize, DisposeAfterUse::YES);
+}
+
+HiRes4Engine::~HiRes4Engine() {
+	delete _boot;
+}
+
 void HiRes4Engine::putSpace(uint x, uint y) const {
 	if (shouldQuit())
 		return;
@@ -405,9 +461,96 @@ void HiRes4Engine::runIntro() {
 
 void HiRes4Engine::init() {
 	_graphics = new GraphicsMan_v2(*_display);
+
+	_boot = new DiskImage();
+	if (!_boot->open(getDiskImageName(0)))
+		error("Failed to open disk image '%s'", getDiskImageName(0).c_str());
+
+	insertDisk(1);
+
+	StreamPtr stream(readSkewedSectors(_boot, 0x05, 0x6, 1));
+	_strings.verbError = readStringAt(*stream, 0x4f);
+	_strings.nounError = readStringAt(*stream, 0x8e);
+	_strings.enterCommand = readStringAt(*stream, 0xbc);
+
+	stream.reset(readSkewedSectors(_boot, 0x05, 0x3, 1));
+	stream->skip(0xd7);
+	_strings_v2.time = readString(*stream, 0xff);
+
+	stream.reset(readSkewedSectors(_boot, 0x05, 0x7, 2));
+	_strings.lineFeeds = readStringAt(*stream, 0xf8);
+
+	stream.reset(readSkewedSectors(_boot, 0x06, 0xf, 3));
+	_strings_v2.saveInsert = readStringAt(*stream, 0x5f);
+	_strings_v2.saveReplace = readStringAt(*stream, 0xe5);
+	_strings_v2.restoreInsert = readStringAt(*stream, 0x132);
+	_strings_v2.restoreReplace = readStringAt(*stream, 0x1c2);
+	_strings.playAgain = readStringAt(*stream, 0x225);
+
+	_messageIds.cantGoThere = IDI_HR4_MSG_CANT_GO_THERE;
+	_messageIds.dontUnderstand = IDI_HR4_MSG_DONT_UNDERSTAND;
+	_messageIds.itemDoesntMove = IDI_HR4_MSG_ITEM_DOESNT_MOVE;
+	_messageIds.itemNotHere = IDI_HR4_MSG_ITEM_NOT_HERE;
+	_messageIds.thanksForPlaying = IDI_HR4_MSG_THANKS_FOR_PLAYING;
+
+	stream.reset(readSkewedSectors(_boot, 0x0a, 0x0, 5));
+	loadMessages(*stream, IDI_HR4_NUM_MESSAGES);
+
+	stream.reset(readSkewedSectors(_boot, 0x05, 0x2, 1));
+	stream->skip(0x80);
+	loadPictures(*stream);
+
+	stream.reset(readSkewedSectors(_boot, 0x09, 0x2, 1));
+	stream->skip(0x05);
+	loadItemPictures(*stream, IDI_HR4_NUM_ITEM_PICS);
+
+	stream.reset(readSkewedSectors(_boot, 0x04, 0x0, 3));
+	stream->skip(0x15);
+	loadItemDescriptions(*stream, IDI_HR4_NUM_ITEM_DESCS);
+
+	stream.reset(readSkewedSectors(_boot, 0x08, 0x2, 6));
+	stream->skip(0xa5);
+	readCommands(*stream, _roomCommands);
+
+	stream.reset(readSkewedSectors(_boot, 0x04, 0xc, 4));
+	stream.reset(decodeData(*stream, 0x218, 0x318, 0xee));
+	readCommands(*stream, _globalCommands);
+
+	stream.reset(readSkewedSectors(_boot, 0x06, 0x6, 1));
+	stream->skip(0x10);
+	loadDroppedItemOffsets(*stream, IDI_HR4_NUM_ITEM_OFFSETS);
+
+	stream.reset(readSkewedSectors(_boot, 0x05, 0x0, 4));
+	loadWords(*stream, _verbs, _priVerbs);
+
+	stream.reset(readSkewedSectors(_boot, 0x0b, 0xb, 7));
+	loadWords(*stream, _nouns, _priNouns);
 }
 
 void HiRes4Engine::initGameState() {
+	_state.vars.resize(IDI_HR4_NUM_VARS);
+
+	StreamPtr stream(readSkewedSectors(_boot, 0x0b, 0x9, 10));
+	stream->skip(0x0e);
+	loadRooms(*stream, IDI_HR4_NUM_ROOMS);
+
+	stream.reset(readSkewedSectors(_boot, 0x0b, 0x0, 13));
+	stream.reset(decodeData(*stream, 0x43, 0x143, 0x91));
+	loadItems(*stream);
+}
+
+void HiRes4Engine::loadRoom(byte roomNr) {
+	if (roomNr == 121) {
+		// Room 121 is missing. This causes problems when we're dumping
+		// scripts with the debugger, so we intercept this room load here.
+		debug("Warning: attempt to load non-existent room 121");
+		_roomData.description.clear();
+		_roomData.pictures.clear();
+		_roomData.commands.clear();
+		return;
+	}
+
+	AdlEngine_v3::loadRoom(roomNr);
 }
 
 class HiRes4Engine_Atari : public AdlEngine_v3 {
@@ -507,11 +650,7 @@ void HiRes4Engine_Atari::loadRoom(byte roomNr) {
 	}
 
 	if (roomNr == 121) {
-		// Room 121 is not present in the Atari version. This causes
-		// problems when we're dumping scripts with the debugger, so
-		// we intercept this room load here.
-		// FIXME: Find out if the Apple II version does have this room
-		// FIXME: Implement more generic handling of invalid rooms?
+		// Room 121 is missing, see Apple II version
 		debug("Warning: attempt to load non-existent room 121");
 		_roomData.description.clear();
 		_roomData.pictures.clear();





More information about the Scummvm-git-logs mailing list