From 07dab293adaedb826435f0fc9c622f0280c45aea Mon Sep 17 00:00:00 2001 From: nmlgc Date: Sat, 9 May 2020 12:11:03 +0200 Subject: [PATCH] [Decompilation] [th01] Input declarations shared between REIIDEN and FUUIN Of which we can express precisely *nothing* as an inline function, because Turbo C++ always emits a useless `JMP SHORT $+2` at the end of such an inlined function if it contains nested `if` statements. This is also what forced some of the functions in 90252cc to be expressed as macros. By now, this is clear enough to be documented separately. And to warrant this separate commit. Completes P0090, funded by Yanga. --- Research/Borland C++ decompilation.md | 2 + th01/hardware/input.hpp | 75 +++++++++++++++++++++++++++ 2 files changed, 77 insertions(+) diff --git a/Research/Borland C++ decompilation.md b/Research/Borland C++ decompilation.md index 466b4e11..c80ff860 100644 --- a/Research/Borland C++ decompilation.md +++ b/Research/Borland C++ decompilation.md @@ -118,6 +118,8 @@ inline optimally though: * Assignments to a pointer in `SI` – that pointer is moved to `DI`, [clobbering that register](#clobbering-di). Try a [class method](#C++) instead. +* Nested `if` statements – inlining will always generate a useless + `JMP SHORT $+2` at the end of the last branch. ## Initialization diff --git a/th01/hardware/input.hpp b/th01/hardware/input.hpp index c4e7fd36..e5270368 100644 --- a/th01/hardware/input.hpp +++ b/th01/hardware/input.hpp @@ -3,3 +3,78 @@ extern unsigned char input_shot; extern bool input_ok; #define input_func_bool(var) { var = true; } else { var = false; } + +// REIIDEN.EXE and FUUIN.EXE +// ------------------------- +// [input_lr] flags… hey, at least two inputs merged into a single variable. +// It's a start. +#define INPUT_RIGHT 0x01 +#define INPUT_LEFT 0x02 + +extern bool input_up; +extern bool input_down; +extern unsigned char input_lr; +extern bool input_strike; +extern bool input_mem_enter; +extern bool input_mem_leave; +extern unsigned char paused; +extern bool done; +extern bool input_bomb; + +#define input_func_flag(var, flag) { var |= flag; } else { var &= ~flag; } + +#define input_onchange(prev_slot, cur_sensed, if_pressed) \ + if(input_prev[prev_slot] != (cur_sensed)) { \ + if(cur_sensed) if_pressed \ + } \ + input_prev[prev_slot] = (cur_sensed); + +#define input_onchange_bool(prev_slot, var, cur_sensed) \ + input_onchange(prev_slot, cur_sensed, input_func_bool(var)) + +#define input_onchange_flag(prev_slot, var, flag, cur_sensed) \ + input_onchange(prev_slot, cur_sensed, input_func_flag(var, flag)) + +#define input_onchange_2( \ + prev_slot_1, prev_slot_2, cur_sensed_1, cur_sensed_2, if_pressed \ +) \ + if( \ + input_prev[prev_slot_1] != (cur_sensed_1) || \ + input_prev[prev_slot_2] != (cur_sensed_2) \ + ) { \ + if(cur_sensed_1 || (cur_sensed_2)) if_pressed \ + } \ + input_prev[prev_slot_1] = (cur_sensed_1); \ + input_prev[prev_slot_2] = (cur_sensed_2); + +#define input_onchange_bool_2( \ + prev_slot_1, prev_slot_2, var, cur_sensed_1, cur_sensed_2 \ +) \ + input_onchange_2(prev_slot_1, prev_slot_2, \ + cur_sensed_1, cur_sensed_2, input_func_bool(var) \ + ) + +#define input_onchange_flag_2( \ + prev_slot_1, prev_slot_2, var, flag, cur_sensed_1, cur_sensed_2 \ +) \ + input_onchange_2(prev_slot_1, prev_slot_2, \ + cur_sensed_1, cur_sensed_2, input_func_flag(var, flag) \ + ) + +#define input_pause_ok_sense(prev_slot_esc, prev_slot_ok, group0, group3) \ + group0 = key_sense(0); \ + group3 = key_sense(3); \ + group0 |= key_sense(0); \ + group3 |= key_sense(3); \ + input_onchange(prev_slot_esc, (group0 & K0_ESC), { \ + paused = (1 - paused); \ + }) \ + input_onchange(prev_slot_ok, (group3 & K3_RETURN), { \ + if((paused == true) && (input_shot == true)) { \ + done = true; \ + } \ + input_ok = true; \ + } else { \ + input_ok = false; \ + }); +// -------------------------