aboutsummaryrefslogtreecommitdiff
path: root/engines/director/lingo/lingo-bytecode.cpp
diff options
context:
space:
mode:
authorScott Percival2019-12-22 22:10:38 +0800
committerScott Percival2019-12-23 08:58:14 +0800
commite943f8c291d1089b095082b3d684ab6e14c637bd (patch)
tree96de5cdb2ba78ef7f1aa060caaf17763141bc1bc /engines/director/lingo/lingo-bytecode.cpp
parentd1347b0ce120b3fef101de0736c243a82932c583 (diff)
downloadscummvm-rg350-e943f8c291d1089b095082b3d684ab6e14c637bd.tar.gz
scummvm-rg350-e943f8c291d1089b095082b3d684ab6e14c637bd.tar.bz2
scummvm-rg350-e943f8c291d1089b095082b3d684ab6e14c637bd.zip
DIRECTOR: LINGO: Fix string constants, make constant pushing inline
Diffstat (limited to 'engines/director/lingo/lingo-bytecode.cpp')
-rw-r--r--engines/director/lingo/lingo-bytecode.cpp83
1 files changed, 69 insertions, 14 deletions
diff --git a/engines/director/lingo/lingo-bytecode.cpp b/engines/director/lingo/lingo-bytecode.cpp
index 735a877008..cd280b0f68 100644
--- a/engines/director/lingo/lingo-bytecode.cpp
+++ b/engines/director/lingo/lingo-bytecode.cpp
@@ -56,7 +56,7 @@ static LingoV4Bytecode lingoV4[] = {
{ 0x41, Lingo::c_intpush, "b" },
{ 0x42, Lingo::c_argcpush, "b" },
{ 0x43, Lingo::c_argcnoretpush, "b" },
- { 0x44, Lingo::c_constpush, "bv" },
+ // 0x44, push a constant
{ 0x45, Lingo::c_namepush, "b" },
{ 0x53, Lingo::c_jump, "jb" },
{ 0x54, Lingo::c_jump, "jbn" },
@@ -69,7 +69,7 @@ static LingoV4Bytecode lingoV4[] = {
{ 0x81, Lingo::c_intpush, "w" },
{ 0x82, Lingo::c_argcpush, "w" },
{ 0x83, Lingo::c_argcnoretpush, "w" },
- { 0x84, Lingo::c_constpush, "wv" },
+ // 0x84, push a constant
{ 0x93, Lingo::c_jump, "jw" },
{ 0x94, Lingo::c_jump, "jwn" },
{ 0x95, Lingo::c_jumpifz, "jw" },
@@ -449,13 +449,24 @@ void Lingo::addCodeV4(Common::SeekableSubReadStreamEndian &stream, ScriptType ty
constant.type = STRING;
constant.u.s = new Common::String();
uint32 pointer = value;
- while (pointer < constsStoreSize) {
+ if (pointer + 4 >= constsStoreSize) {
+ error("Constant string is too small");
+ break;
+ }
+ uint32 length = READ_BE_UINT32(&constsStore[pointer]);
+ pointer += 4;
+ uint32 end = pointer + length;
+ if (end >= constsStoreSize) {
+ error("Constant string is too large");
+ break;
+ }
+ while (pointer < end) {
if (constsStore[pointer] == '\r') {
- constant.u.s += '\n';
+ *constant.u.s += '\n';
} else if (constsStore[pointer] == '\0') {
break;
} else {
- constant.u.s += constsStore[pointer];
+ *constant.u.s += constsStore[pointer];
}
pointer += 1;
}
@@ -548,9 +559,60 @@ void Lingo::addCodeV4(Common::SeekableSubReadStreamEndian &stream, ScriptType ty
Common::Array<uint32> jumpList;
while (pointer < startOffset + length - codeStoreOffset) {
uint8 opcode = codeStore[pointer];
-
pointer += 1;
- if (_lingoV4.contains(opcode)) {
+
+ if (opcode == 0x44 || opcode == 0x84) {
+ // push a constant
+ offsetList.push_back(_currentScript->size());
+ int arg = 0;
+ if (opcode == 0x84) {
+ arg = (uint16)READ_BE_UINT16(&codeStore[pointer]);
+ pointer += 2;
+ } else {
+ arg = (uint8)codeStore[pointer];
+ pointer += 1;
+ }
+ // remove struct size alignment
+ if (arg % 6) {
+ warning("Opcode 0x%02x arg %d not a multiple of 6!", opcode, arg);
+ }
+ arg /= 6;
+ Datum constant = _currentScriptContext->constants[arg];
+ switch (constant.type) {
+ case INT:
+ g_lingo->code1(Lingo::c_intpush);
+ break;
+ case FLOAT:
+ g_lingo->code1(Lingo::c_floatpush);
+ break;
+ case STRING:
+ g_lingo->code1(Lingo::c_stringpush);
+ break;
+ default:
+ error("Unknown constant type %d", constant.type);
+ break;
+ }
+ if (opcode == 0x84) {
+ offsetList.push_back(_currentScript->size());
+ offsetList.push_back(_currentScript->size());
+ } else {
+ offsetList.push_back(_currentScript->size());
+ }
+ switch (constant.type) {
+ case INT:
+ g_lingo->codeInt(constant.u.i);
+ break;
+ case FLOAT:
+ g_lingo->codeFloat(constant.u.f);
+ break;
+ case STRING:
+ g_lingo->codeString(constant.u.s->c_str());
+ break;
+ default:
+ error("Unknown constant type %d", constant.type);
+ break;
+ }
+ } else if (_lingoV4.contains(opcode)) {
offsetList.push_back(_currentScript->size());
g_lingo->code1(_lingoV4[opcode]->func);
@@ -572,13 +634,6 @@ void Lingo::addCodeV4(Common::SeekableSubReadStreamEndian &stream, ScriptType ty
arg = (uint16)READ_BE_UINT16(&codeStore[pointer]);
pointer += 2;
break;
- case 'v':
- // argument refers to a variable; remove struct size alignment
- if (arg % 6) {
- warning("Opcode 0x%02x arg %d not a multiple of 6!", opcode, arg);
- }
- arg /= 6;
- break;
case 'n':
// argument is negative
arg *= -1;