[Scummvm-git-logs] scummvm master -> 5f6c88ef15ff3e82178dab8fffbfc08b677cb100
waltervn
walter at vanniftrik-it.nl
Fri Jul 23 23:10:51 UTC 2021
This automated email contains information about 9 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
28e049e8d6 ADL: Require C++11
ce2742a828 ADL: Add detection entry for early hires1
eb6751a055 ADL: Try VTOC track 0x10 if 0x11 fails
960811fc55 ADL: Add support for another early hires1
f32dde20bd ADL: Scan for executable strings in hires1
56390d5f5f ADL: Add support for hires1 french (early version)
e8dd3b7085 ADL: Add delay after printing strings in hires1
01e6ec1649 ADL: Use slot 15 for autosave
5f6c88ef15 ADL: Add support for later French hires1
Commit: 28e049e8d6edb50152478b42713116215b95fb80
https://github.com/scummvm/scummvm/commit/28e049e8d6edb50152478b42713116215b95fb80
Author: Walter van Niftrik (walter at scummvm.org)
Date: 2021-07-24T00:56:51+02:00
Commit Message:
ADL: Require C++11
Changed paths:
engines/adl/configure.engine
diff --git a/engines/adl/configure.engine b/engines/adl/configure.engine
index c138b64943..4868e8d996 100644
--- a/engines/adl/configure.engine
+++ b/engines/adl/configure.engine
@@ -1,3 +1,3 @@
# This file is included from the main "configure" script
# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
-add_engine adl "ADL" yes "" "" "16bit highres"
+add_engine adl "ADL" yes "" "" "cxx11 16bit highres"
Commit: ce2742a828814900dabfd6ee7089d4694ecab8a4
https://github.com/scummvm/scummvm/commit/ce2742a828814900dabfd6ee7089d4694ecab8a4
Author: Walter van Niftrik (walter at scummvm.org)
Date: 2021-07-24T00:56:51+02:00
Commit Message:
ADL: Add detection entry for early hires1
Changed paths:
engines/adl/detection.cpp
engines/adl/hires1.cpp
diff --git a/engines/adl/detection.cpp b/engines/adl/detection.cpp
index 5fab9057c7..693efaef51 100644
--- a/engines/adl/detection.cpp
+++ b/engines/adl/detection.cpp
@@ -169,6 +169,18 @@ static const AdlGameDescription gameFileDescriptions[] = {
};
static const AdlGameDescription gameDiskDescriptions[] = {
+ { // Hi-Res Adventure #1: Mystery House - Apple II - Contains Simi Valley address
+ {
+ "hires1", "",
+ AD_ENTRY1s("mysthous", "629b9d034cbf8d8e3a612398f53a8dfc", 116480),
+ Common::EN_ANY,
+ Common::kPlatformApple2,
+ ADGF_NO_FLAGS,
+ MH_OPTIONS
+ },
+ GAME_TYPE_HIRES1,
+ GAME_VER_HR1_SIMI
+ },
{ // Hi-Res Adventure #1: Mystery House - Apple II - Contains Coarsegold address
{
"hires1", "",
diff --git a/engines/adl/hires1.cpp b/engines/adl/hires1.cpp
index 0eae793d48..8f6a9248fa 100644
--- a/engines/adl/hires1.cpp
+++ b/engines/adl/hires1.cpp
@@ -262,8 +262,8 @@ void HiRes1Engine::init() {
_files = new Files_Plain();
} else {
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)))
+ // Non-PD versions have an obfuscated VTOC
+ if (!files->open(getDiskImageName(0), (getGameVersion() == GAME_VER_HR1_PD ? 17 : 16)))
error("Failed to open '%s'", getDiskImageName(0).c_str());
_files = files;
}
Commit: eb6751a055abe4400c0fe06415b527389ffcf99b
https://github.com/scummvm/scummvm/commit/eb6751a055abe4400c0fe06415b527389ffcf99b
Author: Walter van Niftrik (walter at scummvm.org)
Date: 2021-07-24T00:56:51+02:00
Commit Message:
ADL: Try VTOC track 0x10 if 0x11 fails
Changed paths:
engines/adl/disk.cpp
engines/adl/disk.h
engines/adl/hires1.cpp
diff --git a/engines/adl/disk.cpp b/engines/adl/disk.cpp
index 4c3c450ad5..dd241e587c 100644
--- a/engines/adl/disk.cpp
+++ b/engines/adl/disk.cpp
@@ -684,10 +684,21 @@ void Files_AppleDOS::readSectorList(TrackSector start, Common::Array<TrackSector
}
}
-void Files_AppleDOS::readVTOC(uint trackVTOC) {
- Common::ScopedPtr<Common::SeekableReadStream> stream(_disk->createReadStream(trackVTOC, 0x00));
+void Files_AppleDOS::readVTOC() {
+ Common::ScopedPtr<Common::SeekableReadStream> stream(_disk->createReadStream(0x11, 0x00));
stream->readByte();
byte track = stream->readByte();
+
+ if (!track) {
+ // VTOC probably obfuscated, try track 0x10
+ stream.reset(_disk->createReadStream(0x10, 0x00));
+ stream->readByte();
+ track = stream->readByte();
+ }
+
+ if (!track)
+ error("VTOC not found");
+
byte sector = stream->readByte();
while (track != 0) {
@@ -815,12 +826,12 @@ Common::SeekableReadStream *Files_AppleDOS::createReadStream(const Common::Strin
return new Common::SeekableSubReadStream(stream, offset, stream->size(), DisposeAfterUse::YES);
}
-bool Files_AppleDOS::open(const Common::String &filename, uint trackVTOC) {
+bool Files_AppleDOS::open(const Common::String &filename) {
_disk = new DiskImage();
if (!_disk->open(filename))
return false;
- readVTOC(trackVTOC);
+ readVTOC();
return true;
}
diff --git a/engines/adl/disk.h b/engines/adl/disk.h
index 4de23e9aea..8759e7efe1 100644
--- a/engines/adl/disk.h
+++ b/engines/adl/disk.h
@@ -134,7 +134,7 @@ public:
Files_AppleDOS();
~Files_AppleDOS() override;
- bool open(const Common::String &filename, uint trackVTOC = 17);
+ bool open(const Common::String &filename);
const DataBlockPtr getDataBlock(const Common::String &filename, uint offset = 0) const override;
Common::SeekableReadStream *createReadStream(const Common::String &filename, uint offset = 0) const override;
@@ -161,7 +161,7 @@ private:
Common::Array<TrackSector> sectors;
};
- void readVTOC(uint trackVTOC);
+ void readVTOC();
void readSectorList(TrackSector start, Common::Array<TrackSector> &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 8f6a9248fa..c29547043e 100644
--- a/engines/adl/hires1.cpp
+++ b/engines/adl/hires1.cpp
@@ -262,8 +262,7 @@ void HiRes1Engine::init() {
_files = new Files_Plain();
} else {
Files_AppleDOS *files = new Files_AppleDOS();
- // Non-PD versions have an obfuscated VTOC
- if (!files->open(getDiskImageName(0), (getGameVersion() == GAME_VER_HR1_PD ? 17 : 16)))
+ if (!files->open(getDiskImageName(0)))
error("Failed to open '%s'", getDiskImageName(0).c_str());
_files = files;
}
Commit: 960811fc554656acfbdf18ca90005102c2208a19
https://github.com/scummvm/scummvm/commit/960811fc554656acfbdf18ca90005102c2208a19
Author: Walter van Niftrik (walter at scummvm.org)
Date: 2021-07-24T00:56:51+02:00
Commit Message:
ADL: Add support for another early hires1
Changed paths:
engines/adl/detection.cpp
engines/adl/hires1.cpp
diff --git a/engines/adl/detection.cpp b/engines/adl/detection.cpp
index 693efaef51..c47f7c3fe6 100644
--- a/engines/adl/detection.cpp
+++ b/engines/adl/detection.cpp
@@ -116,9 +116,9 @@ static const PlainGameDescriptor adlGames[] = {
};
static const AdlGameDescription gameFileDescriptions[] = {
- { // Hi-Res Adventure #1: Mystery House - Apple II - Contains Simi Valley address
+ { // Hi-Res Adventure #1: Mystery House - Apple II - Simi Valley
{
- "hires1", 0,
+ "hires1", "V1",
{
{ "ADVENTURE", 0, "22d9e63a11d69fa033ba1738715ad09a", 29952 },
{ "AUTO LOAD OBJ", 0, "a2ab7be25842e1fa9f1343b0894a8b6f", 4095 },
@@ -132,9 +132,25 @@ static const AdlGameDescription gameFileDescriptions[] = {
GAME_TYPE_HIRES1,
GAME_VER_HR1_SIMI
},
- { // Hi-Res Adventure #1: Mystery House - Apple II - Contains Coarsegold address
+ { // Hi-Res Adventure #1: Mystery House - Apple II - Coarsegold - Without MIXEDON
{
- "hires1", 0,
+ "hires1", "V2",
+ {
+ { "ADVENTURE", 0, "22d9e63a11d69fa033ba1738715ad09a", 29952 },
+ { "AUTO LOAD OBJ", 0, "669b5f313ffdfb373ab8dce5961688d3", 12288 },
+ AD_LISTEND
+ },
+ Common::EN_ANY,
+ Common::kPlatformApple2,
+ ADGF_NO_FLAGS,
+ MH_OPTIONS
+ },
+ GAME_TYPE_HIRES1,
+ GAME_VER_HR1_COARSE
+ },
+ { // Hi-Res Adventure #1: Mystery House - Apple II - Coarsegold - With MIXEDON
+ {
+ "hires1", "V3",
{
{ "ADVENTURE", 0, "22d9e63a11d69fa033ba1738715ad09a", 29952 },
{ "AUTO LOAD OBJ", 0, "f6a6ac60c04c6ba6dff68b92cc279ba2", 12291 },
@@ -169,9 +185,9 @@ static const AdlGameDescription gameFileDescriptions[] = {
};
static const AdlGameDescription gameDiskDescriptions[] = {
- { // Hi-Res Adventure #1: Mystery House - Apple II - Contains Simi Valley address
+ { // Hi-Res Adventure #1: Mystery House - Apple II - Simi Valley
{
- "hires1", "",
+ "hires1", "V1",
AD_ENTRY1s("mysthous", "629b9d034cbf8d8e3a612398f53a8dfc", 116480),
Common::EN_ANY,
Common::kPlatformApple2,
@@ -181,9 +197,21 @@ static const AdlGameDescription gameDiskDescriptions[] = {
GAME_TYPE_HIRES1,
GAME_VER_HR1_SIMI
},
- { // Hi-Res Adventure #1: Mystery House - Apple II - Contains Coarsegold address
+ { // Hi-Res Adventure #1: Mystery House - Apple II - Coarsegold - Without MIXEDON
+ {
+ "hires1", "V2",
+ AD_ENTRY1s("mysthous", "b22561b5327c7dcdb659e2d649749310", 116480),
+ Common::EN_ANY,
+ Common::kPlatformApple2,
+ ADGF_NO_FLAGS,
+ MH_OPTIONS
+ },
+ GAME_TYPE_HIRES1,
+ GAME_VER_HR1_COARSE
+ },
+ { // Hi-Res Adventure #1: Mystery House - Apple II - Coarsegold - With MIXEDON
{
- "hires1", "",
+ "hires1", "V3",
AD_ENTRY1s("mysthous", "8df0b3b3e609a2e40237e2419c1cb767", 116480),
Common::EN_ANY,
Common::kPlatformApple2,
@@ -195,7 +223,7 @@ static const AdlGameDescription gameDiskDescriptions[] = {
},
{ // Hi-Res Adventure #1: Mystery House - Apple II - Roberta Williams Anthology
{
- "hires1", "",
+ "hires1", "PD",
AD_ENTRY1s("mysthous", "54d20eb1ef0084ac3c2d16c31c5b7eb7", 143360),
Common::EN_ANY,
Common::kPlatformApple2,
diff --git a/engines/adl/hires1.cpp b/engines/adl/hires1.cpp
index c29547043e..9a8f149739 100644
--- a/engines/adl/hires1.cpp
+++ b/engines/adl/hires1.cpp
@@ -68,11 +68,6 @@ namespace Adl {
#define IDI_HR1_OFS_PD_TEXT_2 0x016d
#define IDI_HR1_OFS_PD_TEXT_3 0x0259
-#define IDI_HR1_OFS_INTRO_TEXT 0x0066
-#define IDI_HR1_OFS_GAME_OR_HELP 0x000f
-
-#define IDI_HR1_OFS_LOGO_0 0x1003
-
#define IDI_HR1_OFS_ITEMS 0x0100
#define IDI_HR1_OFS_ROOMS 0x050a
#define IDI_HR1_OFS_PICS 0x4b03
@@ -108,7 +103,7 @@ private:
void loadRoom(byte roomNr) override;
void showRoom() override;
- void showInstructions(Common::SeekableReadStream &stream, const uint pages[], bool goHome);
+ void showInstructions(Common::SeekableReadStream &stream);
void wordWrap(Common::String &str) const;
Files *_files;
@@ -125,26 +120,43 @@ private:
} _gameStrings;
};
-void HiRes1Engine::showInstructions(Common::SeekableReadStream &stream, const uint pages[], bool goHome) {
+void HiRes1Engine::showInstructions(Common::SeekableReadStream &stream) {
_display->setMode(Display::kModeText);
- uint page = 0;
- while (pages[page] != 0) {
- if (goHome)
+ for (;;) {
+ byte opc = stream.readByte();
+
+ if (opc != 0x20)
+ error("Error reading instructions");
+
+ uint16 addr = stream.readUint16BE();
+
+ if (addr == 0x58fc) {
+ // HOME
_display->home();
+ } else if (addr == 0x6ffd) {
+ // GETLN1
+ inputString();
- uint count = pages[page++];
- for (uint i = 0; i < count; ++i) {
- _display->printString(readString(stream));
- stream.seek(3, SEEK_CUR);
- }
+ if (shouldQuit())
+ return;
+ } else {
+ // We assume print string call (addr varies per game)
+ Common::String str = readString(stream);
- inputString();
+ if (stream.err() || stream.eos())
+ error("Error reading instructions");
- if (shouldQuit())
- return;
+ // Ctrl-D signifies system command (main binary would be loaded here)
+ size_t posChr4 = str.findFirstOf(_display->asciiToNative(4));
+
+ if (posChr4 != str.npos) {
+ _display->printString(str.substr(0, posChr4));
+ return;
+ }
- stream.seek((goHome ? 6 : 3), SEEK_CUR);
+ _display->printString(str);
+ }
}
}
@@ -153,7 +165,12 @@ void HiRes1Engine::runIntro() {
// Early version have no bitmap in 'AUTO LOAD OBJ'
if (getGameVersion() >= GAME_VER_HR1_COARSE) {
- stream->seek(IDI_HR1_OFS_LOGO_0);
+ // Later binaries have a MIXEDON prepended to it, by skipping it
+ // we can use the same offsets for both variants
+ if (stream->readUint16BE() == 0xad53)
+ stream.reset(_files->createReadStream(IDS_HR1_EXE_0, 3));
+
+ stream->seek(0x1000);
_display->setMode(Display::kModeGraphics);
static_cast<Display_A2 *>(_display)->loadFrameBuffer(*stream);
_display->renderGraphics();
@@ -199,7 +216,7 @@ void HiRes1Engine::runIntro() {
_display->setMode(Display::kModeMixed);
- str = readStringAt(*stream, IDI_HR1_OFS_GAME_OR_HELP);
+ str = readStringAt(*stream, 0xc);
if (getGameVersion() >= GAME_VER_HR1_COARSE) {
bool instructions = false;
@@ -223,17 +240,16 @@ void HiRes1Engine::runIntro() {
}
if (instructions) {
- // This version shows the last page during the loading of the game
- // We wait for a key instead (even though there's no prompt for that).
- const uint pages[] = { 6, 6, 4, 5, 8, 7, 0 };
- stream->seek(IDI_HR1_OFS_INTRO_TEXT);
- showInstructions(*stream, pages, true);
+ stream->seek(0x5d);
+ showInstructions(*stream);
_display->printAsciiString("\r");
}
} else {
- const uint pages[] = { 6, 6, 8, 6, 0 };
- stream->seek(6);
- showInstructions(*stream, pages, false);
+ // This version shows the last page during the loading of the game
+ // We wait for a key instead (even though there's no prompt for that).
+ stream->seek(3);
+ showInstructions(*stream);
+ inputString();
}
stream.reset(_files->createReadStream(IDS_HR1_EXE_1));
Commit: f32dde20bdba851dc54556ad4ce9fbf2ae9c52ab
https://github.com/scummvm/scummvm/commit/f32dde20bdba851dc54556ad4ce9fbf2ae9c52ab
Author: Walter van Niftrik (walter at scummvm.org)
Date: 2021-07-24T00:56:51+02:00
Commit Message:
ADL: Scan for executable strings in hires1
Changed paths:
engines/adl/adl.cpp
engines/adl/adl.h
engines/adl/hires1.cpp
diff --git a/engines/adl/adl.cpp b/engines/adl/adl.cpp
index 5ce0c20b6c..b1b7eeb8ec 100644
--- a/engines/adl/adl.cpp
+++ b/engines/adl/adl.cpp
@@ -145,11 +145,6 @@ Common::String AdlEngine::readStringAt(Common::SeekableReadStream &stream, uint
return readString(stream, until);
}
-void AdlEngine::openFile(Common::File &file, const Common::String &name) const {
- if (!file.open(name))
- error("Error opening '%s'", name.c_str());
-}
-
void AdlEngine::printMessage(uint idx) {
printString(loadMessage(idx));
}
diff --git a/engines/adl/adl.h b/engines/adl/adl.h
index 5442c89e31..28c827c90a 100644
--- a/engines/adl/adl.h
+++ b/engines/adl/adl.h
@@ -266,7 +266,6 @@ protected:
virtual void saveState(Common::WriteStream &stream);
Common::String readString(Common::ReadStream &stream, byte until = 0) const;
Common::String readStringAt(Common::SeekableReadStream &stream, uint offset, byte until = 0) const;
- void openFile(Common::File &file, const Common::String &name) const;
virtual void printString(const Common::String &str) = 0;
virtual Common::String loadMessage(uint idx) const = 0;
diff --git a/engines/adl/hires1.cpp b/engines/adl/hires1.cpp
index 9a8f149739..0ee483d567 100644
--- a/engines/adl/hires1.cpp
+++ b/engines/adl/hires1.cpp
@@ -52,17 +52,6 @@ namespace Adl {
#define IDI_HR1_MSG_DONT_HAVE_IT 127
#define IDI_HR1_MSG_GETTING_DARK 7
-#define IDI_HR1_OFS_STR_ENTER_COMMAND 0x5bbc
-#define IDI_HR1_OFS_STR_VERB_ERROR 0x5b4f
-#define IDI_HR1_OFS_STR_NOUN_ERROR 0x5b8e
-#define IDI_HR1_OFS_STR_PLAY_AGAIN 0x5f1e
-#define IDI_HR1_OFS_STR_CANT_GO_THERE 0x6c0a
-#define IDI_HR1_OFS_STR_DONT_HAVE_IT 0x6c31
-#define IDI_HR1_OFS_STR_DONT_UNDERSTAND 0x6c51
-#define IDI_HR1_OFS_STR_GETTING_DARK 0x6c7c
-#define IDI_HR1_OFS_STR_PRESS_RETURN 0x5f68
-#define IDI_HR1_OFS_STR_LINE_FEEDS 0x59d4
-
#define IDI_HR1_OFS_PD_TEXT_0 0x005d
#define IDI_HR1_OFS_PD_TEXT_1 0x012b
#define IDI_HR1_OFS_PD_TEXT_2 0x016d
@@ -103,6 +92,7 @@ private:
void loadRoom(byte roomNr) override;
void showRoom() override;
+ void extractExeStrings(Common::ReadStream &stream, Common::StringArray &strings);
void showInstructions(Common::SeekableReadStream &stream);
void wordWrap(Common::String &str) const;
@@ -120,6 +110,24 @@ private:
} _gameStrings;
};
+void HiRes1Engine::extractExeStrings(Common::ReadStream &stream, Common::StringArray &strings) {
+ uint32 window = 0;
+
+ for (;;) {
+ window <<= 8;
+ window |= stream.readByte();
+
+ if (stream.eos())
+ return;
+
+ if (stream.err())
+ error("Failed to extract strings from game executable");
+
+ if ((window & 0xffffff) == 0x201576)
+ strings.push_back(readString(stream));
+ }
+}
+
void HiRes1Engine::showInstructions(Common::SeekableReadStream &stream) {
_display->setMode(Display::kModeText);
@@ -288,19 +296,25 @@ void HiRes1Engine::init() {
StreamPtr stream(_files->createReadStream(IDS_HR1_EXE_1));
+ Common::StringArray exeStrings;
+ extractExeStrings(*stream, exeStrings);
+
+ if (exeStrings.size() != 18)
+ error("Failed to load strings from executable");
+
// Some messages have overrides inside the executable
- _gameStrings.cantGoThere = readStringAt(*stream, IDI_HR1_OFS_STR_CANT_GO_THERE);
- _gameStrings.dontHaveIt = readStringAt(*stream, IDI_HR1_OFS_STR_DONT_HAVE_IT);
- _gameStrings.dontUnderstand = readStringAt(*stream, IDI_HR1_OFS_STR_DONT_UNDERSTAND);
- _gameStrings.gettingDark = readStringAt(*stream, IDI_HR1_OFS_STR_GETTING_DARK);
+ _gameStrings.cantGoThere = exeStrings[12];
+ _gameStrings.dontHaveIt = exeStrings[13];
+ _gameStrings.dontUnderstand = exeStrings[14];
+ _gameStrings.gettingDark = exeStrings[15];
// Load other strings from executable
- _strings.enterCommand = readStringAt(*stream, IDI_HR1_OFS_STR_ENTER_COMMAND);
- _strings.verbError = readStringAt(*stream, IDI_HR1_OFS_STR_VERB_ERROR);
- _strings.nounError = readStringAt(*stream, IDI_HR1_OFS_STR_NOUN_ERROR);
- _strings.playAgain = readStringAt(*stream, IDI_HR1_OFS_STR_PLAY_AGAIN);
- _strings.pressReturn = readStringAt(*stream, IDI_HR1_OFS_STR_PRESS_RETURN);
- _strings.lineFeeds = readStringAt(*stream, IDI_HR1_OFS_STR_LINE_FEEDS);
+ _strings.enterCommand = exeStrings[5];
+ _strings.verbError = exeStrings[3];
+ _strings.nounError = exeStrings[4];
+ _strings.playAgain = exeStrings[8];
+ _strings.pressReturn = exeStrings[10];
+ _strings.lineFeeds = exeStrings[1];
// Set message IDs
_messageIds.cantGoThere = IDI_HR1_MSG_CANT_GO_THERE;
Commit: 56390d5f5fb05cbb9ea4448c58399c226715ccd9
https://github.com/scummvm/scummvm/commit/56390d5f5fb05cbb9ea4448c58399c226715ccd9
Author: Walter van Niftrik (walter at scummvm.org)
Date: 2021-07-24T00:56:51+02:00
Commit Message:
ADL: Add support for hires1 french (early version)
Changed paths:
engines/adl/adl.cpp
engines/adl/adl.h
engines/adl/detection.cpp
engines/adl/detection.h
engines/adl/hires1.cpp
engines/adl/metaengine.cpp
diff --git a/engines/adl/adl.cpp b/engines/adl/adl.cpp
index b1b7eeb8ec..c1c40415c7 100644
--- a/engines/adl/adl.cpp
+++ b/engines/adl/adl.cpp
@@ -84,6 +84,8 @@ AdlEngine::AdlEngine(OSystem *syst, const AdlGameDescription *gd) :
_display(nullptr),
_graphics(nullptr),
_textMode(false),
+ _verbErrorPos(19),
+ _nounErrorPos(30),
_linesPrinted(0),
_isRestarting(false),
_isRestoring(false),
@@ -1063,17 +1065,24 @@ Common::String AdlEngine::getWord(const Common::String &line, uint &index) const
Common::String AdlEngine::formatVerbError(const Common::String &verb) const {
Common::String err = _strings.verbError;
- for (uint i = 0; i < verb.size(); ++i)
- err.setChar(verb[i], i + 19);
+
+ if (_verbErrorPos + verb.size() > err.size())
+ error("Failed to format verb error string");
+
+ err.replace(_verbErrorPos, verb.size(), verb);
+
return err;
}
Common::String AdlEngine::formatNounError(const Common::String &verb, const Common::String &noun) const {
Common::String err = _strings.nounError;
- for (uint i = 0; i < verb.size(); ++i)
- err.setChar(verb[i], i + 19);
- for (uint i = 0; i < noun.size(); ++i)
- err.setChar(noun[i], i + 30);
+
+ if (_verbErrorPos + verb.size() > err.size() || _nounErrorPos + noun.size() > err.size())
+ error("Failed to format noun error string");
+
+ err.replace(_verbErrorPos, verb.size(), verb);
+ err.replace(_nounErrorPos, noun.size(), noun);
+
return err;
}
diff --git a/engines/adl/adl.h b/engines/adl/adl.h
index 28c827c90a..ef53c151b2 100644
--- a/engines/adl/adl.h
+++ b/engines/adl/adl.h
@@ -57,6 +57,7 @@ namespace Adl {
Common::String getDiskImageName(const AdlGameDescription &adlDesc, byte volume);
GameType getGameType(const AdlGameDescription &desc);
GameVersion getGameVersion(const AdlGameDescription &desc);
+Common::Language getLanguage(const AdlGameDescription &desc);
Common::Platform getPlatform(const AdlGameDescription &desc);
class Console;
@@ -261,6 +262,7 @@ protected:
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); }
+ Common::Language getLanguage() const { return Adl::getLanguage(*_gameDescription); }
virtual void gameLoop();
virtual void loadState(Common::ReadStream &stream);
virtual void saveState(Common::WriteStream &stream);
@@ -412,6 +414,8 @@ protected:
Common::String lineFeeds;
} _strings;
+ uint32 _verbErrorPos, _nounErrorPos;
+
struct {
uint cantGoThere;
uint dontUnderstand;
diff --git a/engines/adl/detection.cpp b/engines/adl/detection.cpp
index c47f7c3fe6..44ee787282 100644
--- a/engines/adl/detection.cpp
+++ b/engines/adl/detection.cpp
@@ -148,6 +148,22 @@ static const AdlGameDescription gameFileDescriptions[] = {
GAME_TYPE_HIRES1,
GAME_VER_HR1_COARSE
},
+ { // Hi-Res Adventure #1: Mystery House - Apple II - French - Without MIXEDON
+ {
+ "hires1", "VF1",
+ {
+ { "ADVENTURE", 0, "6e2245979871b44a9fec46b4b2ba590a", 29952 },
+ { "AUTO LOAD OBJ", 0, "3d417e923e70abe9a82e51155974027d", 12288 },
+ AD_LISTEND
+ },
+ Common::FR_FRA,
+ Common::kPlatformApple2,
+ ADGF_TESTING,
+ MH_OPTIONS
+ },
+ GAME_TYPE_HIRES1,
+ GAME_VER_HR1_VF1
+ },
{ // Hi-Res Adventure #1: Mystery House - Apple II - Coarsegold - With MIXEDON
{
"hires1", "V3",
@@ -166,7 +182,7 @@ static const AdlGameDescription gameFileDescriptions[] = {
},
{ // Hi-Res Adventure #1: Mystery House - Apple II - Roberta Williams Anthology
{
- "hires1", 0,
+ "hires1", "PD",
{
{ "ADVENTURE", 0, "22d9e63a11d69fa033ba1738715ad09a", 29952 },
{ "AUTO LOAD OBJ", 0, "23bfccfe9fcff9b22cf6c41bde9078ac", 12291 },
diff --git a/engines/adl/detection.h b/engines/adl/detection.h
index c609530b1f..ecd9e22abf 100644
--- a/engines/adl/detection.h
+++ b/engines/adl/detection.h
@@ -61,6 +61,7 @@ enum GameVersion {
GAME_VER_NONE = 0,
GAME_VER_HR1_SIMI = 0,
GAME_VER_HR1_COARSE,
+ GAME_VER_HR1_VF1,
GAME_VER_HR1_PD
};
diff --git a/engines/adl/hires1.cpp b/engines/adl/hires1.cpp
index 0ee483d567..78bb842c97 100644
--- a/engines/adl/hires1.cpp
+++ b/engines/adl/hires1.cpp
@@ -67,9 +67,6 @@ namespace Adl {
#define IDI_HR1_OFS_ITEM_OFFSETS 0x68ff
#define IDI_HR1_OFS_SHAPES 0x4f00
-#define IDI_HR1_OFS_VERBS 0x3800
-#define IDI_HR1_OFS_NOUNS 0x0f00
-
class HiRes1Engine : public AdlEngine {
public:
HiRes1Engine(OSystem *syst, const AdlGameDescription *gd) :
@@ -229,6 +226,14 @@ void HiRes1Engine::runIntro() {
if (getGameVersion() >= GAME_VER_HR1_COARSE) {
bool instructions = false;
+ char keyInstr = 'I';
+ char keyGame = 'G';
+
+ if (getLanguage() == Common::FR_FRA) {
+ keyInstr = 'M';
+ keyGame = 'J';
+ }
+
while (1) {
_display->printString(str);
Common::String s = inputString();
@@ -239,10 +244,10 @@ void HiRes1Engine::runIntro() {
if (s.empty())
continue;
- if (s[0] == _display->asciiToNative('I')) {
+ if (s[0] == _display->asciiToNative(keyInstr)) {
instructions = true;
break;
- } else if (s[0] == _display->asciiToNative('G')) {
+ } else if (s[0] == _display->asciiToNative(keyGame)) {
break;
}
}
@@ -292,7 +297,7 @@ void HiRes1Engine::init() {
}
_graphics = new GraphicsMan_v1<Display_A2>(*static_cast<Display_A2 *>(_display));
- _display->moveCursorTo(Common::Point(0, 3));
+ _display->moveCursorTo(Common::Point(0, 23)); // DOS 3.3
StreamPtr stream(_files->createReadStream(IDS_HR1_EXE_1));
@@ -323,11 +328,21 @@ void HiRes1Engine::init() {
_messageIds.itemNotHere = IDI_HR1_MSG_ITEM_NOT_HERE;
_messageIds.thanksForPlaying = IDI_HR1_MSG_THANKS_FOR_PLAYING;
+ if (getLanguage() == Common::FR_FRA) {
+ _verbErrorPos = 15;
+ _nounErrorPos = 31;
+ }
+
// Load message offsets
stream->seek(IDI_HR1_OFS_MSGS);
for (uint i = 0; i < IDI_HR1_NUM_MESSAGES; ++i)
_messages.push_back(_files->getDataBlock(IDS_HR1_MESSAGES, stream->readUint16LE()));
+ // The French version has 5 additional strings
+ if (getLanguage() == Common::FR_FRA)
+ for (uint i = 0; i < 5; ++i)
+ _messages.push_back(_files->getDataBlock(IDS_HR1_MESSAGES, stream->readUint16LE()));
+
// Load picture data from executable
stream->seek(IDI_HR1_OFS_PICS);
for (uint i = 1; i <= IDI_HR1_NUM_PICS; ++i) {
@@ -357,10 +372,10 @@ void HiRes1Engine::init() {
if (stream->eos() || stream->err())
error("Failed to read game data from '" IDS_HR1_EXE_1 "'");
- stream->seek(IDI_HR1_OFS_VERBS);
+ stream->seek(getLanguage() == Common::FR_FRA ? 0x900 : 0x3800);
loadWords(*stream, _verbs, _priVerbs);
- stream->seek(IDI_HR1_OFS_NOUNS);
+ stream->seek(0xf00);
loadWords(*stream, _nouns, _priNouns);
}
@@ -422,7 +437,7 @@ void HiRes1Engine::printString(const Common::String &str) {
_display->printString(wrap);
if (_messageDelay)
- delay(14 * 166018 / 1000);
+ delay(getLanguage() == Common::FR_FRA ? 2900 : 2250);
}
Common::String HiRes1Engine::loadMessage(uint idx) const {
diff --git a/engines/adl/metaengine.cpp b/engines/adl/metaengine.cpp
index e6f56b279a..795f65ef03 100644
--- a/engines/adl/metaengine.cpp
+++ b/engines/adl/metaengine.cpp
@@ -63,6 +63,10 @@ GameVersion getGameVersion(const AdlGameDescription &adlDesc) {
return adlDesc.version;
}
+Common::Language getLanguage(const AdlGameDescription &adlDesc) {
+ return adlDesc.desc.language;
+}
+
Common::Platform getPlatform(const AdlGameDescription &adlDesc) {
return adlDesc.desc.platform;
}
Commit: e8dd3b7085365818f17fe6965f5209e1ab5daf3e
https://github.com/scummvm/scummvm/commit/e8dd3b7085365818f17fe6965f5209e1ab5daf3e
Author: Walter van Niftrik (walter at scummvm.org)
Date: 2021-07-24T00:56:51+02:00
Commit Message:
ADL: Add delay after printing strings in hires1
Changed paths:
engines/adl/hires1.cpp
diff --git a/engines/adl/hires1.cpp b/engines/adl/hires1.cpp
index 78bb842c97..1bd6310a5a 100644
--- a/engines/adl/hires1.cpp
+++ b/engines/adl/hires1.cpp
@@ -281,8 +281,6 @@ void HiRes1Engine::runIntro() {
// This does mean we need to push out some extra line feeds to clear the screen
_display->printString(_strings.lineFeeds);
inputKey();
- if (shouldQuit())
- return;
}
}
@@ -447,29 +445,39 @@ Common::String HiRes1Engine::loadMessage(uint idx) const {
}
void HiRes1Engine::printMessage(uint idx) {
- // Messages with hardcoded overrides don't delay after printing.
- // It's unclear if this is a bug or not. In some cases the result
- // is that these strings will scroll past the four-line text window
- // before the user gets a chance to read them.
- // NOTE: later games seem to wait for a key when the text window
- // overflows and don't use delays. It might be better to use
- // that system for this game as well.
+ // In the English version, messages with hardcoded overrides don't delay
+ // after printing. It's unclear if this is a bug or not. In most cases
+ // the slow drawing of the room will give the player a chance to read
+ // it. This isn't the case in ScummVM however, so we add a delay after
+ // these messages.
+
+ // In the French version, messages with hardcoded overrides delay
+ // based on string length. This leads to overly long delays on longer
+ // strings. This might be a bug, since other messages have a fixed
+ // delay (that is slightly longer than the English version).
+ // We've chosen to stick with fixed delays here as well.
+
+ // NOTE: Later games wait for a key when the text window overflows and
+ // don't use delays. It might be better to use that system for this game
+ // as well.
switch (idx) {
case IDI_HR1_MSG_CANT_GO_THERE:
_display->printString(_gameStrings.cantGoThere);
- return;
+ break;
case IDI_HR1_MSG_DONT_HAVE_IT:
_display->printString(_gameStrings.dontHaveIt);
- return;
+ break;
case IDI_HR1_MSG_DONT_UNDERSTAND:
_display->printString(_gameStrings.dontUnderstand);
- return;
+ break;
case IDI_HR1_MSG_GETTING_DARK:
_display->printString(_gameStrings.gettingDark);
- return;
+ break;
default:
- printString(loadMessage(idx));
+ return printString(loadMessage(idx));
}
+
+ delay(1500);
}
void HiRes1Engine::drawItems() {
Commit: 01e6ec1649e24c95605be7df0c7a0faf1373b189
https://github.com/scummvm/scummvm/commit/01e6ec1649e24c95605be7df0c7a0faf1373b189
Author: Walter van Niftrik (walter at scummvm.org)
Date: 2021-07-24T00:56:51+02:00
Commit Message:
ADL: Use slot 15 for autosave
Changed paths:
engines/adl/adl.h
engines/adl/metaengine.cpp
diff --git a/engines/adl/adl.h b/engines/adl/adl.h
index ef53c151b2..68a4c3fdea 100644
--- a/engines/adl/adl.h
+++ b/engines/adl/adl.h
@@ -258,6 +258,7 @@ protected:
Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false) override;
bool canSaveGameStateCurrently() override;
virtual Common::String getSaveStateName(int slot) const override;
+ int getAutosaveSlot() const override { return 15; }
Common::String getDiskImageName(byte volume) const { return Adl::getDiskImageName(*_gameDescription, volume); }
GameType getGameType() const { return Adl::getGameType(*_gameDescription); }
diff --git a/engines/adl/metaengine.cpp b/engines/adl/metaengine.cpp
index 795f65ef03..73740de6da 100644
--- a/engines/adl/metaengine.cpp
+++ b/engines/adl/metaengine.cpp
@@ -79,7 +79,8 @@ public:
bool hasFeature(MetaEngineFeature f) const override;
SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const override;
- int getMaximumSaveSlot() const override { return 'O' - 'A'; }
+ int getAutosaveSlot() const override { return 15; }
+ int getMaximumSaveSlot() const override { return 15; }
SaveStateList listSaves(const char *target) const override;
void removeSaveState(const char *target, int slot) const override;
Commit: 5f6c88ef15ff3e82178dab8fffbfc08b677cb100
https://github.com/scummvm/scummvm/commit/5f6c88ef15ff3e82178dab8fffbfc08b677cb100
Author: Walter van Niftrik (walter at scummvm.org)
Date: 2021-07-24T00:56:51+02:00
Commit Message:
ADL: Add support for later French hires1
Changed paths:
engines/adl/adl.h
engines/adl/detection.cpp
engines/adl/detection.h
engines/adl/hires1.cpp
diff --git a/engines/adl/adl.h b/engines/adl/adl.h
index 68a4c3fdea..f84189b3a6 100644
--- a/engines/adl/adl.h
+++ b/engines/adl/adl.h
@@ -279,7 +279,8 @@ protected:
virtual Common::String getLine();
Common::String inputString(byte prompt = 0) const;
byte inputKey(bool showCursor = true) const;
- void getInput(uint &verb, uint &noun);
+ virtual void getInput(uint &verb, uint &noun);
+ Common::String getWord(const Common::String &line, uint &index) const;
virtual Common::String formatVerbError(const Common::String &verb) const;
virtual Common::String formatNounError(const Common::String &verb, const Common::String &noun) const;
@@ -460,7 +461,6 @@ private:
// Text input
byte convertKey(uint16 ascii) const;
- Common::String getWord(const Common::String &line, uint &index) const;
byte _saveVerb, _saveNoun, _restoreVerb, _restoreNoun;
};
diff --git a/engines/adl/detection.cpp b/engines/adl/detection.cpp
index 44ee787282..1373c06e6d 100644
--- a/engines/adl/detection.cpp
+++ b/engines/adl/detection.cpp
@@ -164,6 +164,22 @@ static const AdlGameDescription gameFileDescriptions[] = {
GAME_TYPE_HIRES1,
GAME_VER_HR1_VF1
},
+ { // Hi-Res Adventure #1: Mystery House - Apple II - French - Modified parser
+ {
+ "hires1", "VF2",
+ {
+ { "ADVENTURE", 0, "f9a1add3609b4bc24b5dc4a9db1fec67", 29952 },
+ { "AUTO LOAD OBJ", 0, "2a348058363da4c78a069ee5a2d81a31", 12287 },
+ AD_LISTEND
+ },
+ Common::FR_FRA,
+ Common::kPlatformApple2,
+ ADGF_TESTING,
+ MH_OPTIONS
+ },
+ GAME_TYPE_HIRES1,
+ GAME_VER_HR1_VF2
+ },
{ // Hi-Res Adventure #1: Mystery House - Apple II - Coarsegold - With MIXEDON
{
"hires1", "V3",
@@ -225,6 +241,18 @@ static const AdlGameDescription gameDiskDescriptions[] = {
GAME_TYPE_HIRES1,
GAME_VER_HR1_COARSE
},
+ { // Hi-Res Adventure #1: Mystery House - Apple II - French - Modified parser
+ {
+ "hires1", "VF2",
+ AD_ENTRY1s("mysthous", "7bd1918ffc28e551e5b3baf610982bd3", 116480),
+ Common::FR_FRA,
+ Common::kPlatformApple2,
+ ADGF_TESTING,
+ MH_OPTIONS
+ },
+ GAME_TYPE_HIRES1,
+ GAME_VER_HR1_VF2
+ },
{ // Hi-Res Adventure #1: Mystery House - Apple II - Coarsegold - With MIXEDON
{
"hires1", "V3",
diff --git a/engines/adl/detection.h b/engines/adl/detection.h
index ecd9e22abf..adb251dcd3 100644
--- a/engines/adl/detection.h
+++ b/engines/adl/detection.h
@@ -62,6 +62,7 @@ enum GameVersion {
GAME_VER_HR1_SIMI = 0,
GAME_VER_HR1_COARSE,
GAME_VER_HR1_VF1,
+ GAME_VER_HR1_VF2,
GAME_VER_HR1_PD
};
diff --git a/engines/adl/hires1.cpp b/engines/adl/hires1.cpp
index 1bd6310a5a..3ebb905c2e 100644
--- a/engines/adl/hires1.cpp
+++ b/engines/adl/hires1.cpp
@@ -25,6 +25,7 @@
#include "common/error.h"
#include "common/file.h"
#include "common/stream.h"
+#include "common/memstream.h"
#include "common/ptr.h"
#include "adl/adl.h"
@@ -75,7 +76,7 @@ public:
_messageDelay(true) { }
~HiRes1Engine() override { delete _files; }
-private:
+protected:
// AdlEngine
void runIntro() override;
void init() override;
@@ -555,7 +556,116 @@ void HiRes1Engine::wordWrap(Common::String &str) const {
}
}
+class HiRes1Engine_VF : public HiRes1Engine {
+public:
+ HiRes1Engine_VF(OSystem *syst, const AdlGameDescription *gd) :
+ HiRes1Engine(syst, gd) { }
+
+private:
+ // AdlEngine
+ void runIntro() override;
+ void getInput(uint &verb, uint &noun) override;
+};
+
+void HiRes1Engine_VF::getInput(uint &verb, uint &noun) {
+ // This version has a modified "parser"
+ while (1) {
+ _display->printString(_strings.enterCommand);
+ const Common::String line = getLine();
+
+ if (shouldQuit() || _isRestoring)
+ return;
+
+ uint index = 0;
+ Common::String verbString = getWord(line, index);
+
+ if (!_verbs.contains(verbString)) {
+ // If the verb is not found and it looks like an imperative, try to build the infinitive
+ const size_t ezPos = verbString.find("\xc5\xda"); // "EZ"
+
+ bool found = false;
+
+ if (ezPos != verbString.npos) {
+ const char *suf[] = { "\xc5\xd2", "\xc9\xd2", "\xd2\xc5", nullptr }; // "ER", "IR", "RE"
+
+ for (uint i = 0; suf[i]; ++i) {
+ verbString.replace(ezPos, 2, suf[i]);
+ if (_verbs.contains(verbString)) {
+ found = true;
+ break;
+ }
+ }
+ }
+
+ if (!found) {
+ _display->printString(formatVerbError(verbString));
+ continue;
+ }
+ }
+
+ verb = _verbs[verbString];
+
+ while (1) {
+ // Go over all nouns to find one we know. At the end of the string,
+ // it will always match the empty word (which is in the noun list).
+
+ // The original has a code path to return a noun error here, but
+ // it appears to be non-functional.
+ const Common::String nounString = getWord(line, index);
+
+ if (_nouns.contains(nounString)) {
+ noun = _nouns[nounString];
+ return;
+ }
+ }
+ }
+}
+
+void HiRes1Engine_VF::runIntro() {
+ StreamPtr stream(_files->createReadStream(IDS_HR1_EXE_0));
+
+ stream->seek(0x1000);
+
+ // Title image is one padding byte short, so we first read it into a buffer
+ const uint frameBufferSize = 0x2000;
+ byte *const frameBuffer = (byte *)malloc(frameBufferSize);
+
+ if (stream->read(frameBuffer, frameBufferSize - 1) < frameBufferSize - 1)
+ error("Failed to read title image");
+
+ // Set missing byte
+ frameBuffer[frameBufferSize - 1] = 0;
+ Common::MemoryReadStream frameBufferStream(frameBuffer, frameBufferSize, DisposeAfterUse::YES);
+
+ _display->setMode(Display::kModeGraphics);
+ static_cast<Display_A2 *>(_display)->loadFrameBuffer(frameBufferStream);
+ _display->renderGraphics();
+
+ _display->setMode(Display::kModeMixed);
+
+ Common::String str = readStringAt(*stream, 0xf);
+
+ while (1) {
+ _display->printString(str);
+ const char key = inputKey();
+
+ if (shouldQuit())
+ return;
+
+ if (key == _display->asciiToNative('M')) {
+ stream->seek(0x75);
+ showInstructions(*stream);
+ return;
+ } else if (key == _display->asciiToNative('J')) {
+ return;
+ }
+ }
+}
+
Engine *HiRes1Engine_create(OSystem *syst, const AdlGameDescription *gd) {
+ if (gd->version == GAME_VER_HR1_VF2)
+ return new HiRes1Engine_VF(syst, gd);
+
return new HiRes1Engine(syst, gd);
}
More information about the Scummvm-git-logs
mailing list