diff --git a/config/RSBE01_02/rels/sora_enemy/symbols.txt b/config/RSBE01_02/rels/sora_enemy/symbols.txt index 0dfb0be..9eabb0d 100644 --- a/config/RSBE01_02/rels/sora_enemy/symbols.txt +++ b/config/RSBE01_02/rels/sora_enemy/symbols.txt @@ -61,7 +61,7 @@ fn_41_3BE4 = .text:0x00003BE4; // type:function size:0x20 fn_41_3C04 = .text:0x00003C04; // type:function size:0xFC fn_41_3D00 = .text:0x00003D00; // type:function size:0x150 fn_41_3E50 = .text:0x00003E50; // type:function size:0xDC8 -isNull__10soNullableFv = .text:0x00004C18; // type:function size:0x8 +isNull__10soNullableCFv = .text:0x00004C18; // type:function size:0x8 fn_41_4C20 = .text:0x00004C20; // type:function size:0xF4 fn_41_4D14 = .text:0x00004D14; // type:function size:0x24 fn_41_4D38 = .text:0x00004D38; // type:function size:0x24 diff --git a/config/RSBE01_02/rels/sora_melee/symbols.txt b/config/RSBE01_02/rels/sora_melee/symbols.txt index 73c57f9..940ea0c 100644 --- a/config/RSBE01_02/rels/sora_melee/symbols.txt +++ b/config/RSBE01_02/rels/sora_melee/symbols.txt @@ -74,7 +74,7 @@ fn_27_581C = .text:0x0000581C; // type:function size:0x25C fn_27_5A78 = .text:0x00005A78; // type:function size:0x18C fn_27_5C04 = .text:0x00005C04; // type:function size:0xA0 fn_27_5CA4 = .text:0x00005CA4; // type:function size:0x28C -isNull__10soNullableFv = .text:0x00005F30; // type:function size:0x8 +isNull__10soNullableCFv = .text:0x00005F30; // type:function size:0x8 fn_27_5F38 = .text:0x00005F38; // type:function size:0x190 fn_27_60C8 = .text:0x000060C8; // type:function size:0x4 fn_27_60CC = .text:0x000060CC; // type:function size:0x4 diff --git a/config/RSBE01_02/splits.txt b/config/RSBE01_02/splits.txt index c24cd6b..0f0b6f4 100644 --- a/config/RSBE01_02/splits.txt +++ b/config/RSBE01_02/splits.txt @@ -20,6 +20,13 @@ sora/mt/mt_prng.cpp: .sbss start:0x805A00B8 end:0x805A00C0 .sdata2 start:0x805A1748 end:0x805A176C +sora/ac/ac_cmd_interpreter.cpp: + .text start:0x80139658 end:0x8013CA1C + .rodata start:0x80409520 end:0x8040964C + .data start:0x8045DD78 end:0x8045DDAC + .sdata start:0x8059E6D0 end:0x8059E6D8 + .sdata2 start:0x805A2AA8 end:0x805A2AC0 + Runtime.PPCEABI.H/__init_cpp_exceptions.cpp: .text start:0x803F1A08 end:0x803F1A78 .ctors start:0x804064E0 end:0x804064E4 rename:.ctors$10 diff --git a/config/RSBE01_02/symbols.txt b/config/RSBE01_02/symbols.txt index f6051bc..45d754d 100644 --- a/config/RSBE01_02/symbols.txt +++ b/config/RSBE01_02/symbols.txt @@ -5946,55 +5946,55 @@ fn_80138ED8 = .text:0x80138ED8; // type:function size:0x48 fn_80138F20 = .text:0x80138F20; // type:function size:0x300 fn_80139220 = .text:0x80139220; // type:function size:0x350 fn_80139570 = .text:0x80139570; // type:function size:0xE8 -fn_80139658 = .text:0x80139658; // type:function size:0x70 -fn_801396C8 = .text:0x801396C8; // type:function size:0x40 -fn_80139708 = .text:0x80139708; // type:function size:0x40 -fn_80139748 = .text:0x80139748; // type:function size:0x280 -fn_801399C8 = .text:0x801399C8; // type:function size:0x4 -fn_801399CC = .text:0x801399CC; // type:function size:0x2CC -fn_80139C98 = .text:0x80139C98; // type:function size:0x164 -fn_80139DFC = .text:0x80139DFC; // type:function size:0x34 -fn_80139E30 = .text:0x80139E30; // type:function size:0xD0 -fn_80139F00 = .text:0x80139F00; // type:function size:0x58 -fn_80139F58 = .text:0x80139F58; // type:function size:0x14 -fn_80139F6C = .text:0x80139F6C; // type:function size:0x168 -fn_8013A0D4 = .text:0x8013A0D4; // type:function size:0x8 -fn_8013A0DC = .text:0x8013A0DC; // type:function size:0x134 -fn_8013A210 = .text:0x8013A210; // type:function size:0x130 -fn_8013A340 = .text:0x8013A340; // type:function size:0x16C -fn_8013A4AC = .text:0x8013A4AC; // type:function size:0x74 -fn_8013A520 = .text:0x8013A520; // type:function size:0x8 -fn_8013A528 = .text:0x8013A528; // type:function size:0x68 -fn_8013A590 = .text:0x8013A590; // type:function size:0x10C -fn_8013A69C = .text:0x8013A69C; // type:function size:0x25C -fn_8013A8F8 = .text:0x8013A8F8; // type:function size:0x1C -fn_8013A914 = .text:0x8013A914; // type:function size:0x148 -fn_8013AA5C = .text:0x8013AA5C; // type:function size:0x1D4 -fn_8013AC30 = .text:0x8013AC30; // type:function size:0x428 -fn_8013B058 = .text:0x8013B058; // type:function size:0xC -fn_8013B064 = .text:0x8013B064; // type:function size:0x13C -fn_8013B1A0 = .text:0x8013B1A0; // type:function size:0xF0 -fn_8013B290 = .text:0x8013B290; // type:function size:0x13C -fn_8013B3CC = .text:0x8013B3CC; // type:function size:0x18C -fn_8013B558 = .text:0x8013B558; // type:function size:0xD8 -fn_8013B630 = .text:0x8013B630; // type:function size:0x154 -fn_8013B784 = .text:0x8013B784; // type:function size:0x128 -fn_8013B8AC = .text:0x8013B8AC; // type:function size:0x8 -fn_8013B8B4 = .text:0x8013B8B4; // type:function size:0x1E0 -fn_8013BA94 = .text:0x8013BA94; // type:function size:0x1BC -fn_8013BC50 = .text:0x8013BC50; // type:function size:0x1E0 -fn_8013BE30 = .text:0x8013BE30; // type:function size:0xAC -fn_8013BEDC = .text:0x8013BEDC; // type:function size:0xB0 -fn_8013BF8C = .text:0x8013BF8C; // type:function size:0xE0 -fn_8013C06C = .text:0x8013C06C; // type:function size:0x1E0 -fn_8013C24C = .text:0x8013C24C; // type:function size:0xAC -fn_8013C2F8 = .text:0x8013C2F8; // type:function size:0xB0 -fn_8013C3A8 = .text:0x8013C3A8; // type:function size:0xA0 -fn_8013C448 = .text:0x8013C448; // type:function size:0x12C -fn_8013C574 = .text:0x8013C574; // type:function size:0x144 -fn_8013C6B8 = .text:0x8013C6B8; // type:function size:0x128 -fn_8013C7E0 = .text:0x8013C7E0; // type:function size:0xE8 -fn_8013C8C8 = .text:0x8013C8C8; // type:function size:0x154 +__ct__16acCmdInterpreterFP44soArrayVector<25acCmdInterpreterStackData,8>lP13acAnimCmdConvPCUcf = .text:0x80139658; // type:function size:0x70 +__dt__13acAnimCmdImplFv = .text:0x801396C8; // type:function size:0x40 +__dt__16acCmdInterpreterFv = .text:0x80139708; // type:function size:0x40 +interpretCmd__16acCmdInterpreterFf = .text:0x80139748; // type:function size:0x280 +interpretNotSystemCmd__16acCmdInterpreterFv = .text:0x801399C8; // type:function size:0x4 +resetInterpreter__16acCmdInterpreterFfPC13acAnimCmdConv = .text:0x801399CC; // type:function size:0x2CC +isBreakInterpret__16acCmdInterpreterFv = .text:0x80139C98; // type:function size:0x164 +isSkipEnd__16acCmdInterpreterCFv = .text:0x80139DFC; // type:function size:0x34 +skipNextIfGroup__16acCmdInterpreterFb = .text:0x80139E30; // type:function size:0xD0 +popSystemStack__16acCmdInterpreterFv = .text:0x80139F00; // type:function size:0x58 +pushSystemStack__16acCmdInterpreterFRC25acCmdInterpreterStackData = .text:0x80139F58; // type:function size:0x14 +skipNextSwitchGroup__16acCmdInterpreterFb = .text:0x80139F6C; // type:function size:0x168 +isNull__10soNullableCFv = .text:0x8013A0D4; // type:function size:0x8 +skipNextNotSwitchGroup__16acCmdInterpreterFv = .text:0x8013A0DC; // type:function size:0x134 +skipNextLoopGroup__16acCmdInterpreterFv = .text:0x8013A210; // type:function size:0x130 +skipNextWhileGroup__16acCmdInterpreterFv = .text:0x8013A340; // type:function size:0x16C +getCurrentCmd__16acCmdInterpreterFv = .text:0x8013A4AC; // type:function size:0x74 +getCmdAddress__13acAnimCmdImplCFv = .text:0x8013A520; // type:function size:0x8 +getLastSystemStackData__16acCmdInterpreterFv = .text:0x8013A528; // type:function size:0x68 +dispatchCmdSwitch__16acCmdInterpreterCFPC9acAnimCmd = .text:0x8013A590; // type:function size:0x10C +skipCmd__16acCmdInterpreterFv = .text:0x8013A69C; // type:function size:0x25C +isSleepStackData__16acCmdInterpreterCFl = .text:0x8013A8F8; // type:function size:0x1C +systemCmdFuncWait__16acCmdInterpreterFv = .text:0x8013A914; // type:function size:0x148 +systemCmdFuncWaitSub__16acCmdInterpreterFf = .text:0x8013AA5C; // type:function size:0x1D4 +systemCmdFuncFrame__16acCmdInterpreterFv = .text:0x8013AC30; // type:function size:0x428 +systemCmdFuncFrameClr__16acCmdInterpreterFv = .text:0x8013B058; // type:function size:0xC +systemCmdFuncLoop__16acCmdInterpreterFv = .text:0x8013B064; // type:function size:0x13C +systemCmdFuncPool__16acCmdInterpreterFv = .text:0x8013B1A0; // type:function size:0xF0 +systemCmdFuncBreak__16acCmdInterpreterFv = .text:0x8013B290; // type:function size:0x13C +systemCmdFuncCall__16acCmdInterpreterFv = .text:0x8013B3CC; // type:function size:0x18C +systemCmdFuncJump__16acCmdInterpreterFv = .text:0x8013B558; // type:function size:0xD8 +systemCmdFuncReturn__16acCmdInterpreterFv = .text:0x8013B630; // type:function size:0x154 +systemCmdFuncIf__16acCmdInterpreterFv = .text:0x8013B784; // type:function size:0x128 +dispatchCmdIf__16acCmdInterpreterFPC9acAnimCmd = .text:0x8013B8AC; // type:function size:0x8 +systemCmdFuncIfAnd__16acCmdInterpreterFv = .text:0x8013B8B4; // type:function size:0x1E0 +systemCmdFuncIfOr__16acCmdInterpreterFv = .text:0x8013BA94; // type:function size:0x1BC +systemCmdFuncElsIf__16acCmdInterpreterFv = .text:0x8013BC50; // type:function size:0x1E0 +systemCmdFuncElse__16acCmdInterpreterFv = .text:0x8013BE30; // type:function size:0xAC +systemCmdFuncEndIf__16acCmdInterpreterFv = .text:0x8013BEDC; // type:function size:0xB0 +systemCmdFuncSwitch__16acCmdInterpreterFv = .text:0x8013BF8C; // type:function size:0xE0 +systemCmdFuncCase__16acCmdInterpreterFv = .text:0x8013C06C; // type:function size:0x1E0 +systemCmdFuncDefault__16acCmdInterpreterFv = .text:0x8013C24C; // type:function size:0xAC +systemCmdFuncEndSwitch__16acCmdInterpreterFv = .text:0x8013C2F8; // type:function size:0xB0 +systemCmdFuncBreakSwitch__16acCmdInterpreterFv = .text:0x8013C3A8; // type:function size:0xA0 +systemCmdFuncWhile__16acCmdInterpreterFv = .text:0x8013C448; // type:function size:0x12C +systemCmdFuncWhileAnd__16acCmdInterpreterFv = .text:0x8013C574; // type:function size:0x144 +systemCmdFuncWhileOr__16acCmdInterpreterFv = .text:0x8013C6B8; // type:function size:0x128 +systemCmdFuncEndWhile__16acCmdInterpreterFv = .text:0x8013C7E0; // type:function size:0xE8 +systemCmdFuncEnd__16acCmdInterpreterFv = .text:0x8013C8C8; // type:function size:0x154 fn_8013CA1C = .text:0x8013CA1C; // type:function size:0x10 fn_8013CA2C = .text:0x8013CA2C; // type:function size:0x10 fn_8013CA3C = .text:0x8013CA3C; // type:function size:0x20 @@ -16045,7 +16045,7 @@ fn_803F0B20 = .text:0x803F0B20; // type:function size:0xBC __construct_array = .text:0x803F0BDC; // type:function size:0xF8 __destroy_arr = .text:0x803F0CD4; // type:function size:0x78 fn_803F0D4C = .text:0x803F0D4C; // type:function size:0x80 -fn_803F0DCC = .text:0x803F0DCC; // type:function size:0x30 +__ptmf_test = .text:0x803F0DCC; // type:function size:0x30 fn_803F0DFC = .text:0x803F0DFC; // type:function size:0x3C __ptmf_scall = .text:0x803F0E38; // type:function size:0x28 fn_803F0E60 = .text:0x803F0E60; // type:function size:0x24 @@ -16560,8 +16560,8 @@ lbl_80409420 = .rodata:0x80409420; // type:object size:0xC8 data:4byte lbl_804094E8 = .rodata:0x804094E8; // type:object size:0x20 align:4 data:float lbl_80409508 = .rodata:0x80409508; // type:object size:0xC data:4byte lbl_80409514 = .rodata:0x80409514; // type:object size:0xC data:4byte -lbl_80409520 = .rodata:0x80409520; // type:object size:0x130 -lbl_80409650 = .rodata:0x80409650; // type:object size:0x10 +systemCmdFuncTable = .rodata:0x80409520; // type:object size:0x12C scope:local +lbl_80409650 = .rodata:0x80409650; // type:object size:0x10 align:8 lbl_80409660 = .rodata:0x80409660; // type:object size:0x100 lbl_80409760 = .rodata:0x80409760; // type:object size:0x10 lbl_80409770 = .rodata:0x80409770; // type:object size:0x14 data:4byte @@ -26061,14 +26061,14 @@ jumptable_8045DB98 = .data:0x8045DB98; // type:object size:0x20 scope:local lbl_8045DBB8 = .data:0x8045DBB8; // type:object size:0x184 lbl_8045DD3C = .data:0x8045DD3C; // type:object size:0x2C lbl_8045DD68 = .data:0x8045DD68; // type:object size:0x10 -lbl_8045DD78 = .data:0x8045DD78; // type:object size:0x20 -lbl_8045DD98 = .data:0x8045DD98; // type:object size:0x14 -lbl_8045DDAC = .data:0x8045DDAC; // type:object size:0xC +__vt__16acCmdInterpreter = .data:0x8045DD78; // type:object size:0x20 +lbl_8045DD98 = .data:0x8045DD98; // type:object size:0x14 data:string +lbl_8045DDAC = .data:0x8045DDAC; // type:object size:0xC align:4 lbl_8045DDB8 = .data:0x8045DDB8; // type:object size:0xC -lbl_8045DDC4 = .data:0x8045DDC4; // type:object size:0xC +__vt__10soNullable = .data:0x8045DDC4; // type:object size:0xC lbl_8045DDD0 = .data:0x8045DDD0; // type:object size:0xC lbl_8045DDDC = .data:0x8045DDDC; // type:object size:0x14 data:string -lbl_8045DDF0 = .data:0x8045DDF0; // type:object size:0x34 +__vt__13acAnimCmdImpl = .data:0x8045DDF0; // type:object size:0x34 lbl_8045DE24 = .data:0x8045DE24; // type:object size:0x10 lbl_8045DE34 = .data:0x8045DE34; // type:object size:0x14 lbl_8045DE48 = .data:0x8045DE48; // type:object size:0x30 @@ -29579,9 +29579,9 @@ lbl_8059E6B0 = .sdata:0x8059E6B0; // type:object size:0x8 data:string lbl_8059E6B8 = .sdata:0x8059E6B8; // type:object size:0x8 data:string lbl_8059E6C0 = .sdata:0x8059E6C0; // type:object size:0x8 data:string lbl_8059E6C8 = .sdata:0x8059E6C8; // type:object size:0x8 -lbl_8059E6D0 = .sdata:0x8059E6D0; // type:object size:0x8 +__RTTI__16acCmdInterpreter = .sdata:0x8059E6D0; // type:object size:0x8 lbl_8059E6D8 = .sdata:0x8059E6D8; // type:object size:0x8 -lbl_8059E6E0 = .sdata:0x8059E6E0; // type:object size:0x8 +__RTTI__10soNullable = .sdata:0x8059E6E0; // type:object size:0x8 lbl_8059E6E8 = .sdata:0x8059E6E8; // type:object size:0x8 lbl_8059E6F0 = .sdata:0x8059E6F0; // type:object size:0x8 lbl_8059E6F8 = .sdata:0x8059E6F8; // type:object size:0x8 @@ -30802,7 +30802,7 @@ lbl_805A0358 = .sbss:0x805A0358; // type:object size:0x8 data:byte lbl_805A0360 = .sbss:0x805A0360; // type:object size:0x8 data:4byte lbl_805A0368 = .sbss:0x805A0368; // type:object size:0x8 data:4byte lbl_805A0370 = .sbss:0x805A0370; // type:object size:0x8 data:4byte -lbl_805A0378 = .sbss:0x805A0378; // type:object size:0x8 data:4byte +g_acAnimCmdNull = .sbss:0x805A0378; // type:object size:0x8 data:4byte lbl_805A0380 = .sbss:0x805A0380; // type:object size:0x8 data:4byte lbl_805A0388 = .sbss:0x805A0388; // type:object size:0x8 data:4byte lbl_805A0390 = .sbss:0x805A0390; // type:object size:0x4 data:4byte diff --git a/configure.py b/configure.py index c75db6d..9fb5f73 100755 --- a/configure.py +++ b/configure.py @@ -287,6 +287,7 @@ def MatchingFor(*versions): "host": False, "objects": [ Object(Matching, "sora/mt/mt_prng.cpp", extra_cflags=["-RTTI off"]), + Object(NonMatching, "sora/ac/ac_cmd_interpreter.cpp"), ], }, # Common REL units diff --git a/include/lib/BrawlHeaders b/include/lib/BrawlHeaders index 603dd02..9a56bc6 160000 --- a/include/lib/BrawlHeaders +++ b/include/lib/BrawlHeaders @@ -1 +1 @@ -Subproject commit 603dd02e117af4ae22344d7517c946d4da4f76d5 +Subproject commit 9a56bc6caa23a234c7555c37016ded339ff3c2b1 diff --git a/src/sora/.gitkeep b/src/sora/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/src/sora/ac/ac_cmd_interpreter.cpp b/src/sora/ac/ac_cmd_interpreter.cpp new file mode 100644 index 0000000..4576708 --- /dev/null +++ b/src/sora/ac/ac_cmd_interpreter.cpp @@ -0,0 +1,969 @@ +#include +#include +#include +#include +#include +#include + +typedef void (acCmdInterpreter::*SystemCmdFunc)(void); + +const static SystemCmdFunc SystemCmdFuncTable[25] = { + &acCmdInterpreter::systemCmdFuncEnd, + &acCmdInterpreter::systemCmdFuncWait, + &acCmdInterpreter::systemCmdFuncFrame, + &acCmdInterpreter::systemCmdFuncFrameClr, + &acCmdInterpreter::systemCmdFuncLoop, + &acCmdInterpreter::systemCmdFuncPool, + &acCmdInterpreter::systemCmdFuncBreak, + &acCmdInterpreter::systemCmdFuncCall, + &acCmdInterpreter::systemCmdFuncReturn, + &acCmdInterpreter::systemCmdFuncJump, + &acCmdInterpreter::systemCmdFuncIf, + &acCmdInterpreter::systemCmdFuncIfAnd, + &acCmdInterpreter::systemCmdFuncIfOr, + &acCmdInterpreter::systemCmdFuncElsIf, + &acCmdInterpreter::systemCmdFuncElse, + &acCmdInterpreter::systemCmdFuncEndIf, + &acCmdInterpreter::systemCmdFuncSwitch, + &acCmdInterpreter::systemCmdFuncCase, + &acCmdInterpreter::systemCmdFuncDefault, + &acCmdInterpreter::systemCmdFuncEndSwitch, + &acCmdInterpreter::systemCmdFuncWhile, + &acCmdInterpreter::systemCmdFuncWhileAnd, + &acCmdInterpreter::systemCmdFuncWhileOr, + &acCmdInterpreter::systemCmdFuncEndWhile, + &acCmdInterpreter::systemCmdFuncBreakSwitch +}; + +acCmdInterpreter::acCmdInterpreter(soArrayVector* stk, + s32 mode, acAnimCmdConv* initCmd, const u8* resetMode, float fixedTimeStep) : + m_fixedTimeStep(fixedTimeStep), + m_lastTimeStep(-1.0f), + m_currentCmd(initCmd), + m_copyCurrentCmd(initCmd), + m_stack(stk), + m_currentFrame(0.0f), + unk28(-1.0f), + m_overshoot(0.0f), + m_interpretMode(mode), + unk30Field2(0), + m_dontAdvance(false), + unk32(0), + m_reset(*resetMode) { } + +acCmdInterpreter::~acCmdInterpreter() { } + +inline bool acCmdInterpreter::testCurrentCmd() const { + return m_currentCmd != 0; +} + +inline void acCmdInterpreter::advanceCurrentCmd() { + if (m_currentCmd) { + m_currentCmd++; + } +} + +inline const acAnimCmd* acCmdInterpreter::updateCurrentCmd() { + const acAnimCmdConv* currCmd = m_currentCmd; + if (m_animCmd.getCmdAddress() != currCmd) { + m_animCmd.m_isNull = false; + m_animCmd.cmdAddr = currCmd; + } + return &m_animCmd; +} + +inline s32 acCmdInterpreter::getIdxOfStackData(const acCmdInterpreterStackData::Kind kind) const { + for (s32 i = m_stack->size() - 1; i >= 0; i--) { + if (m_stack->at(static_cast(i))->kind == kind) { + return i; + } + } + return -1; +} + +// Pop the stack until its size is newSize +inline void acCmdInterpreter::popStackToSize(const s32 newSize) { + s32 size = m_stack->size(); + if (newSize >= 0 && newSize < size) { + if (newSize == size - 1) { + m_stack->pop(); + } else { + for (s32 i = 0; i < size - newSize; i++) { + m_stack->pop(); + } + } + } +} + +inline void acCmdInterpreter::interpretOneCmd() { + bool isNonSystemCmd; + SystemCmdFunc scf; + if (!m_currentCmd) { + isNonSystemCmd = true; + } else if (m_currentCmd->group >= 1) { + isNonSystemCmd = false; + } else if (m_currentCmd->type < 0 || m_currentCmd->type >= 25 || m_currentCmd->group < 0) { + isNonSystemCmd = true; + } else if (!(scf = SystemCmdFuncTable[m_currentCmd->type])) { + isNonSystemCmd = true; + } else { + (this->*scf)(); + isNonSystemCmd = true; + } + + if (!isNonSystemCmd) { + interpretNotSystemCmd(); + } + + if (m_dontAdvance == true) { + m_dontAdvance = false; + } else { + advanceCurrentCmd(); + } +} + +void acCmdInterpreter::interpretCmd(float timeStep) { + const acAnimCmdConv* cmd; + if (m_interpretMode > -1) { + unk30Field2 = 0; + if ((m_reset & 0x1) && 0 != (cmd = m_copyCurrentCmd)) { + m_currentCmd = m_copyCurrentCmd = cmd; + m_stack->clear(); + m_dontAdvance = false; + m_currentFrame = 0.0f; + m_overshoot = 0.0f; + } + if (m_currentCmd) { + if (m_interpretMode == 0) { + timeStep = m_fixedTimeStep; + } + if (timeStep < 0.0f) { + return; + } + m_lastTimeStep = timeStep; + if (unk32 == 1) { + unk32 = 0; + } else { + float f = m_currentFrame; + m_currentFrame = f + static_cast(static_cast(timeStep)); + } + acCmdInterpreterStackData* top = getLastSystemStackData(); + if (top && top->kind == acCmdInterpreterStackData::knd0) { // Wait + top->floatData -= m_lastTimeStep; + } + + // Execute the ACMD script + while (m_currentCmd && !isBreakInterpret()) { + interpretOneCmd(); + } + } + } +} + +void acCmdInterpreter::interpretNotSystemCmd() { + +} + +// Direct interpreter at new command provided +void acCmdInterpreter::resetInterpreter(float frame, const acAnimCmdConv *initCmd) { + m_currentCmd = m_copyCurrentCmd = initCmd; + m_stack->clear(); + m_dontAdvance = false; + const float zero = 0; + m_overshoot = m_currentFrame = 0; + if (frame > 0 && !(frame <= 0)) { + unk30Field2 = 2; + unk28 = frame; + m_currentFrame = zero + frame; + // NOTE: similar to skipCmd + if (m_interpretMode <= -1) { + ; + } else { + acCmdInterpreterStackData* top; + s32 size; + // TODO: check for inlined function + while (0 != (top = (size = m_stack->size(), + (size > 0) ? m_stack->at(static_cast(size - 1)) : 0))) { + if (!isSleepStackData(top->kind)) { + break; + } + popSystemStack(); + } + while (!isSkipEnd()) { + interpretOneCmd(); + } + + for (s32 i = m_stack->size() - 1; i >= 0; i--) { + if (m_stack->at(static_cast(i))->kind == acCmdInterpreterStackData::knd7) { + m_stack->erase(i); + } + } + } + unk28 = -1.0f; + } +} + +bool acCmdInterpreter::isBreakInterpret() { + if (!m_currentCmd) { + return true; + } + + acCmdInterpreterStackData* top = getLastSystemStackData(); + if (!top) { + return false; + } + + switch (top->kind) { + case acCmdInterpreterStackData::knd0: { // Wait + if (top->floatData <= 0.0f) { + // Done waiting + m_overshoot = -top->floatData; + popSystemStack(); + return false; + } else { + return true; + } + break; + } + case acCmdInterpreterStackData::Frame: { // Frame + float waitFrame = top->floatData; + if (m_currentFrame >= waitFrame) { + // Reached the desired frame + m_overshoot = m_currentFrame - waitFrame; + popSystemStack(); + return false; + } else { + return true; + } + break; + } + default: { + break; + } + } + return false; +} + +bool acCmdInterpreter::isSkipEnd() const { + if (unk30Field2 == 2) { + return unk28 < 0.0f; + } + return false; +} + +// Advance m_currentCmd until it is pointing at this if-block's EndIf command +void acCmdInterpreter::skipNextIfGroup(bool skippingIfBlock) { + if (!m_currentCmd) { + return; + } + + // Keep track of If nesting within the skipped block, so + // a nested EndIf is not confused with this if group's EndIf + s32 nestedIfBlocks = 0; + + while (true) { + if (m_currentCmd->group == 0) { // SystemCmd + s8 type = m_currentCmd->type; + if (type >= 0x19) { + return; + } + switch (type) { + case 0: { // End + m_dontAdvance = true; + return; + } + case 0xA: { // If + nestedIfBlocks++; + break; + } + case 0xB: case 0xC: { // IfAnd or IfOr + // Only care about IfAnd/IfOr commands if they follow the + // outermost If command... not if they appear in an ElsIf + if (skippingIfBlock && nestedIfBlocks <= 0) { + m_dontAdvance = true; + return; // need to evaluate the next AND/OR term + } + break; + } + case 0xF: { // EndIf + if (nestedIfBlocks > 0) { + nestedIfBlocks--; + break; + } + } + // FALL-THROUGH + case 0xD: case 0xE: { // ElsIf or Else + if (nestedIfBlocks <= 0) { + m_dontAdvance = true; + return; + } + } + } + } + advanceCurrentCmd(); + } + m_dontAdvance = true; +} + +void acCmdInterpreter::popSystemStack() { + if (!m_stack->isEmpty()) + m_stack->pop(); +} + +void acCmdInterpreter::pushSystemStack(const acCmdInterpreterStackData& stackData) { + m_stack->push(stackData); +} + +void acCmdInterpreter::skipNextSwitchGroup(bool doNotSkipCases) { + if (!testCurrentCmd()) { + return; + } + + s32 nestedSwitchBlocks = 0; + while (true) { + const acAnimCmd* currCmd = getCurrentCmd(); + if (!currCmd->isNull() && currCmd->getGroup() == 0) { + s8 type = currCmd->getType(); + if (type >= 0x19) { + return; + } + switch (type) { + case 0: { + m_dontAdvance = true; + return; + } + case 0x10: { + // Switch + nestedSwitchBlocks++; + break; + } + case 0x13: { + // EndSwitch + if (nestedSwitchBlocks > 0) { + nestedSwitchBlocks--; + } else { + m_dontAdvance = true; + return; + } + break; + } + case 0x11: case 0x12: { + // Case or Default + if (doNotSkipCases && nestedSwitchBlocks <= 0) { + m_dontAdvance = true; + return; + } + break; + } + default: { + break; + } + } + } + advanceCurrentCmd(); + } + m_dontAdvance = true; +} + +// Skip consecutive Case and Default commands +void acCmdInterpreter::skipNextNotSwitchGroup() { + if (!m_currentCmd) { + return; + } + + while (true) { + const acAnimCmd* currCmd = getCurrentCmd(); + if (currCmd->isNull() == true || currCmd->getGroup() != 0) { + m_dontAdvance = true; + return; + } + s8 type = currCmd->getType(); + if (type >= 25) { + return; + } + switch (type) { + case 0x10: + case 0: + case 0x13: + default: { + m_dontAdvance = true; + return; + } + case 0x11: case 0x12: { + // Case or Default + advanceCurrentCmd(); + break; + } + } + } +} + +// Skip to the end of this "Loop" block. +// Note that Pool marks the end of a Loop block. The command pointer, +// m_currentCmd, will be advanced to the command immediately +// following the matching Pool because m_dontAdvance is not set +void acCmdInterpreter::skipNextLoopGroup() { + if (!m_currentCmd) { + return; + } + + s32 nestedLoopBlocks = 0; + while (true) { + const acAnimCmd* currCmd = getCurrentCmd(); + if (!currCmd->isNull() && currCmd->getGroup() == 0) { + s8 type = currCmd->getType(); + if (type >= 0x19) { + return; + } + switch (type) { + case 0x5: { + if (nestedLoopBlocks > 0) { + nestedLoopBlocks--; + break; + } + return; + } + case 0x4: { + nestedLoopBlocks++; + } + } + } + advanceCurrentCmd(); + } +} + +void acCmdInterpreter::skipNextWhileGroup() { + if (!m_currentCmd) { + return; + } + + s32 nestedWhileBlocks = 0; + while (true) { + const acAnimCmd* currCmd = getCurrentCmd(); + if (!currCmd->isNull() && currCmd->getGroup() == 0) { + s8 type = currCmd->getType(); + if (type >= 0x19) + return; + switch (type) { + case 0: { + m_dontAdvance = true; + return; + } + case 0x14: { + // While + nestedWhileBlocks++; + break; + } + case 0x15: case 0x16: { + if (nestedWhileBlocks <= 0) { + m_dontAdvance = true; + return; + } + break; + } + case 0x17: { + // EndWhile + if (nestedWhileBlocks > 0) { + nestedWhileBlocks--; + break; + } else { + m_dontAdvance = true; + return; + } + } + } + } + advanceCurrentCmd(); + } +} + +const acAnimCmd* acCmdInterpreter::getCurrentCmd() { + if (!testCurrentCmd()) { + return &g_acAnimCmdNull; + } + return updateCurrentCmd(); +} + +acCmdInterpreterStackData* acCmdInterpreter::getLastSystemStackData() { + s32 size = m_stack->size(); + return (size <= 0) ? 0 : m_stack->at(static_cast(size - 1)); +} + +s32 acCmdInterpreter::dispatchCmdSwitch(const acAnimCmd* cmd) const { + acCmdArg firstArg; + if (!cmd->getArg(&firstArg, 0) || firstArg.getArgType() != 0) { + return 0; + } + + switch (firstArg.getIntData()) { + default: { + break; + } + case 0: { + acCmdArg secondArg; + if (cmd->getArg(&secondArg, 1) == true || !secondArg.isNull()) { + return randi(secondArg.getIntData()); + } + break; + } + } + return 0; +} + +void acCmdInterpreter::skipCmd() { + if (m_interpretMode <= -1) { + return; + } else { + acCmdInterpreterStackData* top; + s32 size; + while (0 != (top = (size = m_stack->size(), + (size > 0) ? m_stack->at(static_cast(size - 1)) : 0))) { + if (!isSleepStackData(top->kind)) { + break; + } + popSystemStack(); + } + while (!isSkipEnd()) { + interpretOneCmd(); + } + + for (s32 i = m_stack->size() - 1; i >= 0; i--) { + if (m_stack->at(static_cast(i))->kind == acCmdInterpreterStackData::knd7) { + m_stack->erase(i); + } + } + } +} + +bool acCmdInterpreter::isSleepStackData(s32 kind) const { + return kind == acCmdInterpreterStackData::knd0 || kind == acCmdInterpreterStackData::Frame; +} + +void acCmdInterpreter::systemCmdFuncWait() { + if (testCurrentCmd()) { + const acAnimCmd* currCmd = getCurrentCmd(); + float waitTime = 0.0f; + if (currCmd->getArgNum() > 0) { + acCmdArg arg; + if (!currCmd->getArg(&arg, 0) || arg.getArgType() != 1) { + return; + } + waitTime = arg.getFloatData(); + } + systemCmdFuncWaitSub(waitTime); + } +} + +void acCmdInterpreter::systemCmdFuncWaitSub(float waitTime) { + float f31 = waitTime; + s32 r0 = unk30Field2; + if (r0 == 2 && unk28 >= 0.0f) { + s32 i = getIdxOfStackData(acCmdInterpreterStackData::knd7); + float f2 = 0.0f; + if (i >= 0) { + f2 = m_stack->at(static_cast(i))->floatData; + float diff = (m_currentFrame - unk28); + f2 -= diff; + if (f2 < 0.0f) { + f2 = 0.0f; + } + } + f2 = unk28 - waitTime - f2; + if (f2 >= 0.0f) { + unk28 = f2; + return; + } + unk28 = -1.0f; + acCmdInterpreterStackData data(acCmdInterpreterStackData::knd0, 0, false, 0, -f2); + pushSystemStack(data); + } else if (r0 == 0) { + if (m_overshoot > 0.0f) { + f31 = waitTime - m_overshoot; + if (f31 <= 0.0f) { + m_overshoot = -f31; + return; + } else { + m_overshoot = 0.0f; + } + } + // Push the wait time onto the stack: + // if m_overshoot <= 0: push waitTime + // if m_overshoot > 0 and waitTime > m_overshoot, push waitTime-m_overshoot + // if m_overshoot > 0 and waitTime <= m_overshoot, don't push anything + acCmdInterpreterStackData data(acCmdInterpreterStackData::knd0, 0, false, 0, f31); + pushSystemStack(data); + } +} + +void acCmdInterpreter::systemCmdFuncFrame() { + const acAnimCmd* currCmd = getCurrentCmd(); + if (currCmd->isArgEmpty() != true) { + acCmdArg arg; + if (!currCmd->getArg(&arg, 0) || arg.getArgType() != 1) { + return; + } + s32 r0 = unk30Field2; + if (r0 == 2) { + if (arg.getFloatData() <= m_currentFrame) { + s32 i = getIdxOfStackData(acCmdInterpreterStackData::knd7); + if (i < 0) { + // No element, so push one onto the stack + acCmdInterpreterStackData data(acCmdInterpreterStackData::knd7, 0, false, 0, arg.getFloatData()); + pushSystemStack(data); + } else { + // update the pre-existing stack element with + // the argument of the Frame command if it is greater than + // the frame already on the stack + acCmdInterpreterStackData *stackPtr = m_stack->at(static_cast(i)); + float f0 = arg.getFloatData(); + float f1 = stackPtr->floatData; + if (f1 < f0) { + stackPtr->floatData = arg.getFloatData(); + } + } + } else { + unk28 = -1.0f; + acCmdInterpreterStackData data(acCmdInterpreterStackData::Frame, 0, false, 0, arg.getFloatData()); + pushSystemStack(data); + } + } else if (r0 == 0) { + if (arg.getFloatData() <= m_currentFrame) { + m_overshoot = m_currentFrame - arg.getFloatData(); + } else { + acCmdInterpreterStackData data(acCmdInterpreterStackData::Frame, 0, false, 0, arg.getFloatData()); + pushSystemStack(data); + m_overshoot = 0.0f; + } + } + } +} + +void acCmdInterpreter::systemCmdFuncFrameClr() { + m_currentFrame = 0.0f; +} + +void acCmdInterpreter::systemCmdFuncLoop() { + const acAnimCmd* currCmd = getCurrentCmd(); + if (currCmd->isArgEmpty() != 1u) { + acCmdArg arg; + if (!currCmd->getArg(&arg, 0) || arg.getArgType() != 0) { + return; + } + // Push loop count and start label + acCmdInterpreterStackData stackData(acCmdInterpreterStackData::Loop, arg.getIntData(), false, m_currentCmd, 0.0f); + pushSystemStack(stackData); + } +} + + +void acCmdInterpreter::systemCmdFuncPool() { + acCmdInterpreterStackData* top = getLastSystemStackData(); + if (!top || top->kind != acCmdInterpreterStackData::Loop) { + return; + } + + if (top->intData < 0) { + if (top->addressData) { + m_currentCmd = top->addressData; + } + return; + } + + if (--top->intData > 0) { + if (top->addressData) { + m_currentCmd = top->addressData; + } + return; + } + + popSystemStack(); +} + +void acCmdInterpreter::systemCmdFuncBreak() { + s32 i = getIdxOfStackData(acCmdInterpreterStackData::Loop); + + if (i >= 0) { + m_stack->at(static_cast(i)); // no effect + advanceCurrentCmd(); + skipNextLoopGroup(); + popStackToSize(i); + } +} + +void acCmdInterpreter::systemCmdFuncCall() { + const acAnimCmdConv* currCmdAddr = getCurrentCmd()->getCmdAddress(); + acCmdArg arg; + bool isCallValid; + if (!getCurrentCmd()->getArg(&arg, 0)) { + isCallValid = false; + } else { + void* callAddr = arg.getAddressData(); + if (!callAddr) { + isCallValid = false; + } else { + if (callAddr) { + m_currentCmd = (const acAnimCmdConv*) callAddr; + } + m_dontAdvance = true; + isCallValid = true; + } + } + + if (isCallValid == true) { + acCmdInterpreterStackData stackData(acCmdInterpreterStackData::ReturnAddress, 0, false, currCmdAddr, 0.0f); + pushSystemStack(stackData); + } +} + +void acCmdInterpreter::systemCmdFuncJump() { + acCmdArg arg; + if (getCurrentCmd()->getArg(&arg, 0)) { + void* jumpAddr = arg.getAddressData(); + if (jumpAddr) { + if (jumpAddr) { + m_currentCmd = (const acAnimCmdConv*) jumpAddr; + } + m_dontAdvance = true; + } + } +} + +// Note: Equivalent to systemCmdFuncEnd, but generates slightly different asm +// NONMATCHING: r30/r31 regswap +void acCmdInterpreter::systemCmdFuncReturn() { + const s32 i = getIdxOfStackData(acCmdInterpreterStackData::ReturnAddress); + if (i < 0) { + m_currentCmd = 0; + m_stack->clear(); + m_dontAdvance = false; + } else { + const acAnimCmdConv* returnAddr = m_stack->at(static_cast(i))->addressData; + if (returnAddr) { + m_currentCmd = returnAddr; + } + popStackToSize(i); + } +} + +void acCmdInterpreter::systemCmdFuncIf() { + if (dispatchCmdIf(getCurrentCmd()) == true) { + acCmdInterpreterStackData stackData(acCmdInterpreterStackData::IfCondition, 0, true, 0, 0.0f); + pushSystemStack(stackData); + } else { + acCmdInterpreterStackData stackData(acCmdInterpreterStackData::IfCondition, 0, false, 0, 0.0f); + pushSystemStack(stackData); + advanceCurrentCmd(); + skipNextIfGroup(true); + } +} + +void acCmdInterpreter::systemCmdFuncIfAnd() { + acCmdInterpreterStackData* top = getLastSystemStackData(); + if (!top || top->kind != acCmdInterpreterStackData::IfCondition) { + return; + } + if (top->boolData == true) { + if (!m_stack->isEmpty()) { + m_stack->pop(); + } + // equivalent to if (2nd operand) + systemCmdFuncIf(); + } else { + // short-circuit + advanceCurrentCmd(); + skipNextIfGroup(true); + } +} + +void acCmdInterpreter::systemCmdFuncIfOr() { + acCmdInterpreterStackData* top = getLastSystemStackData(); + if (!top || top->kind != acCmdInterpreterStackData::IfCondition) { + return; + } + if (top->boolData != true) { + // 1st term is false + if (!m_stack->isEmpty()) { + m_stack->pop(); + } + systemCmdFuncIf(); + } +} + +void acCmdInterpreter::systemCmdFuncElsIf() { + acCmdInterpreterStackData* top = getLastSystemStackData(); + if (!top || top->kind != acCmdInterpreterStackData::IfCondition) { + return; + } + if (top->boolData == true) { + // 'if' clause evaluated to true -> skip block + advanceCurrentCmd(); + skipNextIfGroup(false); + } else { // proceed as normal if statement + if (!m_stack->isEmpty()) { + m_stack->pop(); + } + systemCmdFuncIf(); + } +} + +void acCmdInterpreter::systemCmdFuncElse() { + acCmdInterpreterStackData* top = getLastSystemStackData(); + if (!top || top->kind != acCmdInterpreterStackData::IfCondition) { + return; + } + if (top->boolData == true) { + advanceCurrentCmd(); + skipNextIfGroup(false); + } +} + +void acCmdInterpreter::systemCmdFuncEndIf() { + acCmdInterpreterStackData* top = getLastSystemStackData(); + if (!top || top->kind != acCmdInterpreterStackData::IfCondition) { + return; + } + if (!m_stack->isEmpty()) { + m_stack->pop(); + } +} + +void acCmdInterpreter::systemCmdFuncSwitch() { + const acAnimCmd* currCmd = getCurrentCmd(); + if (currCmd->isArgEmpty() != 1u) { + s32 result = dispatchCmdSwitch(currCmd); + acCmdInterpreterStackData data(acCmdInterpreterStackData::Switch, result, false, 0, 0.0f); + pushSystemStack(data); + } +} + +void acCmdInterpreter::systemCmdFuncCase() { + acCmdInterpreterStackData* top = getLastSystemStackData(); + if (!top || top->kind != acCmdInterpreterStackData::Switch) { + return; + } + const acAnimCmd* currCmd = getCurrentCmd(); + if (currCmd->isArgEmpty() == true) { + advanceCurrentCmd(); + skipNextSwitchGroup(true); + } else { + acCmdArg arg; + if (!currCmd->getArg(&arg, 0)) { + advanceCurrentCmd(); + skipNextSwitchGroup(true); + } else if (top->intData == arg.getIntData()) { + top->boolData = true; + advanceCurrentCmd(); + skipNextNotSwitchGroup(); + } else { + advanceCurrentCmd(); + skipNextSwitchGroup(true); + } + } +} + +void acCmdInterpreter::systemCmdFuncDefault() { + acCmdInterpreterStackData* top = getLastSystemStackData(); + if (!top || top->kind != acCmdInterpreterStackData::Switch) { + return; + } + if (top->boolData == true) { + advanceCurrentCmd(); + skipNextSwitchGroup(true); + } +} + +void acCmdInterpreter::systemCmdFuncEndSwitch() { + acCmdInterpreterStackData* top = getLastSystemStackData(); + if (!top || top->kind != acCmdInterpreterStackData::Switch) { + return; + } + if (!m_stack->isEmpty()) { + m_stack->pop(); + } +} + +void acCmdInterpreter::systemCmdFuncBreakSwitch() { + acCmdInterpreterStackData* top = getLastSystemStackData(); + if (!top || top->kind != acCmdInterpreterStackData::Switch) { + return; + } + advanceCurrentCmd(); + skipNextSwitchGroup(false); +} + +void acCmdInterpreter::systemCmdFuncWhile() { + if (dispatchCmdIf(getCurrentCmd()) == true) { + acCmdInterpreterStackData data(acCmdInterpreterStackData::While, 0, true, m_currentCmd, 0.0f); + pushSystemStack(data); + } else { + acCmdInterpreterStackData data(acCmdInterpreterStackData::While, 0, false, m_currentCmd, 0.0f); + pushSystemStack(data); + advanceCurrentCmd(); + skipNextWhileGroup(); + } +} + +void acCmdInterpreter::systemCmdFuncWhileAnd() { + acCmdInterpreterStackData* top = getLastSystemStackData(); + if (!top || top->kind != acCmdInterpreterStackData::While) { + return; + } + if (top->boolData == true) { + if (dispatchCmdIf(getCurrentCmd()) != true) { + // skip body, and do not jump back + top->boolData = false; + advanceCurrentCmd(); + skipNextWhileGroup(); + } + } else { + advanceCurrentCmd(); + skipNextWhileGroup(); + } +} + +void acCmdInterpreter::systemCmdFuncWhileOr() { + acCmdInterpreterStackData* top = getLastSystemStackData(); + if (!top || top->kind != acCmdInterpreterStackData::While) { + return; + } + if (top->boolData != true) { + if (dispatchCmdIf(getCurrentCmd()) == true) { + top->boolData = true; + } else { + advanceCurrentCmd(); + skipNextWhileGroup(); + } + } +} + +void acCmdInterpreter::systemCmdFuncEndWhile() { + acCmdInterpreterStackData* top = getLastSystemStackData(); + if (!top || top->kind != acCmdInterpreterStackData::While) { + return; + } + const acAnimCmdConv* jumpAddr = top->addressData; + if (!m_stack->isEmpty()) { + m_stack->pop(); + } + if (top->boolData == true) { + if (jumpAddr) { + m_currentCmd = jumpAddr; + } + m_dontAdvance = true; + } +} + +void acCmdInterpreter::systemCmdFuncEnd() { + const s32 i = getIdxOfStackData(acCmdInterpreterStackData::ReturnAddress); + if (i < 0) { + m_currentCmd = 0; + m_stack->clear(); + m_dontAdvance = false; + } else { + const acAnimCmdConv* returnAddr = m_stack->at(static_cast(i))->addressData; + if (returnAddr) { + m_currentCmd = returnAddr; + } + popStackToSize(i); + } +}