aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--backends/platform/androidsdl/androidsdl.mk6
-rw-r--r--dists/androidsdl/scummvm/AndroidAppSettings.cfg2
-rw-r--r--dists/androidsdl/scummvm/AndroidAppSettings.cfg.in2
-rw-r--r--engines/adl/adl.cpp9
-rw-r--r--engines/adl/adl.h3
-rw-r--r--engines/adl/adl_v2.cpp14
-rw-r--r--engines/adl/adl_v2.h5
-rw-r--r--engines/adl/detection.cpp2
-rw-r--r--engines/adl/hires6.cpp33
-rw-r--r--engines/agi/agi.cpp3
-rw-r--r--engines/agi/agi.h28
-rw-r--r--engines/agi/console.cpp26
-rw-r--r--engines/agi/id.cpp97
-rw-r--r--engines/agi/loader_v1.cpp2
-rw-r--r--engines/agi/loader_v2.cpp7
-rw-r--r--engines/agi/loader_v3.cpp2
-rw-r--r--engines/agi/module.mk1
-rw-r--r--engines/agi/op_cmd.cpp25
-rw-r--r--engines/agi/op_dbg.cpp29
-rw-r--r--engines/agi/op_test.cpp33
-rw-r--r--engines/agi/opcodes.cpp140
-rw-r--r--engines/agi/opcodes.h11
-rw-r--r--engines/director/cast.cpp6
-rw-r--r--engines/director/director.cpp20
-rw-r--r--engines/director/director.h13
-rw-r--r--engines/director/frame.cpp5
-rw-r--r--engines/director/lingo/lingo-builtins.cpp16
-rw-r--r--engines/director/lingo/lingo-code.cpp65
-rw-r--r--engines/director/lingo/lingo-codegen.cpp8
-rw-r--r--engines/director/lingo/lingo-funcs.cpp66
-rw-r--r--engines/director/lingo/lingo-gr.cpp186
-rw-r--r--engines/director/lingo/lingo-gr.y69
-rw-r--r--engines/director/lingo/lingo-lex.cpp2
-rw-r--r--engines/director/lingo/lingo-lex.l2
-rw-r--r--engines/director/lingo/lingo.cpp27
-rw-r--r--engines/director/lingo/lingo.h2
-rw-r--r--engines/director/score.cpp13
-rw-r--r--engines/director/score.h1
-rw-r--r--engines/titanic/game/end_explode_ship.cpp16
-rw-r--r--engines/titanic/game/end_explode_ship.h5
-rw-r--r--engines/titanic/game/end_game_credits.cpp3
-rw-r--r--engines/titanic/npcs/bellbot.cpp4
-rw-r--r--engines/titanic/support/credit_text.cpp52
-rw-r--r--engines/titanic/support/credit_text.h13
-rw-r--r--engines/titanic/support/font.cpp2
-rw-r--r--engines/tsage/ringworld2/ringworld2_logic.cpp3
-rw-r--r--graphics/managed_surface.cpp2
-rw-r--r--po/de_DE.po18
-rw-r--r--po/el.po10
-rw-r--r--po/fi_FI.po16
-rw-r--r--po/fr_FR.po16
-rw-r--r--po/hu_HU.po19
-rw-r--r--po/ru_RU.po22
-rw-r--r--po/uk_UA.po24
54 files changed, 661 insertions, 545 deletions
diff --git a/backends/platform/androidsdl/androidsdl.mk b/backends/platform/androidsdl/androidsdl.mk
index 1defb81b97..53c0d27666 100644
--- a/backends/platform/androidsdl/androidsdl.mk
+++ b/backends/platform/androidsdl/androidsdl.mk
@@ -4,8 +4,8 @@ androidsdl:
$(INSTALL) -c -m 644 $(DIST_FILES_THEMES) $(DIST_FILES_ENGINEDATA) release
$(INSTALL) -c -m 644 $(DIST_FILES_DOCS) release
$(CP) $(srcdir)/backends/vkeybd/packs/vkeybd_default.zip release
- zip -j scummvm190-git-appdata.zip release/*
- split -d -b 1000000 scummvm190-git-appdata.zip scummvm190-git-appdata.zip0
- $(RM) -r scummvm190-git-appdata.zip
+ zip -j scummvm_1_10_0-git-appdata.zip release/*
+ split -d -b 1000000 scummvm_1_10_0-git-appdata.zip scummvm_1_10_0-git-appdata.zip0
+ $(RM) -r scummvm_1_10_0-git-appdata.zip
.PHONY: androidsdl
diff --git a/dists/androidsdl/scummvm/AndroidAppSettings.cfg b/dists/androidsdl/scummvm/AndroidAppSettings.cfg
index 1c044fef3e..55300e6edd 100644
--- a/dists/androidsdl/scummvm/AndroidAppSettings.cfg
+++ b/dists/androidsdl/scummvm/AndroidAppSettings.cfg
@@ -23,7 +23,7 @@ InhibitSuspend=y
# If the URL does not contain 'http://' it is treated as file from 'project/jni/application/src/AndroidData' dir -
# these files are put inside .apk package by build system
# Also please avoid 'https://' URLs, many Android devices do not have trust certificates and will fail to connect to SF.net over HTTPS
-AppDataDownloadUrl="!!App data|scummvm190-git-appdata.zip"
+AppDataDownloadUrl="!!App data|scummvm_1_10_0-git-appdata.zip"
# Video color depth - 16 BPP is the fastest and supported for all modes, 24 bpp is supported only
# with SwVideoMode=y, SDL_OPENGL mode supports everything. (16)/(24)/(32)
diff --git a/dists/androidsdl/scummvm/AndroidAppSettings.cfg.in b/dists/androidsdl/scummvm/AndroidAppSettings.cfg.in
index 78756b0da6..897389a36f 100644
--- a/dists/androidsdl/scummvm/AndroidAppSettings.cfg.in
+++ b/dists/androidsdl/scummvm/AndroidAppSettings.cfg.in
@@ -23,7 +23,7 @@ InhibitSuspend=y
# If the URL does not contain 'http://' it is treated as file from 'project/jni/application/src/AndroidData' dir -
# these files are put inside .apk package by build system
# Also please avoid 'https://' URLs, many Android devices do not have trust certificates and will fail to connect to SF.net over HTTPS
-AppDataDownloadUrl="!!App data|scummvm190-git-appdata.zip"
+AppDataDownloadUrl="!!App data|scummvm_1_10_0-git-appdata.zip"
# Video color depth - 16 BPP is the fastest and supported for all modes, 24 bpp is supported only
# with SwVideoMode=y, SDL_OPENGL mode supports everything. (16)/(24)/(32)
diff --git a/engines/adl/adl.cpp b/engines/adl/adl.cpp
index 58d5fa9e67..3887fa92d9 100644
--- a/engines/adl/adl.cpp
+++ b/engines/adl/adl.cpp
@@ -56,6 +56,7 @@ AdlEngine::AdlEngine(OSystem *syst, const AdlGameDescription *gd) :
_display(nullptr),
_graphics(nullptr),
_textMode(false),
+ _linesPrinted(0),
_isRestarting(false),
_isRestoring(false),
_isQuitting(false),
@@ -635,6 +636,8 @@ void AdlEngine::gameLoop() {
if (shouldQuit())
return;
+ _linesPrinted = 0;
+
// If we just restored from the GMM, we skip this command
// set, as no command has been input by the user
if (!_isRestoring)
@@ -888,6 +891,12 @@ bool AdlEngine::canSaveGameStateCurrently() {
// Here we check whether or not the game currently accepts the command
// "SAVE GAME". This prevents saving via the GMM in situations where
// it wouldn't otherwise be possible to do so.
+ for (cmd = _roomData.commands.begin(); cmd != _roomData.commands.end(); ++cmd) {
+ ScriptEnv env(*cmd, _state.room, _saveVerb, _saveNoun);
+ if (matchCommand(env))
+ return env.op() == IDO_ACT_SAVE;
+ }
+
for (cmd = _roomCommands.begin(); cmd != _roomCommands.end(); ++cmd) {
ScriptEnv env(*cmd, _state.room, _saveVerb, _saveNoun);
if (matchCommand(env))
diff --git a/engines/adl/adl.h b/engines/adl/adl.h
index d71d40816e..75c6485a1f 100644
--- a/engines/adl/adl.h
+++ b/engines/adl/adl.h
@@ -239,6 +239,7 @@ protected:
// Engine
Common::Error loadGameState(int slot);
Common::Error saveGameState(int slot, const Common::String &desc);
+ bool canSaveGameStateCurrently();
virtual void gameLoop();
virtual void loadState(Common::ReadStream &stream);
@@ -390,6 +391,7 @@ protected:
// Game state
State _state;
+ uint _linesPrinted;
bool _isRestarting, _isRestoring, _isQuitting;
bool _canSaveNow, _canRestoreNow;
bool _abortScript;
@@ -410,7 +412,6 @@ private:
Common::Error run();
bool hasFeature(EngineFeature f) const;
bool canLoadGameStateCurrently();
- bool canSaveGameStateCurrently();
// Text input
byte convertKey(uint16 ascii) const;
diff --git a/engines/adl/adl_v2.cpp b/engines/adl/adl_v2.cpp
index 272e7801e7..23294391ab 100644
--- a/engines/adl/adl_v2.cpp
+++ b/engines/adl/adl_v2.cpp
@@ -36,7 +36,6 @@ AdlEngine_v2::~AdlEngine_v2() {
AdlEngine_v2::AdlEngine_v2(OSystem *syst, const AdlGameDescription *gd) :
AdlEngine(syst, gd),
- _linesPrinted(0),
_maxLines(4),
_disk(nullptr),
_itemRemoved(false),
@@ -285,9 +284,6 @@ void AdlEngine_v2::showRoom() {
_display->updateHiResScreen();
printString(_roomData.description);
-
- // FIXME: move to main loop?
- _linesPrinted = 0;
}
// TODO: Merge this into AdlEngine?
@@ -615,6 +611,16 @@ int AdlEngine_v2::o2_initDisk(ScriptEnv &e) {
return 0;
}
+bool AdlEngine_v2::canSaveGameStateCurrently() {
+ // Back up first visit flag as it may be changed by this test
+ const bool isFirstTime = getCurRoom().isFirstTime;
+ const bool retval = AdlEngine::canSaveGameStateCurrently();
+
+ getCurRoom().isFirstTime = isFirstTime;
+
+ return retval;
+}
+
int AdlEngine_v2::askForSlot(const Common::String &question) {
while (1) {
_display->printString(question);
diff --git a/engines/adl/adl_v2.h b/engines/adl/adl_v2.h
index 5447974a2e..9d4d5fa600 100644
--- a/engines/adl/adl_v2.h
+++ b/engines/adl/adl_v2.h
@@ -51,6 +51,9 @@ protected:
virtual void showRoom();
void takeItem(byte noun);
+ // Engine
+ bool canSaveGameStateCurrently();
+
virtual DataBlockPtr readDataBlockPtr(Common::ReadStream &f) const;
virtual void adjustDataBlockPtr(byte &track, byte &sector, byte &offset, byte &size) const { }
void loadItems(Common::ReadStream &stream);
@@ -86,7 +89,7 @@ protected:
Common::String restoreInsert, restoreReplace;
} _strings_v2;
- uint _linesPrinted, _maxLines;
+ uint _maxLines;
DiskImage *_disk;
Common::Array<DataBlockPtr> _itemPics;
bool _itemRemoved;
diff --git a/engines/adl/detection.cpp b/engines/adl/detection.cpp
index 02fadd255b..c0b8a8fc75 100644
--- a/engines/adl/detection.cpp
+++ b/engines/adl/detection.cpp
@@ -210,7 +210,7 @@ static const AdlGameDescription gameDescriptions[] = {
},
Common::EN_ANY,
Common::kPlatformApple2,
- ADGF_UNSTABLE,
+ ADGF_TESTING,
GUIO2(GAMEOPTION_COLOR_DEFAULT_ON, GAMEOPTION_SCANLINES)
},
GAME_TYPE_HIRES6
diff --git a/engines/adl/hires6.cpp b/engines/adl/hires6.cpp
index b3b66f6873..0eb47de7fc 100644
--- a/engines/adl/hires6.cpp
+++ b/engines/adl/hires6.cpp
@@ -58,6 +58,9 @@ private:
// AdlEngine_v2
void printString(const Common::String &str);
+ // Engine
+ bool canSaveGameStateCurrently();
+
template <Direction D>
int o_goDirection(ScriptEnv &e);
int o_fluteSound(ScriptEnv &e);
@@ -167,6 +170,7 @@ int HiRes6Engine::o_goDirection(ScriptEnv &e) {
byte room = getCurRoom().connections[D];
if (room == 0) {
+ // Don't penalize invalid directions at escapable Garthim encounter
if (getVar(33) == 2)
setVar(34, getVar(34) + 1);
@@ -176,6 +180,7 @@ int HiRes6Engine::o_goDirection(ScriptEnv &e) {
switchRoom(room);
+ // Escapes an escapable Garthim encounter by going to a different room
if (getVar(33) == 2) {
printMessage(102);
setVar(33, 0);
@@ -200,6 +205,22 @@ int HiRes6Engine::o_fluteSound(ScriptEnv &e) {
return 0;
}
+bool HiRes6Engine::canSaveGameStateCurrently() {
+ // Back up variables that may be changed by this test
+ const byte var2 = getVar(2);
+ const byte var24 = getVar(24);
+ const bool abortScript = _abortScript;
+
+ const bool retval = AdlEngine_v5::canSaveGameStateCurrently();
+
+ setVar(2, var2);
+ setVar(24, var24);
+ _abortScript = abortScript;
+
+ return retval;
+}
+
+
#define SECTORS_PER_TRACK 16
#define BYTES_PER_SECTOR 256
@@ -370,9 +391,6 @@ void HiRes6Engine::showRoom() {
_display->updateHiResScreen();
setVar(2, 0xff);
printString(_roomData.description);
-
- // FIXME: move to main loop?
- _linesPrinted = 0;
}
Common::String HiRes6Engine::formatVerbError(const Common::String &verb) const {
@@ -451,9 +469,12 @@ void HiRes6Engine::printString(const Common::String &str) {
if (getVar(2) == 0xff) {
if (getVar(26) == 0) {
// This checks for special room description string " "
- if (str.size() != 1 || APPLECHAR(str[0]) != APPLECHAR(' '))
- return AdlEngine_v5::printString(s);
- setVar(2, 160);
+ if (str.size() == 1 && APPLECHAR(str[0]) == APPLECHAR(' ')) {
+ setVar(2, 160);
+ } else {
+ AdlEngine_v5::printString(s);
+ setVar(2, 1);
+ }
} else if (getVar(26) == 0xff) {
// Storing the room number in a variable allows for range comparisons
setVar(26, _state.room);
diff --git a/engines/agi/agi.cpp b/engines/agi/agi.cpp
index b293a8e9e5..55872940f5 100644
--- a/engines/agi/agi.cpp
+++ b/engines/agi/agi.cpp
@@ -394,7 +394,6 @@ AgiEngine::AgiEngine(OSystem *syst, const AGIGameDescription *gameDesc) : AgiBas
resetControllers();
- setupOpcodes();
_game._curLogic = NULL;
_veryFirstInitialCycle = true;
_instructionCounter = 0;
@@ -498,6 +497,8 @@ void AgiEngine::initialize() {
} else {
warning("Could not open AGI game");
}
+ // finally set up actual VM opcodes, because we should now have figured out the right AGI version
+ setupOpCodes(getVersion());
debugC(2, kDebugLevelMain, "Init sound");
}
diff --git a/engines/agi/agi.h b/engines/agi/agi.h
index 2b62f9757a..2294593427 100644
--- a/engines/agi/agi.h
+++ b/engines/agi/agi.h
@@ -466,8 +466,6 @@ struct AgiGame {
ScreenObjEntry addToPicView;
- int32 ver; /**< detected game version */
-
bool automaticSave; /**< set by CmdSetSimple() */
char automaticSaveDescription[SAVEDGAME_DESCRIPTION_LEN + 1];
@@ -718,7 +716,20 @@ struct AgiArtificialDelayEntry {
uint16 millisecondsDelay;
};
-typedef void (*AgiCommand)(AgiGame *state, AgiEngine *vm, uint8 *p);
+typedef void (*AgiOpCodeFunction)(AgiGame *state, AgiEngine *vm, uint8 *p);
+
+struct AgiOpCodeEntry {
+ const char *name;
+ const char *parameters;
+ AgiOpCodeFunction functionPtr;
+ uint16 parameterSize;
+};
+
+struct AgiOpCodeDefinitionEntry {
+ const char *name;
+ const char *parameters;
+ AgiOpCodeFunction functionPtr;
+};
class AgiEngine : public AgiBase {
protected:
@@ -856,7 +867,7 @@ public:
void unloadLogic(int16 logicNr);
int runLogic(int16 logicNr);
void debugConsole(int, int, const char *);
- int testIfCode(int);
+ bool testIfCode(int16 logicNr);
void executeAgiCommand(uint8, uint8 *);
private:
@@ -985,10 +996,13 @@ private:
uint32 _passedPlayTimeCycles; // increased by 1 every time we passed a cycle
private:
- AgiCommand _agiCommands[183];
- AgiCommand _agiCondCommands[256];
+ AgiOpCodeEntry _opCodes[256]; // always keep those at 256, so that there is no way for invalid memory access
+ AgiOpCodeEntry _opCodesCond[256];
+
+ void setupOpCodes(uint16 version);
- void setupOpcodes();
+public:
+ const AgiOpCodeEntry *getOpCodesTable() { return _opCodes; }
};
} // End of namespace Agi
diff --git a/engines/agi/console.cpp b/engines/agi/console.cpp
index 9a4a357b44..3729cd3be6 100644
--- a/engines/agi/console.cpp
+++ b/engines/agi/console.cpp
@@ -94,16 +94,18 @@ bool Console::Cmd_SetObj(int argc, const char **argv) {
}
bool Console::Cmd_RunOpcode(int argc, const char **argv) {
+ const AgiOpCodeEntry *opCodes = _vm->getOpCodesTable();
+
if (argc < 2) {
debugPrintf("Usage: runopcode <name> <parameter0> ....\n");
return true;
}
- for (int i = 0; logicNamesCmd[i].name; i++) {
- if (!strcmp(argv[1], logicNamesCmd[i].name)) {
+ for (int i = 0; opCodes[i].name; i++) {
+ if (!strcmp(argv[1], opCodes[i].name)) {
uint8 p[16];
- if ((argc - 2) != logicNamesCmd[i].argumentsLength()) {
- debugPrintf("AGI command wants %d arguments\n", logicNamesCmd[i].argumentsLength());
+ if ((argc - 2) != opCodes[i].parameterSize) {
+ debugPrintf("AGI command wants %d arguments\n", opCodes[i].parameterSize);
return 0;
}
p[0] = argv[2] ? (char)strtoul(argv[2], NULL, 0) : 0;
@@ -112,7 +114,7 @@ bool Console::Cmd_RunOpcode(int argc, const char **argv) {
p[3] = argv[5] ? (char)strtoul(argv[5], NULL, 0) : 0;
p[4] = argv[6] ? (char)strtoul(argv[6], NULL, 0) : 0;
- debugC(5, kDebugLevelMain, "Opcode: %s %s %s %s", logicNamesCmd[i].name, argv[1], argv[2], argv[3]);
+ debugC(5, kDebugLevelMain, "Opcode: %s %s %s %s", opCodes[i].name, argv[1], argv[2], argv[3]);
_vm->executeAgiCommand(i, p);
@@ -392,24 +394,26 @@ bool Console::Cmd_Room(int argc, const char **argv) {
}
bool Console::Cmd_BT(int argc, const char **argv) {
+ const AgiOpCodeEntry *opCodes = _vm->getOpCodesTable();
+
debugPrintf("Current script: %d\nStack depth: %d\n", _vm->_game.curLogicNr, _vm->_game.execStack.size());
uint8 *code = NULL;
uint8 op = 0;
uint8 p[CMD_BSIZE] = { 0 };
- int num;
+ int parameterSize;
Common::Array<ScriptPos>::iterator it;
for (it = _vm->_game.execStack.begin(); it != _vm->_game.execStack.end(); ++it) {
code = _vm->_game.logics[it->script].data;
op = code[it->curIP];
- num = logicNamesCmd[op].argumentsLength();
- memmove(p, &code[it->curIP], num);
- memset(p + num, 0, CMD_BSIZE - num);
+ parameterSize = opCodes[op].parameterSize;
+ memmove(p, &code[it->curIP], parameterSize);
+ memset(p + parameterSize, 0, CMD_BSIZE - parameterSize);
- debugPrintf("%d(%d): %s(", it->script, it->curIP, logicNamesCmd[op].name);
+ debugPrintf("%d(%d): %s(", it->script, it->curIP, opCodes[op].name);
- for (int i = 0; i < num; i++)
+ for (int i = 0; i < parameterSize; i++)
debugPrintf("%d, ", p[i]);
debugPrintf(")\n");
diff --git a/engines/agi/id.cpp b/engines/agi/id.cpp
deleted file mode 100644
index 7985d3b9e4..0000000000
--- a/engines/agi/id.cpp
+++ /dev/null
@@ -1,97 +0,0 @@
-/* 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.
- *
- */
-
-#include "agi/agi.h"
-#include "agi/opcodes.h"
-
-namespace Agi {
-
-//
-// Currently, there is no known difference between v3.002.098 -> v3.002.149
-// So version emulated;
-//
-// 0x0086,
-// 0x0149
-//
-
-/**
- *
- */
-int AgiEngine::setupV2Game(int ver) {
- int ec = errOK;
-
- // Should this go above the previous lines, so we can force emulation versions
- // even for AGDS games? -- dsymonds
- if (getFeatures() & GF_AGDS)
- setVersion(ver = 0x2440); // ALL AGDS games built for 2.440
-
- debug(0, "Setting up for version 0x%04X", ver);
-
- // 'quit' takes 0 args for 2.089
- if (ver == 0x2089)
-// logicNamesCmd[0x86].numArgs = 0;
- logicNamesCmd[0x86].args = "";
-
- // 'print.at' and 'print.at.v' take 3 args before 2.272
- // This is documented in the specs as only < 2.440, but it seems
- // that KQ3 (2.272) needs a 'print.at' taking 4 args.
- if (ver < 0x2272) {
-// logicNamesCmd[0x97].numArgs = 3;
-// logicNamesCmd[0x98].numArgs = 3;
- logicNamesCmd[0x97].args = "vvv";
- logicNamesCmd[0x98].args = "vvv";
- }
-
- return ec;
-}
-
-/**
- *
- */
-int AgiEngine::setupV3Game(int ver) {
- int ec = errOK;
-
- debug(0, "Setting up for version 0x%04X", ver);
-
- // 'unknown176' takes 1 arg for 3.002.086, not 0 args.
- // 'unknown173' also takes 1 arg for 3.002.068, not 0 args.
- // Is this actually used anywhere? -- dsymonds
- if (ver == 0x3086) {
-// logicNamesCmd[0xb0].numArgs = 1;
-// logicNamesCmd[0xad].numArgs = 1;
- logicNamesCmd[0xb0].args = "n";
- logicNamesCmd[0xad].args = "n";
- }
-
- // FIXME: Apply this fix to other games also that use 2 arguments for command 182.
- // 'adj.ego.move.to.x.y' (i.e. command 182) takes 2 arguments for at least the
- // Amiga Gold Rush! (v2.05 1989-03-09) using Amiga AGI 2.316. Amiga's Gold Rush
- // has been set to use AGI 3.149 in ScummVM so that's why this initialization is
- // here and not in setupV2Game.
- if (getGameID() == GID_GOLDRUSH && getPlatform() == Common::kPlatformAmiga)
-// logicNamesCmd[182].numArgs = 2;
- logicNamesCmd[182].args = "vv";
-
- return ec;
-}
-
-} // End of namespace Agi
diff --git a/engines/agi/loader_v1.cpp b/engines/agi/loader_v1.cpp
index 0c569382cf..159e13772a 100644
--- a/engines/agi/loader_v1.cpp
+++ b/engines/agi/loader_v1.cpp
@@ -61,7 +61,7 @@ int AgiLoader_v1::detectGame() {
_filenameDisk0 = _vm->getDiskName(BooterDisk1);
_filenameDisk1 = _vm->getDiskName(BooterDisk2);
- return _vm->setupV2Game(_vm->getVersion());
+ return errOK;
}
int AgiLoader_v1::loadDir_DDP(AgiDir *agid, int offset, int max) {
diff --git a/engines/agi/loader_v2.cpp b/engines/agi/loader_v2.cpp
index 43ef46bd72..bebde69fe9 100644
--- a/engines/agi/loader_v2.cpp
+++ b/engines/agi/loader_v2.cpp
@@ -34,7 +34,12 @@ int AgiLoader_v2::detectGame() {
!Common::File::exists(VIEWDIR))
return errInvalidAGIFile;
- return _vm->setupV2Game(_vm->getVersion());
+ // Should this go above the previous lines, so we can force emulation versions
+ // even for AGDS games? -- dsymonds
+ if (_vm->getFeatures() & GF_AGDS)
+ _vm->setVersion(0x2440); // ALL AGDS games built for 2.440
+
+ return errOK;
}
int AgiLoader_v2::loadDir(AgiDir *agid, const char *fname) {
diff --git a/engines/agi/loader_v3.cpp b/engines/agi/loader_v3.cpp
index 5a208a5114..c21ad41cc5 100644
--- a/engines/agi/loader_v3.cpp
+++ b/engines/agi/loader_v3.cpp
@@ -52,7 +52,7 @@ int AgiLoader_v3::detectGame() {
strncpy(_vm->_game.name, f.c_str(), MIN((uint)8, f.size() > 5 ? f.size() - 5 : f.size()));
debugC(3, kDebugLevelMain, "game.name = %s", _vm->_game.name);
- ec = _vm->setupV3Game(_vm->getVersion());
+ ec = errOK;
found = true;
}
diff --git a/engines/agi/module.mk b/engines/agi/module.mk
index 32c3ac23ed..8ca261f55b 100644
--- a/engines/agi/module.mk
+++ b/engines/agi/module.mk
@@ -9,7 +9,6 @@ MODULE_OBJS := \
font.o \
global.o \
graphics.o \
- id.o \
inv.o \
keyboard.o \
loader_v1.o \
diff --git a/engines/agi/op_cmd.cpp b/engines/agi/op_cmd.cpp
index 8a62fce86c..32400b5afe 100644
--- a/engines/agi/op_cmd.cpp
+++ b/engines/agi/op_cmd.cpp
@@ -1051,9 +1051,10 @@ void cmdReleaseKey(AgiGame *state, AgiEngine *vm, uint8 *parameter) {
}
void cmdAdjEgoMoveToXY(AgiGame *state, AgiEngine *vm, uint8 *parameter) {
+ const AgiOpCodeEntry *opCodeTable = vm->getOpCodesTable();
int8 x, y;
- switch (logicNamesCmd[182].argumentsLength()) {
+ switch (opCodeTable[182].parameterSize) {
// The 2 arguments version is used at least in Amiga Gold Rush!
// (v2.05 1989-03-09, Amiga AGI 2.316) in logics 130 and 150
// (Using arguments (0, 0), (0, 7), (0, 8), (9, 9) and (-9, 9)).
@@ -2308,7 +2309,7 @@ int AgiEngine::runLogic(int16 logicNr) {
AgiGame *state = &_game;
uint8 op = 0;
uint8 p[CMD_BSIZE] = { 0 };
- int num = 0;
+ int curParameterSize = 0;
ScriptPos sp;
//int logic_index = 0;
@@ -2390,14 +2391,18 @@ int AgiEngine::runLogic(int16 logicNr) {
_game.execStack.pop_back();
return 1;
default:
- num = logicNamesCmd[op].argumentsLength();
- memmove(p, state->_curLogic->data + state->_curLogic->cIP, num);
- memset(p + num, 0, CMD_BSIZE - num);
+ curParameterSize = _opCodes[op].parameterSize;
+ memmove(p, state->_curLogic->data + state->_curLogic->cIP, curParameterSize);
+ memset(p + curParameterSize, 0, CMD_BSIZE - curParameterSize);
- debugC(2, kDebugLevelScripts, "%s%s(%d %d %d)", st, logicNamesCmd[op].name, p[0], p[1], p[2]);
+ debugC(2, kDebugLevelScripts, "%s%s(%d %d %d)", st, _opCodes[op].name, p[0], p[1], p[2]);
- _agiCommands[op](&_game, this, p);
- state->_curLogic->cIP += num;
+ if (!_opCodes[op].functionPtr) {
+ error("Illegal opcode %x in logic %d, ip %d", op, state->curLogicNr, state->_curLogic->cIP);
+ }
+
+ _opCodes[op].functionPtr(&_game, this, p);
+ state->_curLogic->cIP += curParameterSize;
}
// if ((op == 0x0B || op == 0x3F || op == 0x40) && logic_index < state->max_logics) {
@@ -2418,9 +2423,9 @@ int AgiEngine::runLogic(int16 logicNr) {
}
void AgiEngine::executeAgiCommand(uint8 op, uint8 *p) {
- debugC(2, kDebugLevelScripts, "%s(%d %d %d)", logicNamesCmd[op].name, p[0], p[1], p[2]);
+ debugC(2, kDebugLevelScripts, "%s(%d %d %d)", _opCodes[op].name, p[0], p[1], p[2]);
- _agiCommands[op](&_game, this, p);
+ _opCodes[op].functionPtr(&_game, this, p);
}
} // End of namespace Agi
diff --git a/engines/agi/op_dbg.cpp b/engines/agi/op_dbg.cpp
index c57782acd5..b35bd3928c 100644
--- a/engines/agi/op_dbg.cpp
+++ b/engines/agi/op_dbg.cpp
@@ -28,16 +28,14 @@ namespace Agi {
#define ip (_game.logics[lognum].cIP)
#define code (_game.logics[lognum].data)
-AgiInstruction logicNamesIf[] = {
- { "OR", "", NULL },
- { "NOT", "", NULL },
- { "ELSE", "", NULL },
- { "IF", "", NULL }
+const char *logicNamesIf[] = {
+ "OR", "NOT", "ELSE", "IF"
};
void AgiEngine::debugConsole(int lognum, int mode, const char *str) {
- AgiInstruction *x;
- uint8 a, z;
+ AgiOpCodeEntry *curOpCodeTable;
+ uint8 parametersLeft, z;
+ uint8 logicNameIdx;
const char *c;
if (str) {
@@ -52,8 +50,6 @@ void AgiEngine::debugConsole(int lognum, int mode, const char *str) {
case 0xFD:
case 0xFE:
case 0xFF:
- x = logicNamesIf;
-
if (_debug.opcodes) {
debugN(0, "%02X %02X %02X %02X %02X %02X %02X %02X %02X\n"
" ",
@@ -67,12 +63,13 @@ void AgiEngine::debugConsole(int lognum, int mode, const char *str) {
(uint8) * (code + (7 + ip)) & 0xFF,
(uint8) * (code + (8 + ip)) & 0xFF);
}
- debugN(0, "%s ", (x + * (code + ip) - 0xFC)->name);
+ logicNameIdx = (*(code + ip)) - 0xFC;
+ debugN(0, "%s ", logicNamesIf[logicNameIdx]);
break;
default:
- x = mode == lCOMMAND_MODE ? logicNamesCmd : logicNamesTest;
- a = x[*(code + ip)].argumentsLength();
- c = x[*(code + ip)].args;
+ curOpCodeTable = mode == lCOMMAND_MODE ? _opCodes : _opCodesCond;
+ parametersLeft = curOpCodeTable[*(code + ip)].parameterSize;
+ c = curOpCodeTable[*(code + ip)].parameters;
if (_debug.opcodes) {
debugN(0, "%02X %02X %02X %02X %02X %02X %02X %02X %02X\n"
@@ -87,9 +84,9 @@ void AgiEngine::debugConsole(int lognum, int mode, const char *str) {
(uint8) * (code + (7 + ip)) & 0xFF,
(uint8) * (code + (8 + ip)) & 0xFF);
}
- debugN(0, "%s ", (x + * (code + ip))->name);
+ debugN(0, "%s ", (curOpCodeTable + * (code + ip))->name);
- for (z = 1; a > 0;) {
+ for (z = 1; parametersLeft > 0;) {
if (*c == 'n') {
debugN(0, "%d", *(code + (ip + z)));
} else {
@@ -97,7 +94,7 @@ void AgiEngine::debugConsole(int lognum, int mode, const char *str) {
}
c++;
z++;
- if (--a > 0)
+ if (--parametersLeft > 0)
debugN(0, ",");
}
break;
diff --git a/engines/agi/op_test.cpp b/engines/agi/op_test.cpp
index 4505668fd1..6afddf844a 100644
--- a/engines/agi/op_test.cpp
+++ b/engines/agi/op_test.cpp
@@ -376,7 +376,7 @@ uint8 AgiEngine::testSaid(uint8 nwords, uint8 *cc) {
return true;
}
-int AgiEngine::testIfCode(int lognum) {
+bool AgiEngine::testIfCode(int16 logicNr) {
AgiGame *state = &_game;
uint8 op;
uint8 p[16];
@@ -387,8 +387,8 @@ int AgiEngine::testIfCode(int lognum) {
int result = true;
while (!(shouldQuit() || _restartGame) && !endTest) {
- if (_debug.enabled && (_debug.logic0 || lognum))
- debugConsole(lognum, lTEST_MODE, NULL);
+ if (_debug.enabled && (_debug.logic0 || logicNr))
+ debugConsole(logicNr, lTEST_MODE, NULL);
op = *(code + ip++);
memmove(p, (code + ip), 16);
@@ -418,7 +418,14 @@ int AgiEngine::testIfCode(int lognum) {
default:
// Evaluate the command and skip the rest of the instruction
- _agiCondCommands[op](state, this, p);
+ _opCodesCond[op].functionPtr(state, this, p);
+ if (state->exitAllLogics) {
+ // required even here, because of at least the timer heuristic
+ // which when triggered waits a bit and processes ScummVM events and user may therefore restore a saved game
+ // fixes bug #9707
+ // TODO: maybe delay restoring the game instead, when GMM is used?
+ return true;
+ }
skipInstruction(op);
// NOT mode is enabled only for one instruction
@@ -457,8 +464,8 @@ int AgiEngine::testIfCode(int lognum) {
else
ip += READ_LE_UINT16(code + ip) + 2;
- if (_debug.enabled && (_debug.logic0 || lognum))
- debugConsole(lognum, 0xFF, result ? "=true" : "=false");
+ if (_debug.enabled && (_debug.logic0 || logicNr))
+ debugConsole(logicNr, 0xFF, result ? "=true" : "=false");
return result;
}
@@ -469,16 +476,26 @@ void AgiEngine::skipInstruction(byte op) {
return;
if (op == 0x0E && state->_vm->getVersion() >= 0x2000) // said
ip += *(code + ip) * 2 + 1;
- else
- ip += logicNamesTest[op].argumentsLength();
+ else {
+ ip += _opCodesCond[op].parameterSize;
+ }
}
void AgiEngine::skipInstructionsUntil(byte v) {
AgiGame *state = &_game;
+ int originalIP = state->_curLogic->cIP;
+
while (1) {
byte op = *(code + ip++);
if (op == v)
return;
+
+ if (op < 0xFC) {
+ if (!_opCodesCond[op].functionPtr) {
+ // security-check
+ error("illegal opcode %x during skipinstructions in script %d at %d (triggered at %d)", op, state->curLogicNr, ip, originalIP);
+ }
+ }
skipInstruction(op);
}
}
diff --git a/engines/agi/opcodes.cpp b/engines/agi/opcodes.cpp
index 472917de77..be6748b40c 100644
--- a/engines/agi/opcodes.cpp
+++ b/engines/agi/opcodes.cpp
@@ -25,10 +25,7 @@
namespace Agi {
-AgiInstruction *logicNamesTest;
-AgiInstruction *logicNamesCmd;
-
-AgiInstruction insV1Test[] = {
+const AgiOpCodeDefinitionEntry opCodesV1Cond[] = {
{ "", "", &condUnknown }, // 00
{ "equaln", "vn", &condEqual }, // 01
{ "equalv", "vv", &condEqualV }, // 02
@@ -48,7 +45,7 @@ AgiInstruction insV1Test[] = {
{ "bit", "nv", &condBit }, // 10
};
-AgiInstruction insV1[] = {
+const AgiOpCodeDefinitionEntry opCodesV1[] = {
{ "return", "", NULL }, // 00
{ "increment", "v", &cmdIncrement }, // 01
{ "decrement", "v", &cmdDecrement }, // 02
@@ -149,7 +146,7 @@ AgiInstruction insV1[] = {
{ "...", "nv", &cmdUnknown }, // 61 # clearbit
};
-AgiInstruction insV2Test[] = {
+AgiOpCodeDefinitionEntry opCodesV2Cond[] = {
{ "", "", &condUnknown }, // 00
{ "equaln", "vn", &condEqual }, // 01
{ "equalv", "vv", &condEqualV }, // 02
@@ -172,7 +169,7 @@ AgiInstruction insV2Test[] = {
{ "in.motion.using.mouse", "", &condUnknown13 } // 13
};
-AgiInstruction insV2[] = {
+AgiOpCodeDefinitionEntry opCodesV2[] = {
{ "return", "", NULL }, // 00
{ "increment", "v", &cmdIncrement }, // 01
{ "decrement", "v", &cmdDecrement }, // 02
@@ -358,36 +355,115 @@ AgiInstruction insV2[] = {
{ "adj.ego.move.to.xy", "", &cmdAdjEgoMoveToXY } // C6
};
-void AgiEngine::setupOpcodes() {
- if (getVersion() >= 0x2000) {
- for (int i = 0; i < ARRAYSIZE(insV2Test); ++i)
- _agiCondCommands[i] = insV2Test[i].func;
- for (int i = 0; i < ARRAYSIZE(insV2); ++i)
- _agiCommands[i] = insV2[i].func;
+//
+// Currently, there is no known difference between v3.002.098 -> v3.002.149
+// So version emulated;
+// 0x0086,
+// 0x0149
+//
- logicNamesTest = insV2Test;
- logicNamesCmd = insV2;
+void AgiEngine::setupOpCodes(uint16 version) {
+ const AgiOpCodeDefinitionEntry *opCodesTable = nullptr;
+ const AgiOpCodeDefinitionEntry *opCodesCondTable = nullptr;
+ uint16 opCodesTableSize = 0;
+ uint16 opCodesCondTableSize = 0;
+ uint16 opCodesTableMaxSize = sizeof(_opCodes) / sizeof(AgiOpCodeEntry);
+ uint16 opCodesCondTableMaxSize = sizeof(_opCodesCond) / sizeof(AgiOpCodeEntry);
- // Alter opcode parameters for specific games
- // TODO: This could be either turned into a game feature, or a version
- // specific check, instead of a game version check
+ debug(0, "Setting up for version 0x%04X", version);
- // The Apple IIGS versions of MH1 and Goldrush both have a parameter for
- // show.mouse and hide.mouse. Fixes bugs #3577754 and #3426946.
- if ((getGameID() == GID_MH1 || getGameID() == GID_GOLDRUSH) &&
- getPlatform() == Common::kPlatformApple2GS) {
- logicNamesCmd[176].args = "n"; // hide.mouse
- logicNamesCmd[178].args = "n"; // show.mouse
- }
+ if (version >= 0x2000) {
+ opCodesTable = opCodesV2;
+ opCodesCondTable = opCodesV2Cond;
+ opCodesTableSize = ARRAYSIZE(opCodesV2);
+ opCodesCondTableSize = ARRAYSIZE(opCodesV2Cond);
} else {
- for (int i = 0; i < ARRAYSIZE(insV1Test); ++i)
- _agiCondCommands[i] = insV1Test[i].func;
- for (int i = 0; i < ARRAYSIZE(insV1); ++i)
- _agiCommands[i] = insV1[i].func;
+ opCodesTable = opCodesV1;
+ opCodesCondTable = opCodesV1Cond;
+ opCodesTableSize = ARRAYSIZE(opCodesV1);
+ opCodesCondTableSize = ARRAYSIZE(opCodesV1Cond);
+ }
- logicNamesTest = insV1Test;
- logicNamesCmd = insV1;
+ // copy data over
+ for (int opCodeNr = 0; opCodeNr < opCodesTableSize; opCodeNr++) {
+ _opCodes[opCodeNr].name = opCodesTable[opCodeNr].name;
+ _opCodes[opCodeNr].parameters = opCodesTable[opCodeNr].parameters;
+ _opCodes[opCodeNr].functionPtr = opCodesTable[opCodeNr].functionPtr;
}
-}
+ for (int opCodeNr = 0; opCodeNr < opCodesCondTableSize; opCodeNr++) {
+ _opCodesCond[opCodeNr].name = opCodesCondTable[opCodeNr].name;
+ _opCodesCond[opCodeNr].parameters = opCodesCondTable[opCodeNr].parameters;
+ _opCodesCond[opCodeNr].functionPtr = opCodesCondTable[opCodeNr].functionPtr;
+ }
+
+ // Alter opcode parameters for specific games
+ if ((version >= 0x2000) && (version < 0x3000)) {
+ // AGI3 adjustments
+
+ // 'quit' takes 0 args for 2.089
+ if (version == 0x2089)
+ _opCodes[0x86].parameters = "";
+
+ // 'print.at' and 'print.at.v' take 3 args before 2.272
+ // This is documented in the specs as only < 2.440, but it seems
+ // that KQ3 (2.272) needs a 'print.at' taking 4 args.
+ if (version < 0x2272) {
+ _opCodes[0x97].parameters = "vvv";
+ _opCodes[0x98].parameters = "vvv";
+ }
+ }
+
+ if (version >= 0x3000) {
+ // AGI3 adjustments
+ // 'unknown176' takes 1 arg for 3.002.086, not 0 args.
+ // 'unknown173' also takes 1 arg for 3.002.068, not 0 args.
+ // Is this actually used anywhere? -- dsymonds
+ if (version == 0x3086) {
+ _opCodes[0xb0].parameters = "n";
+ _opCodes[0xad].parameters = "n";
+ }
+ }
+
+ // TODO: This could be either turned into a game feature, or a version
+ // specific check, instead of a game version check
+ // The Apple IIGS versions of MH1 and Goldrush both have a parameter for
+ // show.mouse and hide.mouse. Fixes bugs #3577754 and #3426946.
+ if ((getGameID() == GID_MH1 || getGameID() == GID_GOLDRUSH) &&
+ getPlatform() == Common::kPlatformApple2GS) {
+ _opCodes[176].parameters = "n"; // hide.mouse
+ _opCodes[178].parameters = "n"; // show.mouse
+ }
+
+ // FIXME: Apply this fix to other games also that use 2 arguments for command 182.
+ // 'adj.ego.move.to.x.y' (i.e. command 182) takes 2 arguments for at least the
+ // Amiga Gold Rush! (v2.05 1989-03-09) using Amiga AGI 2.316. Amiga's Gold Rush
+ // has been set to use AGI 3.149 in ScummVM so that's why this initialization is
+ // here and not in setupV2Game.
+ if (getGameID() == GID_GOLDRUSH && getPlatform() == Common::kPlatformAmiga)
+ _opCodes[182].parameters = "vv";
+
+ // add invalid entries for every opcode, that is not defined at all
+ for (int opCodeNr = opCodesTableSize; opCodeNr < opCodesTableMaxSize; opCodeNr++) {
+ _opCodes[opCodeNr].name = "illegal";
+ _opCodes[opCodeNr].parameters = "";
+ _opCodes[opCodeNr].functionPtr = nullptr;
+ }
+
+ for (int opCodeNr = opCodesCondTableSize; opCodeNr < opCodesCondTableMaxSize; opCodeNr++) {
+ _opCodesCond[opCodeNr].name = "illegal";
+ _opCodesCond[opCodeNr].parameters = "";
+ _opCodesCond[opCodeNr].functionPtr = nullptr;
+ }
+
+ // calculate parameter size
+ for (int opCodeNr = 0; opCodeNr < opCodesTableSize; opCodeNr++) {
+ _opCodes[opCodeNr].parameterSize = strlen( _opCodes[opCodeNr].parameters);
+ }
+
+ for (int opCodeNr = 0; opCodeNr < opCodesCondTableSize; opCodeNr++) {
+ _opCodesCond[opCodeNr].parameterSize = strlen( _opCodesCond[opCodeNr].parameters);
+ }
}
+
+} // End of namespace Agi
diff --git a/engines/agi/opcodes.h b/engines/agi/opcodes.h
index d9644bdcda..63c922dc39 100644
--- a/engines/agi/opcodes.h
+++ b/engines/agi/opcodes.h
@@ -25,17 +25,6 @@
namespace Agi {
-struct AgiInstruction {
- const char *name;
- const char *args;
- AgiCommand func;
-
- int argumentsLength() { return strlen(args); }
-};
-
-extern AgiInstruction *logicNamesTest;
-extern AgiInstruction *logicNamesCmd;
-
void cmdIncrement(AgiGame *state, AgiEngine *vm, uint8 *p);
void cmdDecrement(AgiGame *state, AgiEngine *vm, uint8 *p);
void cmdAssignN(AgiGame *state, AgiEngine *vm, uint8 *p);
diff --git a/engines/director/cast.cpp b/engines/director/cast.cpp
index ed5b05643c..4b391bd8cc 100644
--- a/engines/director/cast.cpp
+++ b/engines/director/cast.cpp
@@ -83,7 +83,7 @@ TextCast::TextCast(Common::ReadStreamEndian &stream, uint16 version) {
textSlant = 0;
palinfo1 = palinfo2 = palinfo3 = 0;
- if (version < 4) {
+ if (version <= 3) {
flags1 = stream.readByte();
borderSize = static_cast<SizeType>(stream.readByte());
gutterSize = static_cast<SizeType>(stream.readByte());
@@ -115,7 +115,7 @@ TextCast::TextCast(Common::ReadStreamEndian &stream, uint16 version) {
fontId = stream.readByte();
fontSize = stream.readByte();
textSlant = 0;
- } else if (version < 5) {
+ } else if (version == 4) {
borderSize = static_cast<SizeType>(stream.readByte());
gutterSize = static_cast<SizeType>(stream.readByte());
boxShadow = static_cast<SizeType>(stream.readByte());
@@ -134,7 +134,7 @@ TextCast::TextCast(Common::ReadStreamEndian &stream, uint16 version) {
byte flags = stream.readByte();
if (flags)
- warning("Unproxessed text cast flags: %x", flags);
+ warning("Unprocessed text cast flags: %x", flags);
fontSize = stream.readUint16();
textSlant = 0;
diff --git a/engines/director/director.cpp b/engines/director/director.cpp
index bfe9a724be..a1ee253087 100644
--- a/engines/director/director.cpp
+++ b/engines/director/director.cpp
@@ -78,7 +78,7 @@ DirectorEngine::DirectorEngine(OSystem *syst, const DirectorGameDescription *gam
_movies = nullptr;
- _nextMovieFrameI = -1;
+ _nextMovie.frameI = -1;
_wm = nullptr;
@@ -165,21 +165,25 @@ Common::Error DirectorEngine::run() {
_currentScore->loadArchive();
// If we came in a loop, then skip as requested
- if (!_nextMovieFrameS.empty())
- _currentScore->setStartToLabel(_nextMovieFrameS);
+ if (!_nextMovie.frameS.empty()) {
+ _currentScore->setStartToLabel(_nextMovie.frameS);
+ _nextMovie.frameS.clear();
+ }
- if (_nextMovieFrameI != -1)
- _currentScore->setCurrentFrame(_nextMovieFrameI);
+ if (_nextMovie.frameI != -1) {
+ _currentScore->setCurrentFrame(_nextMovie.frameI);
+ _nextMovie.frameI = -1;
+ }
_currentScore->startLoop();
// If a loop was requested, do it
- if (!_nextMovie.empty()) {
+ if (!_nextMovie.movie.empty()) {
_lingo->restartLingo();
delete _currentScore;
- Archive *mov = openMainArchive(_nextMovie);
+ Archive *mov = openMainArchive(_nextMovie.movie);
if (!mov) {
warning("nextMovie: No score is loaded");
@@ -190,7 +194,7 @@ Common::Error DirectorEngine::run() {
_currentScore = new Score(this, mov);
debug(0, "Score name %s", _currentScore->getMacName().c_str());
- _nextMovie.clear();
+ _nextMovie.movie.clear();
loop = true;
}
}
diff --git a/engines/director/director.h b/engines/director/director.h
index fdbe8ded48..1c3d77fc71 100644
--- a/engines/director/director.h
+++ b/engines/director/director.h
@@ -62,6 +62,14 @@ enum {
kDebugLingoParse = 1 << 6
};
+struct MovieReference {
+ Common::String movie;
+ Common::String frameS;
+ int frameI;
+
+ MovieReference() { frameI = -1; }
+};
+
extern byte defaultPalette[768];
class DirectorEngine : public ::Engine {
@@ -112,9 +120,8 @@ public:
bool _playbackPaused;
bool _skipFrameAdvance;
- Common::String _nextMovie;
- Common::String _nextMovieFrameS;
- int _nextMovieFrameI;
+ MovieReference _nextMovie;
+ Common::List<MovieReference> _movieStack;
protected:
virtual Common::Error run();
diff --git a/engines/director/frame.cpp b/engines/director/frame.cpp
index 3c73b82af1..d20026cb62 100644
--- a/engines/director/frame.cpp
+++ b/engines/director/frame.cpp
@@ -915,6 +915,11 @@ void Frame::renderText(Graphics::ManagedSurface &surface, uint16 spriteId, Commo
// textCast->fontId = _vm->_wm->_fontMan->getFontIdByName(_vm->getCurrentScore()->_fontMap[textCast->fontId]);
}
+ if (width == 0 || height == 0) {
+ warning("renderText: Requested to draw on an empty surface: %d x %d", width, height);
+ return;
+ }
+
Graphics::MacFont macFont = Graphics::MacFont(textCast->fontId, textCast->fontSize, textCast->textSlant);
const Graphics::Font *font = _vm->_wm->_fontMan->getFont(macFont);
diff --git a/engines/director/lingo/lingo-builtins.cpp b/engines/director/lingo/lingo-builtins.cpp
index f4c26a2193..6411c59d4f 100644
--- a/engines/director/lingo/lingo-builtins.cpp
+++ b/engines/director/lingo/lingo-builtins.cpp
@@ -1505,7 +1505,21 @@ void Lingo::b_cast(int nargs) {
void Lingo::b_field(int nargs) {
Datum d = g_lingo->pop();
- warning("STUB: b_field");
+ int id;
+
+ if (d.type == STRING) {
+ if (g_director->getCurrentScore()->_castsNames.contains(*d.u.s))
+ id = g_director->getCurrentScore()->_castsNames[*d.u.s];
+ else
+ error("b_filed: Reference to non-existent field: %s", d.u.s->c_str());
+ } else if (d.type == INT || d.type == FLOAT) {
+ d.toInt();
+ id = d.u.i;
+ } else {
+ error("b_field: Incorrect reference type: %s", d.type2str());
+ }
+
+ d.u.i = id;
d.type = REFERENCE;
diff --git a/engines/director/lingo/lingo-code.cpp b/engines/director/lingo/lingo-code.cpp
index eeae0534d8..b7fc484d91 100644
--- a/engines/director/lingo/lingo-code.cpp
+++ b/engines/director/lingo/lingo-code.cpp
@@ -43,6 +43,7 @@
// ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
// THIS SOFTWARE.
+#include "director/cast.h"
#include "director/lingo/lingo.h"
#include "director/lingo/lingo-gr.h"
@@ -142,7 +143,7 @@ void Lingo::pushVoid() {
Datum Lingo::pop(void) {
if (_stack.size() == 0)
- error("stack underflow");
+ assert(0);
Datum ret = _stack.back();
_stack.pop_back();
@@ -212,7 +213,7 @@ void Lingo::c_voidpush() {
void Lingo::c_fconstpush() {
Datum d;
inst i = (*g_lingo->_currentScript)[g_lingo->_pc];
- d.u.i = READ_UINT32(&i); // d.u.f value will be read
+ d.u.f = *(double *)(&i);
d.type = FLOAT;
g_lingo->_pc += g_lingo->calcCodeAlignment(sizeof(double));
@@ -305,9 +306,14 @@ void Lingo::c_assign() {
}
if (d1.type == REFERENCE) {
+ if (!g_director->getCurrentScore()->_castsInfo.contains(d1.u.i)) {
+ warning("c_assign: Unknown REFERENCE %d", d1.u.i);
+ g_lingo->pushVoid();
+ return;
+ }
+
warning("STUB: c_assing REFERENCE");
- g_lingo->push(d1);
return;
}
@@ -343,8 +349,6 @@ void Lingo::c_assign() {
}
d1.u.sym->type = d2.type;
-
- g_lingo->push(d1);
}
bool Lingo::verify(Symbol *s) {
@@ -422,8 +426,6 @@ void Lingo::c_theentityassign() {
Datum d = g_lingo->pop();
g_lingo->setTheEntity(entity, id, field, d);
-
- g_lingo->push(d); // Dummy value
}
void Lingo::c_swap() {
@@ -833,7 +835,7 @@ void Lingo::c_repeatwhilecode(void) {
d.toInt();
while (d.u.i) {
- g_lingo->execute(body); /* body */
+ g_lingo->execute(body + savepc - 1); /* body */
if (g_lingo->_returning)
break;
@@ -848,7 +850,7 @@ void Lingo::c_repeatwhilecode(void) {
}
if (!g_lingo->_returning)
- g_lingo->_pc = end; /* next stmt */
+ g_lingo->_pc = end + savepc - 1; /* next stmt */
}
void Lingo::c_repeatwithcode(void) {
@@ -867,14 +869,14 @@ void Lingo::c_repeatwithcode(void) {
error("Cast ref used as index: %s", countername.c_str());
}
- g_lingo->execute(init); /* condition */
+ g_lingo->execute(init + savepc - 1); /* condition */
d = g_lingo->pop();
d.toInt();
counter->u.i = d.u.i;
counter->type = INT;
while (true) {
- g_lingo->execute(body); /* body */
+ g_lingo->execute(body + savepc - 1); /* body */
if (g_lingo->_returning)
break;
@@ -884,7 +886,7 @@ void Lingo::c_repeatwithcode(void) {
}
counter->u.i += inc;
- g_lingo->execute(finish); /* condition */
+ g_lingo->execute(finish + savepc - 1); /* condition */
d = g_lingo->pop();
d.toInt();
@@ -893,7 +895,7 @@ void Lingo::c_repeatwithcode(void) {
}
if (!g_lingo->_returning)
- g_lingo->_pc = end; /* next stmt */
+ g_lingo->_pc = end + savepc - 1; /* next stmt */
}
void Lingo::c_exitRepeat(void) {
@@ -916,14 +918,14 @@ void Lingo::c_ifcode() {
if (d.toInt()) {
debugC(8, kDebugLingoExec, "executing then");
- g_lingo->execute(then);
+ g_lingo->execute(then + savepc - 1);
} else if (elsep) { /* else part? */
debugC(8, kDebugLingoExec, "executing else");
- g_lingo->execute(elsep);
+ g_lingo->execute(elsep + savepc - 1);
}
if (!g_lingo->_returning && !skipEnd) {
- g_lingo->_pc = end; /* next stmt */
+ g_lingo->_pc = end + savepc - 1; /* next stmt */
debugC(8, kDebugLingoExec, "executing end");
} else {
debugC(8, kDebugLingoExec, "Skipped end");
@@ -933,20 +935,25 @@ void Lingo::c_ifcode() {
void Lingo::c_whencode() {
Datum d;
uint start = g_lingo->_pc;
- uint end = READ_UINT32(&(*g_lingo->_currentScript)[start]);
+ uint end = READ_UINT32(&(*g_lingo->_currentScript)[start]) + start - 1;
Common::String eventname((char *)&(*g_lingo->_currentScript)[start + 1]);
start += g_lingo->calcStringAlignment(eventname.c_str()) + 1;
- debugC(3, kDebugLingoExec, "c_whencode([%5d][%5d], %s)", start, end, eventname.c_str());
+ debugC(1, kDebugLingoExec, "c_whencode([%5d][%5d], %s)", start, end, eventname.c_str());
+
+ int entity = g_lingo->_currentEntityId;
+ g_lingo->_currentEntityId = 0;
g_lingo->define(eventname, start, 0, NULL, end);
- if (debugChannelSet(3, kDebugLingoExec)) {
+ g_lingo->_currentEntityId = entity;
+
+ if (debugChannelSet(1, kDebugLingoExec)) {
uint pc = start;
while (pc <= end) {
Common::String instr = g_lingo->decodeInstruction(pc, &pc);
- debugC(3, kDebugLingoExec, "[%5d] %s", pc, instr.c_str());
+ debugC(1, kDebugLingoExec, "[%5d] %s", pc, instr.c_str());
}
}
@@ -996,23 +1003,11 @@ void Lingo::c_play() {
if (mode.u.i == 1 || mode.u.i == 3)
frame = g_lingo->pop();
- if (frame.type == VOID) {
- frame.u.s = new Common::String("<void>");
- frame.type = STRING;
- }
- frame.toString();
-
- if (movie.type == VOID) {
- movie.u.s = new Common::String("<void>");
- movie.type = STRING;
- }
- movie.toString();
-
- warning("STUB: c_play(%s, %s)", frame.u.s->c_str(), movie.u.s->c_str());
+ g_lingo->func_play(frame, movie);
}
void Lingo::c_playdone() {
- warning("STUB: c_playdone()");
+ g_lingo->func_playdone();
}
void Lingo::c_call() {
@@ -1121,7 +1116,7 @@ void Lingo::call(Common::String name, int nargs) {
void Lingo::c_procret() {
if (!g_lingo->_callstack.size()) {
- warning("Call stack underflow");
+ warning("c_procret: Call stack underflow");
g_lingo->_returning = true;
return;
}
diff --git a/engines/director/lingo/lingo-codegen.cpp b/engines/director/lingo/lingo-codegen.cpp
index 0d771ec44e..d69de85e9a 100644
--- a/engines/director/lingo/lingo-codegen.cpp
+++ b/engines/director/lingo/lingo-codegen.cpp
@@ -103,7 +103,7 @@ Common::String Lingo::decodeInstruction(uint pc, uint *newPc) {
{
Datum d;
i = (*_currentScript)[pc++];
- d.u.i = READ_UINT32(&i);
+ d.u.f = *(double *)(&i);
res += Common::String::format(" %f", d.u.f);
break;
@@ -214,7 +214,7 @@ void Lingo::define(Common::String &name, int start, int nargs, Common::String *p
if (prefix)
name = *prefix + "-" + name;
- debugC(3, kDebugLingoCompile, "define(\"%s\", %d, %d, %d)", name.c_str(), start, _currentScript->size() - 1, nargs);
+ debugC(1, kDebugLingoCompile, "define(\"%s\", %d, %d, %d)", name.c_str(), start, _currentScript->size() - 1, nargs);
Symbol *sym = getHandler(name);
if (sym == NULL) { // Create variable if it was not defined
@@ -311,7 +311,6 @@ void Lingo::codeArgStore() {
code1(c_varpush);
codeString(arg->c_str());
code1(c_assign);
- code1(c_xpop);
delete arg;
}
@@ -380,6 +379,9 @@ void Lingo::processIf(int elselabel, int endlabel) {
if (!label)
break;
+ if (else1)
+ else1 = else1 - label;
+
WRITE_UINT32(&ielse1, else1);
(*_currentScript)[label + 2] = ielse1; /* elsepart */
(*_currentScript)[label + 3] = iend; /* end, if cond fails */
diff --git a/engines/director/lingo/lingo-funcs.cpp b/engines/director/lingo/lingo-funcs.cpp
index ddc51f4149..f21f01a967 100644
--- a/engines/director/lingo/lingo-funcs.cpp
+++ b/engines/director/lingo/lingo-funcs.cpp
@@ -172,7 +172,7 @@ void Lingo::func_mciwait(Common::String &s) {
}
void Lingo::func_goto(Datum &frame, Datum &movie) {
- g_director->_playbackPaused = false;
+ _vm->_playbackPaused = false;
if (!_vm->getCurrentScore())
return;
@@ -180,17 +180,29 @@ void Lingo::func_goto(Datum &frame, Datum &movie) {
if (movie.type != VOID) {
movie.toString();
+ Common::String cleanedFilename;
+
+ for (const char *p = movie.u.s->c_str(); *p; p++)
+ if (*p >= 0x20 && *p <= 0x7f)
+ cleanedFilename += *p;
+
bool fileExists = false;
if (_vm->getPlatform() == Common::kPlatformMacintosh) {
Common::MacResManager resMan;
if (resMan.open(*movie.u.s)) {
fileExists = true;
+ cleanedFilename = *movie.u.s;
+ } else if (!movie.u.s->equals(cleanedFilename) && resMan.open(cleanedFilename)) {
+ fileExists = true;
}
} else {
Common::File file;
if (file.open(*movie.u.s)) {
fileExists = true;
+ cleanedFilename = *movie.u.s;
+ } else if (!movie.u.s->equals(cleanedFilename) && file.open(cleanedFilename)) {
+ fileExists = true;
}
}
@@ -199,23 +211,23 @@ void Lingo::func_goto(Datum &frame, Datum &movie) {
return;
}
- _vm->_nextMovie = *movie.u.s;
+ _vm->_nextMovie.movie = cleanedFilename;
_vm->getCurrentScore()->_stopPlay = true;
- _vm->_nextMovieFrameS.clear();
- _vm->_nextMovieFrameI = -1;
+ _vm->_nextMovie.frameS.clear();
+ _vm->_nextMovie.frameI = -1;
if (frame.type == VOID)
return;
if (frame.type == STRING) {
- _vm->_nextMovieFrameS = *frame.u.s;
+ _vm->_nextMovie.frameS = *frame.u.s;
return;
}
frame.toInt();
- _vm->_nextMovieFrameI = frame.u.i;
+ _vm->_nextMovie.frameI = frame.u.i;
return;
}
@@ -243,7 +255,7 @@ void Lingo::func_gotoloop() {
_vm->getCurrentScore()->gotoLoop();
- g_director->_skipFrameAdvance = true;
+ _vm->_skipFrameAdvance = true;
}
void Lingo::func_gotonext() {
@@ -252,7 +264,7 @@ void Lingo::func_gotonext() {
_vm->getCurrentScore()->gotoNext();
- g_director->_skipFrameAdvance = true;
+ _vm->_skipFrameAdvance = true;
}
void Lingo::func_gotoprevious() {
@@ -261,7 +273,43 @@ void Lingo::func_gotoprevious() {
_vm->getCurrentScore()->gotoPrevious();
- g_director->_skipFrameAdvance = true;
+ _vm->_skipFrameAdvance = true;
+}
+
+void Lingo::func_play(Datum &frame, Datum &movie) {
+ MovieReference ref;
+
+ if (movie.type != VOID) {
+ warning("STUB: func_play()");
+
+ return;
+ }
+
+ ref.frameI = _vm->getCurrentScore()->getCurrentFrame();
+
+ _vm->_movieStack.push_back(ref);
+
+ func_goto(frame, movie);
+}
+
+void Lingo::func_playdone() {
+ MovieReference ref = _vm->_movieStack.back();
+
+ _vm->_movieStack.pop_back();
+
+ Datum m, f;
+
+ if (ref.movie.empty()) {
+ m.type = VOID;
+ } else {
+ m.type = STRING;
+ m.u.s = new Common::String(ref.movie);
+ }
+
+ f.type = INT;
+ f.u.i = ref.frameI;
+
+ func_goto(f, m);
}
void Lingo::func_cursor(int c) {
diff --git a/engines/director/lingo/lingo-gr.cpp b/engines/director/lingo/lingo-gr.cpp
index 8d1e84856b..da928f7c09 100644
--- a/engines/director/lingo/lingo-gr.cpp
+++ b/engines/director/lingo/lingo-gr.cpp
@@ -701,13 +701,13 @@ static const yytype_uint16 yyrline[] =
438, 444, 445, 446, 447, 448, 449, 450, 451, 452,
453, 454, 455, 456, 457, 458, 459, 460, 461, 462,
463, 464, 465, 466, 467, 468, 469, 470, 471, 472,
- 473, 474, 475, 478, 483, 484, 485, 486, 487, 489,
- 490, 491, 492, 495, 498, 501, 505, 506, 507, 508,
- 509, 510, 511, 514, 515, 518, 519, 522, 523, 534,
- 535, 536, 537, 540, 543, 548, 549, 552, 553, 556,
- 557, 560, 563, 566, 566, 596, 596, 602, 605, 605,
- 610, 611, 610, 621, 622, 623, 624, 627, 631, 639,
- 640, 641, 644, 645
+ 473, 474, 475, 478, 483, 484, 485, 486, 487, 488,
+ 489, 490, 491, 494, 497, 500, 504, 505, 506, 507,
+ 508, 509, 510, 513, 514, 517, 518, 521, 522, 533,
+ 534, 535, 536, 539, 542, 547, 548, 551, 552, 555,
+ 556, 559, 562, 565, 565, 595, 595, 600, 603, 603,
+ 608, 609, 608, 618, 619, 620, 621, 624, 628, 636,
+ 637, 638, 641, 642
};
#endif
@@ -2261,17 +2261,12 @@ yyreduce:
(yyval.code) = (yyvsp[(5) - (5)].code); ;}
break;
- case 20:
-#line 191 "engines/director/lingo/lingo-gr.y"
- { g_lingo->code1(g_lingo->c_xpop); ;}
- break;
-
case 24:
#line 201 "engines/director/lingo/lingo-gr.y"
{
inst body = 0, end = 0;
- WRITE_UINT32(&body, (yyvsp[(5) - (7)].code));
- WRITE_UINT32(&end, (yyvsp[(6) - (7)].code));
+ WRITE_UINT32(&body, (yyvsp[(5) - (7)].code) - (yyvsp[(1) - (7)].code));
+ WRITE_UINT32(&end, (yyvsp[(6) - (7)].code) - (yyvsp[(1) - (7)].code));
(*g_lingo->_currentScript)[(yyvsp[(1) - (7)].code) + 1] = body; /* body of loop */
(*g_lingo->_currentScript)[(yyvsp[(1) - (7)].code) + 2] = end; /* end, if cond fails */
@@ -2282,10 +2277,10 @@ yyreduce:
#line 214 "engines/director/lingo/lingo-gr.y"
{
inst init = 0, finish = 0, body = 0, end = 0, inc = 0;
- WRITE_UINT32(&init, (yyvsp[(3) - (10)].code));
- WRITE_UINT32(&finish, (yyvsp[(6) - (10)].code));
- WRITE_UINT32(&body, (yyvsp[(8) - (10)].code));
- WRITE_UINT32(&end, (yyvsp[(9) - (10)].code));
+ WRITE_UINT32(&init, (yyvsp[(3) - (10)].code) - (yyvsp[(1) - (10)].code));
+ WRITE_UINT32(&finish, (yyvsp[(6) - (10)].code) - (yyvsp[(1) - (10)].code));
+ WRITE_UINT32(&body, (yyvsp[(8) - (10)].code) - (yyvsp[(1) - (10)].code));
+ WRITE_UINT32(&end, (yyvsp[(9) - (10)].code) - (yyvsp[(1) - (10)].code));
WRITE_UINT32(&inc, 1);
(*g_lingo->_currentScript)[(yyvsp[(1) - (10)].code) + 1] = init; /* initial count value */
(*g_lingo->_currentScript)[(yyvsp[(1) - (10)].code) + 2] = finish;/* final count value */
@@ -2300,10 +2295,10 @@ yyreduce:
#line 232 "engines/director/lingo/lingo-gr.y"
{
inst init = 0, finish = 0, body = 0, end = 0, inc = 0;
- WRITE_UINT32(&init, (yyvsp[(3) - (11)].code));
- WRITE_UINT32(&finish, (yyvsp[(7) - (11)].code));
- WRITE_UINT32(&body, (yyvsp[(9) - (11)].code));
- WRITE_UINT32(&end, (yyvsp[(10) - (11)].code));
+ WRITE_UINT32(&init, (yyvsp[(3) - (11)].code) - (yyvsp[(1) - (11)].code));
+ WRITE_UINT32(&finish, (yyvsp[(7) - (11)].code) - (yyvsp[(1) - (11)].code));
+ WRITE_UINT32(&body, (yyvsp[(9) - (11)].code) - (yyvsp[(1) - (11)].code));
+ WRITE_UINT32(&end, (yyvsp[(10) - (11)].code) - (yyvsp[(1) - (11)].code));
WRITE_UINT32(&inc, -1);
(*g_lingo->_currentScript)[(yyvsp[(1) - (11)].code) + 1] = init; /* initial count value */
(*g_lingo->_currentScript)[(yyvsp[(1) - (11)].code) + 2] = finish;/* final count value */
@@ -2318,7 +2313,7 @@ yyreduce:
#line 246 "engines/director/lingo/lingo-gr.y"
{
inst end = 0;
- WRITE_UINT32(&end, (yyvsp[(3) - (3)].code));
+ WRITE_UINT32(&end, (yyvsp[(3) - (3)].code) - (yyvsp[(1) - (3)].code));
g_lingo->code1(STOP);
(*g_lingo->_currentScript)[(yyvsp[(1) - (3)].code) + 1] = end;
;}
@@ -2342,8 +2337,8 @@ yyreduce:
#line 260 "engines/director/lingo/lingo-gr.y"
{
inst then = 0, end = 0;
- WRITE_UINT32(&then, (yyvsp[(5) - (7)].code));
- WRITE_UINT32(&end, (yyvsp[(6) - (7)].code));
+ WRITE_UINT32(&then, (yyvsp[(5) - (7)].code) - (yyvsp[(1) - (7)].code));
+ WRITE_UINT32(&end, (yyvsp[(6) - (7)].code) - (yyvsp[(1) - (7)].code));
(*g_lingo->_currentScript)[(yyvsp[(1) - (7)].code) + 1] = then; /* thenpart */
(*g_lingo->_currentScript)[(yyvsp[(1) - (7)].code) + 3] = end; /* end, if cond fails */
@@ -2356,9 +2351,9 @@ yyreduce:
#line 270 "engines/director/lingo/lingo-gr.y"
{
inst then = 0, else1 = 0, end = 0;
- WRITE_UINT32(&then, (yyvsp[(5) - (10)].code));
- WRITE_UINT32(&else1, (yyvsp[(8) - (10)].code));
- WRITE_UINT32(&end, (yyvsp[(9) - (10)].code));
+ WRITE_UINT32(&then, (yyvsp[(5) - (10)].code) - (yyvsp[(1) - (10)].code));
+ WRITE_UINT32(&else1, (yyvsp[(8) - (10)].code) - (yyvsp[(1) - (10)].code));
+ WRITE_UINT32(&end, (yyvsp[(9) - (10)].code) - (yyvsp[(1) - (10)].code));
(*g_lingo->_currentScript)[(yyvsp[(1) - (10)].code) + 1] = then; /* thenpart */
(*g_lingo->_currentScript)[(yyvsp[(1) - (10)].code) + 2] = else1; /* elsepart */
(*g_lingo->_currentScript)[(yyvsp[(1) - (10)].code) + 3] = end; /* end, if cond fails */
@@ -2372,25 +2367,25 @@ yyreduce:
#line 282 "engines/director/lingo/lingo-gr.y"
{
inst then = 0, else1 = 0, end = 0;
- WRITE_UINT32(&then, (yyvsp[(5) - (10)].code));
- WRITE_UINT32(&else1, (yyvsp[(7) - (10)].code));
- WRITE_UINT32(&end, (yyvsp[(9) - (10)].code));
+ WRITE_UINT32(&then, (yyvsp[(5) - (10)].code) - (yyvsp[(1) - (10)].code));
+ WRITE_UINT32(&else1, (yyvsp[(7) - (10)].code) - (yyvsp[(1) - (10)].code));
+ WRITE_UINT32(&end, (yyvsp[(9) - (10)].code) - (yyvsp[(1) - (10)].code));
(*g_lingo->_currentScript)[(yyvsp[(1) - (10)].code) + 1] = then; /* thenpart */
(*g_lingo->_currentScript)[(yyvsp[(1) - (10)].code) + 2] = else1; /* elsepart */
(*g_lingo->_currentScript)[(yyvsp[(1) - (10)].code) + 3] = end; /* end, if cond fails */
checkEnd((yyvsp[(10) - (10)].s), "if", true);
- g_lingo->processIf(0, (yyvsp[(9) - (10)].code)); ;}
+ g_lingo->processIf(0, (yyvsp[(9) - (10)].code) - (yyvsp[(1) - (10)].code)); ;}
break;
case 33:
#line 294 "engines/director/lingo/lingo-gr.y"
{
inst then = 0, else1 = 0, end = 0;
- WRITE_UINT32(&then, (yyvsp[(4) - (6)].code));
+ WRITE_UINT32(&then, (yyvsp[(4) - (6)].code) - (yyvsp[(1) - (6)].code));
WRITE_UINT32(&else1, 0);
- WRITE_UINT32(&end, (yyvsp[(6) - (6)].code));
+ WRITE_UINT32(&end, (yyvsp[(6) - (6)].code) - (yyvsp[(1) - (6)].code));
(*g_lingo->_currentScript)[(yyvsp[(1) - (6)].code) + 1] = then; /* thenpart */
(*g_lingo->_currentScript)[(yyvsp[(1) - (6)].code) + 2] = else1; /* elsepart */
(*g_lingo->_currentScript)[(yyvsp[(1) - (6)].code) + 3] = end; /* end, if cond fails */
@@ -2402,9 +2397,9 @@ yyreduce:
#line 304 "engines/director/lingo/lingo-gr.y"
{
inst then = 0, else1 = 0, end = 0;
- WRITE_UINT32(&then, (yyvsp[(4) - (10)].code));
- WRITE_UINT32(&else1, (yyvsp[(8) - (10)].code));
- WRITE_UINT32(&end, (yyvsp[(10) - (10)].code));
+ WRITE_UINT32(&then, (yyvsp[(4) - (10)].code) - (yyvsp[(1) - (10)].code));
+ WRITE_UINT32(&else1, (yyvsp[(8) - (10)].code) - (yyvsp[(1) - (10)].code));
+ WRITE_UINT32(&end, (yyvsp[(10) - (10)].code) - (yyvsp[(1) - (10)].code));
(*g_lingo->_currentScript)[(yyvsp[(1) - (10)].code) + 1] = then; /* thenpart */
(*g_lingo->_currentScript)[(yyvsp[(1) - (10)].code) + 2] = else1; /* elsepart */
(*g_lingo->_currentScript)[(yyvsp[(1) - (10)].code) + 3] = end; /* end, if cond fails */
@@ -2416,14 +2411,14 @@ yyreduce:
#line 314 "engines/director/lingo/lingo-gr.y"
{
inst then = 0, else1 = 0, end = 0;
- WRITE_UINT32(&then, (yyvsp[(4) - (10)].code));
- WRITE_UINT32(&else1, (yyvsp[(6) - (10)].code));
- WRITE_UINT32(&end, (yyvsp[(10) - (10)].code));
+ WRITE_UINT32(&then, (yyvsp[(4) - (10)].code) - (yyvsp[(1) - (10)].code));
+ WRITE_UINT32(&else1, (yyvsp[(6) - (10)].code) - (yyvsp[(1) - (10)].code));
+ WRITE_UINT32(&end, (yyvsp[(10) - (10)].code) - (yyvsp[(1) - (10)].code));
(*g_lingo->_currentScript)[(yyvsp[(1) - (10)].code) + 1] = then; /* thenpart */
(*g_lingo->_currentScript)[(yyvsp[(1) - (10)].code) + 2] = else1; /* elsepart */
(*g_lingo->_currentScript)[(yyvsp[(1) - (10)].code) + 3] = end; /* end, if cond fails */
- g_lingo->processIf(0, (yyvsp[(10) - (10)].code)); ;}
+ g_lingo->processIf(0, (yyvsp[(10) - (10)].code) - (yyvsp[(1) - (10)].code)); ;}
break;
case 36:
@@ -2440,7 +2435,7 @@ yyreduce:
#line 338 "engines/director/lingo/lingo-gr.y"
{
inst then = 0;
- WRITE_UINT32(&then, (yyvsp[(4) - (6)].code));
+ WRITE_UINT32(&then, (yyvsp[(4) - (6)].code) - (yyvsp[(1) - (6)].code));
(*g_lingo->_currentScript)[(yyvsp[(1) - (6)].code) + 1] = then; /* thenpart */
g_lingo->codeLabel((yyvsp[(1) - (6)].code)); ;}
@@ -2450,7 +2445,7 @@ yyreduce:
#line 347 "engines/director/lingo/lingo-gr.y"
{
inst then = 0;
- WRITE_UINT32(&then, (yyvsp[(5) - (6)].code));
+ WRITE_UINT32(&then, (yyvsp[(5) - (6)].code) - (yyvsp[(1) - (6)].code));
(*g_lingo->_currentScript)[(yyvsp[(1) - (6)].code) + 1] = then; /* thenpart */
g_lingo->codeLabel((yyvsp[(1) - (6)].code)); ;}
@@ -2790,33 +2785,32 @@ yyreduce:
case 108:
#line 487 "engines/director/lingo/lingo-gr.y"
- { g_lingo->codeConst(0); // Push fake value on stack
- g_lingo->code1(g_lingo->c_procret); ;}
+ { g_lingo->code1(g_lingo->c_procret); ;}
break;
case 112:
-#line 492 "engines/director/lingo/lingo-gr.y"
+#line 491 "engines/director/lingo/lingo-gr.y"
{
g_lingo->codeFunc((yyvsp[(1) - (1)].s), 0);
delete (yyvsp[(1) - (1)].s); ;}
break;
case 113:
-#line 495 "engines/director/lingo/lingo-gr.y"
+#line 494 "engines/director/lingo/lingo-gr.y"
{
g_lingo->codeFunc((yyvsp[(1) - (2)].s), 1);
delete (yyvsp[(1) - (2)].s); ;}
break;
case 114:
-#line 498 "engines/director/lingo/lingo-gr.y"
+#line 497 "engines/director/lingo/lingo-gr.y"
{
g_lingo->codeFunc((yyvsp[(1) - (2)].s), 1);
delete (yyvsp[(1) - (2)].s); ;}
break;
case 115:
-#line 501 "engines/director/lingo/lingo-gr.y"
+#line 500 "engines/director/lingo/lingo-gr.y"
{
g_lingo->code1(g_lingo->c_voidpush);
g_lingo->codeFunc((yyvsp[(1) - (1)].s), 1);
@@ -2824,172 +2818,171 @@ yyreduce:
break;
case 116:
-#line 505 "engines/director/lingo/lingo-gr.y"
+#line 504 "engines/director/lingo/lingo-gr.y"
{ g_lingo->codeFunc((yyvsp[(1) - (2)].s), (yyvsp[(2) - (2)].narg)); ;}
break;
case 117:
-#line 506 "engines/director/lingo/lingo-gr.y"
+#line 505 "engines/director/lingo/lingo-gr.y"
{ g_lingo->codeFunc((yyvsp[(1) - (4)].s), (yyvsp[(3) - (4)].narg)); ;}
break;
case 118:
-#line 507 "engines/director/lingo/lingo-gr.y"
+#line 506 "engines/director/lingo/lingo-gr.y"
{ g_lingo->codeMe((yyvsp[(3) - (4)].s), 0); ;}
break;
case 119:
-#line 508 "engines/director/lingo/lingo-gr.y"
+#line 507 "engines/director/lingo/lingo-gr.y"
{ g_lingo->codeMe((yyvsp[(3) - (6)].s), (yyvsp[(5) - (6)].narg)); ;}
break;
case 120:
-#line 509 "engines/director/lingo/lingo-gr.y"
+#line 508 "engines/director/lingo/lingo-gr.y"
{ g_lingo->code1(g_lingo->c_open); ;}
break;
case 121:
-#line 510 "engines/director/lingo/lingo-gr.y"
+#line 509 "engines/director/lingo/lingo-gr.y"
{ g_lingo->code2(g_lingo->c_voidpush, g_lingo->c_open); ;}
break;
case 122:
-#line 511 "engines/director/lingo/lingo-gr.y"
+#line 510 "engines/director/lingo/lingo-gr.y"
{ Common::String s(*(yyvsp[(1) - (3)].s)); s += '-'; s += *(yyvsp[(2) - (3)].s); g_lingo->codeFunc(&s, (yyvsp[(3) - (3)].narg)); ;}
break;
case 123:
-#line 514 "engines/director/lingo/lingo-gr.y"
+#line 513 "engines/director/lingo/lingo-gr.y"
{ g_lingo->code1(g_lingo->c_global); g_lingo->codeString((yyvsp[(1) - (1)].s)->c_str()); delete (yyvsp[(1) - (1)].s); ;}
break;
case 124:
-#line 515 "engines/director/lingo/lingo-gr.y"
+#line 514 "engines/director/lingo/lingo-gr.y"
{ g_lingo->code1(g_lingo->c_global); g_lingo->codeString((yyvsp[(3) - (3)].s)->c_str()); delete (yyvsp[(3) - (3)].s); ;}
break;
case 125:
-#line 518 "engines/director/lingo/lingo-gr.y"
+#line 517 "engines/director/lingo/lingo-gr.y"
{ g_lingo->code1(g_lingo->c_property); g_lingo->codeString((yyvsp[(1) - (1)].s)->c_str()); delete (yyvsp[(1) - (1)].s); ;}
break;
case 126:
-#line 519 "engines/director/lingo/lingo-gr.y"
+#line 518 "engines/director/lingo/lingo-gr.y"
{ g_lingo->code1(g_lingo->c_property); g_lingo->codeString((yyvsp[(3) - (3)].s)->c_str()); delete (yyvsp[(3) - (3)].s); ;}
break;
case 127:
-#line 522 "engines/director/lingo/lingo-gr.y"
+#line 521 "engines/director/lingo/lingo-gr.y"
{ g_lingo->code1(g_lingo->c_instance); g_lingo->codeString((yyvsp[(1) - (1)].s)->c_str()); delete (yyvsp[(1) - (1)].s); ;}
break;
case 128:
-#line 523 "engines/director/lingo/lingo-gr.y"
+#line 522 "engines/director/lingo/lingo-gr.y"
{ g_lingo->code1(g_lingo->c_instance); g_lingo->codeString((yyvsp[(3) - (3)].s)->c_str()); delete (yyvsp[(3) - (3)].s); ;}
break;
case 129:
-#line 534 "engines/director/lingo/lingo-gr.y"
+#line 533 "engines/director/lingo/lingo-gr.y"
{ g_lingo->code1(g_lingo->c_gotoloop); ;}
break;
case 130:
-#line 535 "engines/director/lingo/lingo-gr.y"
+#line 534 "engines/director/lingo/lingo-gr.y"
{ g_lingo->code1(g_lingo->c_gotonext); ;}
break;
case 131:
-#line 536 "engines/director/lingo/lingo-gr.y"
+#line 535 "engines/director/lingo/lingo-gr.y"
{ g_lingo->code1(g_lingo->c_gotoprevious); ;}
break;
case 132:
-#line 537 "engines/director/lingo/lingo-gr.y"
+#line 536 "engines/director/lingo/lingo-gr.y"
{
g_lingo->codeConst(1);
g_lingo->code1(g_lingo->c_goto); ;}
break;
case 133:
-#line 540 "engines/director/lingo/lingo-gr.y"
+#line 539 "engines/director/lingo/lingo-gr.y"
{
g_lingo->codeConst(3);
g_lingo->code1(g_lingo->c_goto); ;}
break;
case 134:
-#line 543 "engines/director/lingo/lingo-gr.y"
+#line 542 "engines/director/lingo/lingo-gr.y"
{
g_lingo->codeConst(2);
g_lingo->code1(g_lingo->c_goto); ;}
break;
case 139:
-#line 556 "engines/director/lingo/lingo-gr.y"
+#line 555 "engines/director/lingo/lingo-gr.y"
{ g_lingo->code1(g_lingo->c_playdone); ;}
break;
case 140:
-#line 557 "engines/director/lingo/lingo-gr.y"
+#line 556 "engines/director/lingo/lingo-gr.y"
{
g_lingo->codeConst(1);
g_lingo->code1(g_lingo->c_play); ;}
break;
case 141:
-#line 560 "engines/director/lingo/lingo-gr.y"
+#line 559 "engines/director/lingo/lingo-gr.y"
{
g_lingo->codeConst(3);
g_lingo->code1(g_lingo->c_play); ;}
break;
case 142:
-#line 563 "engines/director/lingo/lingo-gr.y"
+#line 562 "engines/director/lingo/lingo-gr.y"
{
g_lingo->codeConst(2);
g_lingo->code1(g_lingo->c_play); ;}
break;
case 143:
-#line 566 "engines/director/lingo/lingo-gr.y"
+#line 565 "engines/director/lingo/lingo-gr.y"
{ g_lingo->codeSetImmediate(true); ;}
break;
case 144:
-#line 566 "engines/director/lingo/lingo-gr.y"
+#line 565 "engines/director/lingo/lingo-gr.y"
{
g_lingo->codeSetImmediate(false);
g_lingo->codeFunc((yyvsp[(1) - (3)].s), (yyvsp[(3) - (3)].narg)); ;}
break;
case 145:
-#line 596 "engines/director/lingo/lingo-gr.y"
+#line 595 "engines/director/lingo/lingo-gr.y"
{ g_lingo->_indef = true; g_lingo->_currentFactory.clear(); ;}
break;
case 146:
-#line 597 "engines/director/lingo/lingo-gr.y"
+#line 596 "engines/director/lingo/lingo-gr.y"
{
- g_lingo->codeConst(0); // Push fake value on stack
g_lingo->code1(g_lingo->c_procret);
g_lingo->define(*(yyvsp[(2) - (8)].s), (yyvsp[(4) - (8)].code), (yyvsp[(5) - (8)].narg));
g_lingo->_indef = false; ;}
break;
case 147:
-#line 602 "engines/director/lingo/lingo-gr.y"
+#line 600 "engines/director/lingo/lingo-gr.y"
{
g_lingo->codeFactory(*(yyvsp[(2) - (2)].s));
;}
break;
case 148:
-#line 605 "engines/director/lingo/lingo-gr.y"
+#line 603 "engines/director/lingo/lingo-gr.y"
{ g_lingo->_indef = true; ;}
break;
case 149:
-#line 606 "engines/director/lingo/lingo-gr.y"
+#line 604 "engines/director/lingo/lingo-gr.y"
{
g_lingo->code1(g_lingo->c_procret);
g_lingo->define(*(yyvsp[(2) - (8)].s), (yyvsp[(4) - (8)].code), (yyvsp[(5) - (8)].narg) + 1, &g_lingo->_currentFactory);
@@ -2997,19 +2990,18 @@ yyreduce:
break;
case 150:
-#line 610 "engines/director/lingo/lingo-gr.y"
+#line 608 "engines/director/lingo/lingo-gr.y"
{ g_lingo->_indef = true; g_lingo->_currentFactory.clear(); ;}
break;
case 151:
-#line 611 "engines/director/lingo/lingo-gr.y"
+#line 609 "engines/director/lingo/lingo-gr.y"
{ g_lingo->_ignoreMe = true; ;}
break;
case 152:
-#line 611 "engines/director/lingo/lingo-gr.y"
+#line 609 "engines/director/lingo/lingo-gr.y"
{
- g_lingo->codeConst(0); // Push fake value on stack
g_lingo->code1(g_lingo->c_procret);
g_lingo->define(*(yyvsp[(2) - (10)].s), (yyvsp[(4) - (10)].code), (yyvsp[(6) - (10)].narg));
g_lingo->_indef = false;
@@ -3020,32 +3012,32 @@ yyreduce:
break;
case 153:
-#line 621 "engines/director/lingo/lingo-gr.y"
+#line 618 "engines/director/lingo/lingo-gr.y"
{ (yyval.narg) = 0; ;}
break;
case 154:
-#line 622 "engines/director/lingo/lingo-gr.y"
+#line 619 "engines/director/lingo/lingo-gr.y"
{ g_lingo->codeArg((yyvsp[(1) - (1)].s)); (yyval.narg) = 1; ;}
break;
case 155:
-#line 623 "engines/director/lingo/lingo-gr.y"
+#line 620 "engines/director/lingo/lingo-gr.y"
{ g_lingo->codeArg((yyvsp[(3) - (3)].s)); (yyval.narg) = (yyvsp[(1) - (3)].narg) + 1; ;}
break;
case 156:
-#line 624 "engines/director/lingo/lingo-gr.y"
+#line 621 "engines/director/lingo/lingo-gr.y"
{ g_lingo->codeArg((yyvsp[(4) - (4)].s)); (yyval.narg) = (yyvsp[(1) - (4)].narg) + 1; ;}
break;
case 157:
-#line 627 "engines/director/lingo/lingo-gr.y"
+#line 624 "engines/director/lingo/lingo-gr.y"
{ g_lingo->codeArgStore(); ;}
break;
case 158:
-#line 631 "engines/director/lingo/lingo-gr.y"
+#line 628 "engines/director/lingo/lingo-gr.y"
{
g_lingo->code1(g_lingo->c_call);
g_lingo->codeString((yyvsp[(1) - (2)].s)->c_str());
@@ -3055,33 +3047,33 @@ yyreduce:
break;
case 159:
-#line 639 "engines/director/lingo/lingo-gr.y"
+#line 636 "engines/director/lingo/lingo-gr.y"
{ (yyval.narg) = 0; ;}
break;
case 160:
-#line 640 "engines/director/lingo/lingo-gr.y"
+#line 637 "engines/director/lingo/lingo-gr.y"
{ (yyval.narg) = 1; ;}
break;
case 161:
-#line 641 "engines/director/lingo/lingo-gr.y"
+#line 638 "engines/director/lingo/lingo-gr.y"
{ (yyval.narg) = (yyvsp[(1) - (3)].narg) + 1; ;}
break;
case 162:
-#line 644 "engines/director/lingo/lingo-gr.y"
+#line 641 "engines/director/lingo/lingo-gr.y"
{ (yyval.narg) = 1; ;}
break;
case 163:
-#line 645 "engines/director/lingo/lingo-gr.y"
+#line 642 "engines/director/lingo/lingo-gr.y"
{ (yyval.narg) = (yyvsp[(1) - (3)].narg) + 1; ;}
break;
/* Line 1267 of yacc.c. */
-#line 3085 "engines/director/lingo/lingo-gr.cpp"
+#line 3077 "engines/director/lingo/lingo-gr.cpp"
default: break;
}
YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
@@ -3295,6 +3287,6 @@ yyreturn:
}
-#line 648 "engines/director/lingo/lingo-gr.y"
+#line 645 "engines/director/lingo/lingo-gr.y"
diff --git a/engines/director/lingo/lingo-gr.y b/engines/director/lingo/lingo-gr.y
index 86f8743560..35290c67eb 100644
--- a/engines/director/lingo/lingo-gr.y
+++ b/engines/director/lingo/lingo-gr.y
@@ -188,7 +188,7 @@ asgn: tPUT expr tINTO ID {
$$ = $5; }
;
-stmtoneliner: expr { g_lingo->code1(g_lingo->c_xpop); }
+stmtoneliner: expr
| proc
;
@@ -200,8 +200,8 @@ stmt: stmtoneliner
//
| repeatwhile '(' cond ')' stmtlist end ENDCLAUSE {
inst body = 0, end = 0;
- WRITE_UINT32(&body, $5);
- WRITE_UINT32(&end, $6);
+ WRITE_UINT32(&body, $5 - $1);
+ WRITE_UINT32(&end, $6 - $1);
(*g_lingo->_currentScript)[$1 + 1] = body; /* body of loop */
(*g_lingo->_currentScript)[$1 + 2] = end; /* end, if cond fails */
@@ -213,10 +213,10 @@ stmt: stmtoneliner
//
| repeatwith '=' expr end tTO expr end stmtlist end ENDCLAUSE {
inst init = 0, finish = 0, body = 0, end = 0, inc = 0;
- WRITE_UINT32(&init, $3);
- WRITE_UINT32(&finish, $6);
- WRITE_UINT32(&body, $8);
- WRITE_UINT32(&end, $9);
+ WRITE_UINT32(&init, $3 - $1);
+ WRITE_UINT32(&finish, $6 - $1);
+ WRITE_UINT32(&body, $8 - $1);
+ WRITE_UINT32(&end, $9 - $1);
WRITE_UINT32(&inc, 1);
(*g_lingo->_currentScript)[$1 + 1] = init; /* initial count value */
(*g_lingo->_currentScript)[$1 + 2] = finish;/* final count value */
@@ -231,10 +231,10 @@ stmt: stmtoneliner
//
| repeatwith '=' expr end tDOWN tTO expr end stmtlist end ENDCLAUSE {
inst init = 0, finish = 0, body = 0, end = 0, inc = 0;
- WRITE_UINT32(&init, $3);
- WRITE_UINT32(&finish, $7);
- WRITE_UINT32(&body, $9);
- WRITE_UINT32(&end, $10);
+ WRITE_UINT32(&init, $3 - $1);
+ WRITE_UINT32(&finish, $7 - $1);
+ WRITE_UINT32(&body, $9 - $1);
+ WRITE_UINT32(&end, $10 - $1);
WRITE_UINT32(&inc, -1);
(*g_lingo->_currentScript)[$1 + 1] = init; /* initial count value */
(*g_lingo->_currentScript)[$1 + 2] = finish;/* final count value */
@@ -245,7 +245,7 @@ stmt: stmtoneliner
checkEnd($11, "repeat", true); }
| when stmtoneliner end {
inst end = 0;
- WRITE_UINT32(&end, $3);
+ WRITE_UINT32(&end, $3 - $1);
g_lingo->code1(STOP);
(*g_lingo->_currentScript)[$1 + 1] = end;
}
@@ -259,8 +259,8 @@ stmt: stmtoneliner
ifstmt: if cond tTHEN nl stmtlist end ENDCLAUSE {
inst then = 0, end = 0;
- WRITE_UINT32(&then, $5);
- WRITE_UINT32(&end, $6);
+ WRITE_UINT32(&then, $5 - $1);
+ WRITE_UINT32(&end, $6 - $1);
(*g_lingo->_currentScript)[$1 + 1] = then; /* thenpart */
(*g_lingo->_currentScript)[$1 + 3] = end; /* end, if cond fails */
@@ -269,9 +269,9 @@ ifstmt: if cond tTHEN nl stmtlist end ENDCLAUSE {
g_lingo->processIf(0, 0); }
| if cond tTHEN nl stmtlist end tNLELSE stmtlist end ENDCLAUSE {
inst then = 0, else1 = 0, end = 0;
- WRITE_UINT32(&then, $5);
- WRITE_UINT32(&else1, $8);
- WRITE_UINT32(&end, $9);
+ WRITE_UINT32(&then, $5 - $1);
+ WRITE_UINT32(&else1, $8 - $1);
+ WRITE_UINT32(&end, $9 - $1);
(*g_lingo->_currentScript)[$1 + 1] = then; /* thenpart */
(*g_lingo->_currentScript)[$1 + 2] = else1; /* elsepart */
(*g_lingo->_currentScript)[$1 + 3] = end; /* end, if cond fails */
@@ -281,21 +281,21 @@ ifstmt: if cond tTHEN nl stmtlist end ENDCLAUSE {
g_lingo->processIf(0, 0); }
| if cond tTHEN nl stmtlist end begin elseifstmt end ENDCLAUSE {
inst then = 0, else1 = 0, end = 0;
- WRITE_UINT32(&then, $5);
- WRITE_UINT32(&else1, $7);
- WRITE_UINT32(&end, $9);
+ WRITE_UINT32(&then, $5 - $1);
+ WRITE_UINT32(&else1, $7 - $1);
+ WRITE_UINT32(&end, $9 - $1);
(*g_lingo->_currentScript)[$1 + 1] = then; /* thenpart */
(*g_lingo->_currentScript)[$1 + 2] = else1; /* elsepart */
(*g_lingo->_currentScript)[$1 + 3] = end; /* end, if cond fails */
checkEnd($10, "if", true);
- g_lingo->processIf(0, $9); }
+ g_lingo->processIf(0, $9 - $1); }
| if cond tTHEN begin stmtoneliner end {
inst then = 0, else1 = 0, end = 0;
- WRITE_UINT32(&then, $4);
+ WRITE_UINT32(&then, $4 - $1);
WRITE_UINT32(&else1, 0);
- WRITE_UINT32(&end, $6);
+ WRITE_UINT32(&end, $6 - $1);
(*g_lingo->_currentScript)[$1 + 1] = then; /* thenpart */
(*g_lingo->_currentScript)[$1 + 2] = else1; /* elsepart */
(*g_lingo->_currentScript)[$1 + 3] = end; /* end, if cond fails */
@@ -303,9 +303,9 @@ ifstmt: if cond tTHEN nl stmtlist end ENDCLAUSE {
g_lingo->processIf(0, 0); }
| if cond tTHEN begin stmtoneliner end tNLELSE begin stmtoneliner end {
inst then = 0, else1 = 0, end = 0;
- WRITE_UINT32(&then, $4);
- WRITE_UINT32(&else1, $8);
- WRITE_UINT32(&end, $10);
+ WRITE_UINT32(&then, $4 - $1);
+ WRITE_UINT32(&else1, $8 - $1);
+ WRITE_UINT32(&end, $10 - $1);
(*g_lingo->_currentScript)[$1 + 1] = then; /* thenpart */
(*g_lingo->_currentScript)[$1 + 2] = else1; /* elsepart */
(*g_lingo->_currentScript)[$1 + 3] = end; /* end, if cond fails */
@@ -313,14 +313,14 @@ ifstmt: if cond tTHEN nl stmtlist end ENDCLAUSE {
g_lingo->processIf(0, 0); }
| if cond tTHEN begin stmtoneliner end elseifstmtoneliner end elsestmtoneliner end {
inst then = 0, else1 = 0, end = 0;
- WRITE_UINT32(&then, $4);
- WRITE_UINT32(&else1, $6);
- WRITE_UINT32(&end, $10);
+ WRITE_UINT32(&then, $4 - $1);
+ WRITE_UINT32(&else1, $6 - $1);
+ WRITE_UINT32(&end, $10 - $1);
(*g_lingo->_currentScript)[$1 + 1] = then; /* thenpart */
(*g_lingo->_currentScript)[$1 + 2] = else1; /* elsepart */
(*g_lingo->_currentScript)[$1 + 3] = end; /* end, if cond fails */
- g_lingo->processIf(0, $10); }
+ g_lingo->processIf(0, $10 - $1); }
;
elsestmtoneliner: /* nothing */ { $$ = 0; }
@@ -337,7 +337,7 @@ elseifstmtoneliner: elseifstmtoneliner elseifstmtoneliner1
elseifstmtoneliner1: elseif cond tTHEN begin stmt end {
inst then = 0;
- WRITE_UINT32(&then, $4);
+ WRITE_UINT32(&then, $4 - $1);
(*g_lingo->_currentScript)[$1 + 1] = then; /* thenpart */
g_lingo->codeLabel($1); }
@@ -346,7 +346,7 @@ elseifstmtoneliner1: elseif cond tTHEN begin stmt end {
elseifstmt1: elseifstmtoneliner
| elseif cond tTHEN begin stmtlist end {
inst then = 0;
- WRITE_UINT32(&then, $5);
+ WRITE_UINT32(&then, $5 - $1);
(*g_lingo->_currentScript)[$1 + 1] = then; /* thenpart */
g_lingo->codeLabel($1); }
@@ -484,8 +484,7 @@ proc: tPUT expr { g_lingo->code1(g_lingo->c_printtop); }
| gotofunc
| playfunc
| tEXIT tREPEAT { g_lingo->code1(g_lingo->c_exitRepeat); }
- | tEXIT { g_lingo->codeConst(0); // Push fake value on stack
- g_lingo->code1(g_lingo->c_procret); }
+ | tEXIT { g_lingo->code1(g_lingo->c_procret); }
| tGLOBAL globallist
| tPROPERTY propertylist
| tINSTANCE instancelist
@@ -595,7 +594,6 @@ playfunc: tPLAY tDONE { g_lingo->code1(g_lingo->c_playdone); }
// on keyword
defn: tMACRO ID { g_lingo->_indef = true; g_lingo->_currentFactory.clear(); }
begin argdef nl argstore stmtlist {
- g_lingo->codeConst(0); // Push fake value on stack
g_lingo->code1(g_lingo->c_procret);
g_lingo->define(*$2, $4, $5);
g_lingo->_indef = false; }
@@ -609,7 +607,6 @@ defn: tMACRO ID { g_lingo->_indef = true; g_lingo->_currentFactory.clear(); }
g_lingo->_indef = false; } ;
| tON ID { g_lingo->_indef = true; g_lingo->_currentFactory.clear(); } // D3
begin { g_lingo->_ignoreMe = true; } argdef nl argstore stmtlist ENDCLAUSE {
- g_lingo->codeConst(0); // Push fake value on stack
g_lingo->code1(g_lingo->c_procret);
g_lingo->define(*$2, $4, $6);
g_lingo->_indef = false;
diff --git a/engines/director/lingo/lingo-lex.cpp b/engines/director/lingo/lingo-lex.cpp
index 48a5166b95..c931dc8a56 100644
--- a/engines/director/lingo/lingo-lex.cpp
+++ b/engines/director/lingo/lingo-lex.cpp
@@ -746,7 +746,7 @@ using namespace Director;
int yyparse();
static void count() {
- if (debugChannelSet(-1, kDebugLingoCompile))
+ if (debugChannelSet(-1, kDebugLingoParse))
debug("LEXER: Read '%s' at %d:%d", yytext, g_lingo->_linenumber, g_lingo->_colnumber);
g_lingo->_colnumber += strlen(yytext);
diff --git a/engines/director/lingo/lingo-lex.l b/engines/director/lingo/lingo-lex.l
index 37bad1247d..6a38bac047 100644
--- a/engines/director/lingo/lingo-lex.l
+++ b/engines/director/lingo/lingo-lex.l
@@ -37,7 +37,7 @@ using namespace Director;
int yyparse();
static void count() {
- if (debugChannelSet(-1, kDebugLingoCompile))
+ if (debugChannelSet(-1, kDebugLingoParse))
debug("LEXER: Read '%s' at %d:%d", yytext, g_lingo->_linenumber, g_lingo->_colnumber);
g_lingo->_colnumber += strlen(yytext);
diff --git a/engines/director/lingo/lingo.cpp b/engines/director/lingo/lingo.cpp
index cf0038bfdc..ffbbdab933 100644
--- a/engines/director/lingo/lingo.cpp
+++ b/engines/director/lingo/lingo.cpp
@@ -136,17 +136,17 @@ const char *Lingo::findNextDefinition(const char *s) {
return NULL;
if (!strncmp(res, "macro ", 6)) {
- debugC(3, kDebugLingoCompile, "See macro");
+ debugC(1, kDebugLingoCompile, "See macro");
return res;
}
if (!strncmp(res, "factory ", 8)) {
- debugC(3, kDebugLingoCompile, "See factory");
+ debugC(1, kDebugLingoCompile, "See factory");
return res;
}
if (!strncmp(res, "method ", 7)) {
- debugC(3, kDebugLingoCompile, "See method");
+ debugC(1, kDebugLingoCompile, "See method");
return res;
}
@@ -158,7 +158,7 @@ const char *Lingo::findNextDefinition(const char *s) {
}
void Lingo::addCode(const char *code, ScriptType type, uint16 id) {
- debugC(2, kDebugLingoCompile, "Add code \"%s\" for type %s with id %d", code, scriptType2str(type), id);
+ debugC(1, kDebugLingoCompile, "Add code \"%s\" for type %s with id %d", code, scriptType2str(type), id);
if (_scripts[type].contains(id)) {
delete _scripts[type][id];
@@ -175,7 +175,7 @@ void Lingo::addCode(const char *code, ScriptType type, uint16 id) {
const char *begin, *end;
if (!strncmp(code, "menu:", 5)) {
- debugC(2, kDebugLingoCompile, "Parsing menu");
+ debugC(1, kDebugLingoCompile, "Parsing menu");
parseMenu(code);
return;
@@ -200,7 +200,7 @@ void Lingo::addCode(const char *code, ScriptType type, uint16 id) {
else
_inFactory = false;
- debugC(2, kDebugLingoCompile, "Code chunk:\n#####\n%s#####", chunk.c_str());
+ debugC(1, kDebugLingoCompile, "Code chunk:\n#####\n%s#####", chunk.c_str());
parse(chunk.c_str());
@@ -208,7 +208,7 @@ void Lingo::addCode(const char *code, ScriptType type, uint16 id) {
uint pc = 0;
while (pc < _currentScript->size()) {
Common::String instr = decodeInstruction(pc, &pc);
- debugC(3, kDebugLingoCompile, "[%5d] %s", pc, instr.c_str());
+ debugC(2, kDebugLingoCompile, "[%5d] %s", pc, instr.c_str());
}
}
@@ -219,7 +219,7 @@ void Lingo::addCode(const char *code, ScriptType type, uint16 id) {
_hadError = true; // HACK: This is for preventing test execution
- debugC(2, kDebugLingoCompile, "Code chunk:\n#####\n%s#####", begin);
+ debugC(1, kDebugLingoCompile, "Code chunk:\n#####\n%s#####", begin);
parse(begin);
} else {
parse(code);
@@ -236,7 +236,7 @@ void Lingo::addCode(const char *code, ScriptType type, uint16 id) {
uint pc = 0;
while (pc < _currentScript->size()) {
Common::String instr = decodeInstruction(pc, &pc);
- debugC(3, kDebugLingoCompile, "[%5d] %s", pc, instr.c_str());
+ debugC(2, kDebugLingoCompile, "[%5d] %s", pc, instr.c_str());
}
}
}
@@ -247,7 +247,7 @@ void Lingo::executeScript(ScriptType type, uint16 id) {
return;
}
- debugC(2, kDebugLingoExec, "Executing script type: %s, id: %d", scriptType2str(type), id);
+ debugC(1, kDebugLingoExec, "Executing script type: %s, id: %d", scriptType2str(type), id);
_currentScript = _scripts[type][id];
_pc = 0;
@@ -291,7 +291,7 @@ Symbol *Lingo::getHandler(Common::String &name) {
}
void Lingo::processEvent(LEvent event, ScriptType st, int entityId) {
- if (entityId <= 0)
+ if (entityId < 0)
return;
debugC(1, kDebugEvents, "Lingo::processEvent(%s, %s, %d)", _eventHandlerTypes[event], scriptType2str(st), entityId);
@@ -303,11 +303,10 @@ void Lingo::processEvent(LEvent event, ScriptType st, int entityId) {
if (_handlers.contains(ENTITY_INDEX(event, entityId))) {
call(_eventHandlerTypes[event], 0); // D4+ Events
- pop();
} else if (_scripts[st].contains(entityId)) {
executeScript(st, entityId); // D3 list of scripts.
} else {
- debugC(8, kDebugLingoExec, "STUB: processEvent(%s) for %d", _eventHandlerTypes[event], entityId);
+ debugC(3, kDebugLingoExec, "STUB: processEvent(%s) for %d", _eventHandlerTypes[event], entityId);
}
}
@@ -429,6 +428,8 @@ const char *Datum::type2str(bool isk) {
return isk ? "#symbol" : "SYMBOL";
case OBJECT:
return isk ? "#object" : "OBJECT";
+ case REFERENCE:
+ return "REFERENCE";
case VAR:
return isk ? "#var" : "VAR";
default:
diff --git a/engines/director/lingo/lingo.h b/engines/director/lingo/lingo.h
index 550156c1c7..516e91c6ed 100644
--- a/engines/director/lingo/lingo.h
+++ b/engines/director/lingo/lingo.h
@@ -498,6 +498,8 @@ public:
void func_gotoloop();
void func_gotonext();
void func_gotoprevious();
+ void func_play(Datum &frame, Datum &movie);
+ void func_playdone();
void func_cursor(int c);
int func_marker(int m);
diff --git a/engines/director/score.cpp b/engines/director/score.cpp
index 975c6efe33..b876b777bf 100644
--- a/engines/director/score.cpp
+++ b/engines/director/score.cpp
@@ -302,6 +302,9 @@ void Score::loadCastDataVWCR(Common::SeekableSubReadStreamEndian &stream) {
if (size == 0)
continue;
+ if (debugChannelSet(5, kDebugLoading))
+ stream.hexdump(size);
+
uint8 castType = stream.readByte();
switch (castType) {
@@ -361,7 +364,7 @@ void Score::loadCastData(Common::SeekableSubReadStreamEndian &stream, uint16 id,
uint32 size1, size2, size3, castType;
byte unk1 = 0, unk2 = 0, unk3 = 0;
- if (_vm->getVersion() < 4) {
+ if (_vm->getVersion() <= 3) {
size1 = stream.readUint16();
size2 = stream.readUint32();
size3 = 0;
@@ -369,7 +372,7 @@ void Score::loadCastData(Common::SeekableSubReadStreamEndian &stream, uint16 id,
unk1 = stream.readByte();
unk2 = stream.readByte();
unk3 = stream.readByte();
- } else if (_vm->getVersion() < 5) {
+ } else if (_vm->getVersion() == 4) {
size1 = stream.readUint16() + 2;
size2 = stream.readUint32();
size3 = 0;
@@ -647,6 +650,12 @@ void Score::loadCastInfo(Common::SeekableSubReadStreamEndian &stream, uint16 id)
ci->fileName = getString(castStrings[3]);
ci->type = castStrings[4];
+ debugC(5, kDebugLoading, "CastInfo: name: '%s' directory: '%s', fileName: '%s', type: '%s'",
+ ci->name.c_str(), ci->directory.c_str(), ci->fileName.c_str(), ci->type.c_str());
+
+ if (!ci->name.empty())
+ _castsNames[ci->name] = id;
+
_castsInfo[id] = ci;
}
diff --git a/engines/director/score.h b/engines/director/score.h
index 6db5e33988..2e762f0dad 100644
--- a/engines/director/score.h
+++ b/engines/director/score.h
@@ -102,6 +102,7 @@ public:
Common::Array<Frame *> _frames;
Common::HashMap<int, Cast *> _casts;
Common::HashMap<uint16, CastInfo *> _castsInfo;
+ Common::HashMap<Common::String, int> _castsNames;
Common::SortedArray<Label *> *_labels;
Common::HashMap<uint16, Common::String> _actions;
Common::HashMap<uint16, Common::String> _fontMap;
diff --git a/engines/titanic/game/end_explode_ship.cpp b/engines/titanic/game/end_explode_ship.cpp
index 10c80f5863..6253a4df02 100644
--- a/engines/titanic/game/end_explode_ship.cpp
+++ b/engines/titanic/game/end_explode_ship.cpp
@@ -33,25 +33,25 @@ END_MESSAGE_MAP()
void CEndExplodeShip::save(SimpleFile *file, int indent) {
file->writeNumberLine(1, indent);
- file->writeNumberLine(_value1, indent);
- file->writeNumberLine(_value2, indent);
+ file->writeNumberLine(_isExploding, indent);
+ file->writeNumberLine(_unused5, indent);
CGameObject::save(file, indent);
}
void CEndExplodeShip::load(SimpleFile *file) {
file->readNumber();
- _value1 = file->readNumber();
- _value2 = file->readNumber();
+ _isExploding = file->readNumber();
+ _unused5 = file->readNumber();
CGameObject::load(file);
}
bool CEndExplodeShip::ActMsg(CActMsg *msg) {
if (msg->_action == "Arm Bomb") {
- _value1 = 1;
+ _isExploding = true;
} else if (msg->_action == "Disarm Bomb") {
- _value1 = 0;
+ _isExploding = false;
} else if (msg->_action == "TakeOff") {
loadSound("a#31.wav");
loadSound("a#14.wav");
@@ -67,12 +67,12 @@ bool CEndExplodeShip::TimerMsg(CTimerMsg *msg) {
setVisible(true);
playMovie(0, 449, 0);
movieEvent(58);
- playMovie(516, _value1 ? 550 : 551, MOVIE_NOTIFY_OBJECT);
+ playMovie(516, _isExploding ? 550 : 551, MOVIE_NOTIFY_OBJECT);
}
if (msg->_actionVal == 3) {
setGlobalSoundVolume(-4, 2, -1);
- CActMsg actMsg(_value1 ? "ExplodeCredits" : "Credits");
+ CActMsg actMsg(_isExploding ? "ExplodeCredits" : "Credits");
actMsg.execute("EndGameCredits");
}
diff --git a/engines/titanic/game/end_explode_ship.h b/engines/titanic/game/end_explode_ship.h
index c48f822af8..592741e5c0 100644
--- a/engines/titanic/game/end_explode_ship.h
+++ b/engines/titanic/game/end_explode_ship.h
@@ -34,10 +34,11 @@ class CEndExplodeShip : public CGameObject {
bool MovieEndMsg(CMovieEndMsg *msg);
bool MovieFrameMsg(CMovieFrameMsg *msg);
public:
- int _value1, _value2;
+ bool _isExploding;
+ int _unused5;
public:
CLASSDEF;
- CEndExplodeShip() : CGameObject(), _value1(0), _value2(0) {}
+ CEndExplodeShip() : CGameObject(), _isExploding(false), _unused5(0) {}
/**
* Save the data for the class to file
diff --git a/engines/titanic/game/end_game_credits.cpp b/engines/titanic/game/end_game_credits.cpp
index 4edcef0a17..c816f22706 100644
--- a/engines/titanic/game/end_game_credits.cpp
+++ b/engines/titanic/game/end_game_credits.cpp
@@ -31,7 +31,7 @@ BEGIN_MESSAGE_MAP(CEndGameCredits, CGameObject)
ON_MESSAGE(TimerMsg)
END_MESSAGE_MAP()
-CEndGameCredits::CEndGameCredits() : CGameObject(), _flag(0),
+CEndGameCredits::CEndGameCredits() : CGameObject(), _flag(false),
_frameRange(0, 28) {
}
@@ -75,6 +75,7 @@ bool CEndGameCredits::MovieEndMsg(CMovieEndMsg *msg) {
visibleMsg.execute("CreditsBackdrop");
}
+ addTimer(4000, 0);
return true;
}
diff --git a/engines/titanic/npcs/bellbot.cpp b/engines/titanic/npcs/bellbot.cpp
index 36c57fe467..1782161aea 100644
--- a/engines/titanic/npcs/bellbot.cpp
+++ b/engines/titanic/npcs/bellbot.cpp
@@ -135,7 +135,9 @@ bool CBellBot::MovieEndMsg(CMovieEndMsg *msg) {
}
bool CBellBot::Use(CUse *msg) {
- dynamic_cast<CCarry *>(msg->_item)->_npcUse = "Bellbot";
+ CCarry *item = dynamic_cast<CCarry *>(msg->_item);
+ assert(item);
+ item->_npcUse = "Bellbot";
return true;
}
diff --git a/engines/titanic/support/credit_text.cpp b/engines/titanic/support/credit_text.cpp
index da6de6278e..e8da605658 100644
--- a/engines/titanic/support/credit_text.cpp
+++ b/engines/titanic/support/credit_text.cpp
@@ -25,10 +25,10 @@
namespace Titanic {
-CCreditText::CCreditText() : _screenManagerP(nullptr), _field14(0),
- _ticks(0), _fontHeight(1), _objectP(nullptr), _totalHeight(0),
- _field40(0), _field44(0), _field48(0), _field4C(0), _field50(0),
- _field54(0), _field58(0), _counter(0) {
+CCreditText::CCreditText() : _screenManagerP(nullptr), _ticks(0),
+ _fontHeight(1), _objectP(nullptr), _totalHeight(0),
+ _yPos(0), _textR(0), _textG(0), _textB(0), _destR(0),
+ _destG(0), _destB(0), _counter(0) {
}
void CCreditText::clear() {
@@ -37,21 +37,21 @@ void CCreditText::clear() {
}
void CCreditText::load(CGameObject *obj, CScreenManager *screenManager,
- const Rect &rect, int v) {
+ const Rect &rect) {
_objectP = obj;
_screenManagerP = screenManager;
- _field14 = v;
+ _rect = rect;
setup();
_ticks = g_vm->_events->getTicksCount();
- _field40 = 0;
- _field44 = 0xFF;
- _field48 = 0xFF;
- _field4C = 0xFF;
- _field50 = 0;
- _field54 = 0;
- _field58 = 0;
+ _yPos = 0;
+ _textR = 0xFF;
+ _textG = 0xFF;
+ _textB = 0xFF;
+ _destR = 0;
+ _destG = 0;
+ _destB = 0;
_counter = 0;
}
@@ -154,26 +154,26 @@ bool CCreditText::draw() {
return false;
if (++_counter > 200) {
- _field44 += _field50;
- _field48 += _field54;
- _field4C += _field58;
- _field50 = g_vm->getRandomNumber(63) + 192 - _field44;
- _field54 = g_vm->getRandomNumber(63) + 192 - _field48;
- _field58 = g_vm->getRandomNumber(63) + 192 - _field4C;
+ _textR += _destR;
+ _textG += _destG;
+ _textB += _destB;
+ _destR = g_vm->getRandomNumber(63) + 192 - _textR;
+ _destG = g_vm->getRandomNumber(63) + 192 - _textG;
+ _destB = g_vm->getRandomNumber(63) + 192 - _textB;
_counter = 0;
}
// Positioning adjustment, changing lines and/or group if necessary
- int yDiff = (int)(g_vm->_events->getTicksCount() - _ticks) / 22 - _field40;
+ int yDiff = (int)(g_vm->_events->getTicksCount() - _ticks) / 22 - _yPos;
while (yDiff > 0) {
if (_totalHeight > 0) {
if (yDiff < _totalHeight) {
_totalHeight -= yDiff;
- _field40 += yDiff;
+ _yPos += yDiff;
yDiff = 0;
} else {
yDiff -= _totalHeight;
- _field40 += _totalHeight;
+ _yPos += _totalHeight;
_totalHeight = 0;
}
} else {
@@ -182,7 +182,7 @@ bool CCreditText::draw() {
++_lineIt;
yDiff -= _fontHeight;
- _field40 += _fontHeight;
+ _yPos += _fontHeight;
if (_lineIt == (*_groupIt)->_lines.end()) {
// Move to next line group
@@ -204,9 +204,9 @@ bool CCreditText::draw() {
Point textPos;
for (textPos.y = _rect.top + _totalHeight; textPos.y <= _rect.bottom;
textPos.y += _fontHeight) {
- int textR = _field44 + _field50 * _counter / 200;
- int textG = _field48 + _field54 * _counter / 200;
- int textB = _field4C + _field58 * _counter / 200;
+ int textR = _textR + _destR * _counter / 200;
+ int textG = _textG + _destG * _counter / 200;
+ int textB = _textB + _destB * _counter / 200;
// Single iteration loop to figure out RGB values for the line
do {
diff --git a/engines/titanic/support/credit_text.h b/engines/titanic/support/credit_text.h
index 3e5bfca0c2..05392f5048 100644
--- a/engines/titanic/support/credit_text.h
+++ b/engines/titanic/support/credit_text.h
@@ -65,7 +65,6 @@ private:
public:
CScreenManager *_screenManagerP;
Rect _rect;
- int _field14;
CCreditLineGroups _groups;
uint _ticks;
int _fontHeight;
@@ -73,13 +72,9 @@ public:
CCreditLineGroups::iterator _groupIt;
CCreditLines::iterator _lineIt;
int _totalHeight;
- int _field40;
- int _field44;
- int _field48;
- int _field4C;
- int _field50;
- int _field54;
- int _field58;
+ int _yPos;
+ int _textR, _textG, _textB;
+ int _destR, _destG, _destB;
int _counter;
public:
CCreditText();
@@ -93,7 +88,7 @@ public:
* Sets the game object this override is associated with
*/
void load(CGameObject *obj, CScreenManager *screenManager,
- const Rect &rect, int v = 0);
+ const Rect &rect);
/**
* Draw the item
diff --git a/engines/titanic/support/font.cpp b/engines/titanic/support/font.cpp
index f81251b10b..56f1af4718 100644
--- a/engines/titanic/support/font.cpp
+++ b/engines/titanic/support/font.cpp
@@ -214,6 +214,7 @@ void STFont::writeString(CVideoSurface *surface, const Point &destPos, Rect &cli
// Form a rect of the area of the next character to draw
Rect charRect(_chars[c]._offset, textRect.top,
_chars[c]._offset + _chars[c]._width, textRect.bottom);
+ int textX = textPt.x;
if (textPt.x < clipRect.left) {
// Character is either partially or entirely left off-screen
@@ -237,6 +238,7 @@ void STFont::writeString(CVideoSurface *surface, const Point &destPos, Rect &cli
// At this point, we know we've got to draw at least part of a character,
// and have figured out the area of the character to draw
copyRect(surface, textPt, charRect);
+ textPt.x = textX + _chars[c]._width;
}
}
diff --git a/engines/tsage/ringworld2/ringworld2_logic.cpp b/engines/tsage/ringworld2/ringworld2_logic.cpp
index b41abe8cf9..e8d51109b1 100644
--- a/engines/tsage/ringworld2/ringworld2_logic.cpp
+++ b/engines/tsage/ringworld2/ringworld2_logic.cpp
@@ -1228,7 +1228,8 @@ void Ringworld2Game::processEvent(Event &event) {
case Common::KEYCODE_F8:
// F8 - Credits
- R2_GLOBALS._sceneManager.changeScene(205);
+ if (R2_GLOBALS._sceneManager._sceneNumber != 205)
+ R2_GLOBALS._sceneManager.changeScene(205);
break;
case Common::KEYCODE_F10:
diff --git a/graphics/managed_surface.cpp b/graphics/managed_surface.cpp
index fe524724cd..60b2941efa 100644
--- a/graphics/managed_surface.cpp
+++ b/graphics/managed_surface.cpp
@@ -256,7 +256,7 @@ void transBlit(const Surface &src, const Common::Rect &srcRect, Surface &dest, c
for (int destY = destRect.top, scaleYCtr = 0; destY < destRect.bottom; ++destY, scaleYCtr += scaleY) {
if (destY < 0 || destY >= dest.h)
continue;
- const TSRC *srcLine = (const TSRC *)src.getBasePtr(0, scaleYCtr / SCALE_THRESHOLD);
+ const TSRC *srcLine = (const TSRC *)src.getBasePtr(srcRect.left, scaleYCtr / SCALE_THRESHOLD + srcRect.top);
TDEST *destLine = (TDEST *)dest.getBasePtr(destRect.left, destY);
// Loop through drawing the pixels of the row
diff --git a/po/de_DE.po b/po/de_DE.po
index 190e4698fb..9b988fb2d5 100644
--- a/po/de_DE.po
+++ b/po/de_DE.po
@@ -8,10 +8,10 @@ msgstr ""
"Project-Id-Version: ScummVM 1.10.0git\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.scummvm.org\n"
"POT-Creation-Date: 2017-02-21 23:29+0100\n"
-"PO-Revision-Date: 2017-02-08 21:48+0000\n"
-"Last-Translator: Lothar Serra Mari <rootfather@scummvm.org>\n"
-"Language-Team: German <https://translations.scummvm.org/projects/scummvm/"
-"scummvm/de/>\n"
+"PO-Revision-Date: 2017-02-24 12:05+0000\n"
+"Last-Translator: Rouven Bauer <r_bauer11@cs.uni-kl.de>\n"
+"Language-Team: German "
+"<https://translations.scummvm.org/projects/scummvm/scummvm/de/>\n"
"Language: de_DE\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=iso-8859-1\n"
@@ -857,16 +857,15 @@ msgstr "Die Filtereinstellung konnte nicht geändert werden"
#: gui/options.cpp:884
msgid "Show On-screen control"
-msgstr ""
+msgstr "Virtuelle Bedienelemente anzeigen"
#: gui/options.cpp:888
-#, fuzzy
msgid "Touchpad mouse mode"
-msgstr "Touchpad-Modus ausgeschaltet."
+msgstr "Touchpad-Mausmodus"
#: gui/options.cpp:892
msgid "Swap Menu and Back buttons"
-msgstr ""
+msgstr "Vertausche Menü- und Zurück-Buttons"
#: gui/options.cpp:904
msgid "Graphics mode:"
@@ -1117,9 +1116,8 @@ msgid "Speech volume:"
msgstr "Sprachlautst.:"
#: gui/options.cpp:1351
-#, fuzzy
msgid "Control"
-msgstr "Maus steuern"
+msgstr "Steuerung"
#: gui/options.cpp:1383
msgid "FluidSynth Settings"
diff --git a/po/el.po b/po/el.po
index 9a44ee7cbf..84e5a4b0c7 100644
--- a/po/el.po
+++ b/po/el.po
@@ -7,10 +7,10 @@ msgstr ""
"Project-Id-Version: ScummVM 1.10.0git\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.scummvm.org\n"
"POT-Creation-Date: 2017-02-21 23:29+0100\n"
-"PO-Revision-Date: 2017-01-07 02:29+0000\n"
-"Last-Translator: Filippos Karapetis <bluegr@gmail.com>\n"
-"Language-Team: Greek <https://translations.scummvm.org/projects/scummvm/"
-"scummvm/el/>\n"
+"PO-Revision-Date: 2017-02-22 19:57+0000\n"
+"Last-Translator: Arius <alidop@pathfinder.gr>\n"
+"Language-Team: Greek "
+"<https://translations.scummvm.org/projects/scummvm/scummvm/el/>\n"
"Language: el\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=iso-8859-7\n"
@@ -873,7 +873,7 @@ msgstr "Ëåéôïõñãßá Touchpad áðåíåñãïðïéçìÝíç."
#: gui/options.cpp:892
msgid "Swap Menu and Back buttons"
-msgstr ""
+msgstr "ÅíáëëáãÞ ôùí êïõìðéþí Ìåíïý êáé Ðßóù"
#: gui/options.cpp:904
msgid "Graphics mode:"
diff --git a/po/fi_FI.po b/po/fi_FI.po
index 07d754c166..8afdbad484 100644
--- a/po/fi_FI.po
+++ b/po/fi_FI.po
@@ -8,10 +8,10 @@ msgstr ""
"Project-Id-Version: ScummVM 1.6.0git\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.scummvm.org\n"
"POT-Creation-Date: 2017-02-21 23:29+0100\n"
-"PO-Revision-Date: 2017-01-06 16:03+0000\n"
+"PO-Revision-Date: 2017-02-22 17:44+0000\n"
"Last-Translator: Timo Mikkolainen <tmikkola@gmail.com>\n"
-"Language-Team: Finnish <https://translations.scummvm.org/projects/scummvm/"
-"scummvm/fi/>\n"
+"Language-Team: Finnish "
+"<https://translations.scummvm.org/projects/scummvm/scummvm/fi/>\n"
"Language: fi_FI\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=iso-8859-1\n"
@@ -849,16 +849,15 @@ msgstr "Suodatusasetusta ei voitu muuttaa"
#: gui/options.cpp:884
msgid "Show On-screen control"
-msgstr ""
+msgstr "Virtuaalikontrollit"
#: gui/options.cpp:888
-#, fuzzy
msgid "Touchpad mouse mode"
-msgstr "Touchpad tila pois päältä."
+msgstr "Touchpad hiiritila"
#: gui/options.cpp:892
msgid "Swap Menu and Back buttons"
-msgstr ""
+msgstr "Vaihda Menu ja Takaisin nappien paikkaa"
#: gui/options.cpp:904
msgid "Graphics mode:"
@@ -1107,9 +1106,8 @@ msgid "Speech volume:"
msgstr "Puhe:"
#: gui/options.cpp:1351
-#, fuzzy
msgid "Control"
-msgstr "Ohjaa hiirtä"
+msgstr "Kontrollit"
#: gui/options.cpp:1383
msgid "FluidSynth Settings"
diff --git a/po/fr_FR.po b/po/fr_FR.po
index cb0ee2ceeb..3886b99799 100644
--- a/po/fr_FR.po
+++ b/po/fr_FR.po
@@ -8,10 +8,10 @@ msgstr ""
"Project-Id-Version: ScummVM 1.8.0git\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.scummvm.org\n"
"POT-Creation-Date: 2017-02-21 23:29+0100\n"
-"PO-Revision-Date: 2017-02-04 10:14+0000\n"
+"PO-Revision-Date: 2017-02-23 11:45+0000\n"
"Last-Translator: Purple T <zeonk@hotmail.com>\n"
-"Language-Team: French <https://translations.scummvm.org/projects/scummvm/"
-"scummvm/fr/>\n"
+"Language-Team: French "
+"<https://translations.scummvm.org/projects/scummvm/scummvm/fr/>\n"
"Language: fr_FR\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=iso-8859-1\n"
@@ -854,16 +854,15 @@ msgstr "le mode de filtrage n'a pu être changé"
#: gui/options.cpp:884
msgid "Show On-screen control"
-msgstr ""
+msgstr "Afficher les contrôles sur l'écran"
#: gui/options.cpp:888
-#, fuzzy
msgid "Touchpad mouse mode"
-msgstr "Mode touchpad désactivé."
+msgstr "Souris en mode Touchpad"
#: gui/options.cpp:892
msgid "Swap Menu and Back buttons"
-msgstr ""
+msgstr "Inverser les boutons Menu et Retour"
#: gui/options.cpp:904
msgid "Graphics mode:"
@@ -1117,9 +1116,8 @@ msgid "Speech volume:"
msgstr "Dialogues :"
#: gui/options.cpp:1351
-#, fuzzy
msgid "Control"
-msgstr "Contrôles la Souris"
+msgstr "Contrôles"
#: gui/options.cpp:1383
msgid "FluidSynth Settings"
diff --git a/po/hu_HU.po b/po/hu_HU.po
index b4d75d00bc..7f90a1309d 100644
--- a/po/hu_HU.po
+++ b/po/hu_HU.po
@@ -7,10 +7,10 @@ msgstr ""
"Project-Id-Version: ScummVM 1.3.0svn\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.scummvm.org\n"
"POT-Creation-Date: 2017-02-21 23:29+0100\n"
-"PO-Revision-Date: 2017-01-08 06:09+0000\n"
-"Last-Translator: George Kormendi <grubycza@hotmail.com>\n"
-"Language-Team: Hungarian <https://translations.scummvm.org/projects/scummvm/"
-"scummvm/hu/>\n"
+"PO-Revision-Date: 2017-02-24 12:04+0000\n"
+"Last-Translator: Eugene Sandulenko <sev@scummvm.org>\n"
+"Language-Team: Hungarian "
+"<https://translations.scummvm.org/projects/scummvm/scummvm/hu/>\n"
"Language: hu_HU\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=iso-8859-2\n"
@@ -849,9 +849,8 @@ msgid "Show On-screen control"
msgstr ""
#: gui/options.cpp:888
-#, fuzzy
msgid "Touchpad mouse mode"
-msgstr "Touchpad mód letiltva."
+msgstr "Touchpad egér mód"
#: gui/options.cpp:892
msgid "Swap Menu and Back buttons"
@@ -1101,9 +1100,8 @@ msgid "Speech volume:"
msgstr "Beszéd hangerõ:"
#: gui/options.cpp:1351
-#, fuzzy
msgid "Control"
-msgstr "Egér irányitás"
+msgstr "Irányitás"
#: gui/options.cpp:1383
msgid "FluidSynth Settings"
@@ -4257,7 +4255,6 @@ msgid "The \"sky.cpt\" engine data file has an incorrect size."
msgstr "A \"sky.cpt\" motor adatfájl mérete inkorrekt.."
#: engines/sky/detection.cpp:44
-#, fuzzy
msgid "Floppy intro"
msgstr "Floppy intro"
@@ -4379,9 +4376,9 @@ msgid "Saved game #%d quick loaded"
msgstr "Játékállás nem menthetõ %d slotba"
#: engines/toon/toon.cpp:243
-#, fuzzy, c-format
+#, c-format
msgid "Could not quick load the saved game #%d"
-msgstr "Akarod hogy betöltésem a játékállást?"
+msgstr "Nem történt meg a #%d mentett játék gyors betöltése"
#: engines/wintermute/detection.cpp:58
msgid "Show FPS-counter"
diff --git a/po/ru_RU.po b/po/ru_RU.po
index 3b2672575b..fd4caf197b 100644
--- a/po/ru_RU.po
+++ b/po/ru_RU.po
@@ -8,16 +8,16 @@ msgstr ""
"Project-Id-Version: ScummVM 1.8.0svn\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.scummvm.org\n"
"POT-Creation-Date: 2017-02-21 23:29+0100\n"
-"PO-Revision-Date: 2016-12-31 21:04+0000\n"
-"Last-Translator: Ivan Lukyanov <lid-gr@tut.by>\n"
-"Language-Team: Russian <https://translations.scummvm.org/projects/scummvm/"
-"scummvm/ru/>\n"
+"PO-Revision-Date: 2017-02-22 19:56+0000\n"
+"Last-Translator: Eugene Sandulenko <sev@scummvm.org>\n"
+"Language-Team: Russian "
+"<https://translations.scummvm.org/projects/scummvm/scummvm/ru/>\n"
"Language: ru_RU\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=iso-8859-5\n"
"Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
-"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
+"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<="
+"4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
"X-Generator: Weblate 2.9\n"
"X-Language-name: Russian\n"
@@ -851,16 +851,15 @@ msgstr "àÕÖØÜ äØÛìâàÐæØØ ÝÕ ÜÞÖÕâ Ñëâì Ø×ÜÕÝñÝ"
#: gui/options.cpp:884
msgid "Show On-screen control"
-msgstr ""
+msgstr "¿ÞÚÐ×Ðâì ãßàÐÒÛÕÝØÕ íÚàÐÝÞÜ"
#: gui/options.cpp:888
-#, fuzzy
msgid "Touchpad mouse mode"
-msgstr "ÀÕÖØÜ âÐçßÐÔÐ ÒëÚÛîçÕÝ."
+msgstr "ÀÕÖØÜ âÐçßÐÔÐ"
#: gui/options.cpp:892
msgid "Swap Menu and Back buttons"
-msgstr ""
+msgstr "¿ÞÜÕÝïâì ÜÕáâÐÜØ ÚÝÞßÚØ ¼ÕÝî Ø ½Ð×ÐÔ"
#: gui/options.cpp:904
msgid "Graphics mode:"
@@ -1111,9 +1110,8 @@ msgid "Speech volume:"
msgstr "³àÞÜÚ. Þ×ÒãçÚØ:"
#: gui/options.cpp:1351
-#, fuzzy
msgid "Control"
-msgstr "ÃßàÐÒÛÕÝØÕ Üëèìî"
+msgstr "ÃßàÐÒÛÕÝØÕ"
#: gui/options.cpp:1383
msgid "FluidSynth Settings"
diff --git a/po/uk_UA.po b/po/uk_UA.po
index 1d4774c020..c503bcf091 100644
--- a/po/uk_UA.po
+++ b/po/uk_UA.po
@@ -9,16 +9,16 @@ msgstr ""
"Project-Id-Version: ScummVM 1.9.0git\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.scummvm.org\n"
"POT-Creation-Date: 2017-02-21 23:29+0100\n"
-"PO-Revision-Date: 2017-01-01 00:02+0000\n"
+"PO-Revision-Date: 2017-02-22 19:54+0000\n"
"Last-Translator: Eugene Sandulenko <sev@scummvm.org>\n"
-"Language-Team: Ukrainian <https://translations.scummvm.org/projects/scummvm/"
-"scummvm/uk/>\n"
+"Language-Team: Ukrainian "
+"<https://translations.scummvm.org/projects/scummvm/scummvm/uk/>\n"
"Language: uk_UA\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=iso-8859-5\n"
"Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
-"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
+"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<="
+"4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
"X-Generator: Weblate 2.9\n"
"X-Language-name: Ukrainian\n"
@@ -851,16 +851,15 @@ msgstr "ÝÕ ÒÔÐÛÞáï ×ÜöÝØâØ àÕÖØÜ äöÛìâàãÒÐÝÝï"
#: gui/options.cpp:884
msgid "Show On-screen control"
-msgstr ""
+msgstr "¿ÞÚÐ×ãÒÐâØ ÕÚàÐÝÝÕ ÚÕàãÒÐÝÝï"
#: gui/options.cpp:888
-#, fuzzy
msgid "Touchpad mouse mode"
-msgstr "ÀÕÖØÜ âÐçßÐÔã ÒØÜÚÝÕÝÞ."
+msgstr "ÀÕÖØÜ âÐçßÐÔã"
#: gui/options.cpp:892
msgid "Swap Menu and Back buttons"
-msgstr ""
+msgstr "¿ÞÜöÝïâØ ÜöáæïÜØ ÚÝÞßÚØ ¼ÕÝî ö ½Ð×ÐÔ"
#: gui/options.cpp:904
msgid "Graphics mode:"
@@ -1109,9 +1108,8 @@ msgid "Speech volume:"
msgstr "³ãçÝ. Þ×ÒãçÚØ:"
#: gui/options.cpp:1351
-#, fuzzy
msgid "Control"
-msgstr "ÃßàÐÒÛöÝÝï ÜØèÕî"
+msgstr "ºÕàãÒÐÝÝï"
#: gui/options.cpp:1383
msgid "FluidSynth Settings"
@@ -2304,7 +2302,7 @@ msgstr "·ÜöéÕÝÝï ÔÞâØÚöÒ ßÞ Þáö Y"
#: backends/platform/ds/arm9/source/dsoptions.cpp:87
msgid "Use laptop trackpad-style cursor control"
-msgstr "²ØÚÞàØáâÞÒãÒÐâØ ãßàÐÒÛöÝÝï ÚãàáÞàÞÜ ïÚ ÝÐ âàÕÚßÐÔö ÛÐßâÞßöÒ"
+msgstr "²ØÚÞàØáâÞÒãÒÐâØ ÚÕàãÒÐÝÝï ÚãàáÞàÞÜ ïÚ ÝÐ âàÕÚßÐÔö ÛÐßâÞßöÒ"
#: backends/platform/ds/arm9/source/dsoptions.cpp:88
msgid "Tap for left click, double tap right click"
@@ -2495,7 +2493,7 @@ msgstr "¿ÞÚÐ×ÐâØ ÚÛÐÒöÐâãàã"
#: backends/platform/tizen/form.cpp:309
msgid "Control Mouse"
-msgstr "ÃßàÐÒÛöÝÝï ÜØèÕî"
+msgstr "ºÕàãÒÐÝÝï ÜØèÕî"
#: backends/platform/tizen/fs.cpp:259
msgid "[ Data ]"