aboutsummaryrefslogtreecommitdiff
path: root/engines/director
diff options
context:
space:
mode:
authorScott Percival2019-08-18 21:37:05 +0800
committerEugene Sandulenko2019-11-17 22:31:54 +0100
commitffde055357416ee9d7704dbe22004a54090fe1fb (patch)
treeebed2db52522bac624dcc6b35e1535e4fb2870af /engines/director
parent3034fda611e75a5dc9410a82aadc2398ef2fbce3 (diff)
downloadscummvm-rg350-ffde055357416ee9d7704dbe22004a54090fe1fb.tar.gz
scummvm-rg350-ffde055357416ee9d7704dbe22004a54090fe1fb.tar.bz2
scummvm-rg350-ffde055357416ee9d7704dbe22004a54090fe1fb.zip
DIRECTOR: begin interpreter for Lingo V4 bytecode
Diffstat (limited to 'engines/director')
-rw-r--r--engines/director/lingo/lingo-bytecode.cpp96
-rw-r--r--engines/director/lingo/lingo-bytecode.h0
-rw-r--r--engines/director/lingo/lingo-code.cpp61
-rw-r--r--engines/director/lingo/lingo.h6
-rw-r--r--engines/director/module.mk1
-rw-r--r--engines/director/score.cpp24
-rw-r--r--engines/director/score.h1
7 files changed, 188 insertions, 1 deletions
diff --git a/engines/director/lingo/lingo-bytecode.cpp b/engines/director/lingo/lingo-bytecode.cpp
new file mode 100644
index 0000000000..f19ebb7768
--- /dev/null
+++ b/engines/director/lingo/lingo-bytecode.cpp
@@ -0,0 +1,96 @@
+/* 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 "director/lingo/lingo.h"
+
+namespace Director {
+
+static struct LingoV4Bytecode {
+ const char opcode;
+ const inst func;
+} lingoV4[] = {
+ { 0x03, Lingo::c_voidpush },
+ { 0x04, Lingo::c_mul },
+ { 0x05, Lingo::c_add },
+ { 0x06, Lingo::c_sub },
+ { 0x07, Lingo::c_div },
+ { 0x08, Lingo::c_mod },
+ { 0x09, Lingo::c_negate },
+ { 0x0a, Lingo::c_ampersand },
+ { 0x0b, Lingo::c_concat },
+ { 0x0c, Lingo::c_lt },
+ { 0x0d, Lingo::c_le },
+ { 0x0e, Lingo::c_neq },
+ { 0x0f, Lingo::c_eq },
+ { 0x10, Lingo::c_gt },
+ { 0x11, Lingo::c_ge },
+ { 0x12, Lingo::c_and },
+ { 0x13, Lingo::c_or },
+ { 0x14, Lingo::c_not },
+ { 0x15, Lingo::c_contains },
+ { 0x16, Lingo::c_starts },
+ { 0x17, Lingo::c_of },
+ { 0x18, Lingo::c_hilite },
+ { 0x19, Lingo::c_intersects },
+ { 0x1a, Lingo::c_within },
+ { 0x1b, Lingo::c_field },
+ { 0x1c, Lingo::c_tell },
+ { 0x1d, Lingo::c_telldone },
+
+ { 0x41, Lingo::c_intpush },
+ { 0, 0 }
+};
+
+
+void Lingo::addCodeV4(Common::SeekableSubReadStreamEndian &stream, ScriptType type, uint16 id) {
+ debugC(1, kDebugLingoCompile, "Add V4 bytecode for type %s with id %d", scriptType2str(type), id);
+
+ // unk1
+ for (uint32 i = 0; i < 0x10; i++) {
+ stream.readByte();
+ }
+ uint16 code_store_offset = stream.readUint16();
+ // unk2
+ for (uint32 i = 0; i < 0x2e; i++) {
+ stream.readByte();
+ }
+ uint16 functions_offset = stream.readUint16();
+ // unk3
+ for (uint32 i = 0; i < 0x6; i++) {
+ stream.readByte();
+ }
+ uint16 functions_count = stream.readUint16();
+ uint16 unk4 = stream.readUint16();
+ uint16 unk5 = stream.readUint16();
+ uint16 consts_count = stream.readUint16();
+ stream.readUint16();
+ uint16 consts_offset = stream.readUint16();
+ stream.readUint16();
+ uint16 unk6 = stream.readUint16();
+ stream.readUint16();
+ uint16 consts_base = stream.readUint16();
+
+ // preload all the constants
+ stream.seek(consts_offset);
+}
+
+}
diff --git a/engines/director/lingo/lingo-bytecode.h b/engines/director/lingo/lingo-bytecode.h
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/engines/director/lingo/lingo-bytecode.h
diff --git a/engines/director/lingo/lingo-code.cpp b/engines/director/lingo/lingo-code.cpp
index b2733f23b7..85b50cd8ea 100644
--- a/engines/director/lingo/lingo-code.cpp
+++ b/engines/director/lingo/lingo-code.cpp
@@ -85,6 +85,8 @@ static struct FuncDescr {
{ Lingo::c_starts, "c_starts", "" },
{ Lingo::c_intersects, "c_intersects", "" },
{ Lingo::c_within, "c_within", "" },
+ { Lingo::c_field, "c_field", "" },
+ { Lingo::c_of, "c_of", "" }, // D9
{ Lingo::c_charOf, "c_charOf", "" }, // D3
{ Lingo::c_charToOf, "c_charToOf", "" }, // D3
{ Lingo::c_itemOf, "c_itemOf", "" }, // D3
@@ -107,6 +109,8 @@ static struct FuncDescr {
{ Lingo::c_exitRepeat, "c_exitRepeat", "" },
{ Lingo::c_ifcode, "c_ifcode", "oooi" },
{ Lingo::c_tellcode, "c_tellcode", "o" },
+ { Lingo::c_tell, "c_tell", "" },
+ { Lingo::c_telldone, "c_telldone", "" },
{ Lingo::c_whencode, "c_whencode", "os" },
{ Lingo::c_goto, "c_goto", "" },
{ Lingo::c_gotoloop, "c_gotoloop", "" },
@@ -120,6 +124,7 @@ static struct FuncDescr {
{ Lingo::c_property, "c_property", "s" },
{ Lingo::c_instance, "c_instance", "s" },
{ Lingo::c_open, "c_open", "" },
+ { Lingo::c_hilite, "c_hilite", "" },
{ 0, 0, 0 }
};
@@ -243,7 +248,7 @@ void Lingo::c_arraypush() {
Datum d;
inst v = (*g_lingo->_currentScript)[g_lingo->_pc++];
int arraySize = READ_UINT32(&v);
-`
+
warning("STUB: c_arraypush()");
for (int i = 0; i < arraySize; i++)
@@ -640,6 +645,34 @@ void Lingo::c_within() {
g_lingo->push(d1);
}
+void Lingo::c_field() {
+ Datum d1 = g_lingo->pop();
+
+ warning("STUB: c_field: %d", d1.u.i);
+
+ g_lingo->push(d1);
+}
+
+void Lingo::c_of() {
+ Datum first_char = g_lingo->pop();
+ Datum last_char = g_lingo->pop();
+ Datum first_word = g_lingo->pop();
+ Datum last_word = g_lingo->pop();
+ Datum first_item = g_lingo->pop();
+ Datum last_item = g_lingo->pop();
+ Datum first_line = g_lingo->pop();
+ Datum last_line = g_lingo->pop();
+ Datum target = g_lingo->pop();
+
+ warning("STUB: c_of: %d %d %d %d %d %d %d %d %s",
+ first_char.u.i, last_char.u.i, first_word.u.i, last_word.u.i,
+ first_item.u.i, last_item.u.i, first_line.u.i, last_line.u.i,
+ target.u.s->c_str());
+
+ g_lingo->push(target);
+
+}
+
void Lingo::c_charOf() {
Datum d2 = g_lingo->pop();
Datum d1 = g_lingo->pop();
@@ -969,6 +1002,15 @@ void Lingo::c_tellcode() {
warning("STUB: c_tellcode");
}
+void Lingo::c_tell() {
+ Datum d1 = g_lingo->pop();
+ warning("STUB: c_tell %d", d1.u.i);
+}
+
+void Lingo::c_telldone() {
+ warning("STUB: c_telldone");
+}
+
//************************
// Built-in functions
@@ -1187,4 +1229,21 @@ void Lingo::c_open() {
warning("STUB: c_open(%s, %s)", d1.u.s->c_str(), d2.u.s->c_str());
}
+void Lingo::c_hilite() {
+ Datum first_char = g_lingo->pop();
+ Datum last_char = g_lingo->pop();
+ Datum first_word = g_lingo->pop();
+ Datum last_word = g_lingo->pop();
+ Datum first_item = g_lingo->pop();
+ Datum last_item = g_lingo->pop();
+ Datum first_line = g_lingo->pop();
+ Datum last_line = g_lingo->pop();
+ Datum cast_id = g_lingo->pop();
+
+ warning("STUB: c_hilite: %d %d %d %d %d %d %d %d %d",
+ first_char.u.i, last_char.u.i, first_word.u.i, last_word.u.i,
+ first_item.u.i, last_item.u.i, first_line.u.i, last_line.u.i,
+ cast_id.u.i);
+}
+
}
diff --git a/engines/director/lingo/lingo.h b/engines/director/lingo/lingo.h
index bc6a6a1af6..e1a165796e 100644
--- a/engines/director/lingo/lingo.h
+++ b/engines/director/lingo/lingo.h
@@ -163,6 +163,7 @@ public:
void restartLingo();
void addCode(const char *code, ScriptType type, uint16 id);
+ void addCodeV4(Common::SeekableSubReadStreamEndian &stream, ScriptType type, uint16 id);
void executeScript(ScriptType type, uint16 id);
void printStack(const char *s);
Common::String decodeInstruction(uint pc, uint *newPC = NULL);
@@ -252,6 +253,8 @@ public:
static void c_intersects();
static void c_within();
+ static void c_field();
+ static void c_of();
static void c_charOf();
static void c_charToOf();
static void c_itemOf();
@@ -283,6 +286,8 @@ public:
static void c_ifcode();
static void c_whencode();
static void c_tellcode();
+ static void c_tell();
+ static void c_telldone();
static void c_exitRepeat();
static void c_eq();
static void c_neq();
@@ -310,6 +315,7 @@ public:
static void c_playdone();
static void c_open();
+ static void c_hilite();
void printSTUBWithArglist(const char *funcname, int nargs, const char *prefix = "STUB:");
void convertVOIDtoString(int arg, int nargs);
diff --git a/engines/director/module.mk b/engines/director/module.mk
index 73f4a4ed7c..e445e576f4 100644
--- a/engines/director/module.mk
+++ b/engines/director/module.mk
@@ -20,6 +20,7 @@ MODULE_OBJS = \
lingo/lingo-gr.o \
lingo/lingo.o \
lingo/lingo-builtins.o \
+ lingo/lingo-bytecode.o \
lingo/lingo-code.o \
lingo/lingo-codegen.o \
lingo/lingo-events.o \
diff --git a/engines/director/score.cpp b/engines/director/score.cpp
index 19128ab414..e9f49336d9 100644
--- a/engines/director/score.cpp
+++ b/engines/director/score.cpp
@@ -180,6 +180,19 @@ void Score::loadArchive() {
setSpriteCasts();
loadSpriteImages(false);
+ // Try to load compiled Lingo scripts
+ if (_vm->getVersion() == 4) {
+ Common::Array<uint16> lscr = _movieArchive->getResourceIDList(MKTAG('L','s','c','r'));
+ if (lscr.size() > 0) {
+ debugC(2, kDebugLoading, "****** Loading %d Lscr resources", lscr.size());
+
+ for (Common::Array<uint16>::iterator iterator = lscr.begin(); iterator != lscr.end(); ++iterator) {
+ loadLingoScript(*_movieArchive->getResource(MKTAG('L','s','c','r'), *iterator));
+ }
+ }
+
+ }
+
// Try to load movie script, it sits in resource A11
if (_vm->getVersion() <= 3) {
Common::Array<uint16> stxt = _movieArchive->getResourceIDList(MKTAG('S','T','X','T'));
@@ -872,6 +885,17 @@ bool Score::processImmediateFrameScript(Common::String s, int id) {
return false;
}
+void Score::loadLingoScript(Common::SeekableSubReadStreamEndian &stream) {
+ if (_vm->getVersion() == 4) {
+
+ _lingo->addCodeV4(stream, kMovieScript, _movieScriptCount);
+
+ } else {
+ error("Score::loadLingoScript: unsuported Director version (%d)", _vm->getVersion());
+ }
+ _movieScriptCount++;
+}
+
void Score::loadScriptText(Common::SeekableSubReadStreamEndian &stream) {
/*uint32 unk1 = */ stream.readUint32();
uint32 strLen = stream.readUint32();
diff --git a/engines/director/score.h b/engines/director/score.h
index 40ef85cad0..7c663d559e 100644
--- a/engines/director/score.h
+++ b/engines/director/score.h
@@ -101,6 +101,7 @@ private:
void loadFrames(Common::SeekableSubReadStreamEndian &stream);
void loadLabels(Common::SeekableSubReadStreamEndian &stream);
void loadActions(Common::SeekableSubReadStreamEndian &stream);
+ void loadLingoScript(Common::SeekableSubReadStreamEndian &stream);
void loadScriptText(Common::SeekableSubReadStreamEndian &stream);
void loadFileInfo(Common::SeekableSubReadStreamEndian &stream);
void loadFontMap(Common::SeekableSubReadStreamEndian &stream);