From e943f8c291d1089b095082b3d684ab6e14c637bd Mon Sep 17 00:00:00 2001 From: Scott Percival Date: Sun, 22 Dec 2019 22:10:38 +0800 Subject: DIRECTOR: LINGO: Fix string constants, make constant pushing inline --- engines/director/lingo/lingo-bytecode.cpp | 83 +++++++++++++++++++++++++------ engines/director/lingo/lingo-code.cpp | 8 --- engines/director/lingo/lingo.h | 1 - 3 files changed, 69 insertions(+), 23 deletions(-) (limited to 'engines') 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 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; diff --git a/engines/director/lingo/lingo-code.cpp b/engines/director/lingo/lingo-code.cpp index 2157f3e190..13e825724e 100644 --- a/engines/director/lingo/lingo-code.cpp +++ b/engines/director/lingo/lingo-code.cpp @@ -66,7 +66,6 @@ static struct FuncDescr { { Lingo::c_floatpush, "c_floatpush", "f" }, { Lingo::c_stringpush, "c_stringpush", "s" }, { Lingo::c_symbolpush, "c_symbolpush", "s" }, // D3 - { Lingo::c_constpush, "c_constpush", "i" }, { Lingo::c_namepush, "c_namepush", "i" }, { Lingo::c_varpush, "c_varpush", "s" }, { Lingo::c_setImmediate,"c_setImmediate","i" }, @@ -250,13 +249,6 @@ void Lingo::c_symbolpush() { g_lingo->push(Datum(new Common::String(s))); } -void Lingo::c_constpush() { - Datum d; - int i = g_lingo->readInt(); - d = g_lingo->_currentScriptContext->constants[i]; - g_lingo->push(d); -} - void Lingo::c_namepush() { Datum d; int i = g_lingo->readInt(); diff --git a/engines/director/lingo/lingo.h b/engines/director/lingo/lingo.h index ff294c25a0..26d49176e3 100644 --- a/engines/director/lingo/lingo.h +++ b/engines/director/lingo/lingo.h @@ -295,7 +295,6 @@ public: static void c_floatpush(); static void c_stringpush(); static void c_symbolpush(); - static void c_constpush(); static void c_namepush(); static void c_varpush(); static void c_argcpush(); -- cgit v1.2.3