aboutsummaryrefslogtreecommitdiff
path: root/engines/sci
diff options
context:
space:
mode:
authorTravis Howell2009-07-11 11:48:01 +0000
committerTravis Howell2009-07-11 11:48:01 +0000
commite3398c0cc73999524e92774fb889a0d22eea552b (patch)
treeff1534d1e5e72f1965b747b21b594ef30d5e16ab /engines/sci
parent0577bee93893a55be1b2a067ec18f3c8ad462358 (diff)
parent2ceea652e62b301adea4628cebe4116191aa4998 (diff)
downloadscummvm-rg350-e3398c0cc73999524e92774fb889a0d22eea552b.tar.gz
scummvm-rg350-e3398c0cc73999524e92774fb889a0d22eea552b.tar.bz2
scummvm-rg350-e3398c0cc73999524e92774fb889a0d22eea552b.zip
Merged revisions 42360-42361,42364-42366,42368-42378,42380 via svnmerge from
https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk ........ r42360 | Kirben | 2009-07-11 10:38:50 +1000 (Sat, 11 Jul 2009) | 1 line Fix recent regression in AGOSEngine_Simon1::drawImage(). ........ r42361 | wjpalenstijn | 2009-07-11 10:47:32 +1000 (Sat, 11 Jul 2009) | 3 lines Fix SAGA outline generation algorithm for characters that are copies of earlier characters. (5 characters in IHNM.) This fixes #1904624. ........ r42364 | Kirben | 2009-07-11 11:40:53 +1000 (Sat, 11 Jul 2009) | 1 line Fix bug #2819628 - DETECTOR: Atlantis CD sets wrong gui options. ........ r42365 | lordhoto | 2009-07-11 11:54:27 +1000 (Sat, 11 Jul 2009) | 1 line Fix graphics not updating, when loading a save in Kyra1. This fixes problems when loading saves in rooms like Brynn's temple, which play animations directly on scene enter. ........ r42366 | lordhoto | 2009-07-11 11:54:42 +1000 (Sat, 11 Jul 2009) | 1 line Removed the now uneeded "Screen::_disableScreen" flag. ........ r42368 | dreammaster | 2009-07-11 15:10:13 +1000 (Sat, 11 Jul 2009) | 1 line Bugfix to show the mouse cursor when restarting the game after returning to launcher ........ r42369 | dreammaster | 2009-07-11 15:12:17 +1000 (Sat, 11 Jul 2009) | 1 line Active background screens are now properly freed when the game exits ........ r42370 | dreammaster | 2009-07-11 15:14:42 +1000 (Sat, 11 Jul 2009) | 1 line Added initialisation of paging screens when the game starts ........ r42371 | thebluegr | 2009-07-11 16:19:29 +1000 (Sat, 11 Jul 2009) | 1 line Fixed regression in the script parser from commit 42260 ........ r42372 | thebluegr | 2009-07-11 16:33:19 +1000 (Sat, 11 Jul 2009) | 1 line Applied a slightly modified patch from clone2727 which adds static selector names to some demos which are missing them (KQ4, LSL1, LSL3, Iceman and Christmas1992) ........ r42373 | thebluegr | 2009-07-11 16:34:25 +1000 (Sat, 11 Jul 2009) | 1 line Removed an invalid detection entry ........ r42374 | thebluegr | 2009-07-11 16:43:01 +1000 (Sat, 11 Jul 2009) | 1 line Applied slightly modified patch 2819002 - "SCI: resource-view-patch on SQ5/German fix" ........ r42375 | thebluegr | 2009-07-11 16:53:39 +1000 (Sat, 11 Jul 2009) | 1 line Applied patch 2818733 - "SCI: Timer iterator for audio resources played via doSound" ........ r42376 | Kirben | 2009-07-11 17:03:28 +1000 (Sat, 11 Jul 2009) | 1 line Only error out, if checkStaticSelectorNames() fails. ........ r42377 | dreammaster | 2009-07-11 18:16:55 +1000 (Sat, 11 Jul 2009) | 1 line Bugfix to properly save the currently playing midi music when saving a scene ........ r42378 | wjpalenstijn | 2009-07-11 19:45:25 +1000 (Sat, 11 Jul 2009) | 1 line Fix oversight in r42361 and also handle consecutive copied characters in SAGA. ........ r42380 | drmccoy | 2009-07-11 20:24:06 +1000 (Sat, 11 Jul 2009) | 1 line Explicitely instantiate the decompressWizImage() templates, so that they won't be optimized away, as they are also used in akos.cpp ........ svn-id: r42381
Diffstat (limited to 'engines/sci')
-rw-r--r--engines/sci/console.cpp7
-rw-r--r--engines/sci/debug.h2
-rw-r--r--engines/sci/detection.cpp10
-rw-r--r--engines/sci/engine/kernel.cpp43
-rw-r--r--engines/sci/engine/kernel.h6
-rw-r--r--engines/sci/engine/ksound.cpp17
-rw-r--r--engines/sci/engine/scriptdebug.cpp6
-rw-r--r--engines/sci/engine/static_selectors.cpp429
-rw-r--r--engines/sci/engine/vm.cpp90
-rw-r--r--engines/sci/module.mk1
-rw-r--r--engines/sci/resource.cpp15
-rw-r--r--engines/sci/sfx/iterator.cpp35
-rw-r--r--engines/sci/sfx/iterator.h6
-rw-r--r--engines/sci/sfx/iterator_internal.h22
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 ---------*/
/**********************************/