diff options
Diffstat (limited to 'engines/sci')
-rw-r--r-- | engines/sci/console.cpp | 7 | ||||
-rw-r--r-- | engines/sci/debug.h | 2 | ||||
-rw-r--r-- | engines/sci/detection.cpp | 10 | ||||
-rw-r--r-- | engines/sci/engine/kernel.cpp | 43 | ||||
-rw-r--r-- | engines/sci/engine/kernel.h | 6 | ||||
-rw-r--r-- | engines/sci/engine/ksound.cpp | 17 | ||||
-rw-r--r-- | engines/sci/engine/scriptdebug.cpp | 6 | ||||
-rw-r--r-- | engines/sci/engine/static_selectors.cpp | 429 | ||||
-rw-r--r-- | engines/sci/engine/vm.cpp | 90 | ||||
-rw-r--r-- | engines/sci/module.mk | 1 | ||||
-rw-r--r-- | engines/sci/resource.cpp | 15 | ||||
-rw-r--r-- | engines/sci/sfx/iterator.cpp | 35 | ||||
-rw-r--r-- | engines/sci/sfx/iterator.h | 6 | ||||
-rw-r--r-- | engines/sci/sfx/iterator_internal.h | 22 |
14 files changed, 610 insertions, 79 deletions
diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index 7f20e4013d..ebf9656739 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -545,7 +545,7 @@ bool Console::cmdSetParseNodes(int argc, const char **argv) { bool Console::cmdRegisters(int argc, const char **argv) { DebugPrintf("Current register values:\n"); - DebugPrintf("acc=%04x:%04x prev=%04x:%04x &rest=%x\n", PRINT_REG(_vm->_gamestate->r_acc), PRINT_REG(_vm->_gamestate->r_prev), scriptState.restadjust); + DebugPrintf("acc=%04x:%04x prev=%04x:%04x &rest=%x\n", PRINT_REG(_vm->_gamestate->r_acc), PRINT_REG(_vm->_gamestate->r_prev), scriptState.restAdjust); if (!_vm->_gamestate->_executionStack.empty()) { EngineState *s = _vm->_gamestate; // for PRINT_STK @@ -3226,11 +3226,6 @@ static int c_gfx_draw_viewobj(EngineState *s, const Common::Array<cmd_param_t> & int c_stepover(EngineState *s, const Common::Array<cmd_param_t> &cmdParams) { int opcode, opnumber; - if (!g_debugstate_valid) { - printf("Not in debug state\n"); - return 1; - } - opcode = s->_heap[*p_pc]; opnumber = opcode >> 1; if (opnumber == 0x22 /* callb */ || opnumber == 0x23 /* calle */ || diff --git a/engines/sci/debug.h b/engines/sci/debug.h index 0963159c98..cd2de2b3a9 100644 --- a/engines/sci/debug.h +++ b/engines/sci/debug.h @@ -46,7 +46,7 @@ struct ScriptState { int old_pc_offset; StackPtr old_sp; ExecStack *xs; - int16 restadjust; + int16 restAdjust; reg_t *variables[4]; // global, local, temp, param, as immediate pointers reg_t *variables_base[4]; // Used for referencing VM ops SegmentId variables_seg[4]; // Same as above, contains segment IDs diff --git a/engines/sci/detection.cpp b/engines/sci/detection.cpp index a80baf182e..566d82405a 100644 --- a/engines/sci/detection.cpp +++ b/engines/sci/detection.cpp @@ -800,16 +800,6 @@ static const struct SciGameDescription SciGameDescriptions[] = { }, #endif // ENABLE_SCI32 - // Hoyle 1 - English DOS Non-Interactive Demo - {{"hoyle1", "Demo", { - {"resource.map", 0, "60f764020a6b788bbbe415dbc2ccb9f3", 931}, - {"resource.000", 0, "5fe3670e3ddcd4f85c10013b5453141a", 615522}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH}, - GF_FOR_SCI0_BEFORE_629, - SCI_VERSION_AUTODETECT, - SCI_VERSION_0 - }, - // Hoyle 1 - English DOS (supplied by wibble92 in bug report #2644547) // SCI interpreter version 0.000.530 {{"hoyle1", "", { diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index dd2d0dc61a..4133f4cb3b 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -384,10 +384,15 @@ Kernel::~Kernel() { void Kernel::detectSciFeatures() { Resource *r = _resmgr->findResource(ResourceId(kResourceTypeVocab, VOCAB_RESOURCE_SNAMES), 0); - if (!r) // No such resource? - error("Kernel: Could not retrieve selector names"); + Common::StringList staticSelectorTable; + + if (!r) { // No such resource? + staticSelectorTable = checkStaticSelectorNames(); + if (staticSelectorTable.empty()) + error("Kernel: Could not retrieve selector names"); + } - int count = READ_LE_UINT16(r->data) + 1; // Counter is slightly off + int count = staticSelectorTable.empty() ? READ_LE_UINT16(r->data) + 1 : staticSelectorTable.size(); // Counter is slightly off features = 0; // Initialize features based on SCI version @@ -397,10 +402,16 @@ void Kernel::detectSciFeatures() { } for (int i = 0; i < count; i++) { - int offset = READ_LE_UINT16(r->data + 2 + i * 2); - int len = READ_LE_UINT16(r->data + offset); - - Common::String tmp((const char *)r->data + offset + 2, len); + Common::String tmp; + + if (staticSelectorTable.empty()) { + int offset = READ_LE_UINT16(r->data + 2 + i * 2); + int len = READ_LE_UINT16(r->data + offset); + + tmp = Common::String((const char *)r->data + offset + 2, len); + } else { + tmp = staticSelectorTable[i]; + } if (tmp == "setTarget") // "motionInited" can also be used features &= ~kFeatureOldScriptHeader; @@ -459,8 +470,22 @@ void Kernel::detectSciFeatures() { void Kernel::loadSelectorNames() { Resource *r = _resmgr->findResource(ResourceId(kResourceTypeVocab, VOCAB_RESOURCE_SNAMES), 0); - if (!r) // No such resource? - error("Kernel: Could not retrieve selector names"); + if (!r) { // No such resource? + // Check if we have a table for this game + // Some demos do not have a selector table + Common::StringList staticSelectorTable = checkStaticSelectorNames(); + + if (staticSelectorTable.empty()) + error("Kernel: Could not retrieve selector names"); + + for (uint32 i = 0; i < staticSelectorTable.size(); i++) { + _selectorNames.push_back(staticSelectorTable[i]); + if (features & kFeatureOldScriptHeader) + _selectorNames.push_back(staticSelectorTable[i]); + } + + return; + } int count = READ_LE_UINT16(r->data) + 1; // Counter is slightly off diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index 4814bd0317..17997e4a20 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -157,6 +157,12 @@ private: * Loads the kernel selector names. */ void loadSelectorNames(); + + /** + * Check for any hardcoded selector table we might have that can be used + * if a game is missing the selector names. + */ + Common::StringList checkStaticSelectorNames(); /** * Maps special selectors diff --git a/engines/sci/engine/ksound.cpp b/engines/sci/engine/ksound.cpp index 7614b2bc10..4ba8971397 100644 --- a/engines/sci/engine/ksound.cpp +++ b/engines/sci/engine/ksound.cpp @@ -148,6 +148,9 @@ SongIterator *build_iterator(EngineState *s, int song_nr, SongIteratorType type, return songit_new(song->data, song->size, type, id); } +SongIterator *build_timeriterator(EngineState *s, int delta) { + return new_timer_iterator(delta); +} void process_sound_events(EngineState *s) { /* Get all sound events, apply their changes to the heap */ int result; @@ -798,6 +801,7 @@ reg_t kDoSound_SCI1(EngineState *s, int funct_nr, int argc, reg_t *argv) { int looping = GET_SEL32V(obj, loop); //int vol = GET_SEL32V(obj, vol); int pri = GET_SEL32V(obj, pri); + int sampleLen = 0; Song *song = s->_sound._songlib.findSong(handle); if (GET_SEL32V(obj, nodePtr) && (song && number != song->_resourceNum)) { @@ -815,8 +819,11 @@ reg_t kDoSound_SCI1(EngineState *s, int funct_nr, int argc, reg_t *argv) { s->_version >= SCI_VERSION_1_1) { // Found a relevant audio resource, play it s->_sound.stopAudio(); - PUT_SEL32V(obj, signal, s->_sound.startAudio(65535, number)); - return s->r_acc; + warning("Initializing audio resource instead of requested sound resource %d\n", number); + sampleLen = s->_sound.startAudio(65535, number); + // Also create iterator, that will fire SI_FINISHED event, when the sound is done playing + s->_sound.sfx_add_song(build_timeriterator(s, sampleLen), 0, handle, number); + PUT_SEL32V(obj, signal, sampleLen); } else { if (!s->resmgr->testResource(ResourceId(kResourceTypeSound, number))) { warning("Could not open song number %d", number); @@ -825,11 +832,11 @@ reg_t kDoSound_SCI1(EngineState *s, int funct_nr, int argc, reg_t *argv) { PUT_SEL32V(obj, signal, -1); return s->r_acc; } + debugC(2, kDebugLevelSound, "Initializing song number %d\n", number); + s->_sound.sfx_add_song(build_iterator(s, number, SCI_SONG_ITERATOR_TYPE_SCI1, + handle), 0, handle, number); } - debugC(2, kDebugLevelSound, "Initializing song number %d\n", number); - s->_sound.sfx_add_song(build_iterator(s, number, SCI_SONG_ITERATOR_TYPE_SCI1, - handle), 0, handle, number); PUT_SEL32(obj, nodePtr, obj); PUT_SEL32(obj, handle, obj); } diff --git a/engines/sci/engine/scriptdebug.cpp b/engines/sci/engine/scriptdebug.cpp index 9f69d21e2a..7f5f201079 100644 --- a/engines/sci/engine/scriptdebug.cpp +++ b/engines/sci/engine/scriptdebug.cpp @@ -235,11 +235,11 @@ reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecod if (pos == scriptState.xs->addr.pc) { // Extra information if debugging the current opcode if (opcode == op_callk) { - int stackframe = (scr[pos.offset + 2] >> 1) + (scriptState.restadjust); + int stackframe = (scr[pos.offset + 2] >> 1) + (scriptState.restAdjust); int argc = ((scriptState.xs->sp)[- stackframe - 1]).offset; if (!s->_kernel->hasOldScriptHeader()) - argc += (scriptState.restadjust); + argc += (scriptState.restAdjust); printf(" Kernel params: ("); @@ -250,7 +250,7 @@ reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecod } printf(")\n"); } else if ((opcode == op_send) || (opcode == op_self)) { - int restmod = scriptState.restadjust; + int restmod = scriptState.restAdjust; int stackframe = (scr[pos.offset + 1] >> 1) + restmod; reg_t *sb = scriptState.xs->sp; uint16 selector; diff --git a/engines/sci/engine/static_selectors.cpp b/engines/sci/engine/static_selectors.cpp new file mode 100644 index 0000000000..c1d0ad9bac --- /dev/null +++ b/engines/sci/engine/static_selectors.cpp @@ -0,0 +1,429 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +// We place selector vocab name tables here for any game that doesn't have +// them. This includes the King's Quest IV Demo and LSL3 Demo. + +#ifndef SCI_STATIC_SELECTORS_H +#define SCI_STATIC_SELECTORS_H + +#include "sci/engine/kernel.h" + +namespace Sci { + +struct SelectorRemap { + const char *name; + uint32 slot; +}; + +// Taken from King's Quest IV (Full Game) +static const SelectorRemap kq4_demo_selectors[] = { + { "init", 87 }, + { "play", 42 }, + { "replay", 65 }, + { "x", 4 }, + { "y", 3 }, + { "z", 85 }, + { "priority", 63 }, + { "view", 5 }, + { "loop", 6 }, + { "cel", 7 }, + { "brLeft", 20 }, + { "brRight", 22 }, + { "brTop", 19 }, + { "brBottom", 21 }, + { "xStep", 54 }, + { "yStep", 55 }, + { "nsBottom", 11 }, + { "nsTop", 9 }, + { "nsLeft", 10 }, + { "nsRight", 12 }, + { "font", 33 }, + { "text", 26 }, + { "type", 34 }, + { "state", 32 }, + { "doit", 60 }, + { "delete", 84 }, + { "signal", 17 }, + { "underBits", 8 }, + { "canBeHere", 57 }, + { "client", 45 }, + { "dx", 46 }, + { "dy", 47 }, + { "xStep", 54 }, + { "yStep", 55 }, + { "b-moveCnt", 48 }, + { "b-i1", 49 }, + { "b-i2", 50 }, + { "b-di", 51 }, + { "b-xAxis", 52 }, + { "b-incr", 53 }, + { "completed", 158 }, + { "illegalBits", 18 }, + { "dispose", 88 }, + { "prevSignal", 129 }, + { "message", 40 }, + { "modifiers", 64 }, + { "cue", 121 }, + { "owner", 130 }, + { "handle", 44 }, + { "number", 43 }, + { "max", 37 }, + { "cursor", 36 }, + { "claimed", 76 }, + { "edgeHit", 225 }, + { "wordFail", 71 }, + { "syntaxFail", 72 }, + { "semanticFail", 73 }, + { "cycler", 165 }, + { "elements", 27 }, + { "lsTop", 13 }, + { "lsBottom", 15 }, + { "lsLeft", 14 }, + { "lsRight", 16 }, + { "baseSetter", 208 }, + { "who", 39 }, + { "distance", 173 }, + { "mover", 59 }, + { "looper", 62 }, + { "isBlocked", 61 }, + { "heading", 58 }, + { "mode", 30 }, + { "caller", 119 }, + { "moveDone", 169 }, + { "size", 96 }, + { "moveSpeed", 56 }, + { "motionCue", 161 }, + { "setTarget", 171 } +}; + +// Taken from EcoQuest 2 (Demo) +static const SelectorRemap christmas1992_selectors[] = { + { "init", 110 }, + { "play", 39 }, + { "replay", 62 }, + { "x", 1 }, + { "y", 0 }, + { "z", 82 }, + { "priority", 60 }, + { "view", 2 }, + { "loop", 3 }, + { "cel", 4 }, + { "brLeft", 17 }, + { "brRight", 19 }, + { "brTop", 16 }, + { "brBottom", 18 }, + { "xStep", 51 }, + { "yStep", 52 }, + { "nsBottom", 8 }, + { "nsTop", 6 }, + { "nsLeft", 7 }, + { "nsRight", 9 }, + { "font", 30 }, + { "text", 23 }, + { "type", 31 }, + { "state", 29 }, + { "doit", 57 }, + { "delete", 81 }, + { "signal", 14 }, + { "underBits", 5 }, + { "canBeHere", 450 }, + { "client", 42 }, + { "dx", 43 }, + { "dy", 44 }, + { "xStep", 51 }, + { "yStep", 52 }, + { "b-moveCnt", 45 }, + { "b-i1", 46 }, + { "b-i2", 47 }, + { "b-di", 48 }, + { "b-xAxis", 49 }, + { "b-incr", 50 }, + { "completed", 250 }, + { "illegalBits", 15 }, + { "dispose", 111 }, + { "prevSignal", 171 }, + { "message", 37 }, + { "modifiers", 61 }, + { "cue", 145 }, + { "owner", 172 }, + { "handle", 90 }, + { "number", 40 }, + { "max", 34 }, + { "cursor", 33 }, + { "claimed", 73 }, + { "edgeHit", 333 }, + { "wordFail", 68 }, + { "syntaxFail", 69 }, + { "semanticFail", 70 }, + { "cycler", 255 }, + { "elements", 24 }, + { "lsTop", 10 }, + { "lsBottom", 12 }, + { "lsLeft", 11 }, + { "lsRight", 13 }, + { "baseSetter", 310 }, + { "who", 36 }, + { "distance", 264 }, + { "mover", 56 }, + { "looper", 59 }, + { "isBlocked", 58 }, + { "heading", 55 }, + { "mode", 27 }, + { "caller", 143 }, + { "moveDone", 97 }, + { "vol", 94 }, + { "pri", 95 }, + { "min", 91 }, + { "sec", 92 }, + { "frame", 93 }, + { "dataInc", 89 }, + { "size", 86 }, + { "palette", 88 }, + { "moveSpeed", 53 }, + { "cantBeHere", 54 }, + { "nodePtr", 41 }, + { "flags", 99 }, + { "points", 87 }, + { "syncCue", 271 }, + { "syncTime", 270 }, + { "printLang", 84 }, + { "subtitleLang", 85 }, + { "parseLang", 83 }, + { "setVol", 178 } +}; + +// Taken from Leisure Suit Larry 1 VGA (Full Game) +static const SelectorRemap lsl1_demo_selectors[] = { + { "init", 104 }, + { "play", 42 }, + { "replay", 65 }, + { "x", 4 }, + { "y", 3 }, + { "z", 85 }, + { "priority", 63 }, + { "view", 5 }, + { "loop", 6 }, + { "cel", 7 }, + { "brLeft", 20 }, + { "brRight", 22 }, + { "brTop", 19 }, + { "brBottom", 21 }, + { "xStep", 54 }, + { "yStep", 55 }, + { "nsBottom", 11 }, + { "nsTop", 9 }, + { "nsLeft", 10 }, + { "nsRight", 12 }, + { "font", 33 }, + { "text", 26 }, + { "type", 34 }, + { "state", 32 }, + { "doit", 60 }, + { "delete", 84 }, + { "signal", 17 }, + { "underBits", 8 }, + { "canBeHere", 232 }, + { "client", 45 }, + { "dx", 46 }, + { "dy", 47 }, + { "xStep", 54 }, + { "yStep", 55 }, + { "b-moveCnt", 48 }, + { "b-i1", 49 }, + { "b-i2", 50 }, + { "b-di", 51 }, + { "b-xAxis", 52 }, + { "b-incr", 53 }, + { "completed", 210 }, + { "illegalBits", 18 }, + { "dispose", 105 }, + { "prevSignal", 149 }, + { "message", 40 }, + { "modifiers", 64 }, + { "cue", 136 }, + { "owner", 150 }, + { "handle", 93 }, + { "number", 43 }, + { "max", 37 }, + { "cursor", 36 }, + { "claimed", 76 }, + { "edgeHit", 321 }, + { "wordFail", 71 }, + { "syntaxFail", 72 }, + { "semanticFail", 73 }, + { "cycler", 215 }, + { "elements", 27 }, + { "lsTop", 13 }, + { "lsBottom", 15 }, + { "lsLeft", 14 }, + { "lsRight", 16 }, + { "baseSetter", 290 }, + { "who", 39 }, + { "distance", 224 }, + { "mover", 59 }, + { "looper", 62 }, + { "isBlocked", 61 }, + { "heading", 58 }, + { "mode", 30 }, + { "caller", 134 }, + { "moveDone", 100 }, + { "vol", 97 }, + { "pri", 98 }, + { "min", 94 }, + { "sec", 95 }, + { "frame", 96 }, + { "dataInc", 92 }, + { "size", 89 }, + { "palette", 91 }, + { "moveSpeed", 56 }, + { "cantBeHere", 57 }, + { "nodePtr", 44 }, + { "flags", 102 }, + { "points", 90 }, + { "syncCue", 248 }, + { "syncTime", 247 }, + { "printLang", 87 }, + { "subtitleLang", 88 }, + { "parseLang", 86 }, + { "setVol", 156 }, + { "motionCue", 213 }, + { "setTarget", 221 }, + { "egoMoveSpeed", 370 } +}; + +// Taken from Codename: Iceman (Full Game) +static const SelectorRemap iceman_demo_selectors[] = { + { "init", 87 }, + { "play", 42 }, + { "replay", 65 }, + { "x", 4 }, + { "y", 3 }, + { "z", 85 }, + { "priority", 63 }, + { "view", 5 }, + { "loop", 6 }, + { "cel", 7 }, + { "brLeft", 20 }, + { "brRight", 22 }, + { "brTop", 19 }, + { "brBottom", 21 }, + { "xStep", 54 }, + { "yStep", 55 }, + { "nsBottom", 11 }, + { "nsTop", 9 }, + { "nsLeft", 10 }, + { "nsRight", 12 }, + { "font", 33 }, + { "text", 26 }, + { "type", 34 }, + { "state", 32 }, + { "doit", 60 }, + { "delete", 84 }, + { "signal", 17 }, + { "underBits", 8 }, + { "canBeHere", 57 }, + { "client", 45 }, + { "dx", 46 }, + { "dy", 47 }, + { "xStep", 54 }, + { "yStep", 55 }, + { "b-moveCnt", 48 }, + { "b-i1", 49 }, + { "b-i2", 50 }, + { "b-di", 51 }, + { "b-xAxis", 52 }, + { "b-incr", 53 }, + { "completed", 159 }, + { "illegalBits", 18 }, + { "dispose", 88 }, + { "prevSignal", 129 }, + { "message", 40 }, + { "modifiers", 64 }, + { "cue", 121 }, + { "owner", 130 }, + { "handle", 44 }, + { "number", 43 }, + { "max", 37 }, + { "cursor", 36 }, + { "claimed", 76 }, + { "edgeHit", 236 }, + { "wordFail", 71 }, + { "syntaxFail", 72 }, + { "semanticFail", 73 }, + { "cycler", 164 }, + { "elements", 27 }, + { "lsTop", 13 }, + { "lsBottom", 15 }, + { "lsLeft", 14 }, + { "lsRight", 16 }, + { "baseSetter", 207 }, + { "who", 39 }, + { "distance", 173 }, + { "mover", 59 }, + { "looper", 62 }, + { "isBlocked", 61 }, + { "heading", 58 }, + { "mode", 30 }, + { "caller", 119 }, + { "moveDone", 170 }, + { "size", 96 }, + { "moveSpeed", 56 }, + { "flags", 368 }, + { "points", 316 }, + { "motionCue", 162 }, + { "setTarget", 171 } +}; + +// A macro for loading one of the above tables in the function below +#define USE_SELECTOR_TABLE(x) \ + do { \ + for (uint32 i = 0; i < ARRAYSIZE(x); i++) { \ + if (x[i].slot >= names.size()) \ + names.resize(x[i].slot + 1); \ + names[x[i].slot] = x[i].name; \ + } \ + } while (0) + +Common::StringList Kernel::checkStaticSelectorNames() { + Common::String gameID = ((SciEngine*)g_engine)->getGameID(); + + Common::StringList names; + + if (gameID == "kq4sci") + USE_SELECTOR_TABLE(kq4_demo_selectors); + else if (gameID == "lsl3" || gameID == "iceman") // identical, except iceman has "flags" + USE_SELECTOR_TABLE(iceman_demo_selectors); + else if (gameID == "christmas1992") + USE_SELECTOR_TABLE(christmas1992_selectors); + else if (gameID == "lsl1sci") + USE_SELECTOR_TABLE(lsl1_demo_selectors); + + return names; +} + +} // End of namespace Sci + +#endif // SCI_STATIC_SELECTORS_H diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index e0ac60f152..d220547c92 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -552,7 +552,7 @@ void run_vm(EngineState *s, int restoring) { StackPtr s_temp; // Temporary stack pointer int16 opparams[4]; // opcode parameters - scriptState.restadjust = s->restAdjust; + scriptState.restAdjust = s->restAdjust; // &rest adjusts the parameter count by this value // Current execution data: scriptState.xs = &(s->_executionStack.back()); @@ -931,17 +931,17 @@ void run_vm(EngineState *s, int restoring) { case 0x20: { // call int argc = (opparams[1] >> 1) // Given as offset, but we need count - + 1 + scriptState.restadjust; + + 1 + scriptState.restAdjust; StackPtr call_base = scriptState.xs->sp - argc; - scriptState.xs->sp[1].offset += scriptState.restadjust; - - xs_new = add_exec_stack_entry(s, make_reg(scriptState.xs->addr.pc.segment, - scriptState.xs->addr.pc.offset + opparams[0]), - scriptState.xs->sp, scriptState.xs->objp, - (validate_arithmetic(*call_base)) + scriptState.restadjust, - call_base, NULL_SELECTOR, scriptState.xs->objp, - s->_executionStack.size()-1, scriptState.xs->local_segment); - scriptState.restadjust = 0; // Used up the &rest adjustment + scriptState.xs->sp[1].offset += scriptState.restAdjust; + + xs_new = add_exec_stack_entry(s, make_reg(scriptState.xs->addr.pc.segment, + scriptState.xs->addr.pc.offset + opparams[0]), + scriptState.xs->sp, scriptState.xs->objp, + (validate_arithmetic(*call_base)) + scriptState.restAdjust, + call_base, NULL_SELECTOR, scriptState.xs->objp, + s->_executionStack.size()-1, scriptState.xs->local_segment); + scriptState.restAdjust = 0; // Used up the &rest adjustment scriptState.xs->sp = call_base; s->_executionStackPosChanged = true; @@ -953,8 +953,8 @@ void run_vm(EngineState *s, int restoring) { scriptState.xs->sp -= (opparams[1] >> 1) + 1; if (!s->_kernel->hasOldScriptHeader()) { - scriptState.xs->sp -= scriptState.restadjust; - s->restAdjust = 0; // We just used up the restadjust, remember? + scriptState.xs->sp -= scriptState.restAdjust; + s->restAdjust = 0; // We just used up the scriptState.restAdjust, remember? } if (opparams[0] >= (int)s->_kernel->_kernelFuncs.size()) { @@ -963,15 +963,15 @@ void run_vm(EngineState *s, int restoring) { int argc = ASSERT_ARITHMETIC(scriptState.xs->sp[0]); if (!s->_kernel->hasOldScriptHeader()) - argc += scriptState.restadjust; + argc += scriptState.restAdjust; if (s->_kernel->_kernelFuncs[opparams[0]].signature - && !kernel_matches_signature(s, - s->_kernel->_kernelFuncs[opparams[0]].signature, argc, - scriptState.xs->sp + 1)) { + && !kernel_matches_signature(s, + s->_kernel->_kernelFuncs[opparams[0]].signature, argc, + scriptState.xs->sp + 1)) { error("[VM] Invalid arguments to kernel call %x\n", opparams[0]); } else { - s->r_acc = s->_kernel->_kernelFuncs[opparams[0]].fun(s, opparams[0], + s->r_acc = s->_kernel->_kernelFuncs[opparams[0]].fun(s, opparams[0], argc, scriptState.xs->sp + 1); } // Call kernel function @@ -983,33 +983,33 @@ void run_vm(EngineState *s, int restoring) { s->_executionStackPosChanged = true; if (!s->_kernel->hasOldScriptHeader()) - scriptState.restadjust = s->restAdjust; + scriptState.restAdjust = s->restAdjust; } break; case 0x22: // callb - temp = ((opparams[1] >> 1) + scriptState.restadjust + 1); + temp = ((opparams[1] >> 1) + scriptState.restAdjust + 1); s_temp = scriptState.xs->sp; scriptState.xs->sp -= temp; - scriptState.xs->sp[0].offset += scriptState.restadjust; - xs_new = execute_method(s, 0, opparams[0], s_temp, scriptState.xs->objp, + scriptState.xs->sp[0].offset += scriptState.restAdjust; + xs_new = execute_method(s, 0, opparams[0], s_temp, scriptState.xs->objp, scriptState.xs->sp[0].offset, scriptState.xs->sp); - scriptState.restadjust = 0; // Used up the &rest adjustment + scriptState.restAdjust = 0; // Used up the &rest adjustment if (xs_new) // in case of error, keep old stack s->_executionStackPosChanged = true; break; case 0x23: // calle - temp = ((opparams[2] >> 1) + scriptState.restadjust + 1); + temp = ((opparams[2] >> 1) + scriptState.restAdjust + 1); s_temp = scriptState.xs->sp; scriptState.xs->sp -= temp; - scriptState.xs->sp[0].offset += scriptState.restadjust; - xs_new = execute_method(s, opparams[0], opparams[1], s_temp, scriptState.xs->objp, + scriptState.xs->sp[0].offset += scriptState.restAdjust; + xs_new = execute_method(s, opparams[0], opparams[1], s_temp, scriptState.xs->objp, scriptState.xs->sp[0].offset, scriptState.xs->sp); - scriptState.restadjust = 0; // Used up the &rest adjustment + scriptState.restAdjust = 0; // Used up the &rest adjustment if (xs_new) // in case of error, keep old stack s->_executionStackPosChanged = true; @@ -1027,7 +1027,7 @@ void run_vm(EngineState *s, int restoring) { s->_executionStack.pop_back(); s->_executionStackPosChanged = true; - s->restAdjust = scriptState.restadjust; // Update &rest + s->restAdjust = scriptState.restAdjust; // Update &rest return; // "Hard" return } @@ -1059,37 +1059,37 @@ void run_vm(EngineState *s, int restoring) { case 0x25: // send s_temp = scriptState.xs->sp; - scriptState.xs->sp -= ((opparams[0] >> 1) + scriptState.restadjust); // Adjust stack + scriptState.xs->sp -= ((opparams[0] >> 1) + scriptState.restAdjust); // Adjust stack - scriptState.xs->sp[1].offset += scriptState.restadjust; - xs_new = send_selector(s, s->r_acc, s->r_acc, s_temp, - (int)(opparams[0] >> 1) + scriptState.restadjust, scriptState.xs->sp); + scriptState.xs->sp[1].offset += scriptState.restAdjust; + xs_new = send_selector(s, s->r_acc, s->r_acc, s_temp, + (int)(opparams[0] >> 1) + (uint16)scriptState.restAdjust, scriptState.xs->sp); if (xs_new && xs_new != scriptState.xs) s->_executionStackPosChanged = true; - scriptState.restadjust = 0; + scriptState.restAdjust = 0; break; case 0x28: // class - s->r_acc = get_class_address(s, (unsigned)opparams[0], SCRIPT_GET_LOCK, + s->r_acc = get_class_address(s, (unsigned)opparams[0], SCRIPT_GET_LOCK, scriptState.xs->addr.pc); break; case 0x2a: // self s_temp = scriptState.xs->sp; - scriptState.xs->sp -= ((opparams[0] >> 1) + scriptState.restadjust); // Adjust stack + scriptState.xs->sp -= ((opparams[0] >> 1) + scriptState.restAdjust); // Adjust stack - scriptState.xs->sp[1].offset += scriptState.restadjust; - xs_new = send_selector(s, scriptState.xs->objp, scriptState.xs->objp, - s_temp, (int)(opparams[0] >> 1) + scriptState.restadjust, + scriptState.xs->sp[1].offset += scriptState.restAdjust; + xs_new = send_selector(s, scriptState.xs->objp, scriptState.xs->objp, + s_temp, (int)(opparams[0] >> 1) + (uint16)scriptState.restAdjust, scriptState.xs->sp); if (xs_new && xs_new != scriptState.xs) s->_executionStackPosChanged = true; - scriptState.restadjust = 0; + scriptState.restAdjust = 0; break; case 0x2b: // super @@ -1099,24 +1099,24 @@ void run_vm(EngineState *s, int restoring) { error("[VM]: Invalid superclass in object"); else { s_temp = scriptState.xs->sp; - scriptState.xs->sp -= ((opparams[1] >> 1) + scriptState.restadjust); // Adjust stack + scriptState.xs->sp -= ((opparams[1] >> 1) + scriptState.restAdjust); // Adjust stack - scriptState.xs->sp[1].offset += scriptState.restadjust; - xs_new = send_selector(s, r_temp, scriptState.xs->objp, s_temp, - (int)(opparams[1] >> 1) + scriptState.restadjust, + scriptState.xs->sp[1].offset += scriptState.restAdjust; + xs_new = send_selector(s, r_temp, scriptState.xs->objp, s_temp, + (int)(opparams[1] >> 1) + (uint16)scriptState.restAdjust, scriptState.xs->sp); if (xs_new && xs_new != scriptState.xs) s->_executionStackPosChanged = true; - scriptState.restadjust = 0; + scriptState.restAdjust = 0; } break; case 0x2c: // &rest temp = (uint16) opparams[0]; // First argument - scriptState.restadjust = MAX<uint16>(scriptState.xs->argc - temp + 1, 0); // +1 because temp counts the paramcount while argc doesn't + scriptState.restAdjust = MAX<int16>(scriptState.xs->argc - temp + 1, 0); // +1 because temp counts the paramcount while argc doesn't for (; temp <= scriptState.xs->argc; temp++) PUSH32(scriptState.xs->variables_argp[temp]); diff --git a/engines/sci/module.mk b/engines/sci/module.mk index f2c58bcd8d..bada214b61 100644 --- a/engines/sci/module.mk +++ b/engines/sci/module.mk @@ -33,6 +33,7 @@ MODULE_OBJS = \ engine/script.o \ engine/scriptdebug.o \ engine/seg_manager.o \ + engine/static_selectors.o \ engine/stringfrag.o \ engine/state.o \ engine/vm.o \ diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index 5fdc286894..a0aa40bcd5 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -883,6 +883,21 @@ void ResourceManager::processPatch(ResourceSource *source, ResourceType restype, debug("Patching %s failed - resource type mismatch", source->location_name.c_str()); return; } + + // Fixes SQ5/German, patch file special case logic taken from SCI View disassembly + if (patch_data_offset & 0x80) { + switch (patch_data_offset & 0x7F) { + case 0: + patch_data_offset = 24; + break; + case 1: + patch_data_offset = 2; + break; + default: + warning("Resource patch unsupported special case %X\n", patch_data_offset); + } + } + if (patch_data_offset + 2 >= fsize) { debug("Patching %s failed - patch starting at offset %d can't be in file of size %d", source->location_name.c_str(), patch_data_offset + 2, fsize); diff --git a/engines/sci/sfx/iterator.cpp b/engines/sci/sfx/iterator.cpp index ebba4bceac..6c5706a8c1 100644 --- a/engines/sci/sfx/iterator.cpp +++ b/engines/sci/sfx/iterator.cpp @@ -1164,6 +1164,41 @@ int CleanupSongIterator::nextCommand(byte *buf, int *result) { return SI_FINISHED; } +/**********************/ +/*-- Timer iterator --*/ +/**********************/ +TimerSongIterator::TimerSongIterator(int delta) + : _delta(delta) { +} + +int TimerSongIterator::nextCommand(byte *buf, int *result) { + if (_delta) { + return _delta; + } + return SI_FINISHED; +} + +SongIterator *TimerSongIterator::handleMessage(Message msg) { + return NULL; +} + +int TimerSongIterator::getTimepos() { + return 0; +} + +Audio::AudioStream *TimerSongIterator::getAudioStream() { + return NULL; +} + +SongIterator *TimerSongIterator::clone(int delta) { + TimerSongIterator *newit = new TimerSongIterator(*this); + return newit; +} + +SongIterator *new_timer_iterator(int delta) { + return new TimerSongIterator(delta); +} + /**********************************/ /*-- Fast-forward song iterator --*/ /**********************************/ diff --git a/engines/sci/sfx/iterator.h b/engines/sci/sfx/iterator.h index 547c479bbf..4e6df367c9 100644 --- a/engines/sci/sfx/iterator.h +++ b/engines/sci/sfx/iterator.h @@ -281,6 +281,12 @@ int songit_next(SongIterator **it, byte *buf, int *result, int mask); */ SongIterator *songit_new(byte *data, uint size, SongIteratorType type, songit_id_t id); +/* Constructs a new song timer iterator object +** Parameters: (int) delta: The delta after which to fire SI_FINISHED +** Returns : (SongIterator *) A newly allocated but uninitialized song +** iterator +*/ +SongIterator *new_timer_iterator(int delta); /* Handles a message to the song iterator ** Parameters: (SongIterator **): A reference to the variable storing the song iterator diff --git a/engines/sci/sfx/iterator_internal.h b/engines/sci/sfx/iterator_internal.h index 7d5a17fd25..00044b8ab7 100644 --- a/engines/sci/sfx/iterator_internal.h +++ b/engines/sci/sfx/iterator_internal.h @@ -181,6 +181,28 @@ private: #define PLAYMASK_NONE 0x0 +/***************************/ +/*--------- Timer ---------*/ +/***************************/ + +/** + * A song iterator which waits a specified time and then fires + * SI_FINISHED. Used by DoSound, where audio resources are played (SCI1) + */ +class TimerSongIterator : public SongIterator { +protected: + int _delta; /**!< Remaining time */ + +public: + TimerSongIterator(int delta); + + int nextCommand(byte *buf, int *result); + Audio::AudioStream *getAudioStream(); + SongIterator *handleMessage(Message msg); + int getTimepos(); + SongIterator *clone(int delta); +}; + /**********************************/ /*--------- Fast Forward ---------*/ /**********************************/ |