diff --git a/th05/main/boss/render.cpp b/th05/main/boss/render.cpp index d3cf1810..bbe8b54e 100644 --- a/th05/main/boss/render.cpp +++ b/th05/main/boss/render.cpp @@ -58,6 +58,15 @@ extern lineset_t linesets[LINESET_COUNT]; /// Stage 6 - Shinki /// ---------------- +#define SHINKI_SPINLINE_MOVE_W (PLAYFIELD_W / 6) /* pixel_t! */ +#define SHINKI_SPINLINE_MOVE_SPEED to_sp(0.25f) +#define SHINKI_SPINLINE_TOP to_sp(80.0f) +#define SHINKI_SPINLINE_BOTTOM to_sp(PLAYFIELD_H - 64) +#define SHINKI_TYPE_D_BG_H 128 + +#define SHINKI_SPINLINE_MOVE_DURATION \ + (SHINKI_SPINLINE_MOVE_W * SHINKI_SPINLINE_MOVE_SPEED) + static const int SHINKI_LINESET_COUNT = 2; static const int PARTICLES_UNINITIALIZED = (-1 & 0xFF); @@ -70,6 +79,46 @@ static const int SHINKI_LINE_4 = (3 * 6); extern unsigned char shinki_bg_linesets_zoomed_out; extern int shinki_bg_type_a_particles_alive; extern bool shinki_bg_type_b_initialized; +extern unsigned int shinki_bg_spinline_frames; +extern bool shinki_bg_type_c_initialized; +extern bool shinki_bg_type_d_initialized; + +#define shinki_spinline_x_and_angle(set, delta) \ + if(set->radius[SHINKI_LINE_MAIN] > to_sp(96.0f)) { \ + set->radius[SHINKI_LINE_MAIN] -= 0.125f; \ + } \ + if( \ + (shinki_bg_spinline_frames & ( \ + (SHINKI_SPINLINE_MOVE_DURATION * 2) - 1) \ + ) < SHINKI_SPINLINE_MOVE_DURATION \ + ) { \ + set->center[SHINKI_LINE_MAIN].x.v += delta; \ + } else { \ + set->center[SHINKI_LINE_MAIN].x.v -= delta; \ + } \ + set->angle[SHINKI_LINE_MAIN] += (delta / 2); + +#define shinki_spinline_y_formation_top(set, delta, set_i, line_i) \ + delta = (SHINKI_SPINLINE_TOP - set->center[SHINKI_LINE_MAIN].y); \ + set_i = 0; \ + while(set_i < SHINKI_LINESET_COUNT) { \ + for(line_i = SHINKI_LINE_4; line_i >= 0; line_i--) { \ + set->center[line_i].y.v += delta; \ + } \ + set_i++; \ + set++; \ + } + +#define shinki_spinline_y_formation_bottom(set, delta, set_i, line_i) \ + delta = (set->center[SHINKI_LINE_MAIN].y - SHINKI_SPINLINE_BOTTOM); \ + set_i = 0; \ + while(set_i < SHINKI_LINESET_COUNT) { \ + for(line_i = SHINKI_LINE_4; line_i >= 0; line_i--) { \ + set->center[line_i].y.v -= delta; \ + } \ + set_i++; \ + set++; \ + } void near shinki_bg_particles_render(void) { @@ -205,10 +254,10 @@ void pascal near grcg_lineset_line_put(lineset_t near &set, int i) grcg_line(x1, y1, x2, y2); } -// Copies lines [0; 17] to lines [1..18]. -void pascal near lineset_forward_copy(lineset_t near &set) +// Copies lines [0..17] to lines [1..18]. +void pascal near shinki_lineset_forward_copy(lineset_t near &set) { - for(int i = (LINESET_LINE_COUNT - 2); i > 0; i--) { + for(int i = SHINKI_LINE_4; i > 0; i--) { set.center[i] = set.center[i - 1]; set.angle[i] = set.angle[i - 1]; set.radius[i].v = set.radius[i - 1].v; @@ -249,7 +298,7 @@ void near shinki_bg_type_a_update_and_render(void) lineset_t near *set = linesets; int i = 0; while(i < SHINKI_LINESET_COUNT) { - lineset_forward_copy(*set); + shinki_lineset_forward_copy(*set); set->radius[SHINKI_LINE_MAIN] += 4.0f; vector2_at( set->center[SHINKI_LINE_MAIN], @@ -321,4 +370,152 @@ void near shinki_bg_type_b_update_part1(void) particle++; } } + +// Particles: Blue, at random X positions, falling down +// Lines: Spinning and horizontally shifting at both sides of Shinki's wings, +// starting near the center of the playfield, moving up to +// [SHINKI_SPINLINE_TOP], and then pushed *down* into a vertical +// formation, until the set has reached its target velocity. +void near shinki_bg_type_b_update_and_render(void) +{ + // MODDERS: Just fuse into this function. + shinki_bg_type_b_update_part1(); + + lineset_t near *set; + int set_i; + subpixel_t delta; + int line_i; + + delta = SHINKI_SPINLINE_MOVE_SPEED; + set = linesets; + set_i = 0; + while(set_i < SHINKI_LINESET_COUNT) { + shinki_lineset_forward_copy(*set); + set->center[SHINKI_LINE_MAIN].y.v += set->velocity_y.v; + if(set->velocity_y > to_sp(-14.0f)) { + set->velocity_y.v -= ( + (stage_frame_mod4 == 0) ? to_sp(0.0625f) : to_sp(0.0f) + ); + } + shinki_spinline_x_and_angle(set, delta); + + set_i++; + set++; + delta = -delta; + } + + shinki_bg_spinline_frames++; + + set = linesets; + if(set->center[SHINKI_LINE_MAIN].y < SHINKI_SPINLINE_TOP) { + shinki_spinline_y_formation_top(set, delta, set_i, line_i); + } + + shinki_bg_render_blue_particles_and_lines(); +} + +void near shinki_bg_type_c_update_part1(void) +{ + boss_particle_t near *particle; + int i; + + if(!shinki_bg_type_c_initialized) { + particle = boss_particles; + if(particle->velocity.y < to_sp(0.0f)) { + i = 0; + while(i < BOSS_PARTICLE_COUNT) { + particle->origin.y.set(PLAYFIELD_H + 1.0f); + i++; + particle++; + } + shinki_bg_type_c_initialized++; + } + } + + particle = boss_particles; + i = 0; + while(i < BOSS_PARTICLE_COUNT) { + if(particle->velocity.y.v > to_sp(-10.0f)) { + particle->velocity.y.v -= stage_frame_mod2; + } + i++; + particle++; + } +} + +// Particles: Blue, keeping their random X positions from type B, rising +// Lines: Moving back up to [SHINKI_SPINLINE_TOP], starting at the Y velocity +// they had from the previous background type. Then, moving down to +// [SHINKI_SPINLINE_BOTTOM], and then pushed *up* into a vertical +// formation, until the set has reached its target velocity. +void near shinki_bg_type_c_update_and_render(void) +{ + // MODDERS: Just fuse into this function. + shinki_bg_type_c_update_part1(); + + lineset_t near *set; + int set_i; + subpixel_t delta; + int line_i; + + delta = SHINKI_SPINLINE_MOVE_SPEED; + set = linesets; + set_i = 0; + while(set_i < SHINKI_LINESET_COUNT) { + shinki_lineset_forward_copy(*set); + set->center[SHINKI_LINE_MAIN].y.v += set->velocity_y.v; + if(set->velocity_y < to_sp(14.0f)) { + set->velocity_y.v += stage_frame_mod2; + } + shinki_spinline_x_and_angle(set, delta); + + set_i++; + set++; + delta = -delta; + } + + shinki_bg_spinline_frames++; + + set = linesets; + // [velocity_y] is still negative from type B in the beginning. Continue + // applying friction until [velocity_y] gets positive again + if(set->center[SHINKI_LINE_MAIN].y < SHINKI_SPINLINE_TOP) { + shinki_spinline_y_formation_top(set, delta, set_i, line_i); + } else if(set->center[SHINKI_LINE_MAIN].y > SHINKI_SPINLINE_BOTTOM) { + shinki_spinline_y_formation_bottom(set, delta, set_i, line_i); + } + + shinki_bg_render_blue_particles_and_lines(); +} + +// Rising "smoke" particles. +void near shinki_bg_type_d_update(void) +{ + boss_particle_t near *particle; + int i; + + if(!shinki_bg_type_d_initialized) { + particle = boss_particles; + i = 0; + while(i < BOSS_PARTICLE_COUNT) { + particle->origin.y.v = to_sp(PLAYFIELD_H - SHINKI_TYPE_D_BG_H); + particle->velocity.y.set(-1.0f); + i++; + particle++; + } + shinki_bg_type_d_initialized++; + } + + particle = boss_particles; + i = 0; + while(i < BOSS_PARTICLE_COUNT) { + int cel = ((PARTICLE_CELS - 1) - (particle->pos.y.v / to_sp(64.0f))); + if(cel < 0) { + cel = 0; + } + particle->patnum = (PAT_PARTICLE + cel); + i++; + particle++; + } +} /// ---------------- diff --git a/th05_main.asm b/th05_main.asm index 083b1a53..608560b4 100644 --- a/th05_main.asm +++ b/th05_main.asm @@ -3533,417 +3533,14 @@ loc_D322: yumeko_bg_render endp _shinki_bg_particles_render procdesc c near - GRCG_LINESET_LINE_PUT procdesc pascal near \ - set:near ptr, i:word - LINESET_FORWARD_COPY procdesc pascal near \ - set:near ptr _shinki_bg_type_a_update_and_rend procdesc c near - _shinki_bg_type_b_update_part1 procdesc c near + _shinki_bg_type_b_update_and_rend procdesc c near + _shinki_bg_type_c_update_and_rend procdesc c near + _shinki_bg_type_d_update procdesc c near main__TEXT ends main_0_TEXT segment word public 'CODE' use16 -; =============== S U B R O U T I N E ======================================= - -; Attributes: bp-based frame - -sub_D774 proc near - -var_4 = word ptr -4 -var_2 = word ptr -2 - - enter 4, 0 - push si - push di - call _shinki_bg_type_b_update_part1 - mov [bp+var_2], 4 - mov si, offset _linesets - xor di, di - jmp short loc_D7E8 -; --------------------------------------------------------------------------- - -loc_D789: - call lineset_forward_copy pascal, si - mov ax, [si+lineset_t.LS_velocity_y] - add [si+lineset_t.LS_center.y], ax - cmp [si+lineset_t.LS_velocity_y], (-14 shl 4) - jle short loc_D7AB - cmp _stage_frame_mod4, 0 - jnz short loc_D7A6 - mov ax, 1 - jmp short loc_D7A8 -; --------------------------------------------------------------------------- - -loc_D7A6: - xor ax, ax - -loc_D7A8: - sub [si+lineset_t.LS_velocity_y], ax - -loc_D7AB: - cmp [si+lineset_t.LS_radius], (96 shl 4) - jle short loc_D7B6 - sub [si+lineset_t.LS_radius], 2 - -loc_D7B6: - mov ax, word_21D72 - and ax, 511 - cmp ax, 256 - jnb short loc_D7C8 - mov ax, [bp+var_2] - add [si+lineset_t.LS_center.x], ax - jmp short loc_D7CD -; --------------------------------------------------------------------------- - -loc_D7C8: - mov ax, [bp+var_2] - sub [si+lineset_t.LS_center.x], ax - -loc_D7CD: - mov ax, [bp+var_2] - cwd - sub ax, dx - sar ax, 1 - add al, [si+lineset_t.LS_angle] - mov [si+lineset_t.LS_angle], al - inc di - add si, size lineset_t - mov ax, [bp+var_2] - neg ax - mov [bp+var_2], ax - -loc_D7E8: - cmp di, 2 - jl short loc_D789 - inc word_21D72 - mov si, offset _linesets - cmp [si+lineset_t.LS_center.y], (80 shl 4) - jge short loc_D82E - mov ax, (80 shl 4) - sub ax, [si+lineset_t.LS_center.y] - mov [bp+var_2], ax - xor di, di - jmp short loc_D829 -; --------------------------------------------------------------------------- - -loc_D808: - mov [bp+var_4], (LINESET_LINE_COUNT - 2) - jmp short loc_D81E -; --------------------------------------------------------------------------- - -loc_D80F: - mov bx, [bp+var_4] - shl bx, 2 - mov ax, [bp+var_2] - add [bx+si+lineset_t.LS_center.y], ax - dec [bp+var_4] - -loc_D81E: - cmp [bp+var_4], 0 - jge short loc_D80F - inc di - add si, size lineset_t - -loc_D829: - cmp di, 2 - jl short loc_D808 - -loc_D82E: - call _grcg_setmode_rmw_seg1 - mov ah, GC_BRG - call _grcg_setcolor_direct_seg1_raw - call _shinki_bg_particles_render - call grcg_lineset_line_put pascal, offset lineset0, 18 - call grcg_lineset_line_put pascal, offset lineset0, 12 - call grcg_lineset_line_put pascal, offset lineset1, 18 - call grcg_lineset_line_put pascal, offset lineset1, 12 - mov ah, GC_RG - call _grcg_setcolor_direct_seg1_raw - call grcg_lineset_line_put pascal, offset lineset0, 6 - call grcg_lineset_line_put pascal, offset lineset1, 6 - mov ah, 0Fh - call _grcg_setcolor_direct_seg1_raw - call grcg_lineset_line_put pascal, offset lineset0, 0 - call grcg_lineset_line_put pascal, offset lineset1, 0 - GRCG_OFF_CLOBBERING dx - pop di - pop si - leave - retn -sub_D774 endp - - -; =============== S U B R O U T I N E ======================================= - -; Attributes: bp-based frame - -sub_D88D proc near - push bp - mov bp, sp - push si - cmp byte_21D74, 0 - jnz short loc_D8B7 - mov si, offset _boss_particles - cmp [si+boss_particle_t.BP_velocity.y], 0 - jge short loc_D8B7 - xor dx, dx - jmp short loc_D8AE -; --------------------------------------------------------------------------- - -loc_D8A5: - mov [si+boss_particle_t.BP_origin.y], ((PLAYFIELD_H + 1) shl 4) - inc dx - add si, size boss_particle_t - -loc_D8AE: - cmp dx, BOSS_PARTICLE_COUNT - jl short loc_D8A5 - inc byte_21D74 - -loc_D8B7: - mov si, offset _boss_particles - xor dx, dx - jmp short loc_D8D1 -; --------------------------------------------------------------------------- - -loc_D8BE: - cmp [si+boss_particle_t.BP_velocity.y], (-10 shl 4) - jle short loc_D8CD - mov al, _stage_frame_mod2 - mov ah, 0 - sub [si+boss_particle_t.BP_velocity.y], ax - -loc_D8CD: - inc dx - add si, size boss_particle_t - -loc_D8D1: - cmp dx, BOSS_PARTICLE_COUNT - jl short loc_D8BE - pop si - pop bp - retn -sub_D88D endp - - -; =============== S U B R O U T I N E ======================================= - -; Attributes: bp-based frame - -sub_D8D9 proc near - -@@line_i = word ptr -4 -var_2 = word ptr -2 - - enter 4, 0 - push si - push di - call sub_D88D - mov [bp+var_2], 4 - mov si, offset _linesets - xor di, di - jmp short loc_D944 -; --------------------------------------------------------------------------- - -loc_D8EE: - call lineset_forward_copy pascal, si - mov ax, [si+lineset_t.LS_velocity_y] - add [si+lineset_t.LS_center.y], ax - cmp [si+lineset_t.LS_velocity_y], (14 shl 4) - jge short loc_D907 - mov al, _stage_frame_mod2 - mov ah, 0 - add [si+lineset_t.LS_velocity_y], ax - -loc_D907: - cmp [si+lineset_t.LS_radius], (96 shl 4) - jle short loc_D912 - sub [si+lineset_t.LS_radius], 2 - -loc_D912: - mov ax, word_21D72 - and ax, 511 - cmp ax, 256 - jnb short loc_D924 - mov ax, [bp+var_2] - add [si+lineset_t.LS_center.x], ax - jmp short loc_D929 -; --------------------------------------------------------------------------- - -loc_D924: - mov ax, [bp+var_2] - sub [si+lineset_t.LS_center.x], ax - -loc_D929: - mov ax, [bp+var_2] - cwd - sub ax, dx - sar ax, 1 - add al, [si+lineset_t.LS_angle] - mov [si+lineset_t.LS_angle], al - inc di - add si, size lineset_t - mov ax, [bp+var_2] - neg ax - mov [bp+var_2], ax - -loc_D944: - cmp di, 2 - jl short loc_D8EE - inc word_21D72 - mov si, offset _linesets - cmp [si+lineset_t.LS_center.y], (80 shl 4) - jge short loc_D98C - mov ax, (80 shl 4) - sub ax, [si+lineset_t.LS_center.y] - mov [bp+var_2], ax - xor di, di - jmp short loc_D985 -; --------------------------------------------------------------------------- - -loc_D964: - mov [bp+@@line_i], (LINESET_LINE_COUNT - 2) - jmp short loc_D97A -; --------------------------------------------------------------------------- - -loc_D96B: - mov bx, [bp+@@line_i] - shl bx, 2 - mov ax, [bp+var_2] - add [bx+si+lineset_t.LS_center.y], ax - dec [bp+@@line_i] - -loc_D97A: - cmp [bp+@@line_i], 0 - jge short loc_D96B - inc di - add si, size lineset_t - -loc_D985: - cmp di, 2 - jl short loc_D964 - jmp short loc_D9C6 -; --------------------------------------------------------------------------- - -loc_D98C: - cmp [si+lineset_t.LS_center.y], (304 shl 4) - jle short loc_D9C6 - mov ax, [si+lineset_t.LS_center.y] - add ax, (-304 shl 4) - mov [bp+var_2], ax - xor di, di - jmp short loc_D9C1 -; --------------------------------------------------------------------------- - -loc_D9A0: - mov [bp+@@line_i], (LINESET_LINE_COUNT - 2) - jmp short loc_D9B6 -; --------------------------------------------------------------------------- - -loc_D9A7: - mov bx, [bp+@@line_i] - shl bx, 2 - mov ax, [bp+var_2] - sub [bx+si+lineset_t.LS_center.y], ax - dec [bp+@@line_i] - -loc_D9B6: - cmp [bp+@@line_i], 0 - jge short loc_D9A7 - inc di - add si, size lineset_t - -loc_D9C1: - cmp di, 2 - jl short loc_D9A0 - -loc_D9C6: - call _grcg_setmode_rmw_seg1 - mov ah, GC_BRG - call _grcg_setcolor_direct_seg1_raw - call _shinki_bg_particles_render - call grcg_lineset_line_put pascal, offset lineset0, 18 - call grcg_lineset_line_put pascal, offset lineset0, 12 - call grcg_lineset_line_put pascal, offset lineset1, 18 - call grcg_lineset_line_put pascal, offset lineset1, 12 - mov ah, GC_RG - call _grcg_setcolor_direct_seg1_raw - call grcg_lineset_line_put pascal, offset lineset0, 6 - call grcg_lineset_line_put pascal, offset lineset1, 6 - mov ah, 0Fh - call _grcg_setcolor_direct_seg1_raw - call grcg_lineset_line_put pascal, offset lineset0, 0 - call grcg_lineset_line_put pascal, offset lineset1, 0 - GRCG_OFF_CLOBBERING dx - pop di - pop si - leave - retn -sub_D8D9 endp - - -; =============== S U B R O U T I N E ======================================= - -; Attributes: bp-based frame - -sub_DA25 proc near - -@@cel = word ptr -2 - - enter 2, 0 - push si - cmp byte_21D75, 0 - jnz short loc_DA4F - mov si, offset _boss_particles - xor cx, cx - jmp short loc_DA46 -; --------------------------------------------------------------------------- - -loc_DA38: - mov [si+boss_particle_t.BP_origin.y], (240 shl 4) - mov [si+boss_particle_t.BP_velocity.y], (-1 shl 4) - inc cx - add si, size boss_particle_t - -loc_DA46: - cmp cx, BOSS_PARTICLE_COUNT - jl short loc_DA38 - inc byte_21D75 - -loc_DA4F: - mov si, offset _boss_particles - xor cx, cx - jmp short loc_DA7E -; --------------------------------------------------------------------------- - -loc_DA56: - mov ax, [si+boss_particle_t.BP_pos.y] - mov bx, (64 shl 4) - cwd - idiv bx - mov dx, (PARTICLE_CELS - 1) - sub dx, ax - mov [bp+@@cel], dx - cmp [bp+@@cel], 0 - jge short loc_DA72 - mov [bp+@@cel], 0 - -loc_DA72: - mov al, byte ptr [bp+@@cel] - add al, PAT_PARTICLE - mov [si+boss_particle_t.BP_patnum], al - inc cx - add si, size boss_particle_t - -loc_DA7E: - cmp cx, BOSS_PARTICLE_COUNT - jl short loc_DA56 - pop si - leave - retn -sub_DA25 endp - - ; =============== S U B R O U T I N E ======================================= ; Attributes: bp-based frame @@ -4003,7 +3600,7 @@ loc_DAEC: cmp _boss_phase, 8 jnb short loc_DAFB call sub_E92E - call sub_D774 + call _shinki_bg_type_b_update_and_rend leave retn ; --------------------------------------------------------------------------- @@ -4012,7 +3609,7 @@ loc_DAFB: cmp _boss_phase, 0Ch jnb short loc_DB0A call sub_E92E - call sub_D8D9 + call _shinki_bg_type_c_update_and_rend leave retn ; --------------------------------------------------------------------------- @@ -4020,7 +3617,7 @@ loc_DAFB: loc_DB0A: call cdg_put_noalpha_8 pascal, large (32 shl 16) or 256, 17 call sub_E950 - call sub_DA25 + call _shinki_bg_type_d_update call grcg_setcolor pascal, (GC_RMW shl 16) + 6 call _shinki_bg_particles_render GRCG_OFF_CLOBBERING dx @@ -26970,15 +26567,17 @@ byte_21762 db 0 include th04/sprites/pointnum.asp include th05/formats/bb_playchar[data].asm public _shinki_bg_linesets_zoomed_out, _shinki_bg_type_a_particles_alive -public _shinki_bg_type_b_initialized +public _shinki_bg_type_b_initialized, _shinki_bg_spinline_frames +public _shinki_bg_type_c_initialized +public _shinki_bg_type_d_initialized _shinki_bg_linesets_zoomed_out db 0 db 0 _shinki_bg_type_a_particles_alive dw (-1 and 255) _shinki_bg_type_b_initialized db 0 db 0 -word_21D72 dw 0 -byte_21D74 db 0 -byte_21D75 db 0 +_shinki_bg_spinline_frames dw 0 +_shinki_bg_type_c_initialized db 0 +_shinki_bg_type_d_initialized db 0 byte_21D76 db 0 db 0 include th04/main/player/shot_laser[data].asm