From 63e92572796cffb2c698b27674f1627bc24cce97 Mon Sep 17 00:00:00 2001 From: nmlgc Date: Thu, 12 Oct 2023 02:36:32 +0200 Subject: [PATCH] [Decompilation] [th04/th05] Dialog: Blocking main function Part of P0259, funded by Splashman and Yanga. --- th04/main/demo.hpp | 13 +++--- th04/main/dialog/first.cpp | 20 +++++++++ th04/main/dialog/shared.cpp | 9 +--- th04/main/dialog/shared.hpp | 13 ++++++ th04_main.asm | 33 +-------------- th05/main/dialog/first.cpp | 60 +++++++++++++++++++++++++++ th05/shiftjis/fns.hpp | 6 +++ th05_main.asm | 83 ++++++------------------------------- 8 files changed, 119 insertions(+), 118 deletions(-) diff --git a/th04/main/demo.hpp b/th04/main/demo.hpp index ff2f1f60..2e65cca7 100644 --- a/th04/main/demo.hpp +++ b/th04/main/demo.hpp @@ -1,11 +1,10 @@ // Properly declared, DEMO?.REC uses this structure: -// -// template struct REC { -// input_replay_t input[Frames]; -// bool shift[Frames]; -// }; -// -// This declaration would also work with the overly large TH05 Extra Stage +template struct REC { + input_replay_t input[Frames]; + bool shift[Frames]; +}; + +// The above declaration would also work with the overly long TH05 Extra Stage // Clear replay. However, ZUN not only uses the same pointer for both that // replay and regular ones, he also only accesses the [shift] flag via adding // either DEMO_N or DEMO_N_EXTRA to the stage frame index. TH05 calculates that diff --git a/th04/main/dialog/first.cpp b/th04/main/dialog/first.cpp index 2b9405c5..17c9ff05 100644 --- a/th04/main/dialog/first.cpp +++ b/th04/main/dialog/first.cpp @@ -227,3 +227,23 @@ void near dialog_run(void) } overlay_wipe(); } + +void dialog_animate(void) +{ + dialog_init(); + dialog_pre(); + dialog_run(); + + /* TODO: Replace with the decompiled call + * tiles_activate_and_render_all_for_next_N_frames(2); + * once that function is part of the same segment */ + _asm { + push 2; + nop; + push cs; + call near ptr tiles_activate_and_render_all_for_next_N_frames; + } + + dialog_exit(); + dialog_post(); +} diff --git a/th04/main/dialog/shared.cpp b/th04/main/dialog/shared.cpp index e0f2e96d..e1cdd413 100644 --- a/th04/main/dialog/shared.cpp +++ b/th04/main/dialog/shared.cpp @@ -27,14 +27,7 @@ bool near std_update_frames_then_animate_dialog_and_activate_boss_if_done(void) } #endif - /* TODO: Replace with the decompiled call - * dialog_animate(); - * once that function is part of this translation unit */ - _asm { - nop; - push cs; - call near ptr dialog_animate; - } + dialog_animate(); std_update = std_update_done; bg_render_not_bombing = boss_bg_render_func; diff --git a/th04/main/dialog/shared.hpp b/th04/main/dialog/shared.hpp index c7267416..a3a8a84c 100644 --- a/th04/main/dialog/shared.hpp +++ b/th04/main/dialog/shared.hpp @@ -167,6 +167,19 @@ inline void dialog_text_put(shiftjis_t* const& text) { } \ } +inline void dialog_pre(void) { + overlay_wipe(); + palette_settone(100); + graph_accesspage(page_front); + dialog_box_fade_in_animate(); + playfield_copy_front_to_back(); +} + +inline void dialog_post(void) { + graph_accesspage(page_back); + frame_delay(1); +} + // Script commands // --------------- diff --git a/th04_main.asm b/th04_main.asm index 08504a5a..c17dbcb7 100644 --- a/th04_main.asm +++ b/th04_main.asm @@ -1764,7 +1764,6 @@ public @TILES_RENDER$QV @tiles_render$qv endp extern @tiles_activate$qv:proc - extern @TILES_ACTIVATE_AND_RENDER_ALL_FO$QUC:proc TILE_TEXT ends mai_TEXT segment word public 'CODE' use16 @@ -1905,37 +1904,7 @@ DIALOG_TEXT segment byte public 'CODE' use16 extern @dialog_load_yuuka5_defeat_bad$qv:proc @dialog_free$qv procdesc near @std_update_frames_then_animate_d$qv procdesc near - @playfield_copy_front_to_back$qv procdesc near - @dialog_box_fade_in_animate$qv procdesc near - @dialog_run$qv procdesc pascal near - -; =============== S U B R O U T I N E ======================================= - -; Attributes: bp-based frame -public @dialog_animate$qv -@dialog_animate$qv proc far - push bp - mov bp, sp - call @dialog_init$qv - call @overlay_wipe$qv - mov PaletteTone, 100 - call far ptr palette_show - graph_accesspage _page_front - call @dialog_box_fade_in_animate$qv - call @playfield_copy_front_to_back$qv - call @dialog_run$qv - push 2 - nopcall @tiles_activate_and_render_all_fo$quc - call @dialog_exit$qv - graph_accesspage _page_back - push 1 - call frame_delay - pop bp - retf -@dialog_animate$qv endp - - @dialog_init$qv procdesc near - @dialog_exit$qv procdesc near + extern @dialog_animate$qv:proc DIALOG_TEXT ends BOSS_EXP_TEXT segment byte public 'CODE' use16 diff --git a/th05/main/dialog/first.cpp b/th05/main/dialog/first.cpp index ea0bd5c0..9b6d94e1 100644 --- a/th05/main/dialog/first.cpp +++ b/th05/main/dialog/first.cpp @@ -8,8 +8,13 @@ void near main_pat_exalice_override_and_super_clean_stage(void); // ----------------------- #include +#include "th02/main/execl.hpp" #include "th04/main/dialog/shared.cpp" +#include "th04/main/demo.hpp" +#include "th04/score.h" +#include "th05/mem.h" #include "th05/playchar.h" +#include "th05/resident.hpp" #include "th05/formats/dialog.hpp" #include "th05/main/dialog/dialog.hpp" #include "th05/sprites/main_pat.h" @@ -225,3 +230,58 @@ void near dialog_run(void) } overlay_wipe(); } + +void dialog_animate(void) +{ + // If we get here during a replay, we assume it's the hidden Extra Stage + // one because it's the only one that's long enough, and then skip the + // dialog. + // You might argue that this is gross and ZUN should have just added a + // proper skip feature that would still run through the script for its side + // effects, but the only bad aspect I can see is that this happens here and + // not at the call site. In regular gameplay, the (hardcoded) boss render + // functions rely on the dialog scripts for loading their sprites at the + // intended patnums, so it would have made much more sense to hardcode all + // of these load calls and completely remove the dependency on game data. + if(resident->demo_num != 0) { + extern int8_t dialog_sequence_id; + if(dialog_sequence_id == 0) { + // Pre-boss. Replicate all asset load calls that would be done if + // `_DM06.TX2` would run normally, ... + #undef BGM_EXTRA_BOSS_FN + #undef DEMO_EXTRA_PART_2_FN + extern const char st06_bb1[]; + extern const char st06_bb2[]; + extern const char BGM_EXTRA_BOSS_FN[]; + extern const char DEMO_EXTRA_PART_2_FN[]; + + main_pat_exalice_override_and_super_clean_stage(); + super_entry_bfnt(st06_bb1); + super_entry_bfnt(st06_bb2); + snd_load(BGM_EXTRA_BOSS_FN, SND_LOAD_SONG); + snd_kaja_func(KAJA_SONG_PLAY, 0); + + // ... then load the second half of the replay. + // ZUN bloat: This could have definitely been integrated into + // demo_load(), including the avoided reallocation. + file_ropen(DEMO_EXTRA_PART_2_FN); + file_read(DemoBuf, (DEMO_N_EXTRA * sizeof(REC<1>))); + file_close(); + stage_frame = 0; // This is actually the index into [DemoBuf]. + dialog_sequence_id++; + } else { + // Post-boss. Just return to the title screen. + #undef BINARY_OP + #define BINARY_OP DIALOG_BINARY_OP + extern const char BINARY_OP[]; + demo_end(); + } + return; + } + + cdg_free(CDG_BG_PLAYCHAR_BOMB); // "dialog_init()" + dialog_pre(); + dialog_run(); + dialog_exit(); + dialog_post(); +} diff --git a/th05/shiftjis/fns.hpp b/th05/shiftjis/fns.hpp index 075941ba..471207a1 100644 --- a/th05/shiftjis/fns.hpp +++ b/th05/shiftjis/fns.hpp @@ -1,3 +1,9 @@ +#define BINARY_OP "op" + +#define BGM_EXTRA_BOSS_FN "st06b" + +#define DEMO_EXTRA_PART_2_FN "DEMO5.REC" + #define EYECATCH_FN "eye.cdg" #define FACESET_PLAYCHAR_FORMAT "KaO0.cD2" diff --git a/th05_main.asm b/th05_main.asm index 03dd44f4..e38d645f 100644 --- a/th05_main.asm +++ b/th05_main.asm @@ -3183,69 +3183,7 @@ DIALOG_TEXT segment byte public 'CODE' use16 @dialog_load$qv procdesc near @dialog_free$qv procdesc near @std_update_frames_then_animate_d$qv procdesc near - @playfield_copy_front_to_back$qv procdesc near - @dialog_box_fade_in_animate$qv procdesc near - @dialog_run$qv procdesc near - -; =============== S U B R O U T I N E ======================================= - -; Attributes: bp-based frame -public @dialog_animate$qv -@dialog_animate$qv proc far - push bp - mov bp, sp - les bx, _resident - cmp es:[bx+resident_t.demo_num], 0 - jz short loc_F333 - cmp byte_221EC, 0 - jnz short loc_F318 - call @main_pat_exalice_override_and_su$qv - call super_entry_bfnt pascal, ds, offset aSt06_bb1 ; "st06.bb1" - call super_entry_bfnt pascal, ds, offset aSt06_bb2 ; "st06.bb2" - call snd_load pascal, ds, offset aSt06b, SND_LOAD_SONG - kajacall KAJA_SONG_PLAY - push ds - push offset aDemo5_rec ; "DEMO5.REC" - call file_ropen - call file_read pascal, large [_DemoBuf], (DEMO_N * 4) * 2 - call file_close - mov _stage_frame, 0 - inc byte_221EC - pop bp - retf -; --------------------------------------------------------------------------- - -loc_F318: - push word ptr _DemoBuf+2 - call hmem_free - push 8 - call palette_black_out - push ds - push offset aOp_0 ; "op" - nopcall @GameExecl$qnxc - pop bp - retf -; --------------------------------------------------------------------------- - -loc_F333: - call cdg_free pascal, CDG_BG_PLAYCHAR_BOMB - call @overlay_wipe$qv - mov PaletteTone, 100 - call far ptr palette_show - graph_accesspage _page_front - call @dialog_box_fade_in_animate$qv - call @playfield_copy_front_to_back$qv - call @dialog_run$qv - call @dialog_exit$qv - graph_accesspage _page_back - push 1 - call frame_delay - pop bp - retf -@dialog_animate$qv endp - - @dialog_exit$qv procdesc near - @main_pat_exalice_override_and_su$qv procdesc near + extern @dialog_animate$qv:proc DIALOG_TEXT ends BOSS_EXP_TEXT segment byte public 'CODE' use16 @@ -19882,16 +19820,19 @@ include th04/main/frames[data].asm public _dialog_fn _dialog_fn dd a_dm00_tx2 include th04/main/dialog/dialog[data].asm -byte_221EC db 0 +public _dialog_sequence_id +_dialog_sequence_id db 0 a_dm00_tx2 db '_DM00.TX2',0 -public _dialog_kanji_buf + +public _dialog_kanji_buf, _st06_bb1, _st06_bb2, _BGM_EXTRA_BOSS_FN +public _DEMO_EXTRA_PART_2_FN, _DIALOG_BINARY_OP _dialog_kanji_buf db ' ',0 -aSt06_bb1 db 'st06.bb1',0 -aSt06_bb2 db 'st06.bb2',0 -aSt06b db 'st06b',0 -aDemo5_rec db 'DEMO5.REC',0 -; char aOp_0[] -aOp_0 db 'op',0 +_st06_bb1 db 'st06.bb1',0 +_st06_bb2 db 'st06.bb2',0 +_BGM_EXTRA_BOSS_FN db 'st06b',0 +_DEMO_EXTRA_PART_2_FN db 'DEMO5.REC',0 +_DIALOG_BINARY_OP db 'op',0 + public _faceset_boss_format, _faceset_playchar_format public _BOMB_BG_REIMU_FN, _BOMB_BG_MARISA_FN, _BOMB_BG_MIMA_FN public _BOMB_BG_YUUKA_FN, _MIKO16_EXALICE_FN