From 51de73bcc93d2ff9d5413d28e4369df65d3241c4 Mon Sep 17 00:00:00 2001 From: nmlgc Date: Tue, 9 Jun 2020 20:39:44 +0200 Subject: [PATCH] [Decompilation] [th01] Orb physics MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit "Physics". Not only did ZUN restrict the X velocity to the 5 discrete states of -8, -4, 0, 4, and 8 (because hey, unaligned blitting is slow anyway?), but gravity is also only applied every 5 frames. We're still missing quite a bit of usage code, but these are the core functions. One of which turned out to be undecompilable, due to… a rigorously defined instruction order when performing arithmetic between `double`s and `float`s?! Still, spelling out all this stuff in ASM seems much better than somehow splitting the data segment, just so that we can immediately use literals there. Part of P0097, funded by Ember2528. --- Makefile.mak | 2 +- Research/Borland C++ decompilation.md | 35 ++- th01/main/player/orb.cpp | 134 +++++++++ th01/main/player/orb.hpp | 42 +++ th01/main/player/orb[bss].asm | 3 +- th01/main/player/orb[data].asm | 14 + th01/main_01.cpp | 2 +- th01/main_01_.cpp | 13 + th01_reiiden.asm | 395 ++++++-------------------- 9 files changed, 334 insertions(+), 306 deletions(-) create mode 100644 th01/main/player/orb.cpp create mode 100644 th01/main/player/orb[data].asm create mode 100644 th01/main_01_.cpp diff --git a/Makefile.mak b/Makefile.mak index 04dd1d92..e96d87e0 100644 --- a/Makefile.mak +++ b/Makefile.mak @@ -59,7 +59,7 @@ bin\th01\op.exe: bin\piloadc.obj bin\th01\op.obj th01\op_01.cpp th01\op_02.c th0 $** | -bin\th01\reiiden.exe: bin\piloadc.obj bin\th01\reiiden.obj th01\main_01.cpp th01\main_02.c th01\main_03.c th01\main_04.c th01\main_05.c th01\main_06.cpp th01\main_07.cpp th01\main_08.cpp th01\main_12.c th01\main_13.cpp th01\main_13_.cpp th01\main_14.c th01\main_16.c th01\main_19.cpp th01\main_25.cpp th01\main_27.cpp th01\main_38.cpp +bin\th01\reiiden.exe: bin\piloadc.obj bin\th01\reiiden.obj th01\main_01.cpp th01\main_01_.cpp th01\main_02.c th01\main_03.c th01\main_04.c th01\main_05.c th01\main_06.cpp th01\main_07.cpp th01\main_08.cpp th01\main_12.c th01\main_13.cpp th01\main_13_.cpp th01\main_14.c th01\main_16.c th01\main_19.cpp th01\main_25.cpp th01\main_27.cpp th01\main_38.cpp $(CC) $(CFLAGS) -ml -3 -DGAME=1 -DBINARY='M' -nbin\th01\ -eREIIDEN.EXE @&&| $** | diff --git a/Research/Borland C++ decompilation.md b/Research/Borland C++ decompilation.md index da6541cb..b108f4e4 100644 --- a/Research/Borland C++ decompilation.md +++ b/Research/Borland C++ decompilation.md @@ -33,7 +33,7 @@ where the scalar-type variable is declared in relation to them. | `MOV al, var`
`MOV ah, 0`| `var` is *unsigned char* | | `MOV al, var`
`CBW` | `var` is *char*, `AX` is *int* | -## Arithmetic +## Integer arithmetic | | | |-|-| @@ -55,6 +55,39 @@ must be spelled out to silence the `Possibly incorrect assignment` warning. `SUB` means that `??` is unsigned. Might require suffixing `imm` with `u` in case it's part of an arithmetic expression that was promoted to `int`. +## Floating-point arithmetic + +* Since the x87 FPU can only load from memory, all temporary results of + arithmetic are spilled to one single compiler-generated variable (`fpu_tmp`) + on the stack, which is reused across all of the function: + + | | | + |-|-| + | `MOV  AX, myint`
`INC  AX`
`MOV  fpu_tmp, ax`
`FILD fpu_tmp`
`FSTP ret` | `float ret = (myint + 1)` | + +* The same `fpu_tmp` variable is also used as the destination for `FNSTSW`, + used in comparisons. + +* Performing arithmetic or comparisons between `float` and `double` variables + *always* `FLD`s the `float` first, before emitting the corresponding FPU + instruction for the `double`, regardless of how the variables are placed in + the expression. The instruction order only matches the expression order for + literals: + + ```c++ + char ret; + float f; + double d; + + ret = (f > d); // FLD f, FCOMP d + ret = (d > f); // FLD f, FCOMP d + + ret = (d > 3.14f); // FLD d, FCOMP 3.14f + ret = (3.14f > d); // FLD 3.14f, FCOMP d + ret = (f > 3.14); // FLD f, FCOMP 3.14 + 4 + ret = (3.14 > f); // FLD 3.14, FCOMP f + 4 + ``` + ## `switch` statements * Sequence of the individual cases is identical in both C and ASM diff --git a/th01/main/player/orb.cpp b/th01/main/player/orb.cpp new file mode 100644 index 00000000..57ab7d5c --- /dev/null +++ b/th01/main/player/orb.cpp @@ -0,0 +1,134 @@ +#include "th01/main/playfld.hpp" +#include "th01/main/player/orb.hpp" + +extern const double ORB_VELOCITY_Y_MIN; +extern const float ORB_VELOCITY_Y_MAX; +extern const double ORB_COEFFICIENT_OF_RESTITUTION; + +inline double gravity_for(const double& force) +{ + return ((orb_force_frame / 5) + orb_force); +} +/// Temporary data segment workarounds +/// ---------------------------------- +// Also needs to be spelled out in ASM to avoid the unwanted WAIT instruction +// afterwards. +#define GRAVITY_FOR(force) \ + _AX = orb_force_frame / 5; \ + asm mov [bp-2], ax; \ + asm fild word ptr [bp-2]; \ + asm fadd force; + +// Neither WAIT nor FWAIT emit the emulated WAIT we want... +#define FWAIT db 0xCD, 0x3D; +/// ---------------------------------- + +int orb_velocity_y_update(void) +{ + /* TODO: Proper decompilation, once data can be emitted here: + * ---------------------------------------------------------- + orb_velocity_y = gravity_for(orb_force); + if(orb_velocity_y > ORB_VELOCITY_Y_MAX) { + orb_velocity_y = ORB_VELOCITY_Y_MAX; + } else if(orb_velocity_y < ORB_VELOCITY_Y_MIN) { + orb_velocity_y = ORB_VELOCITY_Y_MIN; + } + return gravity_for(orb_force); + * ---------------------------------------------------------- + * Performing arithmetic or comparisons between a double (orb_velocity_y) + * and a float (ORB_VELOCITY_Y_MAX) variable always FLDs the float first, + * before emitting the corresponding FPU instruction with the double, + * which is not what we want here. + */ + GRAVITY_FOR(orb_force); + asm { + fstp orb_velocity_y; + fld orb_velocity_y; + fcomp ORB_VELOCITY_Y_MAX; + fstsw [bp-2]; + FWAIT; + mov ax, [bp-2]; + sahf; + jbe min_velocity_check; + fld ORB_VELOCITY_Y_MAX; + } + goto set_velocity; +min_velocity_check: + if(orb_velocity_y < ORB_VELOCITY_Y_MIN) asm { + fld ORB_VELOCITY_Y_MIN; +set_velocity: + fstp orb_velocity_y; + FWAIT; + } + return gravity_for(orb_force); +} + +#define random_velocity_change(val, new_velocity) \ + if(orb_force_frame < 17) { \ + if((rand() % 50) == val) { \ + orb_velocity_x = new_velocity; \ + } \ + } + +void orb_force_new(double immediate, orb_force_t force) +{ + extern const float ORB_FORCE_2_0; + extern const double ORB_FORCE_SHOT_BASE; + + if(force == OF_BOUNCE_FROM_GROUND) { + orb_force = (-orb_velocity_y * ORB_COEFFICIENT_OF_RESTITUTION); + if(orb_velocity_x == OVX_0) { + random_velocity_change(0, OVX_4_LEFT); + random_velocity_change(1, OVX_4_RIGHT); + } + } + if(force == OF_BOUNCE_FROM_TOP) { + orb_force = ((-orb_velocity_y) - (orb_force_frame / 4)); + } + if(force == OF_SHOT) { + /* TODO: Proper decompilation, once data can be emitted here: + * ---------------------------------------------------------- + orb_force = ((orb_velocity_y / ORB_FORCE_2_0) + ORB_FORCE_SHOT_BASE); + * ---------------------------------------------------------- + * Performing arithmetic or comparisons between a double + * (orb_velocity_y) and a float (ORB_FORCE_2_0) variable always FLDs + * the float first, before emitting the corresponding FPU instruction + * with the double, which is not what we want here. + */ + asm { + fld orb_velocity_y; + fdiv ORB_FORCE_2_0; + fadd ORB_FORCE_SHOT_BASE; + fstp orb_force; + FWAIT; + } + } + if(force == OF_IMMEDIATE) { + orb_force = immediate; + } + orb_force_frame = 0; +} + +void orb_move_x(orb_velocity_x_t velocity_x) +{ + switch(velocity_x) { + case OVX_4_LEFT: orb_cur_left -= 4; break; + case OVX_4_RIGHT: orb_cur_left += 4; break; + case OVX_8_LEFT: orb_cur_left -= 8; break; + case OVX_8_RIGHT: orb_cur_left += 8; break; + } + if(orb_cur_left <= ORB_LEFT_MIN) { + if(orb_velocity_x == OVX_4_LEFT) { + orb_velocity_x = OVX_4_RIGHT; + } else if(orb_velocity_x == OVX_8_LEFT) { + orb_velocity_x = OVX_8_RIGHT; + } + } + if(orb_cur_left >= ORB_LEFT_MAX) { + if(orb_velocity_x == OVX_4_RIGHT) { + orb_velocity_x = OVX_4_LEFT; + } else if(orb_velocity_x == OVX_8_RIGHT) { + orb_velocity_x = OVX_8_LEFT; + } + } +} diff --git a/th01/main/player/orb.hpp b/th01/main/player/orb.hpp index d7186e3e..3882ef6f 100644 --- a/th01/main/player/orb.hpp +++ b/th01/main/player/orb.hpp @@ -11,3 +11,45 @@ static const int ORB_TOP_START = ( ORB_TOP_MAX - 88); extern int orb_cur_left, orb_cur_top; extern int orb_prev_left, orb_prev_top; + +/// Physics +/// ------- +#pragma option -b +enum orb_velocity_x_t { + OVX_0 = 0, + OVX_4_LEFT = 1, + OVX_4_RIGHT = 2, + OVX_8_LEFT = 3, + OVX_8_RIGHT = 4, +}; + +enum orb_force_t { + OF_BOUNCE_FROM_GROUND = 0, + OF_BOUNCE_FROM_TOP = 1, + OF_SHOT = 2, + OF_IMMEDIATE = 3, // new force passed directly in [immediate] +}; +#pragma option -b. + +// Initial value of the current force acting on the orb +extern double orb_force; + +// Number of frames that [orb_force] has been acting on the orb +extern int orb_force_frame; + +extern orb_velocity_x_t orb_velocity_x; +extern double orb_velocity_y; + +// Applies a new force of the given type onto the orb. Sets [orb_force], and +// reses [orb_force_frame]. +void orb_force_new(double immediate, orb_force_t force); + +// Updates [orb_velocity_y] with the currently active force, and returns the +// orb's velocity for this frame, in pixels to be added to [orb_cur_top]. +int orb_velocity_y_update(void); + +// Updates [orb_cur_left] *and* the global [orb_velocity_x] (!) to bounce the +// orb off the left or right edge of the playfield, if necessary, depending on +// the passed [velocity_x]. +void orb_move_x(orb_velocity_x_t velocity_x); +/// ------- diff --git a/th01/main/player/orb[bss].asm b/th01/main/player/orb[bss].asm index ed194a36..c8ca5a03 100644 --- a/th01/main/player/orb[bss].asm +++ b/th01/main/player/orb[bss].asm @@ -9,6 +9,7 @@ ORB_TOP_MAX = (PLAYFIELD_BOTTOM - ORB_H) ORB_LEFT_START = (ORB_LEFT_MAX - 8) ORB_TOP_START = ( ORB_TOP_MAX - 88) -public _orb_cur_left, _orb_cur_top +public _orb_cur_left, _orb_cur_top, _orb_force_frame _orb_cur_left dw ? _orb_cur_top dw ? +_orb_force_frame dw ? diff --git a/th01/main/player/orb[data].asm b/th01/main/player/orb[data].asm new file mode 100644 index 00000000..2d13f123 --- /dev/null +++ b/th01/main/player/orb[data].asm @@ -0,0 +1,14 @@ +OVX_0 = 0 +OVX_4_LEFT = 1 +OVX_4_RIGHT = 2 +OVX_8_LEFT = 3 +OVX_8_RIGHT = 4 + +OF_BOUNCE_FROM_GROUND = 0 +OF_BOUNCE_FROM_TOP = 1 +OF_SHOT = 2 +OF_IMMEDIATE = 3 + +public _orb_velocity_y, _orb_force +_orb_velocity_y dq 0.0 +_orb_force dq 0.0 diff --git a/th01/main_01.cpp b/th01/main_01.cpp index f4c75181..84b7b1aa 100644 --- a/th01/main_01.cpp +++ b/th01/main_01.cpp @@ -1,6 +1,6 @@ /* ReC98 * ----- - * Code segment #1 of TH01's REIIDEN.EXE + * 1st part of code segment #1 of TH01's REIIDEN.EXE */ extern "C" { diff --git a/th01/main_01_.cpp b/th01/main_01_.cpp new file mode 100644 index 00000000..38d90c48 --- /dev/null +++ b/th01/main_01_.cpp @@ -0,0 +1,13 @@ +/* ReC98 + * ----- + * 2nd part of code segment #1 of TH01's REIIDEN.EXE + */ + +#pragma codeseg main_01__TEXT main_01 + +extern "C" { +#include "ReC98.h" + +#include "th01/main/player/orb.cpp" + +} diff --git a/th01_reiiden.asm b/th01_reiiden.asm index 098e9220..868a128a 100644 --- a/th01_reiiden.asm +++ b/th01_reiiden.asm @@ -65,7 +65,7 @@ include th01/main/playfld.inc extern _toupper:proc extern _vsprintf:proc -main_01 group main_01_TEXT, main_01__TEXT +main_01 group main_01_TEXT, main_01__TEXT, main_01___TEXT main_13 group main_13_TEXT, main_13__TEXT main_19 group main_19_TEXT, main_19__TEXT main_25 group main_25_TEXT, main_25__TEXT @@ -1744,221 +1744,13 @@ loc_C5B1: pop bp retf sub_C466 endp +main_01__TEXT ends +main_01___TEXT segment byte public 'CODE' use16 -; =============== S U B R O U T I N E ======================================= - -; Attributes: bp-based frame - -sub_C5B4 proc far - -var_2 = word ptr -2 - - enter 2, 0 - mov ax, word_36C2C - mov bx, 5 - cwd - idiv bx - mov [bp+var_2], ax - fild [bp+var_2] - fadd dbl_34A9C - fstp dbl_34A94 - fld dbl_34A94 - fcomp flt_34B64 - fstsw [bp+var_2] - fwait - mov ax, [bp+var_2] - sahf - jbe short loc_C5EF - fld flt_34B64 - jmp short loc_C60A -; --------------------------------------------------------------------------- - -loc_C5EF: - fld dbl_34A94 - fcomp dbl_34B68 - fstsw [bp+var_2] - fwait - mov ax, [bp+var_2] - sahf - jnb short loc_C611 - fld dbl_34B68 - -loc_C60A: - fstp dbl_34A94 - fwait - -loc_C611: - mov ax, word_36C2C - mov bx, 5 - cwd - idiv bx - mov [bp+var_2], ax - fild [bp+var_2] - fadd dbl_34A9C - call ftol@ - leave - retf -sub_C5B4 endp - - -; =============== S U B R O U T I N E ======================================= - -; Attributes: bp-based frame - -; int __cdecl __far sub_C62D(double, int) -sub_C62D proc far - -var_2 = word ptr -2 -arg_0 = qword ptr 6 -arg_8 = word ptr 0Eh - - enter 2, 0 - push si - mov si, [bp+arg_8] - or si, si - jnz short loc_C68D - fld dbl_34A94 - fchs - fmul dbl_34B70 - fstp dbl_34A9C - fwait - cmp word_34A7C, 0 - jnz short loc_C68D - cmp word_36C2C, 11h - jge short loc_C670 - call IRand - mov bx, 32h ; '2' - cwd - idiv bx - or dx, dx - jnz short loc_C670 - mov word_34A7C, 1 - -loc_C670: - cmp word_36C2C, 11h - jge short loc_C68D - call IRand - mov bx, 32h ; '2' - cwd - idiv bx - cmp dx, 1 - jnz short loc_C68D - mov word_34A7C, 2 - -loc_C68D: - cmp si, 1 - jnz short loc_C6B4 - mov ax, word_36C2C - mov bx, 4 - cwd - idiv bx - mov [bp+var_2], ax - fild [bp+var_2] - fld dbl_34A94 - fchs - fsubrp st(1), st - fstp dbl_34A9C - fwait - -loc_C6B4: - cmp si, 2 - jnz short loc_C6CF - fld dbl_34A94 - fdiv flt_34B78 - fadd dbl_34B7C - fstp dbl_34A9C - fwait - -loc_C6CF: - cmp si, 3 - jnz short loc_C6DF - fld [bp+arg_0] - fstp dbl_34A9C - fwait - -loc_C6DF: - mov word_36C2C, 0 - pop si - leave - retf -sub_C62D endp - - -; =============== S U B R O U T I N E ======================================= - -; Attributes: bp-based frame - -sub_C6E8 proc far - -arg_0 = word ptr 6 - - push bp - mov bp, sp - mov bx, [bp+arg_0] - dec bx - cmp bx, 3 - ja short loc_C715 - add bx, bx - jmp cs:off_C75E[bx] - -loc_C6FB: - sub _orb_cur_left, 4 - jmp short loc_C715 -; --------------------------------------------------------------------------- - -loc_C702: - add _orb_cur_left, 4 - jmp short loc_C715 -; --------------------------------------------------------------------------- - -loc_C709: - sub _orb_cur_left, 8 - jmp short loc_C715 -; --------------------------------------------------------------------------- - -loc_C710: - add _orb_cur_left, 8 - -loc_C715: - cmp _orb_cur_left, 0 - jg short loc_C738 - cmp word_34A7C, 1 - jnz short loc_C72B - mov word_34A7C, 2 - jmp short loc_C738 -; --------------------------------------------------------------------------- - -loc_C72B: - cmp word_34A7C, 3 - jnz short loc_C738 - mov word_34A7C, 4 - -loc_C738: - cmp _orb_cur_left, ORB_LEFT_MAX - jl short loc_C75C - cmp word_34A7C, 2 - jnz short loc_C74F - mov word_34A7C, 1 - pop bp - retf -; --------------------------------------------------------------------------- - -loc_C74F: - cmp word_34A7C, 4 - jnz short loc_C75C - mov word_34A7C, 3 - -loc_C75C: - pop bp - retf -sub_C6E8 endp - -; --------------------------------------------------------------------------- -off_C75E dw offset loc_C6FB - dw offset loc_C702 - dw offset loc_C709 - dw offset loc_C710 + extern _orb_velocity_y_update:proc + extern _orb_force_new:proc + extern _orb_move_x:proc ; =============== S U B R O U T I N E ======================================= @@ -1975,24 +1767,23 @@ arg_0 = word ptr 6 mov si, [bp+arg_0] cmp word_34A86, 0 jnz loc_C816 - push word_34A7C - call sub_C6E8 + call _orb_move_x stdcall, _orb_velocity_x pop cx - call sub_C5B4 + call _orb_velocity_y_update add _orb_cur_top, ax inc word_34A92 - cmp word_34A7C, 1 + cmp _orb_velocity_x, OVX_4_LEFT jz short loc_C799 - cmp word_34A7C, 3 + cmp _orb_velocity_x, OVX_8_LEFT jnz short loc_C79D loc_C799: inc word_34A7E loc_C79D: - cmp word_34A7C, 2 + cmp _orb_velocity_x, OVX_4_RIGHT jz short loc_C7AB - cmp word_34A7C, 4 + cmp _orb_velocity_x, OVX_8_RIGHT jnz short loc_C7AF loc_C7AB: @@ -2011,12 +1802,12 @@ loc_C7BC: loc_C7C9: cmp _orb_cur_top, ORB_TOP_MAX jle short loc_C7F4 - push 0 ; int - fld dbl_34B70 + push OF_BOUNCE_FROM_GROUND + fld _ORB_COEFFICIENT_OF_RESTITUTION sub sp, 8 fstp [bp+var_C] fwait - call sub_C62D + call _orb_force_new add sp, 0Ah mov _orb_cur_top, ORB_TOP_MAX mov word_34A84, 0 @@ -2024,12 +1815,12 @@ loc_C7C9: loc_C7F4: cmp _orb_cur_top, ORB_TOP_MIN jge short loc_C816 - push 1 ; int + push OF_BOUNCE_FROM_TOP fldz sub sp, 8 fstp [bp+var_C] fwait - call sub_C62D + call _orb_force_new add sp, 0Ah mov _orb_cur_top, ORB_TOP_MIN @@ -4007,10 +3798,10 @@ loc_DB04: loc_DB0A: fld dbl_34FF5 - fstp dbl_34A9C + fstp _orb_force fwait - mov word_36C2C, 0 - mov word_34A7C, 1 + mov _orb_force_frame, 0 + mov _orb_velocity_x, OVX_4_LEFT mov _orb_prev_left, ORB_LEFT_START mov _orb_prev_top, ORB_TOP_START mov byte_34A57, 0 @@ -4165,7 +3956,7 @@ loc_DCCA: call sub_181AC call sub_1851E inc dword_36C20 - inc word_36C2C + inc _orb_force_frame inc dword_34A62 inc _bomb_doubletap_frames test byte ptr _rand, 3 @@ -4735,7 +4526,7 @@ sub_E319 proc far retf sub_E319 endp -main_01__TEXT ends +main_01___TEXT ends ; =========================================================================== @@ -18612,14 +18403,14 @@ loc_1AD1A: mov ax, _player_left sub ax, _orb_cur_left jnz short loc_1AD66 - mov word_34A7C, 0 + mov _orb_velocity_x, OVX_0 call IRand mov bx, 8 cwd idiv bx or dx, dx jnz short loc_1AD4E - mov word_34A7C, 1 + mov _orb_velocity_x, OVX_4_LEFT loc_1AD4E: call IRand @@ -18630,15 +18421,15 @@ loc_1AD4E: jnz short loc_1AD6C loc_1AD5E: - mov word_34A7C, 1 + mov _orb_velocity_x, OVX_4_LEFT jmp short loc_1AD6C ; --------------------------------------------------------------------------- loc_1AD66: - mov word_34A7C, 2 + mov _orb_velocity_x, OVX_4_RIGHT loc_1AD6C: - push 3 + push OF_IMMEDIATE mov ax, si cwd sub ax, dx @@ -18684,38 +18475,38 @@ loc_1ADBB: jge short loc_1AE0A cmp si, 65h ; 'e' jnz short loc_1ADCD - mov word_34A7C, 1 + mov _orb_velocity_x, OVX_4_LEFT jmp short loc_1ADF2 ; --------------------------------------------------------------------------- loc_1ADCD: cmp si, 66h ; 'f' jnz short loc_1ADDA - mov word_34A7C, 2 + mov _orb_velocity_x, OVX_4_RIGHT jmp short loc_1ADF2 ; --------------------------------------------------------------------------- loc_1ADDA: cmp si, 67h ; 'g' jnz short loc_1ADE7 - mov word_34A7C, 4 + mov _orb_velocity_x, OVX_8_RIGHT jmp short loc_1ADF2 ; --------------------------------------------------------------------------- loc_1ADE7: cmp si, 68h ; 'h' jnz short loc_1ADF2 - mov word_34A7C, 3 + mov _orb_velocity_x, OVX_8_LEFT loc_1ADF2: - push 3 ; int + push OF_IMMEDIATE fld dbl_35B49 loc_1ADF9: sub sp, 8 fstp [bp+var_E] fwait - call sub_C62D + call _orb_force_new add sp, 0Ah loc_1AE0A: @@ -29184,28 +28975,28 @@ loc_20F14: loc_20F24: mov _orb_cur_top, ax - cmp word_34A7C, 2 + cmp _orb_velocity_x, OVX_4_RIGHT jnz short loc_20F3C cmp [bp+var_6], 0 jge short loc_20F3C - mov word_34A7C, 1 + mov _orb_velocity_x, OVX_4_LEFT jmp short loc_20F4F ; --------------------------------------------------------------------------- loc_20F3C: - cmp word_34A7C, 1 + cmp _orb_velocity_x, OVX_4_LEFT jnz short loc_20F4F cmp [bp+var_6], 0 jle short loc_20F4F - mov word_34A7C, 2 + mov _orb_velocity_x, OVX_4_RIGHT loc_20F4F: - push 0 ; int + push OF_BOUNCE_FROM_GROUND fld flt_35C9A sub sp, 8 fstp [bp+var_1A] fwait - call sub_C62D + call _orb_force_new add sp, 0Ah loc_20F67: @@ -29348,13 +29139,13 @@ loc_21060: cmp word ptr es:[bx], 0 jnz short loc_210B1 inc word ptr es:[bx] - push 3 ; int - fld dbl_34A94 + push OF_IMMEDIATE + fld _orb_velocity_y fchs sub sp, 8 fstp [bp+var_1A] fwait - call sub_C62D + call _orb_force_new add sp, 0Ah loc_210B1: @@ -29388,13 +29179,13 @@ loc_210C6: cmp word ptr es:[bx], 0 jnz short loc_21117 inc word ptr es:[bx] - push 3 ; int - fld dbl_34A94 + push OF_IMMEDIATE + fld _orb_velocity_y fchs sub sp, 8 fstp [bp+var_1A] fwait - call sub_C62D + call _orb_force_new add sp, 0Ah loc_21117: @@ -29431,42 +29222,42 @@ loc_2112C: jnz short loc_211CD inc word ptr es:[bx] mov byte_39EB2, 1 - cmp word_34A7C, 0 + cmp _orb_velocity_x, OVX_0 jnz short loc_21198 - push 3 ; int - fld dbl_34A94 + push OF_IMMEDIATE + fld _orb_velocity_y fchs sub sp, 8 fstp [bp+var_1A] fwait - call sub_C62D + call _orb_force_new add sp, 0Ah jmp short loc_211CD ; --------------------------------------------------------------------------- loc_21198: - cmp word_34A7C, 1 + cmp _orb_velocity_x, OVX_4_LEFT jnz short loc_211A4 mov ax, 2 jmp short loc_211CA ; --------------------------------------------------------------------------- loc_211A4: - cmp word_34A7C, 2 + cmp _orb_velocity_x, OVX_4_RIGHT jnz short loc_211B0 mov ax, 1 jmp short loc_211CA ; --------------------------------------------------------------------------- loc_211B0: - cmp word_34A7C, 3 + cmp _orb_velocity_x, OVX_8_LEFT jnz short loc_211BC mov ax, 4 jmp short loc_211CA ; --------------------------------------------------------------------------- loc_211BC: - cmp word_34A7C, 4 + cmp _orb_velocity_x, OVX_8_RIGHT jnz short loc_211C8 mov ax, 3 jmp short loc_211CA @@ -29476,7 +29267,7 @@ loc_211C8: xor ax, ax loc_211CA: - mov word_34A7C, ax + mov _orb_velocity_x, ax loc_211CD: mov ax, si @@ -29512,42 +29303,42 @@ loc_211E2: jnz short loc_21283 inc word ptr es:[bx] mov byte_39EB2, 1 - cmp word_34A7C, 0 + cmp _orb_velocity_x, OVX_0 jnz short loc_2124E - push 3 ; int - fld dbl_34A94 + push OF_IMMEDIATE + fld _orb_velocity_y fchs sub sp, 8 fstp [bp+var_1A] fwait - call sub_C62D + call _orb_force_new add sp, 0Ah jmp short loc_21283 ; --------------------------------------------------------------------------- loc_2124E: - cmp word_34A7C, 1 + cmp _orb_velocity_x, OVX_4_LEFT jnz short loc_2125A mov ax, 2 jmp short loc_21280 ; --------------------------------------------------------------------------- loc_2125A: - cmp word_34A7C, 2 + cmp _orb_velocity_x, OVX_4_RIGHT jnz short loc_21266 mov ax, 1 jmp short loc_21280 ; --------------------------------------------------------------------------- loc_21266: - cmp word_34A7C, 3 + cmp _orb_velocity_x, OVX_8_LEFT jnz short loc_21272 mov ax, 4 jmp short loc_21280 ; --------------------------------------------------------------------------- loc_21272: - cmp word_34A7C, 4 + cmp _orb_velocity_x, OVX_8_RIGHT jnz short loc_2127E mov ax, 3 jmp short loc_21280 @@ -29557,7 +29348,7 @@ loc_2127E: xor ax, ax loc_21280: - mov word_34A7C, ax + mov _orb_velocity_x, ax loc_21283: mov ax, si @@ -30121,8 +29912,8 @@ loc_21777: mov bx, 5 cwd idiv bx - mov word_34A7C, dx - push 3 ; int + mov _orb_velocity_x, dx + push OF_IMMEDIATE call IRand mov bx, 13h cwd @@ -30133,7 +29924,7 @@ loc_21777: sub sp, 8 fstp [bp+var_12] fwait - call sub_C62D + call _orb_force_new add sp, 0Ah mov ax, point_39EB9.x mov _orb_cur_left, ax @@ -30595,26 +30386,26 @@ loc_21B11: dec word ptr es:[bx] les bx, [bp+arg_4] mov word ptr es:[bx], 1 - cmp word_34A7C, 1 + cmp _orb_velocity_x, OVX_4_LEFT jz short loc_21B53 - cmp word_34A7C, 3 + cmp _orb_velocity_x, OVX_8_LEFT jz short loc_21B53 - cmp word_34A7C, 2 + cmp _orb_velocity_x, OVX_4_RIGHT jz short loc_21B5B - cmp word_34A7C, 4 + cmp _orb_velocity_x, OVX_8_RIGHT jz short loc_21B5B - cmp word_34A7C, 0 + cmp _orb_velocity_x, OVX_0 jnz short loc_21B61 cmp _orb_cur_left, (PLAYFIELD_CENTER - (ORB_W / 2)) jge short loc_21B5B loc_21B53: - mov word_34A7C, 2 + mov _orb_velocity_x, OVX_4_RIGHT jmp short loc_21B61 ; --------------------------------------------------------------------------- loc_21B5B: - mov word_34A7C, 1 + mov _orb_velocity_x, OVX_4_LEFT loc_21B61: movsx eax, [bp+arg_12] @@ -49544,10 +49335,10 @@ loc_2C8AE: mov _orb_cur_top, ORB_TOP_START mov _player_left, PLAYER_LEFT_START fld dbl_35FAA - fstp dbl_34A9C + fstp _orb_force fwait - mov word_36C2C, 0 - mov word_34A7C, 1 + mov _orb_force_frame, 0 + mov _orb_velocity_x, OVX_4_LEFT mov byte_34A57, 0 mov byte_34A58, 0 push 0 @@ -55170,7 +54961,7 @@ arg_8 = word ptr 0Eh sub ax, di cmp ax, 8 jle short loc_2FEB2 - mov word_34A7C, 1 + mov _orb_velocity_x, OVX_4_LEFT jmp short loc_2FEE6 ; --------------------------------------------------------------------------- @@ -55183,7 +54974,7 @@ loc_2FEB2: sub ax, di cmp ax, 8 jnz short loc_2FECD - mov word_34A7C, 0 + mov _orb_velocity_x, OVX_0 jmp short loc_2FEE6 ; --------------------------------------------------------------------------- @@ -55196,23 +54987,22 @@ loc_2FECD: sub ax, di cmp ax, 0FFF0h jle short loc_2FEE6 - mov word_34A7C, 2 + mov _orb_velocity_x, OVX_4_RIGHT loc_2FEE6: - push 2 ; int + push OF_SHOT fldz sub sp, 8 fstp [bp+var_E] fwait - call sub_C62D + call _orb_force_new add sp, 0Ah les bx, [bp+arg_0] add bx, si mov byte ptr es:[bx+30h], 0 - push word_34A7C - call sub_C6E8 + call _orb_move_x stdcall, _orb_velocity_x pop cx - call sub_C5B4 + call _orb_velocity_y_update add _orb_cur_top, ax mov ax, 1 jmp short loc_2FF20 @@ -57321,7 +57111,8 @@ word_34A74 dw 0 dw 0 word_34A78 dw 0 dw 0 -word_34A7C dw 0 +public _orb_velocity_x +_orb_velocity_x dw 0 word_34A7E dw 0 _rem_lives dw 4 word_34A82 dw 0 @@ -57334,8 +57125,7 @@ public _orb_prev_left, _orb_prev_top _orb_prev_left dw ORB_LEFT_START _orb_prev_top dw ORB_TOP_START word_34A92 dw 0 -dbl_34A94 dq 0.0 -dbl_34A9C dq 0.0 +include th01/main/player/orb[data].asm byte_34AA4 db 0 unk_34AA5 db 0Fh db 0Fh @@ -57413,11 +57203,13 @@ a0m db 1Bh,'[0m',0 s2 db 'empty.grf',0 aKuzi1_grc db 'kuzi1.grc',0 aKuzi2_grc db 'kuzi2.grc',0 -flt_34B64 dd 16.0 -dbl_34B68 dq -16.0 -dbl_34B70 dq 0.78 -flt_34B78 dd 2.0 -dbl_34B7C dq -10.0 +public _ORB_VELOCITY_Y_MAX, _ORB_VELOCITY_Y_MIN +public _ORB_COEFFICIENT_OF_RESTITUTION, _ORB_FORCE_2_0, _ORB_FORCE_SHOT_BASE +_ORB_VELOCITY_Y_MAX dd 16.0 +_ORB_VELOCITY_Y_MIN dq -16.0 +_ORB_COEFFICIENT_OF_RESTITUTION dq 0.78 +_ORB_FORCE_2_0 dd 2.0 +_ORB_FORCE_SHOT_BASE dq -10.0 aVovVtvrvd db 'o`trd',0 aB@nKjb@b@pic db '@ĊJ@@I',0 aBB@b@b@b@b@b@ db '@@@@@@',0 @@ -58437,7 +58229,6 @@ _mode_debug db ? dword_36C20 dd ? include th01/main/player/player[bss].asm include th01/main/player/orb[bss].asm -word_36C2C dw ? db 1275 dup(?) unk_37129 db ? ; db 645 dup(?)