From 0724d972de7debcab971d94a2413d33a85842a41 Mon Sep 17 00:00:00 2001 From: nmlgc Date: Fri, 10 Jun 2022 21:36:01 +0200 Subject: [PATCH] [Decompilation] [th01] Kikuri: Move all data to C land 5th PC-98 Touhou boss completely decompiled, 26 to go! Part of P0200, funded by Yanga. --- th01/main/boss/b15j.cpp | 71 +++++++++++------------------- th01/main/boss/entity_a.hpp | 14 ++++-- th01_reiiden.asm | 86 ++----------------------------------- 3 files changed, 40 insertions(+), 131 deletions(-) diff --git a/th01/main/boss/b15j.cpp b/th01/main/boss/b15j.cpp index 4be5aa66..e5d02278 100644 --- a/th01/main/boss/b15j.cpp +++ b/th01/main/boss/b15j.cpp @@ -100,11 +100,17 @@ enum kikuri_hp_t { PHASE_6_END_HP = 0, }; +// Global boss state that is defined here for some reason +// ------------------------------------------------------ + +Palette4 boss_palette; +// ------------------------------------------------------ + // State that's suddenly no longer shared with other bosses // -------------------------------------------------------- #define boss_phase kikuri_phase -extern int8_t boss_phase; +int8_t boss_phase; // -------------------------------------------------------- // Entities @@ -115,14 +121,13 @@ static const int SOUL_CELS = 3; static const int TEAR_COUNT = 10; -#define tear_anim_frame kikuri_tear_anim_frame -#define souls kikuri_souls -#define tears kikuri_tears // Nonzero values are also used to indicate whether a given tear is alive. -extern int8_t tear_anim_frame[TEAR_COUNT]; +int8_t tear_anim_frame[TEAR_COUNT]; -extern CBossEntitySized souls[SOUL_COUNT + 3]; -extern CBossEntity tears[10]; +CBossEntity souls_raw[SOUL_COUNT + 3]; +CBossEntity tears[10]; + +#define souls reinterpret_cast *>(souls_raw) #define kikuri_ent_load(tmp_i) { \ souls[0].load("tamasii.bos", 0); \ @@ -175,8 +180,7 @@ enum kikuri_phase_4_subphase_t { _kikuri_phase_4_subphase_t_FORCE_INT16 = 0x7FFF }; -#define pattern_state kikuri_pattern_state -extern union { +union { int interval; int speed_multiplied_by_8; } pattern_state; @@ -513,13 +517,9 @@ inline void entrance_symmetric_line_1_to_0( void near pattern_symmetric_spiral_from_disc(void) { - #define angle pattern0_angle - #define drift pattern0_drift - #define distance pattern0_distance - - extern unsigned char angle; - extern unsigned char drift; - extern pixel_t distance; + static unsigned char angle; + static unsigned char drift; + static pixel_t distance; screen_x_t left; screen_y_t top; @@ -549,10 +549,6 @@ void near pattern_symmetric_spiral_from_disc(void) angle -= 0x08; drift++; } - - #undef distance - #undef drift - #undef angle } void near pattern_spinning_aimed_rings(void) @@ -740,9 +736,7 @@ void near pattern_souls_single_aimed_pellet_and_move_diagonally(void) int near pattern_4_spiral_along_disc(void) { - #define angle pattern6_angle - - extern unsigned char angle; + static unsigned char angle; if(boss_phase_frame < 100) { return 0; @@ -780,8 +774,6 @@ int near pattern_4_spiral_along_disc(void) } } return 0; - - #undef angle } int near pattern_single_lasers_from_left_eye(void) @@ -895,9 +887,7 @@ int near pattern_vertical_lasers_from_top(void) // [shootout_lasers] would be indexed out of bounds otherwise. static_assert(LASER_COUNT <= SHOOTOUT_LASER_COUNT); - #define random_range_x_half pattern9_random_range_x_half - - extern pixel_t random_range_x_half; + static pixel_t random_range_x_half; if(boss_phase_frame < KEYFRAME_START) { return 3; @@ -935,28 +925,20 @@ int near pattern_vertical_lasers_from_top(void) return 0; } return 3; - - #undef random_range_x_half } void kikuri_main(void) { - #define hit kikuri_hit - #define entrance_ring_radius_base kikuri_entrance_ring_radius_base - #define initial_hp_rendered kikuri_initial_hp_rendered - - struct hack { unsigned char col[4]; }; // XXX - - extern struct { + static struct { bool16 invincible; int invincibility_frame; - void update_and_render(const struct hack &flash_colors) { + void update_and_render(const unsigned char (&flash_colors)[4]) { boss_hit_update_and_render( invincibility_frame, invincible, boss_hp, - flash_colors.col, + flash_colors, sizeof(flash_colors), 7000, boss_nop, @@ -964,9 +946,9 @@ void kikuri_main(void) ); } } hit; - extern pixel_t entrance_ring_radius_base; - extern bool initial_hp_rendered; - extern struct { + static pixel_t entrance_ring_radius_base; + static bool initial_hp_rendered; + static struct { union { kikuri_phase_4_subphase_t subphase_4; int phase_6_pattern; @@ -977,11 +959,10 @@ void kikuri_main(void) boss_phase_frame++; hit.invincibility_frame++; } - } phase; - extern struct hack kikuri_invincibility_flash_colors; + } phase = { P4_SOUL_ACTIVATION, 0 }; int i; - struct hack flash_colors = kikuri_invincibility_flash_colors; + const unsigned char flash_colors[] = { 6, 11, 8, 2 }; // Entrance animation if(boss_phase == 0) { diff --git a/th01/main/boss/entity_a.hpp b/th01/main/boss/entity_a.hpp index f160553e..3ad87826 100644 --- a/th01/main/boss/entity_a.hpp +++ b/th01/main/boss/entity_a.hpp @@ -33,6 +33,8 @@ public: char zero_3; unsigned char bos_slot; + CBossEntity(); + // Even Turbo C++ 4.0J implements copy constructors for trivially // constructible types via an equivalent of memcpy() by default. This // constructor downgrades that to dumb single-member assignment, and is @@ -296,10 +298,14 @@ public: // Despite CBossEntity's own width and height fields, ZUN still likes to // statically hardcode the intended sprite sizes when calculating offsets -// within a .BOS sprite. Since bosses either declare their own instances or -// #define more readable names for each instance of [boss_entities], we might -// as well use the opportunity to lift up these static sizes into the type -// system, and avoid the need for per-boss boilerplate coordinate functions. +// within a .BOS sprite. Since bosses #define more readable names for each +// instance of [boss_entities], we might as well use the opportunity to lift up +// these static sizes into the type system, and avoid the need for per-boss +// boilerplate coordinate functions. +// +// (Due to CBossEntity unfortunately having a non-inlined default constructor, +// we can't ever directly declare instance of this template without emitting +// another constructor for this class.) template struct CBossEntitySized : public CBossEntity { screen_x_t cur_center_x(void) const { return (cur_left + (W / 2)); diff --git a/th01_reiiden.asm b/th01_reiiden.asm index badfcbf7..38d4cced 100644 --- a/th01_reiiden.asm +++ b/th01_reiiden.asm @@ -67,7 +67,6 @@ main_29 group main_29_TEXT, main_29__TEXT main_31 group main_31_TEXT, main_31__TEXT main_32 group main_32_TEXT, main_32__TEXT main_33 group main_33_TEXT, main_33__TEXT -main_34 group main_34_TEXT, main_34__TEXT ; =========================================================================== @@ -5086,7 +5085,7 @@ sub_17041 proc far CBossEntity__ctor boss_entity_3 CBossEntity__ctor boss_entity_4 push seg main_21 - push offset sub_17096 + push offset @CBossEntity@$bctr$qv push 5 pushd 5 push size CBossEntity @@ -5102,8 +5101,8 @@ sub_17041 endp ; =============== S U B R O U T I N E ======================================= ; Attributes: bp-based frame - -sub_17096 proc far +public @CBossEntity@$bctr$qv +@CBossEntity@$bctr$qv proc far arg_0 = dword ptr 6 @@ -5131,7 +5130,7 @@ loc_170C3: mov ax, word ptr [bp+arg_0] pop bp retf -sub_17096 endp +@CBossEntity@$bctr$qv endp main_21__TEXT ends @@ -14707,41 +14706,6 @@ main_34_TEXT segment byte public 'CODE' use16 extern @kikuri_main$qv:proc main_34_TEXT ends -main_34__TEXT segment byte public 'CODE' use16 - assume cs:main_34 - ;org 4 - assume es:nothing, ss:nothing, ds:_DATA, fs:nothing, gs:nothing - -; =============== S U B R O U T I N E ======================================= - -; Attributes: bp-based frame - -sub_24DFF proc far - push bp - mov bp, sp - push seg main_21 - push offset sub_17096 - push 5 - pushd 5 - push size CBossEntity - push ds - push offset _kikuri_souls - call @_vector_new_$qnvuiuluie ; _vector_new_(void *,uint,ulong,uint,...) - push seg main_21 - push offset sub_17096 - push 5 - pushd KIKURI_TEAR_COUNT - push size CBossEntity - push ds - push offset _kikuri_tears - call @_vector_new_$qnvuiuluie ; _vector_new_(void *,uint,ulong,uint,...) - add sp, 20h - pop bp - retf -sub_24DFF endp - -main_34__TEXT ends - ; =========================================================================== ; Segment type: Pure code @@ -15321,12 +15285,6 @@ aBoss1_bos db 'boss1.bos',0 aBoss1_2_bos db 'boss1_2.bos',0 aBoss1_3_bos db 'boss1_3.bos',0 aBoss1_grp_0 db 'boss1.grp',0 -public _phase -_phase label word - dw 0 ; ax - dw 0 ; phase_6_pattern -public _kikuri_invincibility_flash_color -_kikuri_invincibility_flash_color db 6, 11, 8, 2 extern _game_cleared:byte extern _unused_boss_stage_flag:word extern _pellet_destroy_score_delta:word @@ -15343,9 +15301,6 @@ _INIT_ segment word public 'INITDATA' use16 db 1 db 20h dd sub_21819 - db 1 - db 20h - dd sub_24DFF _INIT_ ends .data? @@ -15619,39 +15574,6 @@ speed_3A385 dw ? angle_3A387 db ? byte_3A388 db ? point_3A389 Point - db ? -public _boss_palette, _kikuri_phase -_boss_palette palette_t -_kikuri_phase db ? - -KIKURI_TEAR_COUNT = 10 - -public _kikuri_tear_anim_frame, _kikuri_souls, _kikuri_tears -_kikuri_tear_anim_frame db KIKURI_TEAR_COUNT dup(?) -_kikuri_souls CBossEntity 5 dup () -_kikuri_tears CBossEntity 10 dup () - -public _kikuri_pattern_state -_kikuri_pattern_state dw ? - -public _pattern0_angle, _pattern0_drift, _pattern0_distance -_pattern0_angle db ? -_pattern0_drift db ? -_pattern0_distance dw ? - -public _pattern6_angle -_pattern6_angle db ? - -public _pattern9_random_range_x_half -_pattern9_random_range_x_half dw ? - -public _kikuri_hit -public _kikuri_entrance_ring_radius_base, _kikuri_initial_hp_rendered -_kikuri_hit label byte - dw ? ; invincible - dw ? ; invincibility_frame -_kikuri_entrance_ring_radius_base dw ? -_kikuri_initial_hp_rendered db ? extern _boss_hp:word extern _boss_phase_frame:word extern _boss_phase:byte