From 8d4057366eafa09de1322827394018a648c58166 Mon Sep 17 00:00:00 2001 From: Alexander Batalov Date: Mon, 12 Jun 2023 08:13:31 +0300 Subject: [PATCH] Handle objects in opGetRotationToTile Fixes #302 --- src/interpreter_extra.cc | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/src/interpreter_extra.cc b/src/interpreter_extra.cc index b2d3295..0da70a2 100644 --- a/src/interpreter_extra.cc +++ b/src/interpreter_extra.cc @@ -4663,8 +4663,31 @@ static void opGetPartyMember(Program* program) // 0x45C6DC static void opGetRotationToTile(Program* program) { - int tile2 = programStackPopInteger(program); - int tile1 = programStackPopInteger(program); + // CE: There is a bug in Olympus (tgrdqest) - object is passed as one of the + // arguments instead of tile. Original game (x86) does not distinguish + // between integers and pointers, so one of the tiles is silently ignored + // while calculating rotation. As a workaround this opcode now accepts + // both integers and objects. + ProgramValue value2 = programStackPopValue(program); + ProgramValue value1 = programStackPopValue(program); + + int tile2; + if (value2.isInt()) { + tile2 = value2.integerValue; + } else if (value2.isPointer()) { + tile2 = static_cast(value2.pointerValue)->tile; + } else { + programFatalError("script error: %s: invalid arg 2 to rotation_to_tile", program->name); + } + + int tile1; + if (value1.isInt()) { + tile1 = value1.integerValue; + } else if (value1.isPointer()) { + tile1 = static_cast(value1.pointerValue)->tile; + } else { + programFatalError("script error: %s: invalid arg 1 to rotation_to_tile", program->name); + } int rotation = tileGetRotationTo(tile1, tile2); programStackPushInteger(program, rotation);