From 5d557a243759122c09a31b6205ec8a8a84f91091 Mon Sep 17 00:00:00 2001 From: nmlgc Date: Sun, 2 Jan 2022 03:24:44 +0100 Subject: [PATCH] [Decompilation] [th01] Sariel: Pattern 4/16 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The one with the single snowflake, detonating into a 94-pixel hitbox… Part of P0177, funded by Yanga. --- th01/main/boss/b20m.cpp | 169 ++++++++++++++++++++++ th01/sprites/shape8x8.hpp | 2 + th01_reiiden.asm | 291 +++----------------------------------- 3 files changed, 188 insertions(+), 274 deletions(-) diff --git a/th01/main/boss/b20m.cpp b/th01/main/boss/b20m.cpp index 07cda8f2..62205fe4 100644 --- a/th01/main/boss/b20m.cpp +++ b/th01/main/boss/b20m.cpp @@ -31,6 +31,7 @@ extern "C" { #include "th01/formats/ptn.hpp" #include "th01/formats/stagedat.hpp" #include "th01/sprites/pellet.h" +#include "th01/sprites/shape8x8.hpp" #include "th01/main/spawnray.hpp" #include "th01/main/vars.hpp" #include "th01/main/boss/entity_a.hpp" @@ -73,6 +74,8 @@ static const pixel_t WAND_H = 96; enum sariel_colors_t { COL_LASER = 4, COL_PARTICLE2X2 = 4, + COL_DETONATION = 5, + COL_DETONATION_START = 6, COL_AIR = 12, COL_BIRD = 15, // Yes, just a single one, changed by the background image. }; @@ -86,6 +89,7 @@ extern union { int frame; int speed_multiplied_by_8; int interval; + int start_frame; int unknown; } pattern_state; extern bool16 invincible; @@ -1263,3 +1267,168 @@ void pascal near particles2x2_vertical_unput_update_render(bool16 from_bottom) #undef left #undef col } + +void near pattern_detonating_snowflake(void) +{ + enum { + HITBOX_W = 96, + RADIUS_MAX = (HITBOX_W / 2), + STEP_OUTER = 0x08, + STEP_INNER = 0x06, + }; + + enum phase_t { + P_RESET = -1, + P_WAND_RAISE = 0, + P_FLAKE_SPAWN = 1, + P_FLAKE_MOVING = 2, + P_DETONATION_START = 3, + P_DETONATION_ACTIVE = 5, + + _phase_t_FORCE_INT16 = 0x7FFF + }; + + #define state pattern3_state + #define left pattern3_left + #define star_left pattern3_star_left + #define top pattern3_top + #define star_top pattern3_star_top + #define velocity_y pattern3_velocity_y + #define velocity_x pattern3_velocity_x + #define radius_outer_1 pattern3_radius_outer_1 + #define radius_outer_2 pattern3_radius_outer_2 + #define radius_inner pattern3_radius_inner + + extern union { + phase_t phase; + int detonation_frame; + } state; + extern Subpixel left; + extern screen_x_t star_left; + extern Subpixel top; + extern vram_y_t star_top; + extern Subpixel velocity_y; + extern Subpixel velocity_x; + extern pixel_t radius_outer_1; + extern pixel_t radius_outer_2; + extern pixel_t radius_inner; + + #define ellipse_put(radius_x, radius_y, col, angle_step) { \ + shape_ellipse_arc_put( \ + left.to_pixel(), player_center_y(), radius_x, radius_y, \ + col, angle_step, 0x00, 0xFF \ + ); \ + } + + #define ellipse_sloppy_unput(radius_x, radius_y, angle_step) { \ + shape_ellipse_arc_sloppy_unput( \ + left.to_pixel(), player_center_y(), radius_x, radius_y, \ + angle_step, 0x00, 0xFF \ + ); \ + } + + if(boss_phase_frame < 10) { + state.phase = P_RESET; + select_for_rank(pattern_state.start_frame, 160, 160, 160, 160); + } + + if((boss_phase_frame % pattern_state.start_frame) == 0) { + state.phase = P_WAND_RAISE; + } + + if(state.phase == P_WAND_RAISE) { + state.phase = static_cast(wand_render_raise_both()); + } + if(state.phase == P_FLAKE_SPAWN) { + mdrv2_se_play(6); + left.v = to_sp(WAND_EMIT_LEFT); + top.v = to_sp(WAND_EMIT_TOP); + vector2_between( + WAND_EMIT_LEFT, + WAND_EMIT_TOP, + (player_left + (PLAYER_W / 2) - (FLAKE_W / 2)), + (player_top + (PLAYER_H / 2) - (FLAKE_H / 2)), + velocity_x.v, + velocity_y.v, + to_sp(7.0f) + ); + state.phase = P_FLAKE_MOVING; + } + if(state.phase == P_FLAKE_MOVING) { + shape8x8_sloppy_unput(left.to_pixel(), top.to_pixel()); + + top.v += velocity_y.v; + if(top.v >= to_sp(PLAYFIELD_BOTTOM - (FLAKE_H / 2))) { + state.phase = P_DETONATION_START; + wand_lower_both(); + return; + } + left.v += velocity_x.v; + shape8x8_flake_put(left.to_pixel(), top.to_pixel(), V_WHITE); + } + if(state.phase == P_DETONATION_START) { + ellipse_put(RADIUS_MAX, 16, COL_DETONATION_START, STEP_OUTER); + ellipse_put(16, RADIUS_MAX, COL_DETONATION_START, STEP_OUTER); + ellipse_put(24, 24, V_WHITE, STEP_INNER); + radius_outer_1 = RADIUS_MAX; + radius_outer_2 = 16; + radius_inner = 24; + // ZUN bug: Assigning a subpixel to a regular pixel. Will affect a + // single frame, until the X position is randomized again. + star_left = left.v; + star_top = (PLAYFIELD_BOTTOM - (rand() % RADIUS_MAX)); + mdrv2_se_play(10); + } + if(state.phase >= P_DETONATION_START) { + state.detonation_frame++; + } + if( + (state.phase >= P_DETONATION_ACTIVE) && + ((state.detonation_frame % 8) == 0) + ) { + shape8x8_sloppy_unput(star_left, star_top); + ellipse_sloppy_unput(radius_outer_1, radius_outer_2, STEP_OUTER); + ellipse_sloppy_unput(radius_outer_2, radius_outer_1, STEP_OUTER); + ellipse_sloppy_unput(radius_inner, radius_inner, STEP_INNER); + + radius_outer_1 -= 6; + radius_outer_2 += 6; + radius_inner += 4; + star_left = ((rand() % ((HITBOX_W * 2) / 3)) + left.to_pixel() - ( + ((HITBOX_W * 2) / 6) - (FLAKE_W / 2) + )); + star_top = (PLAYFIELD_BOTTOM - (rand() % RADIUS_MAX)); + if(radius_outer_1 <= 8) { + state.phase = P_RESET; + return; + } + + ellipse_put(radius_outer_1, radius_outer_2, COL_DETONATION, STEP_OUTER); + ellipse_put(radius_outer_2, radius_outer_1, COL_DETONATION, STEP_OUTER); + ellipse_put(radius_inner, radius_inner, V_WHITE, STEP_INNER); + shape8x8_star_put(star_left, star_top, V_WHITE); + } + + if( + !player_invincible && + ((left.to_pixel() + ((HITBOX_W / 2) - (PLAYER_W / 2))) > player_left) && + ((left.to_pixel() - ((HITBOX_W / 2) + (PLAYER_W / 2))) < player_left) && + (state.phase >= P_DETONATION_START) + ) { + done = true; + } + + #undef ellipse_put + #undef ellipse_sloppy_unput + + #undef radius_inner + #undef radius_outer_2 + #undef radius_outer_1 + #undef velocity_x + #undef velocity_y + #undef star_top + #undef top + #undef star_left + #undef left + #undef state +} diff --git a/th01/sprites/shape8x8.hpp b/th01/sprites/shape8x8.hpp index 095aaabc..0f86e92f 100644 --- a/th01/sprites/shape8x8.hpp +++ b/th01/sprites/shape8x8.hpp @@ -14,5 +14,7 @@ typedef enum { // For consistency in usage code... static const pixel_t DIAMOND_W = 8; static const pixel_t DIAMOND_H = 8; +static const pixel_t FLAKE_W = 8; +static const pixel_t FLAKE_H = 8; extern const dot_rect_t(8, 8) sSHAPE8X8[SHAPE8X8_COUNT]; diff --git a/th01_reiiden.asm b/th01_reiiden.asm index 671324c7..c32da6f9 100644 --- a/th01_reiiden.asm +++ b/th01_reiiden.asm @@ -5160,8 +5160,6 @@ main_23_TEXT segment byte public 'CODE' use16 extern _grc_load:proc extern _grc_put_8:proc extern _grcg_put_8x8_mono:proc - extern @shape8x8_star_put$qiii:proc - extern @shape8x8_flake_put$qiii:proc extern @shape_ellipse_arc_put$qiiiiiucucuc:proc extern @shape_ellipse_arc_sloppy_unput$qiiiiucucuc:proc extern _graph_r_lineloop_put:proc @@ -22434,7 +22432,6 @@ main_36_TEXT segment byte public 'CODE' use16 @shield_render_both$qv procdesc near @WAND_RENDER_RAISE_BOTH$QI procdesc pascal near \ restart:word - @wand_lower_both$qv procdesc near @dress_render_both$qv procdesc near @pattern_vortices$qv procdesc near @pattern_random_purple_lasers$qv procdesc near @@ -22443,6 +22440,7 @@ main_36_TEXT segment byte public 'CODE' use16 image_id_new:word @PARTICLES2X2_VERTICAL_UNPUT_UPDA$QI procdesc pascal near \ from_bottom:word + @pattern_detonating_snowflake$qv procdesc near main_36_TEXT ends main_36__TEXT segment byte public 'CODE' use16 @@ -22454,266 +22452,6 @@ include th01/main/boss/anim.inc sariel_shield equ -; =============== S U B R O U T I N E ======================================= - -; Attributes: bp-based frame - -sub_29FE9 proc near - push bp - mov bp, sp - cmp _boss_phase_frame, 10 - jge short loc_2A010 - mov word_35E03, 0FFFFh - call @sariel_select_for_rank$qmiiiii c, offset _sariel_pattern_state, ds, large 160 or (160 shl 16), large 160 or (160 shl 16) - -loc_2A010: - mov ax, _boss_phase_frame - cwd - idiv _sariel_pattern_state - or dx, dx - jnz short loc_2A022 - mov word_35E03, 0 - -loc_2A022: - cmp word_35E03, 0 - jnz short loc_2A031 - call @wand_render_raise_both$qi pascal, 0 - mov word_35E03, ax - -loc_2A031: - cmp word_35E03, 1 - jnz short loc_2A073 - push 6 - call _mdrv2_se_play - mov subpixel_x_3AF32, (340 shl 4) - mov subpixel_y_3AF36, (64 shl 4) - push 112 - push ds - push offset y_3AF3A - push ds - push offset x_3AF3C - push 380 - mov ax, _player_left - add ax, 12 - push ax - push (64 shl 16) or 340 - call _vector2_between - add sp, 14h - mov word_35E03, 2 - -loc_2A073: - cmp word_35E03, 2 - jnz short loc_2A0CF - push (8 shl 16) or 16 - mov ax, subpixel_y_3AF36 - sar ax, 4 - push ax - mov ax, subpixel_x_3AF32 - sar ax, 4 - push ax - call _egc_copy_rect_1_to_0_16 - add sp, 8 - mov ax, y_3AF3A - add subpixel_y_3AF36, ax - cmp subpixel_y_3AF36, (396 shl 4) - jl short loc_2A0B0 - mov word_35E03, 3 - call @wand_lower_both$qv - pop bp - retn -; --------------------------------------------------------------------------- - -loc_2A0B0: - mov ax, x_3AF3C - add subpixel_x_3AF32, ax - push 7 ; col - mov ax, subpixel_y_3AF36 - sar ax, 4 - push ax ; top - mov ax, subpixel_x_3AF32 - sar ax, 4 - push ax ; left - call @shape8x8_flake_put$qiii - add sp, 6 - -loc_2A0CF: - cmp word_35E03, 3 - jnz loc_2A16A - push 255 ; angle_end - push 0 ; angle_start - push 8 ; angle_step - push 16 or (6 shl 16) ; (radius_y) or (col shl 16) - push 384 or (48 shl 16) ; (center_y) or (radius_x shl 16) - mov ax, subpixel_x_3AF32 - sar ax, 4 - push ax ; center_x - call @shape_ellipse_arc_put$qiiiiiucucuc - push 255 - push 0 ; angle_start - push 8 ; angle_step - push 48 or (6 shl 16) ; (radius_y) or (col shl 16) - push 384 or (16 shl 16) ; (center_y) or (radius_x shl 16) - mov ax, subpixel_x_3AF32 - sar ax, 4 - push ax ; center_x - call @shape_ellipse_arc_put$qiiiiiucucuc - push 255 ; angle_end - push 0 ; angle_start - push 6 ; angle_step - push 24 or (7 shl 16) ; (radius_y) or (col shl 16) - push 384 or (24 shl 16) ; (center_y) or (radius_x shl 16) - mov ax, subpixel_x_3AF32 - sar ax, 4 - push ax ; center_x - call @shape_ellipse_arc_put$qiiiiiucucuc - mov pixel_3AF3E, 48 - mov pixel_3AF40, 16 - mov pixel_3AF42, 24 - mov ax, subpixel_x_3AF32 - mov x_3AF34, ax - call IRand - mov bx, 48 - cwd - idiv bx - mov ax, RES_Y - sub ax, dx - mov y_3AF38, ax - push 0Ah - call _mdrv2_se_play - add sp, 32h - -loc_2A16A: - cmp word_35E03, 3 - jl short loc_2A175 - inc word_35E03 - -loc_2A175: - cmp word_35E03, 5 - jl loc_2A2BA - mov ax, word_35E03 - mov bx, 8 - cwd - idiv bx - or dx, dx - jnz loc_2A2BA - call _egc_copy_rect_1_to_0_16 stdcall, x_3AF34, y_3AF38, 16, bx - push 255 ; angle_end - push 0 ; angle_start - push 8 ; angle_step - push pixel_3AF40 ; radius_y - push pixel_3AF3E ; radius_x - push 384 ; center_y - mov ax, subpixel_x_3AF32 - sar ax, 4 - push ax ; center_x - call @shape_ellipse_arc_sloppy_unput$qiiiiucucuc - push 255 ; angle_end - push 0 ; angle_start - push 8 ; angle_step - push pixel_3AF3E ; radius_y - push pixel_3AF40 ; radius_x - push 384 ; center_y - mov ax, subpixel_x_3AF32 - sar ax, 4 - push ax ; center_x - call @shape_ellipse_arc_sloppy_unput$qiiiiucucuc - push 255 ; angle_end - push 0 ; angle_start - push 6 ; angle_step - push pixel_3AF42 ; radius_y - push pixel_3AF42 ; radius_x - push 384 ; center_y - mov ax, subpixel_x_3AF32 - sar ax, 4 - push ax ; center_x - call @shape_ellipse_arc_sloppy_unput$qiiiiucucuc - add sp, 32h - sub pixel_3AF3E, 6 - add pixel_3AF40, 6 - add pixel_3AF42, 4 - call IRand - mov bx, 40h - cwd - idiv bx - mov ax, subpixel_x_3AF32 - sar ax, 4 - add dx, ax - add dx, -28 - mov x_3AF34, dx - call IRand - mov bx, 48 - cwd - idiv bx - mov ax, RES_Y - sub ax, dx - mov y_3AF38, ax - cmp pixel_3AF3E, 8 - jg short loc_2A245 - mov word_35E03, 0FFFFh - pop bp - retn -; --------------------------------------------------------------------------- - -loc_2A245: - push 255 ; angle_end - push 0 ; angle_start - push 8 ; angle_step - push 5 ; col - push pixel_3AF40 ; radius_y - push pixel_3AF3E ; radius_x - push 384 ; center_y - mov ax, subpixel_x_3AF32 - sar ax, 4 - push ax ; center_x - call @shape_ellipse_arc_put$qiiiiiucucuc - push 255 ; angle_end - push 0 ; angle_start - push 8 ; angle_step - push 5 ; col - push pixel_3AF3E ; radius_y - push pixel_3AF40 ; radius_x - push 384 ; center_y - mov ax, subpixel_x_3AF32 - sar ax, 4 - push ax ; center_x - call @shape_ellipse_arc_put$qiiiiiucucuc - push 255 ; angle_end - push 0 ; angle_start - push 6 ; angle_step - push 7 ; col - push pixel_3AF42 ; radius_y - push pixel_3AF42 ; radius_x - push 384 ; center_y - mov ax, subpixel_x_3AF32 - sar ax, 4 - push ax ; center_x - call @shape_ellipse_arc_put$qiiiiiucucuc - add sp, 30h - call @shape8x8_star_put$qiii c, x_3AF34, y_3AF38, 7 - -loc_2A2BA: - cmp _player_invincible, 0 - jnz short loc_2A2EB - mov ax, subpixel_x_3AF32 - sar ax, 4 - add ax, 32 - cmp ax, _player_left - jle short loc_2A2EB - mov ax, subpixel_x_3AF32 - sar ax, 4 - add ax, -64 - cmp ax, _player_left - jge short loc_2A2EB - cmp word_35E03, 3 - jl short loc_2A2EB - mov _done, 1 - -loc_2A2EB: - pop bp - retn -sub_29FE9 endp - - ; =============== S U B R O U T I N E ======================================= ; Attributes: bp-based frame @@ -26012,7 +25750,7 @@ loc_2C4D8: call @particles2x2_vertical_unput_upda$qi pascal, 0 cmp word_35E95, 0 jnz short loc_2C502 - call sub_29FE9 + call @pattern_detonating_snowflake$qv jmp short loc_2C50C ; --------------------------------------------------------------------------- @@ -27472,7 +27210,8 @@ _pattern2_eggs_alive dw 0 public _particles2x2_vertical_col _particles2x2_vertical_col db PARTICLE2X2_COUNT dup(0) -word_35E03 dw 0FFFFh +public _pattern3_state +_pattern3_state dw -1 dd 0 dd 0 dd 0 @@ -27939,15 +27678,19 @@ _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 ? -y_3AF38 dw ? -y_3AF3A dw ? -x_3AF3C dw ? -pixel_3AF3E dw ? -pixel_3AF40 dw ? -pixel_3AF42 dw ? +public _pattern3_left, _pattern3_star_left, _pattern3_top, _pattern3_star_top +public _pattern3_velocity_y, _pattern3_velocity_x, _pattern3_radius_outer_1 +public _pattern3_radius_outer_2, _pattern3_radius_inner +_pattern3_left dw ? +_pattern3_star_left dw ? +_pattern3_top dw ? +_pattern3_star_top dw ? +_pattern3_velocity_y dw ? +_pattern3_velocity_x dw ? +_pattern3_radius_outer_1 dw ? +_pattern3_radius_outer_2 dw ? +_pattern3_radius_inner dw ? + angle_3AF44 db ? word_3AF45 dw ? db 240 dup(?)