[Decompilation] [th01] Sariel: 2×2 particle system (vertical)

Maximum floating-point decadence yet again, for an effect that you
barely even notice (and your brain probably didn't, either).
Fun fact: They stop animating during the background transition
animation I've just decompiled previously.

Completes P0176, funded by Ember2528.
This commit is contained in:
nmlgc 2022-01-01 23:55:01 +01:00
parent a78c4ff0f3
commit c5dc45b1c4
4 changed files with 144 additions and 277 deletions

View File

@ -101,6 +101,11 @@ static inline vram_offset_t vram_offset_divmul(screen_x_t x, vram_y_t y)
return (x / BYTE_DOTS) + (y * ROW_SIZE);
}
static inline vram_offset_t vram_offset_divmul_double(double x, double y)
{
return (x / BYTE_DOTS) + (y * ROW_SIZE);
}
static inline vram_offset_t vram_offset_divmul_wtf(screen_x_t x, vram_y_t y)
{
return ((((x + RES_X) / BYTE_DOTS) + (y * ROW_SIZE)) - ROW_SIZE);
@ -182,6 +187,11 @@ static inline vram_offset_t vram_offset_divshift_wtf(screen_x_t x, vram_y_t y)
#define grcg_put(offset, src, bit_count) \
VRAM_PUT(B, offset, src, bit_count)
#define grcg_put_emptyopt(offset, src, bit_count) \
if(src) { \
grcg_put(offset, src, bit_count); \
}
#define grcg_put_8(offset, src) \
/* Nope, pokeb() doesn't generate the same code */ \
*reinterpret_cast<dots8_t *>(MK_FP(SEG_PLANE_B, offset)) = src
@ -189,5 +199,6 @@ static inline vram_offset_t vram_offset_divshift_wtf(screen_x_t x, vram_y_t y)
#define grcg_snap(dst, offset, bit_count) \
VRAM_SNAP(dst, B, offset, bit_count)
#define egc_put grcg_put
#define egc_snap grcg_snap
#define egc_put grcg_put
#define egc_put_emptyopt grcg_put_emptyopt
#define egc_snap grcg_snap

View File

@ -72,6 +72,7 @@ static const pixel_t WAND_H = 96;
enum sariel_colors_t {
COL_LASER = 4,
COL_PARTICLE2X2 = 4,
COL_AIR = 12,
COL_BIRD = 15, // Yes, just a single one, changed by the background image.
};
@ -204,6 +205,34 @@ static const int SPAWNCROSS_CELS = 2;
static const main_ptn_slot_t PTN_SLOT_WAND_LOWERED = PTN_SLOT_BOSS_1;
// ----
// 2×2 particles (just "particles" was taken)
// -------------
static const pixel_t PARTICLE2X2_W = 2;
static const pixel_t PARTICLE2X2_H = 2;
static const int PARTICLE2X2_COUNT = 30;
static const dots8_t sPARTICLE2X2 = 0xC0; // (** )
#define particle2x2_linear_vram_offset(vo, first_bit, left, top) { \
vo = vram_offset_divmul_double(left, top); \
first_bit = (static_cast<screen_x_t>(left) % BYTE_DOTS); \
}
#define particle2x2_snap_2(dots, vo, first_bit) { \
dots[0] = grcg_chunk(vo, 8); \
/* Parentheses omitted for code generation reasons */ \
dots[1] = grcg_chunk(vo + ROW_SIZE, 8); \
dots[0] &= (sPARTICLE2X2 >> first_bit); \
dots[1] &= (sPARTICLE2X2 >> first_bit); \
}
#define particle2x2_put(vo, first_bit, dots) { \
grcg_put_emptyopt(vo, dots[0], 8); \
/* Parentheses omitted for code generation reasons */ \
grcg_put_emptyopt(vo + ROW_SIZE, dots[1], 8); \
}
// -------------
// Temporary storage for compiler-generated string literals
// --------------------------------------------------------
@ -1151,3 +1180,86 @@ void pascal near bg_transition(int image_id_new)
#undef cell_y
#undef cell_x
}
void pascal near particles2x2_vertical_unput_update_render(bool16 from_bottom)
{
#define col particles2x2_vertical_col
#define left particles2x2_vertical_left
#define top particles2x2_vertical_top
#define velocity_y particles2x2_vertical_velocity_y
// Also indicates whether a particle is alive.
extern uint4_t col[PARTICLE2X2_COUNT];
extern double left[PARTICLE2X2_COUNT];
extern double top[PARTICLE2X2_COUNT];
extern double velocity_y[PARTICLE2X2_COUNT];
int i;
vram_offset_t vo;
int first_bit;
DotRect<dots8_t, PARTICLE2X2_H> dots;
if((boss_phase_frame % 7) == 0) {
for(i = 0; i < PARTICLE2X2_COUNT; i++) {
if(col[i] != 0) {
continue;
}
left[i] = (rand() % RES_X);
top[i] = ((from_bottom == false) ? 0 : (RES_Y - 1 - PARTICLE2X2_H));
velocity_y[i] = ((from_bottom == false)
? (( rand() % 15) + 2)
: ((-rand() % 15) - 8)
);
col[i] = COL_PARTICLE2X2;
break;
}
}
if((boss_phase_frame % 2) != 0) {
return;
}
for(i = 0; i < PARTICLE2X2_COUNT; i++) {
if(col[i] == 0) {
continue;
}
grcg_setcolor_tcr(COL_AIR);
particle2x2_linear_vram_offset(vo, first_bit, left[i], top[i]);
// Lazy trick to avoid having to touch two adjacent VRAM bytes? Why
// though, you've got a 16-bit CPU. And why not just shift it to the
// next VRAM byte (= 1 pixel to the right) rather than 7 pixels to the
// left? And why is this done every frame?
if(first_bit == ((BYTE_DOTS - PARTICLE2X2_W) + 1)) {
first_bit = 0;
}
// Unblit
graph_accesspage_func(1); particle2x2_snap_2(dots, vo, first_bit);
grcg_setcolor_rmw(COL_AIR);
graph_accesspage_func(0); particle2x2_put(vo, first_bit, dots);
// Update
top[i] += velocity_y[i];
// Recalculate VRAM offset and clip
vo = vram_offset_divmul_double(left[i], top[i]);
if((vo >= (((RES_Y - PARTICLE2X2_H) + 1) * ROW_SIZE) || (vo < 0))) {
col[i] = 0;
continue;
}
// Render
grcg_setcolor_tcr(COL_AIR);
graph_accesspage_func(1); particle2x2_snap_2(dots, vo, first_bit);
grcg_setcolor_rmw(col[i]);
graph_accesspage_func(0); particle2x2_put(vo, first_bit, dots);
}
grcg_off();
#undef velocity_y
#undef top
#undef left
#undef col
}

View File

@ -1,8 +1,6 @@
// Temporary data storage
// ----------------------
float f8_0 = 8.0;
float f80_0 = 80.0;
double d0_1 = 0.1;
double dminus0_1 = -0.1;
float f640_0 = 640.0;

View File

@ -22441,6 +22441,8 @@ main_36_TEXT segment byte public 'CODE' use16
@pattern_birds_on_ellipse_arc$qv procdesc near
@BG_TRANSITION$QI procdesc pascal near \
image_id_new:word
@PARTICLES2X2_VERTICAL_UNPUT_UPDA$QI procdesc pascal near \
from_bottom:word
main_36_TEXT ends
main_36__TEXT segment byte public 'CODE' use16
@ -22452,259 +22454,6 @@ include th01/main/boss/anim.inc
sariel_shield equ <boss_entity_0>
; =============== S U B R O U T I N E =======================================
; Attributes: bp-based frame
sub_29D8B proc near
var_6 = word ptr -6
var_4 = byte ptr -4
var_3 = byte ptr -3
var_2 = word ptr -2
arg_0 = word ptr 4
enter 6, 0
push si
push di
mov ax, _boss_phase_frame
mov bx, 7
cwd
idiv bx
or dx, dx
jnz loc_29E32
xor si, si
jmp loc_29E2B
; ---------------------------------------------------------------------------
loc_29DA5:
cmp byte ptr [si+1445h], 0
jnz short loc_29E2A
call IRand
mov bx, 280h
cwd
idiv bx
mov [bp+var_6], dx
fild [bp+var_6]
mov bx, si
shl bx, 3
fstp qword ptr [bx+62C2h]
fwait
cmp [bp+arg_0], 0
jnz short loc_29DD4
xor ax, ax
jmp short loc_29DD7
; ---------------------------------------------------------------------------
loc_29DD4:
mov ax, 18Dh
loc_29DD7:
mov [bp+var_6], ax
fild [bp+var_6]
mov bx, si
shl bx, 3
fstp qword ptr [bx+63B2h]
fwait
cmp [bp+arg_0], 0
jnz short loc_29E00
call IRand
mov bx, 0Fh
cwd
idiv bx
add dx, 2
jmp short loc_29E10
; ---------------------------------------------------------------------------
loc_29E00:
call IRand
neg ax
mov bx, 0Fh
cwd
idiv bx
add dx, 0FFF8h
loc_29E10:
mov [bp+var_6], dx
fild [bp+var_6]
mov bx, si
shl bx, 3
fstp qword ptr [bx+64A2h]
fwait
mov byte ptr [si+1445h], 4
jmp short loc_29E32
; ---------------------------------------------------------------------------
loc_29E2A:
inc si
loc_29E2B:
cmp si, 1Eh
jl loc_29DA5
loc_29E32:
mov ax, _boss_phase_frame
mov bx, 2
cwd
idiv bx
or dx, dx
jnz loc_29FE3
xor si, si
jmp loc_29FD7
; ---------------------------------------------------------------------------
loc_29E46:
cmp byte ptr [si+1445h], 0
jz loc_29FD6
call _grcg_setcolor_tcr stdcall, 12
pop cx
mov bx, si
shl bx, 3
fld qword ptr [bx+62C2h]
fdiv _f8_0
mov bx, si
shl bx, 3
fld qword ptr [bx+63B2h]
fmul _f80_0
faddp st(1), st
call ftol@
mov di, ax
mov bx, si
shl bx, 3
fld qword ptr [bx+62C2h]
call ftol@
mov bx, 8
cwd
idiv bx
mov [bp+var_2], dx
cmp [bp+var_2], 7
jnz short loc_29EA2
mov [bp+var_2], 0
loc_29EA2:
push 1
call _graph_accesspage_func
les bx, _VRAM_PLANE_B
add bx, di
mov al, es:[bx]
mov [bp+var_4], al
mov bx, word ptr _VRAM_PLANE_B
add bx, di
mov al, es:[bx+50h]
mov [bp+var_3], al
mov ax, 0C0h ; '?'
mov cl, byte ptr [bp+var_2]
sar ax, cl
and [bp+var_4], al
mov ax, 0C0h ; '?'
sar ax, cl
and [bp+var_3], al
call _grcg_setcolor_rmw stdcall, 12
push 0
call _graph_accesspage_func
add sp, 6
cmp [bp+var_4], 0
jz short loc_29EF8
les bx, _VRAM_PLANE_B
add bx, di
mov al, [bp+var_4]
mov es:[bx], al
loc_29EF8:
cmp [bp+var_3], 0
jz short loc_29F0B
les bx, _VRAM_PLANE_B
add bx, di
mov al, [bp+var_3]
mov es:[bx+50h], al
loc_29F0B:
mov bx, si
shl bx, 3
fld qword ptr [bx+64A2h]
mov bx, si
shl bx, 3
fadd qword ptr [bx+63B2h]
mov bx, si
shl bx, 3
fstp qword ptr [bx+63B2h]
mov bx, si
shl bx, 3
fld qword ptr [bx+62C2h]
fdiv _f8_0
mov bx, si
shl bx, 3
fld qword ptr [bx+63B2h]
fmul _f80_0
faddp st(1), st
call ftol@
mov di, ax
cmp di, 7CB0h
jge short loc_29F5B
or di, di
jge short loc_29F62
loc_29F5B:
mov byte ptr [si+1445h], 0
jmp short loc_29FD6
; ---------------------------------------------------------------------------
loc_29F62:
call _grcg_setcolor_tcr stdcall, 12
push 1
call _graph_accesspage_func
les bx, _VRAM_PLANE_B
add bx, di
mov al, es:[bx]
mov [bp+var_4], al
mov bx, word ptr _VRAM_PLANE_B
add bx, di
mov al, es:[bx+50h]
mov [bp+var_3], al
mov ax, 0C0h ; '?'
mov cl, byte ptr [bp+var_2]
sar ax, cl
and [bp+var_4], al
mov ax, 0C0h ; '?'
sar ax, cl
and [bp+var_3], al
mov al, [si+1445h]
cbw
call _grcg_setcolor_rmw stdcall, ax
push 0
call _graph_accesspage_func
add sp, 8
cmp [bp+var_4], 0
jz short loc_29FC3
les bx, _VRAM_PLANE_B
add bx, di
mov al, [bp+var_4]
mov es:[bx], al
loc_29FC3:
cmp [bp+var_3], 0
jz short loc_29FD6
les bx, _VRAM_PLANE_B
add bx, di
mov al, [bp+var_3]
mov es:[bx+50h], al
loc_29FD6:
inc si
loc_29FD7:
cmp si, 1Eh
jl loc_29E46
call _grcg_off_func
loc_29FE3:
pop di
pop si
leave
retn 2
sub_29D8B endp
; =============== S U B R O U T I N E =======================================
; Attributes: bp-based frame
@ -24639,11 +24388,11 @@ loc_2B3F4:
mov bx, si
shl bx, 3
fld qword ptr [bx+66B7h]
fdiv _f8_0
fdiv dword ptr ds:[15EAh]
mov bx, si
shl bx, 3
fld qword ptr [bx+67A7h]
fmul _f80_0
fmul dword ptr ds:[15EEh]
faddp st(1), st
call ftol@
mov di, ax
@ -24761,11 +24510,11 @@ loc_2B54A:
mov bx, si
shl bx, 3
fld qword ptr [bx+66B7h]
fdiv _f8_0
fdiv dword ptr ds:[15EAh]
mov bx, si
shl bx, 3
fld qword ptr [bx+67A7h]
fmul _f80_0
fmul dword ptr ds:[15EEh]
faddp st(1), st
call ftol@
mov di, ax
@ -26260,8 +26009,7 @@ loc_2C4D8:
inc _sariel_invincibility_frame
call @shield_render_both$qv
call @dress_render_both$qv
push 0
call sub_29D8B
call @particles2x2_vertical_unput_upda$qi pascal, 0
cmp word_35E95, 0
jnz short loc_2C502
call sub_29FE9
@ -26473,8 +26221,7 @@ loc_2C6F2:
inc _sariel_invincibility_frame
call @shield_render_both$qv
call @dress_render_both$qv
push 1
call sub_29D8B
call @particles2x2_vertical_unput_upda$qi pascal, 1
fldz
sub sp, 8
fstp [bp+var_12]
@ -27705,6 +27452,7 @@ _spawnray_target_prev_y dw 999
BIRD_COUNT = 30
VORTEX_COUNT = 2
PARTICLE2X2_COUNT = 30
public _birds_alive
_birds_alive db BIRD_COUNT dup(0)
@ -27721,15 +27469,9 @@ _pattern2_wand_raise_animation_do db 0
_pattern2_pellet_group db 0
_pattern2_eggs_alive dw 0
dd 0
dd 0
dd 0
dd 0
dd 0
dd 0
dd 0
db 0
db 0
public _particles2x2_vertical_col
_particles2x2_vertical_col db PARTICLE2X2_COUNT dup(0)
word_35E03 dw 0FFFFh
dd 0
dd 0
@ -27797,8 +27539,6 @@ _sariel_invincibility_flash_colors db 3, 4, 5
extern _boss6_a2_grp:byte
extern _boss6_a3_grp:byte
extern _boss6_a4_grp:byte
extern _f8_0:dword
extern _f80_0:dword
extern _d0_1:qword
extern _dminus0_1:qword
extern _f640_0:dword
@ -28192,7 +27932,13 @@ _bg_transition_cell_y dw ?
_bg_transition_cell_vo dw ?
_bg_transition_stripe_col_base dw ?
_bg_transition_gust_id dw ?
db 720 dup(?)
public _particles2x2_vertical_left, _particles2x2_vertical_top
public _particles2x2_vertical_velocity_y
_particles2x2_vertical_left dq PARTICLE2X2_COUNT dup(?)
_particles2x2_vertical_top dq PARTICLE2X2_COUNT dup(?)
_particles2x2_vertical_velocity_y dq PARTICLE2X2_COUNT dup(?)
subpixel_x_3AF32 dw ?
x_3AF34 dw ?
subpixel_y_3AF36 dw ?