aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/adl/adl_v2.cpp33
-rw-r--r--engines/adl/adl_v2.h2
-rw-r--r--engines/adl/adl_v3.cpp24
-rw-r--r--engines/adl/adl_v3.h2
-rw-r--r--engines/adl/adl_v4.cpp15
-rw-r--r--engines/adl/adl_v4.h2
-rw-r--r--engines/adl/hires0.cpp26
-rw-r--r--engines/adl/hires2.cpp26
-rw-r--r--engines/adl/hires4.cpp69
-rw-r--r--engines/adl/hires4.h25
-rw-r--r--engines/adl/hires6.cpp31
11 files changed, 158 insertions, 97 deletions
diff --git a/engines/adl/adl_v2.cpp b/engines/adl/adl_v2.cpp
index e18f3339f8..2b9a1b061a 100644
--- a/engines/adl/adl_v2.cpp
+++ b/engines/adl/adl_v2.cpp
@@ -359,9 +359,42 @@ DataBlockPtr AdlEngine_v2::readDataBlockPtr(Common::ReadStream &f) const {
if (track == 0 && sector == 0 && offset == 0 && size == 0)
return DataBlockPtr();
+ adjustDataBlockPtr(track, sector, offset, size);
+
return _disk->getDataBlock(track, sector, offset, size);
}
+void AdlEngine_v2::loadItems(Common::SeekableReadStream &stream) {
+ byte id;
+ while ((id = stream.readByte()) != 0xff && !stream.eos() && !stream.err()) {
+ Item item = Item();
+ item.id = id;
+ item.noun = stream.readByte();
+ item.room = stream.readByte();
+ item.picture = stream.readByte();
+ item.isLineArt = stream.readByte(); // Disk number in later games
+ item.position.x = stream.readByte();
+ item.position.y = stream.readByte();
+ item.state = stream.readByte();
+ item.description = stream.readByte();
+
+ stream.readByte(); // Struct size
+
+ byte picListSize = stream.readByte();
+
+ // Flag to keep track of what has been drawn on the screen
+ stream.readByte();
+
+ for (uint i = 0; i < picListSize; ++i)
+ item.roomPictures.push_back(stream.readByte());
+
+ _state.items.push_back(item);
+ }
+
+ if (stream.eos() || stream.err())
+ error("Error loading items");
+}
+
int AdlEngine_v2::o2_isFirstTime(ScriptEnv &e) {
OP_DEBUG_0("\t&& IS_FIRST_TIME()");
diff --git a/engines/adl/adl_v2.h b/engines/adl/adl_v2.h
index 327b36e913..e8894b5e87 100644
--- a/engines/adl/adl_v2.h
+++ b/engines/adl/adl_v2.h
@@ -52,6 +52,8 @@ protected:
void takeItem(byte noun);
virtual DataBlockPtr readDataBlockPtr(Common::ReadStream &f) const;
+ virtual void adjustDataBlockPtr(byte &track, byte &sector, byte &offset, byte &size) const { }
+ void loadItems(Common::SeekableReadStream &stream);
void checkTextOverflow(char c);
diff --git a/engines/adl/adl_v3.cpp b/engines/adl/adl_v3.cpp
index 6b93acde61..6551524c9e 100644
--- a/engines/adl/adl_v3.cpp
+++ b/engines/adl/adl_v3.cpp
@@ -32,6 +32,30 @@ Common::String AdlEngine_v3::getItemDescription(const Item &item) const {
return _itemDesc[item.description - 1];
}
+void AdlEngine_v3::loadItemDescriptions(Common::SeekableReadStream &stream, byte count) {
+ int32 startPos = stream.pos();
+ uint16 baseAddr = stream.readUint16LE();
+debug("%04x", baseAddr);
+ // This code assumes that the first pointer points to a string that
+ // directly follows the pointer table
+ assert(baseAddr != 0);
+ baseAddr -= count * 2;
+
+ for (uint i = 0; i < count; ++i) {
+ stream.seek(startPos + i * 2);
+ uint16 offset = stream.readUint16LE();
+
+ if (offset > 0) {
+ stream.seek(startPos + offset - baseAddr);
+ _itemDesc.push_back(readString(stream, 0xff));
+ } else
+ _itemDesc.push_back(Common::String());
+ }
+
+ if (stream.eos() || stream.err())
+ error("Error loading item descriptions");
+}
+
typedef Common::Functor1Mem<ScriptEnv &, int, AdlEngine_v3> OpcodeV3;
void AdlEngine_v3::setupOpcodeTables() {
diff --git a/engines/adl/adl_v3.h b/engines/adl/adl_v3.h
index 759b17cc6f..b0d40f3993 100644
--- a/engines/adl/adl_v3.h
+++ b/engines/adl/adl_v3.h
@@ -38,6 +38,8 @@ protected:
virtual void setupOpcodeTables();
Common::String getItemDescription(const Item &item) const;
+ void loadItemDescriptions(Common::SeekableReadStream &stream, byte count);
+
int o3_isNounNotInRoom(ScriptEnv &e);
int o3_listInv(ScriptEnv &e);
diff --git a/engines/adl/adl_v4.cpp b/engines/adl/adl_v4.cpp
index 602ee25683..ed20c82513 100644
--- a/engines/adl/adl_v4.cpp
+++ b/engines/adl/adl_v4.cpp
@@ -59,21 +59,8 @@ void AdlEngine_v4::applyDiskOffset(byte &track, byte &sector) const {
track += _diskOffsets[_curDisk].track;
}
-DataBlockPtr AdlEngine_v4::readDataBlockPtr(Common::ReadStream &f) const {
- byte track = f.readByte();
- byte sector = f.readByte();
- byte offset = f.readByte();
- byte size = f.readByte();
-
- if (f.eos() || f.err())
- error("Error reading DataBlockPtr");
-
- if (track == 0 && sector == 0 && offset == 0 && size == 0)
- return DataBlockPtr();
-
+void AdlEngine_v4::adjustDataBlockPtr(byte &track, byte &sector, byte &offset, byte &size) const {
applyDiskOffset(track, sector);
-
- return _disk->getDataBlock(track, sector, offset, size);
}
typedef Common::Functor1Mem<ScriptEnv &, int, AdlEngine_v4> OpcodeV4;
diff --git a/engines/adl/adl_v4.h b/engines/adl/adl_v4.h
index dc9a27501e..79aa824d92 100644
--- a/engines/adl/adl_v4.h
+++ b/engines/adl/adl_v4.h
@@ -49,7 +49,7 @@ protected:
Common::String getItemDescription(const Item &item) const;
// AdlEngine_v2
- virtual DataBlockPtr readDataBlockPtr(Common::ReadStream &f) const;
+ virtual void adjustDataBlockPtr(byte &track, byte &sector, byte &offset, byte &size) const;
void applyDiskOffset(byte &track, byte &sector) const;
diff --git a/engines/adl/hires0.cpp b/engines/adl/hires0.cpp
index 875a06c73d..5bfe482c7c 100644
--- a/engines/adl/hires0.cpp
+++ b/engines/adl/hires0.cpp
@@ -134,31 +134,7 @@ void HiRes0Engine::initGameState() {
stream.reset(_disk->createReadStream(0x21, 0x0));
- byte id;
- while ((id = stream->readByte()) != 0xff) {
- Item item = Item();
- item.id = id;
- item.noun = stream->readByte();
- item.room = stream->readByte();
- item.picture = stream->readByte();
- item.isLineArt = stream->readByte();
- item.position.x = stream->readByte();
- item.position.y = stream->readByte();
- item.state = stream->readByte();
- item.description = stream->readByte();
-
- stream->readByte(); // Struct size
-
- byte picListSize = stream->readByte();
-
- // Flag to keep track of what has been drawn on the screen
- stream->readByte();
-
- for (uint i = 0; i < picListSize; ++i)
- item.roomPictures.push_back(stream->readByte());
-
- _state.items.push_back(item);
- }
+ loadItems(*stream);
}
Engine *HiRes0Engine_create(OSystem *syst, const AdlGameDescription *gd) {
diff --git a/engines/adl/hires2.cpp b/engines/adl/hires2.cpp
index d0e459c96c..34de51885a 100644
--- a/engines/adl/hires2.cpp
+++ b/engines/adl/hires2.cpp
@@ -157,31 +157,7 @@ void HiRes2Engine::initGameState() {
stream.reset(_disk->createReadStream(0x21, 0x0, 0x00, 2));
- byte id;
- while ((id = stream->readByte()) != 0xff) {
- Item item = Item();
- item.id = id;
- item.noun = stream->readByte();
- item.room = stream->readByte();
- item.picture = stream->readByte();
- item.isLineArt = stream->readByte(); // Is this still used in this way?
- item.position.x = stream->readByte();
- item.position.y = stream->readByte();
- item.state = stream->readByte();
- item.description = stream->readByte();
-
- stream->readByte(); // Struct size
-
- byte picListSize = stream->readByte();
-
- // Flag to keep track of what has been drawn on the screen
- stream->readByte();
-
- for (uint i = 0; i < picListSize; ++i)
- item.roomPictures.push_back(stream->readByte());
-
- _state.items.push_back(item);
- }
+ loadItems(*stream);
}
Engine *HiRes2Engine_create(OSystem *syst, const AdlGameDescription *gd) {
diff --git a/engines/adl/hires4.cpp b/engines/adl/hires4.cpp
index 22fd9c2f81..1ce2a44c4a 100644
--- a/engines/adl/hires4.cpp
+++ b/engines/adl/hires4.cpp
@@ -27,24 +27,89 @@
#include "common/stream.h"
#include "adl/hires4.h"
+#include "adl/detection.h"
#include "adl/display.h"
#include "adl/graphics.h"
#include "adl/disk.h"
namespace Adl {
-void HiRes4Engine::runIntro() const {
+HiRes4Engine::~HiRes4Engine() {
+ delete _disk2;
+ delete _disk3;
}
void HiRes4Engine::init() {
_graphics = new Graphics_v2(*_display);
+
+ const char *const *names = getDiskImageNames();
+
+ _disk = new DiskImage();
+ if (!_disk->open(names[0]))
+ error("Failed to open disk image '%s'", names[0]);
+
+ _disk2 = new DiskImage();
+ if (!_disk2->open(names[1]))
+ error("Failed to open disk image '%s'", names[1]);
+
+ _disk3 = new DiskImage();
+ if (!_disk3->open(names[2]))
+ error("Failed to open disk image '%s'", names[2]);
+
+ StreamPtr stream(createReadStream(_disk, 0x06, 0xd, 0x12, 2));
+ loadItemDescriptions(*stream, IDI_HR4_NUM_ITEM_DESCS);
+
+ stream.reset(createReadStream(_disk, 0x05, 0x4, 0x00, 3));
+ loadWords(*stream, _verbs, _priVerbs);
+
+ stream.reset(createReadStream(_disk, 0x03, 0xb, 0x00, 6));
+ loadWords(*stream, _nouns, _priNouns);
}
void HiRes4Engine::initGameState() {
+ StreamPtr stream(createReadStream(_disk, 0x02, 0xc, 0x00, 12));
+ loadItems(*stream);
+}
+
+Common::SeekableReadStream *HiRes4Engine::createReadStream(DiskImage *disk, byte track, byte sector, byte offset, byte size) const {
+ adjustDataBlockPtr(track, sector, offset, size);
+ return disk->createReadStream(track, sector, offset, size);
+}
+
+void HiRes4Engine_Atari::adjustDataBlockPtr(byte &track, byte &sector, byte &offset, byte &size) const {
+ // Convert the Apple II disk offsets in the game, to Atari disk offsets
+ uint sectorIndex = (track * 16 + sector + 1) << 1;
+
+ // Atari uses 128 bytes per sector vs. 256 on the Apple II
+ // Note that size indicates *additional* sectors to read after reading one sector
+ size *= 2;
+
+ if (offset >= 128) {
+ // Offset in the second half of an Apple II sector, skip one sector and adjust offset
+ ++sectorIndex;
+ offset -= 128;
+ } else {
+ // Offset in the first half of an Apple II sector, we need to read one additional sector
+ ++size;
+ }
+
+ // Compute track/sector for Atari's 18 sectors per track (sectorIndex is 1-based)
+ track = (sectorIndex - 1) / 18;
+ sector = (sectorIndex - 1) % 18;
+}
+
+const char *const *HiRes4Engine_Atari::getDiskImageNames() const {
+ static const char *const disks[] = { "ULYS1A.XFD", "ULYS1B.XFD", "ULYS2C.XFD" };
+ return disks;
}
Engine *HiRes4Engine_create(OSystem *syst, const AdlGameDescription *gd) {
- return new HiRes4Engine(syst, gd);
+ switch (gd->desc.platform) {
+ case Common::kPlatformAtariST:
+ return new HiRes4Engine_Atari(syst, gd);
+ default:
+ error("Unsupported platform");
+ }
}
} // End of namespace Adl
diff --git a/engines/adl/hires4.h b/engines/adl/hires4.h
index f1c429ce38..a578080857 100644
--- a/engines/adl/hires4.h
+++ b/engines/adl/hires4.h
@@ -29,15 +29,36 @@
namespace Adl {
+#define IDI_HR4_NUM_ITEM_DESCS 44
+
class HiRes4Engine : public AdlEngine_v3 {
public:
+ ~HiRes4Engine();
+
+protected:
HiRes4Engine(OSystem *syst, const AdlGameDescription *gd) : AdlEngine_v3(syst, gd) { }
-private:
// AdlEngine
- void runIntro() const;
void init();
void initGameState();
+
+ Common::SeekableReadStream *createReadStream(DiskImage *disk, byte track, byte sector, byte offset = 0, byte size = 0) const;
+ virtual const char *const *getDiskImageNames() const = 0;
+
+ // FIXME: use an array?
+ DiskImage *_disk2, *_disk3;
+};
+
+class HiRes4Engine_Atari : public HiRes4Engine {
+public:
+ HiRes4Engine_Atari(OSystem *syst, const AdlGameDescription *gd) : HiRes4Engine(syst, gd) { }
+
+private:
+ // AdlEngine_v2
+ virtual void adjustDataBlockPtr(byte &track, byte &sector, byte &offset, byte &size) const;
+
+ // HiRes4Engine
+ virtual const char *const *getDiskImageNames() const;
};
} // End of namespace Adl
diff --git a/engines/adl/hires6.cpp b/engines/adl/hires6.cpp
index e9df7b513a..cf06591f6d 100644
--- a/engines/adl/hires6.cpp
+++ b/engines/adl/hires6.cpp
@@ -141,9 +141,8 @@ void HiRes6Engine::init() {
// Item descriptions
stream.reset(loadSectors(_boot, 0x6, 0xb, 2));
- stream->seek(0x34);
- for (uint i = 0; i < IDI_HR6_NUM_ITEM_DESCS; ++i)
- _itemDesc.push_back(readString(*stream, 0xff));
+ stream->seek(0x16);
+ loadItemDescriptions(*stream, IDI_HR6_NUM_ITEM_DESCS);
// Load dropped item offsets
stream.reset(_boot->createReadStream(0x8, 0x9, 0x16));
@@ -287,31 +286,7 @@ void HiRes6Engine::initGameState() {
StreamPtr stream(_boot->createReadStream(0x3, 0xe, 0x03));
- byte id;
- while ((id = stream->readByte()) != 0xff) {
- Item item = Item();
- item.id = id;
- item.noun = stream->readByte();
- item.room = stream->readByte();
- item.picture = stream->readByte();
- item.isLineArt = stream->readByte(); // Now seems to be disk number
- item.position.x = stream->readByte();
- item.position.y = stream->readByte();
- item.state = stream->readByte();
- item.description = stream->readByte();
-
- stream->readByte(); // Struct size
-
- byte picListSize = stream->readByte();
-
- // Flag to keep track of what has been drawn on the screen
- stream->readByte();
-
- for (uint i = 0; i < picListSize; ++i)
- item.roomPictures.push_back(stream->readByte());
-
- _state.items.push_back(item);
- }
+ loadItems(*stream);
_currVerb = _currNoun = 0;
}