mirror of https://github.com/nmlgc/ReC98.git
134 lines
3.8 KiB
C++
134 lines
3.8 KiB
C++
#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;
|
|
}
|
|
}
|
|
}
|