From 6a4c475bb2475372f70976e6562bdb6fece4e600 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 23 Mar 2009 22:34:53 +0000 Subject: Patch #2676453: INDY3/FOA: series IQ with ScummVM GUI svn-id: r39649 --- engines/scumm/input.cpp | 14 +++------- engines/scumm/script_v5.cpp | 68 +++++++++++++++++++++++++++++++++++++++++---- engines/scumm/scumm.cpp | 14 ++++++++++ engines/scumm/scumm_v5.h | 4 ++- 4 files changed, 83 insertions(+), 17 deletions(-) (limited to 'engines/scumm') diff --git a/engines/scumm/input.cpp b/engines/scumm/input.cpp index 96c120eec7..83e9357d5e 100644 --- a/engines/scumm/input.cpp +++ b/engines/scumm/input.cpp @@ -440,16 +440,10 @@ void ScummEngine_v3::processKeyboard(Common::KeyState lastKeyHit) { // SCUMM var 244 is the episode score // and var 245 is the series score char text[50]; - - // FIXME: Currently, the series score does not work properly - // This workaround just sets it equal to the episode score - // However, at the end of the game, it does show the episode - // score by itself - int a = _scummVars[245]; - if (!a) - a = _scummVars[244]; - - sprintf(text, "IQ Points: Episode = %d, Series = %d", _scummVars[244], a); + + updateIQPoints(); + + sprintf(text, "IQ Points: Episode = %d, Series = %d", _scummVars[244], _scummVars[245]); Indy3IQPointsDialog indy3IQPointsDialog(this, text); runDialog(indy3IQPointsDialog); } diff --git a/engines/scumm/script_v5.cpp b/engines/scumm/script_v5.cpp index 4072f8f720..a8cd1336e3 100644 --- a/engines/scumm/script_v5.cpp +++ b/engines/scumm/script_v5.cpp @@ -954,7 +954,11 @@ void ScummEngine_v5::loadVars() { if (a == STRINGID_IQ_SERIES && b == STRINGID_IQ_SERIES) { // Zak256 loads the IQ script-slot but does not use it -> ignore it if (_game.id == GID_INDY3) { - loadIQPoints(); + byte *ptr = getResourceAddress(rtString, STRINGID_IQ_SERIES); + if (ptr) { + int size = getResourceSize(rtString, STRINGID_IQ_SERIES); + loadIQPoints(ptr, size); + } } break; } @@ -1001,6 +1005,53 @@ void ScummEngine_v5::loadVars() { } } +/** + * IQ Point calculation for Indy3. + * The scripts that perform this task are + * - script-9 (save/load dialog initialization, loads room 14), + * - room-14-204 (load series IQ string), + * - room-14-205 (save series IQ string), + * - room-14-206 (calculate series IQ string). + * Unfortunately script-9 contains lots of GUI stuff so calling this script + * directly is not possible. The other scripts depend on script-9. + */ +void ScummEngine_v5::updateIQPoints() { + int seriesIQ; + int episodeIQStringSize; + byte *episodeIQString; + byte seriesIQString[73]; + + // load string with IQ points given per puzzle in any savegame + // IMPORTANT: the resource string STRINGID_IQ_SERIES is only valid while + // the original save/load dialog is executed, so do not use it here. + memset(seriesIQString, 0, sizeof(seriesIQString)); + loadIQPoints(seriesIQString, sizeof(seriesIQString)); + + // string with IQ points given per puzzle in current savegame + episodeIQString = getResourceAddress(rtString, STRINGID_IQ_EPISODE); + if (!episodeIQString) + return; + episodeIQStringSize = getResourceSize(rtString, STRINGID_IQ_EPISODE); + if (episodeIQStringSize < 73) + return; + + // merge episode and series IQ strings and calculate series IQ + seriesIQ = 0; + // iterate over puzzles (each of the first 73 bytes corresponds to a puzzle's IQ) + for (int i = 0; i < 73 ; ++i) { + char puzzleIQ = seriesIQString[i]; + // if puzzle is solved copy points to episode string + if (puzzleIQ > 0) + episodeIQString[i] = puzzleIQ; + // add puzzle's IQ-points to series IQ + seriesIQ += episodeIQString[i]; + } + _scummVars[245] = seriesIQ; + + // save series IQ string + saveIQPoints(); +} + void ScummEngine_v5::saveIQPoints() { // save Indy3 IQ-points Common::OutSaveFile *file; @@ -1008,22 +1059,22 @@ void ScummEngine_v5::saveIQPoints() { file = _saveFileMan->openForSaving(filename.c_str()); if (file != NULL) { - int size = getResourceSize(rtString, STRINGID_IQ_EPISODE); byte *ptr = getResourceAddress(rtString, STRINGID_IQ_EPISODE); - file->write(ptr, size); + if (ptr) { + int size = getResourceSize(rtString, STRINGID_IQ_EPISODE); + file->write(ptr, size); + } delete file; } } -void ScummEngine_v5::loadIQPoints() { +void ScummEngine_v5::loadIQPoints(byte *ptr, int size) { // load Indy3 IQ-points Common::InSaveFile *file; Common::String filename = _targetName + ".iq"; file = _saveFileMan->openForLoading(filename.c_str()); if (file != NULL) { - int size = getResourceSize(rtString, STRINGID_IQ_SERIES); - byte *ptr = getResourceAddress(rtString, STRINGID_IQ_SERIES); byte *tmp = (byte*)malloc(size); int nread = file->read(tmp, size); if (nread == size) { @@ -2403,6 +2454,11 @@ void ScummEngine_v5::o5_startScript() { } runScript(script, (op & 0x20) != 0, (op & 0x40) != 0, data); + + // WORKAROUND: Indy3 does not save the series IQ automatically after changing it. + // Save on IQ increment (= script 125 was executed). + if (_game.id == GID_INDY3 && script == 125) + updateIQPoints(); } void ScummEngine_v5::o5_stopObjectCode() { diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp index 1ab4d50d3d..441150bc9c 100644 --- a/engines/scumm/scumm.cpp +++ b/engines/scumm/scumm.cpp @@ -2082,6 +2082,20 @@ void ScummEngine::scummLoop_handleSaveLoad() { } } +void ScummEngine_v5::scummLoop_handleSaveLoad() { + byte saveLoad = (_saveLoadFlag != 0); + + ScummEngine::scummLoop_handleSaveLoad(); + + // update IQ points after loading + if (saveLoad == 2) { + if (_game.id == GID_INDY3) + updateIQPoints(); + if (_game.id == GID_INDY4) + runScript(145, 0, 0, 0); + } +} + #ifdef ENABLE_SCUMM_7_8 void ScummEngine_v8::scummLoop_handleSaveLoad() { ScummEngine::scummLoop_handleSaveLoad(); diff --git a/engines/scumm/scumm_v5.h b/engines/scumm/scumm_v5.h index 763a6ee2af..78562cd1e9 100644 --- a/engines/scumm/scumm_v5.h +++ b/engines/scumm/scumm_v5.h @@ -65,6 +65,7 @@ protected: virtual const char *getOpcodeDesc(byte i); virtual void scummLoop_handleActors(); + virtual void scummLoop_handleSaveLoad(); virtual void setupScummVars(); virtual void resetScummVars(); @@ -78,7 +79,8 @@ protected: void saveVars(); void loadVars(); void saveIQPoints(); - void loadIQPoints(); + void loadIQPoints(byte *ptr, int size); + void updateIQPoints(); virtual int getVar(); virtual int getVarOrDirectByte(byte mask); -- cgit v1.2.3