From bdda3447a3c0eebc31ac3202699a397ca4122ddf Mon Sep 17 00:00:00 2001 From: Walter van Niftrik Date: Sat, 3 Feb 2018 11:42:03 +0100 Subject: ADL: Add support for an early hires1 version --- engines/adl/adl.cpp | 10 ++---- engines/adl/adl.h | 5 ++- engines/adl/detection.cpp | 85 +++++++++++++++++++++++++++++++++++++++-------- engines/adl/detection.h | 17 ++++++---- engines/adl/disk.cpp | 22 ++++++------ engines/adl/disk.h | 10 +++--- engines/adl/hires1.cpp | 62 +++++++++++++++++++--------------- engines/adl/hires4.cpp | 4 +-- engines/adl/hires6.cpp | 2 +- 9 files changed, 145 insertions(+), 72 deletions(-) (limited to 'engines') diff --git a/engines/adl/adl.cpp b/engines/adl/adl.cpp index fba97db98b..bf04860d14 100644 --- a/engines/adl/adl.cpp +++ b/engines/adl/adl.cpp @@ -74,10 +74,6 @@ AdlEngine::AdlEngine(OSystem *syst, const AdlGameDescription *gd) : DebugMan.addDebugChannel(kDebugChannelScript, "Script", "Trace script execution"); } -Common::String AdlEngine::getDiskImageName(byte volume) const { - return Adl::getDiskImageName(_gameDescription->desc, volume); -} - bool AdlEngine::pollEvent(Common::Event &event) const { _console->onFrame(); @@ -256,15 +252,15 @@ void AdlEngine::loadWords(Common::ReadStream &stream, WordMap &map, Common::Stri break; // WORKAROUND: Missing verb list terminator in hires3 - if (_gameDescription->gameType == GAME_TYPE_HIRES3 && index == 72 && synonyms == 0) + if (getGameType() == GAME_TYPE_HIRES3 && index == 72 && synonyms == 0) return; // WORKAROUND: Missing noun list terminator in hires3 - if (_gameDescription->gameType == GAME_TYPE_HIRES3 && index == 113) + if (getGameType() == GAME_TYPE_HIRES3 && index == 113) return; // WORKAROUND: Missing noun list terminator in hires5 region 15 - if (_gameDescription->gameType == GAME_TYPE_HIRES5 && _state.region == 15 && index == 81) + if (getGameType() == GAME_TYPE_HIRES5 && _state.region == 15 && index == 81) return; for (uint i = 0; i < synonyms; ++i) { diff --git a/engines/adl/adl.h b/engines/adl/adl.h index 44f16edab6..d53cf5a67c 100644 --- a/engines/adl/adl.h +++ b/engines/adl/adl.h @@ -40,6 +40,7 @@ #include "adl/console.h" #include "adl/disk.h" #include "adl/sound.h" +#include "adl/detection.h" namespace Common { class ReadStream; @@ -241,7 +242,9 @@ protected: Common::Error saveGameState(int slot, const Common::String &desc); bool canSaveGameStateCurrently(); - Common::String getDiskImageName(byte volume) const; + Common::String getDiskImageName(byte volume) const { return Adl::getDiskImageName(*_gameDescription, volume); } + GameType getGameType() const { return Adl::getGameType(*_gameDescription); } + GameVersion getGameVersion() const { return Adl::getGameVersion(*_gameDescription); } virtual void gameLoop(); virtual void loadState(Common::ReadStream &stream); virtual void saveState(Common::WriteStream &stream); diff --git a/engines/adl/detection.cpp b/engines/adl/detection.cpp index 7e395169b1..7c196d34cb 100644 --- a/engines/adl/detection.cpp +++ b/engines/adl/detection.cpp @@ -87,8 +87,30 @@ static const PlainGameDescriptor adlGames[] = { { 0, 0 } }; +struct AdlGameDescription { + ADGameDescription desc; + GameType gameType; + GameVersion version; +}; + static const AdlGameDescription gameFileDescriptions[] = { - { // Hi-Res Adventure #1: Mystery House - Apple II - 1987 PD release + { // Hi-Res Adventure #1: Mystery House - Apple II - 2nd release + { + "hires1", 0, + { + { "ADVENTURE", 0, "22d9e63a11d69fa033ba1738715ad09a", 29952 }, + { "AUTO LOAD OBJ", 0, "f6a6ac60c04c6ba6dff68b92cc279ba2", 12291 }, + AD_LISTEND + }, + Common::EN_ANY, + Common::kPlatformApple2, + ADGF_NO_FLAGS, + GUIO2(GAMEOPTION_COLOR_DEFAULT_OFF, GAMEOPTION_SCANLINES) + }, + GAME_TYPE_HIRES1, + GAME_VER_HR1_COARSE + }, + { // Hi-Res Adventure #1: Mystery House - Apple II - Roberta Williams Anthology { "hires1", 0, { @@ -102,9 +124,10 @@ static const AdlGameDescription gameFileDescriptions[] = { ADGF_NO_FLAGS, GUIO2(GAMEOPTION_COLOR_DEFAULT_OFF, GAMEOPTION_SCANLINES) }, - GAME_TYPE_HIRES1 + GAME_TYPE_HIRES1, + GAME_VER_HR1_PD }, - { AD_TABLE_END_MARKER, GAME_TYPE_NONE } + { AD_TABLE_END_MARKER, GAME_TYPE_NONE, GAME_VER_NONE } }; static const AdlGameDescription gameDiskDescriptions[] = { @@ -120,7 +143,23 @@ static const AdlGameDescription gameDiskDescriptions[] = { ADGF_NO_FLAGS, GUIO2(GAMEOPTION_COLOR_DEFAULT_OFF, GAMEOPTION_SCANLINES) }, - GAME_TYPE_HIRES1 + GAME_TYPE_HIRES1, + GAME_VER_HR1_PD + }, + { // Hi-Res Adventure #1: Mystery House - Apple II - 2nd release + { + "hires1", 0, + { + { "mysthous", 0, "8df0b3b3e609a2e40237e2419c1cb767", 116480 }, + AD_LISTEND + }, + Common::EN_ANY, + Common::kPlatformApple2, + ADGF_NO_FLAGS, + GUIO2(GAMEOPTION_COLOR_DEFAULT_OFF, GAMEOPTION_SCANLINES) + }, + GAME_TYPE_HIRES1, + GAME_VER_HR1_COARSE }, { // Hi-Res Adventure #2: Wizard and the Princess - Apple II - Roberta Williams Anthology { @@ -134,7 +173,8 @@ static const AdlGameDescription gameDiskDescriptions[] = { ADGF_NO_FLAGS, GUIO2(GAMEOPTION_COLOR_DEFAULT_ON, GAMEOPTION_SCANLINES) }, - GAME_TYPE_HIRES2 + GAME_TYPE_HIRES2, + GAME_VER_NONE }, { // Hi-Res Adventure #0: Mission Asteroid - Apple II - Roberta Williams Anthology { @@ -148,7 +188,8 @@ static const AdlGameDescription gameDiskDescriptions[] = { ADGF_NO_FLAGS, GUIO2(GAMEOPTION_COLOR_DEFAULT_ON, GAMEOPTION_SCANLINES) }, - GAME_TYPE_HIRES0 + GAME_TYPE_HIRES0, + GAME_VER_NONE }, { // Hi-Res Adventure #3: Cranston Manor - Apple II { @@ -162,7 +203,8 @@ static const AdlGameDescription gameDiskDescriptions[] = { ADGF_NO_FLAGS, GUIO2(GAMEOPTION_COLOR_DEFAULT_ON, GAMEOPTION_SCANLINES) }, - GAME_TYPE_HIRES3 + GAME_TYPE_HIRES3, + GAME_VER_NONE }, { // Hi-Res Adventure #4: Ulysses and the Golden Fleece - Apple II - Load 'N' Go { @@ -177,7 +219,8 @@ static const AdlGameDescription gameDiskDescriptions[] = { ADGF_NO_FLAGS, GUIO2(GAMEOPTION_COLOR_DEFAULT_ON, GAMEOPTION_SCANLINES) }, - GAME_TYPE_HIRES4 + GAME_TYPE_HIRES4, + GAME_VER_NONE }, { // Hi-Res Adventure #4: Ulysses and the Golden Fleece - Atari 8-bit - Re-release { @@ -194,7 +237,8 @@ static const AdlGameDescription gameDiskDescriptions[] = { ADGF_UNSTABLE, GUIO2(GAMEOPTION_COLOR_DEFAULT_ON, GAMEOPTION_SCANLINES) }, - GAME_TYPE_HIRES4 + GAME_TYPE_HIRES4, + GAME_VER_NONE }, { // Hi-Res Adventure #5: Time Zone - Apple II - Version 1.1 - Roberta Williams Anthology { @@ -219,7 +263,8 @@ static const AdlGameDescription gameDiskDescriptions[] = { ADGF_NO_FLAGS, GUIO2(GAMEOPTION_COLOR_DEFAULT_ON, GAMEOPTION_SCANLINES) }, - GAME_TYPE_HIRES5 + GAME_TYPE_HIRES5, + GAME_VER_NONE }, { // Hi-Res Adventure #6: The Dark Crystal - Apple II - Roberta Williams Anthology { @@ -236,9 +281,10 @@ static const AdlGameDescription gameDiskDescriptions[] = { ADGF_NO_FLAGS, GUIO2(GAMEOPTION_COLOR_DEFAULT_ON, GAMEOPTION_SCANLINES) }, - GAME_TYPE_HIRES6 + GAME_TYPE_HIRES6, + GAME_VER_NONE }, - { AD_TABLE_END_MARKER, GAME_TYPE_NONE } + { AD_TABLE_END_MARKER, GAME_TYPE_NONE, GAME_VER_NONE } }; struct DiskImageExt { @@ -392,7 +438,8 @@ void AdlMetaEngine::removeSaveState(const char *target, int slot) const { g_system->getSavefileManager()->removeSavefile(fileName); } -Common::String getDiskImageName(const ADGameDescription &desc, byte volume) { +Common::String getDiskImageName(const AdlGameDescription &adlDesc, byte volume) { + const ADGameDescription &desc = adlDesc.desc; for (uint i = 0; desc.filesDescriptions[i].fileName; ++i) { const ADGameFileDescription &fDesc = desc.filesDescriptions[i]; @@ -413,6 +460,18 @@ Common::String getDiskImageName(const ADGameDescription &desc, byte volume) { error("Disk volume %d not found", volume); } +GameType getGameType(const AdlGameDescription &adlDesc) { + return adlDesc.gameType; +} + +GameVersion getGameVersion(const AdlGameDescription &adlDesc) { + return adlDesc.version; +} + +Common::Platform getPlatform(const AdlGameDescription &adlDesc) { + return adlDesc.desc.platform; +} + bool AdlMetaEngine::addFileProps(const FileMap &allFiles, Common::String fname, ADFilePropertiesMap &filePropsMap) const { if (filePropsMap.contains(fname)) return true; diff --git a/engines/adl/detection.h b/engines/adl/detection.h index ac8d834059..6f0ae6795b 100644 --- a/engines/adl/detection.h +++ b/engines/adl/detection.h @@ -23,8 +23,6 @@ #ifndef ADL_DETECTION_H #define ADL_DETECTION_H -#include "engines/advancedDetector.h" - namespace Adl { #define SAVEGAME_VERSION 0 @@ -41,12 +39,19 @@ enum GameType { GAME_TYPE_HIRES6 }; -struct AdlGameDescription { - ADGameDescription desc; - GameType gameType; +enum GameVersion { + GAME_VER_NONE = 0, + GAME_VER_HR1_SIMI = 0, // On-Line Systems (Simi Valley) + GAME_VER_HR1_COARSE, // On-Line Systems (Coarsegold) + GAME_VER_HR1_PD // Sierra On-Line PD release }; -Common::String getDiskImageName(const ADGameDescription &desc, byte volume); +struct AdlGameDescription; + +Common::String getDiskImageName(const AdlGameDescription &adlDesc, byte volume); +GameType getGameType(const AdlGameDescription &desc); +GameVersion getGameVersion(const AdlGameDescription &desc); +Common::Platform getPlatform(const AdlGameDescription &desc); } // End of namespace Adl diff --git a/engines/adl/disk.cpp b/engines/adl/disk.cpp index b715180d2e..27bc9b318c 100644 --- a/engines/adl/disk.cpp +++ b/engines/adl/disk.cpp @@ -405,15 +405,15 @@ Common::SeekableReadStream *Files_Plain::createReadStream(const Common::String & return new Common::SeekableSubReadStream(f, offset, f->size(), DisposeAfterUse::YES); } -Files_DOS33::~Files_DOS33() { +Files_AppleDOS::~Files_AppleDOS() { delete _disk; } -Files_DOS33::Files_DOS33() : +Files_AppleDOS::Files_AppleDOS() : _disk(nullptr) { } -void Files_DOS33::readSectorList(TrackSector start, Common::Array &list) { +void Files_AppleDOS::readSectorList(TrackSector start, Common::Array &list) { TrackSector index = start; while (index.track != 0) { @@ -445,8 +445,8 @@ void Files_DOS33::readSectorList(TrackSector start, Common::Array & } } -void Files_DOS33::readVTOC() { - Common::ScopedPtr stream(_disk->createReadStream(0x11, 0x00)); +void Files_AppleDOS::readVTOC(uint trackVTOC) { + Common::ScopedPtr stream(_disk->createReadStream(trackVTOC, 0x00)); stream->readByte(); byte track = stream->readByte(); byte sector = stream->readByte(); @@ -491,11 +491,11 @@ void Files_DOS33::readVTOC() { } } -const DataBlockPtr Files_DOS33::getDataBlock(const Common::String &filename, uint offset) const { +const DataBlockPtr Files_AppleDOS::getDataBlock(const Common::String &filename, uint offset) const { return Common::SharedPtr(new Files::DataBlock(this, filename, offset)); } -Common::SeekableReadStream *Files_DOS33::createReadStreamText(const TOCEntry &entry) const { +Common::SeekableReadStream *Files_AppleDOS::createReadStreamText(const TOCEntry &entry) const { byte *buf = (byte *)malloc(entry.sectors.size() * kSectorSize); byte *p = buf; @@ -520,7 +520,7 @@ Common::SeekableReadStream *Files_DOS33::createReadStreamText(const TOCEntry &en return new Common::MemoryReadStream(buf, p - buf, DisposeAfterUse::YES); } -Common::SeekableReadStream *Files_DOS33::createReadStreamBinary(const TOCEntry &entry) const { +Common::SeekableReadStream *Files_AppleDOS::createReadStreamBinary(const TOCEntry &entry) const { byte *buf = (byte *)malloc(entry.sectors.size() * kSectorSize); Common::ScopedPtr stream(_disk->createReadStream(entry.sectors[0].track, entry.sectors[0].sector)); @@ -553,7 +553,7 @@ Common::SeekableReadStream *Files_DOS33::createReadStreamBinary(const TOCEntry & return new Common::MemoryReadStream(buf, size, DisposeAfterUse::YES); } -Common::SeekableReadStream *Files_DOS33::createReadStream(const Common::String &filename, uint offset) const { +Common::SeekableReadStream *Files_AppleDOS::createReadStream(const Common::String &filename, uint offset) const { if (!_toc.contains(filename)) error("Failed to locate '%s'", filename.c_str()); @@ -576,12 +576,12 @@ Common::SeekableReadStream *Files_DOS33::createReadStream(const Common::String & return new Common::SeekableSubReadStream(stream, offset, stream->size(), DisposeAfterUse::YES); } -bool Files_DOS33::open(const Common::String &filename) { +bool Files_AppleDOS::open(const Common::String &filename, uint trackVTOC) { _disk = new DiskImage(); if (!_disk->open(filename)) return false; - readVTOC(); + readVTOC(trackVTOC); return true; } diff --git a/engines/adl/disk.h b/engines/adl/disk.h index 0ebe2e05c3..a13c2eeb47 100644 --- a/engines/adl/disk.h +++ b/engines/adl/disk.h @@ -128,12 +128,12 @@ public: }; // Data in files contained in Apple DOS 3.3 disk image -class Files_DOS33 : public Files { +class Files_AppleDOS : public Files { public: - Files_DOS33(); - ~Files_DOS33(); + Files_AppleDOS(); + ~Files_AppleDOS(); - bool open(const Common::String &filename); + 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; @@ -160,7 +160,7 @@ private: Common::Array sectors; }; - void readVTOC(); + void readVTOC(uint trackVTOC); void readSectorList(TrackSector start, Common::Array &list); Common::SeekableReadStream *createReadStreamText(const TOCEntry &entry) const; Common::SeekableReadStream *createReadStreamBinary(const TOCEntry &entry) const; diff --git a/engines/adl/hires1.cpp b/engines/adl/hires1.cpp index 2dcbd16e51..fe7ed20b3a 100644 --- a/engines/adl/hires1.cpp +++ b/engines/adl/hires1.cpp @@ -35,7 +35,6 @@ namespace Adl { #define IDS_HR1_EXE_0 "AUTO LOAD OBJ" #define IDS_HR1_EXE_1 "ADVENTURE" -#define IDS_HR1_LOADER "MYSTERY.HELLO" #define IDS_HR1_MESSAGES "MESSAGES" #define IDI_HR1_NUM_ROOMS 41 @@ -73,7 +72,6 @@ namespace Adl { #define IDI_HR1_OFS_GAME_OR_HELP 0x000f #define IDI_HR1_OFS_LOGO_0 0x1003 -#define IDI_HR1_OFS_LOGO_1 0x1800 #define IDI_HR1_OFS_ITEMS 0x0100 #define IDI_HR1_OFS_ROOMS 0x050a @@ -133,31 +131,44 @@ void HiRes1Engine::runIntro() { _display->setMode(DISPLAY_MODE_HIRES); _display->loadFrameBuffer(*stream); _display->updateHiResScreen(); - delay(4000); - if (shouldQuit()) - return; + if (getGameVersion() == GAME_VER_HR1_PD) { + // Only the PD version shows a title screen during the load + delay(4000); - _display->setMode(DISPLAY_MODE_TEXT); + if (shouldQuit()) + return; + } - StreamPtr basic(_files->createReadStream(IDS_HR1_LOADER)); Common::String str; - str = readStringAt(*basic, IDI_HR1_OFS_PD_TEXT_0, '"'); - _display->printAsciiString(str + '\r'); + // Show the PD disclaimer for the PD release + if (getGameVersion() == GAME_VER_HR1_PD) { + // The PD release on the Roberta Williams Anthology disc has a PDE + // splash screen. The original HELLO file has been renamed to + // MYSTERY.HELLO. It's unclear whether or not this splash screen + // was present in the original PD release back in 1987. + StreamPtr basic(_files->createReadStream("MYSTERY.HELLO")); - str = readStringAt(*basic, IDI_HR1_OFS_PD_TEXT_1, '"'); - _display->printAsciiString(str + "\r\r"); + _display->setMode(DISPLAY_MODE_TEXT); + _display->home(); - str = readStringAt(*basic, IDI_HR1_OFS_PD_TEXT_2, '"'); - _display->printAsciiString(str + "\r\r"); + str = readStringAt(*basic, IDI_HR1_OFS_PD_TEXT_0, '"'); + _display->printAsciiString(str + '\r'); - str = readStringAt(*basic, IDI_HR1_OFS_PD_TEXT_3, '"'); - _display->printAsciiString(str + '\r'); + str = readStringAt(*basic, IDI_HR1_OFS_PD_TEXT_1, '"'); + _display->printAsciiString(str + "\r\r"); - inputKey(); - if (g_engine->shouldQuit()) - return; + str = readStringAt(*basic, IDI_HR1_OFS_PD_TEXT_2, '"'); + _display->printAsciiString(str + "\r\r"); + + str = readStringAt(*basic, IDI_HR1_OFS_PD_TEXT_3, '"'); + _display->printAsciiString(str + '\r'); + + inputKey(); + if (g_engine->shouldQuit()) + return; + } _display->setMode(DISPLAY_MODE_MIXED); @@ -213,25 +224,24 @@ void HiRes1Engine::runIntro() { _display->setMode(DISPLAY_MODE_MIXED); - // Title screen shown during loading - stream.reset(_files->createReadStream(IDS_HR1_EXE_1)); - stream->seek(IDI_HR1_OFS_LOGO_1); - _display->loadFrameBuffer(*stream); - _display->updateHiResScreen(); - delay(2000); + // As we switch back to graphics mode, the title screen is briefly visible here + // (and in the PD version, it's a different title screen from the initial one). + // As this is probably non-intentional, we skip it and go straight to the game. } void HiRes1Engine::init() { if (Common::File::exists("ADVENTURE")) { _files = new Files_Plain(); } else { - Files_DOS33 *files = new Files_DOS33(); - if (!files->open(getDiskImageName(0))) + Files_AppleDOS *files = new Files_AppleDOS(); + // The 2nd release obfuscates the VTOC (same may be true for the 1st release) + if (!files->open(getDiskImageName(0), (getGameVersion() == GAME_VER_HR1_COARSE ? 16 : 17))) error("Failed to open '%s'", getDiskImageName(0).c_str()); _files = files; } _graphics = new GraphicsMan(*_display); + _display->moveCursorTo(Common::Point(0, 3)); StreamPtr stream(_files->createReadStream(IDS_HR1_EXE_1)); diff --git a/engines/adl/hires4.cpp b/engines/adl/hires4.cpp index 2aa9763883..df71e2ecef 100644 --- a/engines/adl/hires4.cpp +++ b/engines/adl/hires4.cpp @@ -419,7 +419,7 @@ void HiRes4Engine::runIntroLoading(Common::SeekableReadStream &adventure) { } void HiRes4Engine::runIntro() { - Common::ScopedPtr files(new Files_DOS33()); + Common::ScopedPtr files(new Files_AppleDOS()); files->open(getDiskImageName(0)); while (!shouldQuit()) { @@ -737,7 +737,7 @@ void HiRes4Engine_Atari::adjustDataBlockPtr(byte &track, byte §or, byte &off } Engine *HiRes4Engine_create(OSystem *syst, const AdlGameDescription *gd) { - switch (gd->desc.platform) { + switch (getPlatform(*gd)) { case Common::kPlatformApple2: return new HiRes4Engine(syst, gd); case Common::kPlatformAtari8Bit: diff --git a/engines/adl/hires6.cpp b/engines/adl/hires6.cpp index a8d2f3f88c..7f1a285d71 100644 --- a/engines/adl/hires6.cpp +++ b/engines/adl/hires6.cpp @@ -273,7 +273,7 @@ void HiRes6Engine::runIntro() { _display->loadFrameBuffer(*stream); // Load copyright string from boot file - Files_DOS33 *files(new Files_DOS33()); + Files_AppleDOS *files(new Files_AppleDOS()); if (!files->open(getDiskImageName(0))) error("Failed to open disk volume 0"); -- cgit v1.2.3