From 0393af6f0fac7e5e46aad8817d1f434aa0c2c488 Mon Sep 17 00:00:00 2001 From: nmlgc Date: Tue, 18 Jan 2022 01:51:27 +0100 Subject: [PATCH] [Decompilation] [th01] Sariel: Pattern 14/16 The one where evenly spaced, randomly aimed pellets rain down from an imaginary horizontal line at the seal's center Y coordinate. Featuring an equally broken symmetric spawn ray variant. Part of P0180, funded by Yanga. --- th01/main/boss/b20m.cpp | 107 ++++++++++++++++++++++ th01_reiiden.asm | 198 ++-------------------------------------- 2 files changed, 115 insertions(+), 190 deletions(-) diff --git a/th01/main/boss/b20m.cpp b/th01/main/boss/b20m.cpp index 4e3bf616..786e73e2 100644 --- a/th01/main/boss/b20m.cpp +++ b/th01/main/boss/b20m.cpp @@ -109,6 +109,7 @@ extern union { int interval; int start_frame; pixel_t velocity_x; + int pellet_count; int unknown; } pattern_state; extern bool16 invincible; @@ -459,6 +460,19 @@ template < : (((PLAYFIELD_RIGHT - DebrisOffsetX) - target_l_x) + offset); } + // Almost a correct unblitting call, except for the top coordinate... + void debris_sloppy_unput( + x_direction_t ray_id, pixel_t offset = 0, pixel_t additional_h = 0 + ) const { + egc_copy_rect_1_to_0_16( + debris_left(ray_id), + ((target_y - (DEBRIS_H / 4)) + offset), + DEBRIS_W, + (DEBRIS_H + additional_h) + ); + } + + // Worse. void unput_and_put( x_direction_t ray_id, const vortex_or_debris_cel_t &debris_cel, @@ -488,6 +502,19 @@ template < ); } + // Better. + void unput_and_put( + x_direction_t ray_id, const vortex_or_debris_cel_t &debris_cel + ) const { + debris_sloppy_unput(ray_id); + spawnray_unput_and_put( + OriginX, OriginY, target_x(ray_id), target_y, V_WHITE + ); + vortex_or_debris_put_8( + debris_left(ray_id), (target_y - (DEBRIS_H / 2)), debris_cel + ); + } + void ray_unput_right(pixel_t velocity_x) const { // spawnray_unput_and_put() could have done this as well, no need to // change APIs... @@ -498,6 +525,25 @@ template < ); } + void unput_broken(pixel_t velocity_y) const { + debris_sloppy_unput(X_RIGHT, -velocity_y, velocity_y); + debris_sloppy_unput(X_LEFT, -velocity_y, (velocity_y + 10)); // ??? + + // ZUN bug: Should of course be [velocity_y] rather than 4. These calls + // therefore unblit lines at angles that completely differ from the + // intended spawn rays. It doesn't matter for the left one, which + // actually isn't visible when this code gets to run, but the right one + // does indeed stay visible after this function. You only barely notice + // it because the one pattern that calls this function then spawns + // pellets on top of both rays, and it's *their* sloppy unblitting code + // that ends up gradually unblitting the right ray over the next few + // frames, as a side effect. + // Again, spawnray_unput_and_put() would have just done the correct + // thing. + graph_r_line_unput(OriginX, OriginY, target_x(X_LEFT), (target_y + 4)); + graph_r_line_unput(OriginX, OriginY, target_x(X_RIGHT), (target_y + 4)); + } + void fire_random_to_bottom( unsigned char &angle, x_direction_t from_dir, subpixel_t speed ) const { @@ -2370,3 +2416,64 @@ void pascal near pattern_curved_spray_leftright_once(int &frame) #undef spray } + +void pascal near pattern_rain_from_seal_center(int &frame) +{ + enum { + VELOCITY_Y = 8, + }; + + #define rays pattern13_rays + #define debris_cel_cur pattern13_debris_cel_cur + #define debris_cel_prev pattern13_debris_cel_prev + + extern struct SymmetricSpawnraysWithDebris< + SEAL_CENTER_X, SEAL_CENTER_Y, DEBRIS_W + > rays; + extern vortex_or_debris_cel_t debris_cel_cur; + extern vortex_or_debris_cel_t debris_cel_prev; + + if(frame < 50) { + return; + } else if(frame == 50) { + rays.target_l_x = PLAYFIELD_LEFT; + rays.target_y = (PLAYFIELD_BOTTOM - 1); + debris_cel_cur = C_DEBRIS; + debris_cel_prev = C_DEBRIS; + sariel_select_for_rank(pattern_state.pellet_count, 30, 35, 40, 45); + } + + if(rays.target_y > SEAL_CENTER_Y) { + if((frame % 2) == 0) { + rays.unput_and_put(X_LEFT, debris_cel_cur); + } else if((frame % 2) == 1) { + rays.unput_and_put(X_RIGHT, debris_cel_cur); + debris_cel_prev = debris_cel_cur; + debris_cel_cur = debris_cel_next(debris_cel_cur); + rays.target_y -= VELOCITY_Y; + } + if((frame % 10) == 0) { + mdrv2_se_play(6); + } + return; + } + + mdrv2_se_play(3); + rays.unput_broken(VELOCITY_Y); + + for(int i = 0; i < pattern_state.pellet_count; i++) { + Pellets.add_single( + (PLAYFIELD_LEFT + ((PLAYFIELD_W / pattern_state.pellet_count) * i)), + SEAL_CENTER_Y, + rand(), + to_sp(1.0f), + PM_GRAVITY, + to_sp(0.1f) + ); + } + frame = 0; + + #undef debris_cel_prev + #undef debris_cel_cur + #undef ray +} diff --git a/th01_reiiden.asm b/th01_reiiden.asm index 3a2344ec..b14b726e 100644 --- a/th01_reiiden.asm +++ b/th01_reiiden.asm @@ -22425,8 +22425,6 @@ main_36_TEXT segment byte public 'CODE' use16 extern @sariel_load_and_init$qv:proc @wand_lowered_snap$qv procdesc near extern @sariel_free$qv:proc - @SPAWNRAY_UNPUT_AND_PUT$QIIIII procdesc pascal near \ - origin:Point, target_x:word, target_y:word, col:word @BIRDS_RESET_FIRE_SPAWN_UNPUT_UPD$QDDDDC procdesc pascal near @shield_render_both$qv procdesc near @WAND_RENDER_RAISE_BOTH$QI procdesc pascal near \ @@ -22454,6 +22452,8 @@ main_36_TEXT segment byte public 'CODE' use16 frame:word @PATTERN_CURVED_SPRAY_LEFTRIGHT_O$QMI procdesc pascal near \ frame_seg:word, frame_off:word + @PATTERN_RAIN_FROM_SEAL_CENTER$QMI procdesc pascal near \ + frame_seg:word, frame_off:word main_36_TEXT ends main_36__TEXT segment byte public 'CODE' use16 @@ -22465,188 +22465,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_2B83C proc near - -arg_0 = dword ptr 4 - - push bp - mov bp, sp - push si - les bx, [bp+arg_0] - cmp word ptr es:[bx], 32h ; '2' - jl loc_2BA24 - les bx, [bp+arg_0] - cmp word ptr es:[bx], 32h ; '2' - jnz short loc_2B883 - mov point_3B330.x, 0 - mov point_3B330.y, RES_Y - 1 - mov grc_image_3B334, 3 - mov word_3B336, 3 - call @sariel_select_for_rank$qmiiiii c, offset _sariel_pattern_state, ds, large 30 or (35 shl 16), large 40 or (45 shl 16) - -loc_2B883: - cmp point_3B330.y, 185 - jle loc_2B97C - les bx, [bp+arg_0] - mov ax, es:[bx] - mov bx, 2 - cwd - idiv bx - or dx, dx - jnz short loc_2B8E3 - push (32 shl 16) or 32 - mov ax, point_3B330.y - add ax, -8 - push ax - push point_3B330.x - call _egc_copy_rect_1_to_0_16 - call @spawnray_unput_and_put$qiiiii pascal, ((RES_X / 2) shl 16) or 185, point_3B330.x, point_3B330.y, 7 - push 7 ; col - push grc_image_3B334 ; image - push GRC_SLOT_BOSS_1 ; slot - mov ax, point_3B330.y - add ax, -16 - push ax ; top - push point_3B330.x ; left - call _grc_put_8 - add sp, 12h - jmp short loc_2B95F -; --------------------------------------------------------------------------- - -loc_2B8E3: - les bx, [bp+arg_0] - mov ax, es:[bx] - mov bx, 2 - cwd - idiv bx - cmp dx, 1 - jnz short loc_2B95F - push (32 shl 16) or 32 - mov ax, point_3B330.y - add ax, -8 - push ax - mov ax, 608 - sub ax, point_3B330.x - push ax - call _egc_copy_rect_1_to_0_16 - push ((RES_X / 2) shl 16) or 185 - mov ax, RES_X - 1 - sub ax, point_3B330.x - push ax - push point_3B330.y - push 7 - call @spawnray_unput_and_put$qiiiii - push 7 ; col - push grc_image_3B334 ; image - push GRC_SLOT_BOSS_1 ; slot - mov ax, point_3B330.y - add ax, -16 - push ax ; top - mov ax, 608 - sub ax, point_3B330.x - push ax ; left - call _grc_put_8 - add sp, 12h - mov ax, grc_image_3B334 - mov word_3B336, ax - cmp grc_image_3B334, 5 - jge short loc_2B954 - inc ax - jmp short loc_2B957 -; --------------------------------------------------------------------------- - -loc_2B954: - mov ax, 3 - -loc_2B957: - mov grc_image_3B334, ax - sub point_3B330.y, 8 - -loc_2B95F: - les bx, [bp+arg_0] - mov ax, es:[bx] - mov bx, 0Ah - cwd - idiv bx - or dx, dx - jnz loc_2BA24 - push 6 - call _mdrv2_se_play - pop cx - jmp loc_2BA24 -; --------------------------------------------------------------------------- - -loc_2B97C: - push 3 - call _mdrv2_se_play - push (40 shl 16) or 32 - mov ax, point_3B330.y - add ax, -16 - push ax - mov ax, 608 - sub ax, point_3B330.x - push ax - call _egc_copy_rect_1_to_0_16 - push (50 shl 16) or 32 - mov ax, point_3B330.y - add ax, -16 - push ax - push point_3B330.x - call _egc_copy_rect_1_to_0_16 - mov ax, point_3B330.y - add ax, 4 - push ax - push point_3B330.x - push (185 shl 16) or 320 - call _graph_r_line_unput - mov ax, point_3B330.y - add ax, 4 - push ax - mov ax, RES_X - 1 - sub ax, point_3B330.x - push ax - push (185 shl 16) or 320 - call _graph_r_line_unput - add sp, 22h - xor si, si - jmp short loc_2BA16 -; --------------------------------------------------------------------------- - -loc_2B9EA: - pushd 0 or (0 shl 16) - push PM_GRAVITY or (1 shl 16) - push (1 shl 4) - call IRand - push ax - push 185 - mov ax, PLAYFIELD_RIGHT - cwd - idiv _sariel_pattern_state - imul si - push ax - push ds - push offset _Pellets - call @CPellets@add_single$qiiuci15pellet_motion_tiii - add sp, 14h - inc si - -loc_2BA16: - cmp si, _sariel_pattern_state - jl short loc_2B9EA - les bx, [bp+arg_0] - mov word ptr es:[bx], 0 - -loc_2BA24: - pop si - pop bp - retn 4 -sub_2B83C endp - - ; =============== S U B R O U T I N E ======================================= ; Attributes: bp-based frame @@ -24285,9 +24103,7 @@ loc_2CB73: call sub_2BB46 loc_2CB84: - push ds - push offset _boss_phase_frame - call sub_2B83C + call @pattern_rain_from_seal_center$qmi pascal, ds, offset _boss_phase_frame jmp short loc_2CBA4 ; --------------------------------------------------------------------------- @@ -25699,9 +25515,11 @@ CurvedSpray ends public _pattern12_spray _pattern12_spray CurvedSpray -point_3B330 Point -grc_image_3B334 dw ? -word_3B336 dw ? +public _pattern13_rays, _pattern13_debris_cel_cur, _pattern13_debris_cel_prev +_pattern13_rays SymmetricSpawnraysWithDebris +_pattern13_debris_cel_cur dw ? +_pattern13_debris_cel_prev dw ? + x_3B338 dw ? y_3B338 dw ? speed_3B33C dw ?