From 023cdacc3640c035d5e55afb5478e0f4bbcf9f3c Mon Sep 17 00:00:00 2001 From: nmlgc Date: Wed, 9 Nov 2022 19:24:52 +0100 Subject: [PATCH] [Decompilation] [th03/th04/th05] Cutscenes: Script loading and freeing Part of P0223, funded by Blue Bolt and rosenrose. --- Makefile.mak | 8 ++-- th03/cutscene.cpp | 1 + th03/cutscene/cutscene.cpp | 37 +++++++++++++++++ th03/cutscene/cutscene.hpp | 14 +++++++ th03_mainl.asm | 82 ++++++-------------------------------- th04/cutscene.cpp | 1 + th04_maine.asm | 59 +++++---------------------- th05/cutscene.cpp | 1 + th05_maine.asm | 43 ++++---------------- 9 files changed, 87 insertions(+), 159 deletions(-) create mode 100644 th03/cutscene.cpp create mode 100644 th04/cutscene.cpp create mode 100644 th05/cutscene.cpp diff --git a/Makefile.mak b/Makefile.mak index cd952c08..549ef4ba 100644 --- a/Makefile.mak +++ b/Makefile.mak @@ -103,7 +103,7 @@ bin\th03\main.exe: bin\th03\main.obj th03\main_010.cpp th03\main_011.cpp bin\th0 $** | -bin\th03\mainl.exe: bin\th03\mainl.obj bin\th03\cfg_lres.obj bin\th03\scoredat.obj th03\regist.cpp bin\th01\vplanset.obj bin\th02\snd_mode.obj bin\th02\snd_pmdr.obj bin\th02\snd_dlyv.obj bin\th02\snd_load.obj bin\th03\vector2.obj bin\th03\exit.obj bin\th03\cdg_put.obj bin\th02\frmdely1.obj bin\th03\input_s.obj bin\th03\pi_put.obj bin\th03\pi_put_i.obj bin\th02\snd_se_r.obj bin\th03\snd_se.obj bin\th03\snd_kaja.obj bin\th03\initmain.obj bin\th03\cdg_load.obj th03\exitmain.cpp bin\th03\grppsafx.obj bin\th03\snd_dlym.obj bin\th03\inp_wait.obj bin\th03\pi_load.obj bin\th03\pi_put_q.obj bin\th03\inp_m_w.obj bin\th03\cdg_p_na.obj bin\th03\hfliplut.obj +bin\th03\mainl.exe: bin\th03\mainl.obj th03\cutscene.cpp bin\th03\cfg_lres.obj bin\th03\scoredat.obj th03\regist.cpp bin\th01\vplanset.obj bin\th02\snd_mode.obj bin\th02\snd_pmdr.obj bin\th02\snd_dlyv.obj bin\th02\snd_load.obj bin\th03\vector2.obj bin\th03\exit.obj bin\th03\cdg_put.obj bin\th02\frmdely1.obj bin\th03\input_s.obj bin\th03\pi_put.obj bin\th03\pi_put_i.obj bin\th02\snd_se_r.obj bin\th03\snd_se.obj bin\th03\snd_kaja.obj bin\th03\initmain.obj bin\th03\cdg_load.obj th03\exitmain.cpp bin\th03\grppsafx.obj bin\th03\snd_dlym.obj bin\th03\inp_wait.obj bin\th03\pi_load.obj bin\th03\pi_put_q.obj bin\th03\inp_m_w.obj bin\th03\cdg_p_na.obj bin\th03\hfliplut.obj $(CC) $(CFLAGS) $(LARGE_LFLAGS) -3 -Z -DGAME=3 -DBINARY='L' -nbin\th03\ -eMAINL.EXE @&&| $** | @@ -131,8 +131,8 @@ bin\th04\main.exe: bin\th04\main.obj bin\th04\slowdown.obj th04\demo.cpp th04\em $** | -bin\th04\maine.exe: bin\th04\maine.obj bin\th04\cfg_lres.obj th04\maine011.cpp bin\th01\vplanset.obj bin\th02\frmdely1.obj bin\th03\pi_put.obj bin\th04\cdg_put.obj bin\th04\exit.obj bin\th04\initmain.obj bin\th04\input_s.obj bin\th04\snd_se_r.obj bin\th04\snd_se.obj bin\th04\bgimage.obj bin\th04\bgimager.obj bin\th03\pi_load.obj bin\th03\pi_put_q.obj bin\th04\cdg_load.obj bin\th03\hfliplut.obj bin\th04\input_w.obj bin\th04\vector.obj bin\th04\snd_pmdr.obj bin\th04\snd_mmdr.obj bin\th04\snd_kaja.obj bin\th04\snd_mode.obj bin\th04\snd_dlym.obj bin\th04\cdg_p_pl.obj bin\th04\snd_load.obj - $(CC) $(CFLAGS) $(LARGE_LFLAGS) -DGAME=4 -DBINARY='E' -Z -nbin\th04\ -eMAINE.EXE @&&| +bin\th04\maine.exe: bin\th04\maine.obj bin\th04\cfg_lres.obj th04\cutscene.cpp th04\maine011.cpp bin\th01\vplanset.obj bin\th02\frmdely1.obj bin\th03\pi_put.obj bin\th04\cdg_put.obj bin\th04\exit.obj bin\th04\initmain.obj bin\th04\input_s.obj bin\th04\snd_se_r.obj bin\th04\snd_se.obj bin\th04\bgimage.obj bin\th04\bgimager.obj bin\th03\pi_load.obj bin\th03\pi_put_q.obj bin\th04\cdg_load.obj bin\th03\hfliplut.obj bin\th04\input_w.obj bin\th04\vector.obj bin\th04\snd_pmdr.obj bin\th04\snd_mmdr.obj bin\th04\snd_kaja.obj bin\th04\snd_mode.obj bin\th04\snd_dlym.obj bin\th04\cdg_p_pl.obj bin\th04\snd_load.obj + $(CC) $(CFLAGS) $(LARGE_LFLAGS) -DGAME=4 -DBINARY='E' -3 -Z -nbin\th04\ -eMAINE.EXE @&&| $** | @@ -154,7 +154,7 @@ bin\th05\main.exe: bin\th05\main.obj bin\th04\slowdown.obj th05\demo.cpp th05\em $** | -bin\th05\maine.exe: bin\th05\maine.obj bin\th04\cfg_lres.obj th05\maine011.cpp th05\regist.cpp th05\staff.cpp bin\th04\cdg_p_na.obj bin\th04\snd_se_r.obj bin\th04\snd_se.obj bin\th04\bgimage.obj bin\th04\exit.obj bin\th05\vector.obj bin\th05\bgimager.obj bin\th05\snd_load.obj bin\th05\snd_kaja.obj bin\th05\pi_cpp_1.obj bin\th05\pi_asm_1.obj bin\th05\pi_cpp_2.obj bin\th05\pi_asm_2.obj bin\th05\initmain.obj bin\th05\input_s.obj bin\th05\inp_h_w.obj bin\th05\snd_dlym.obj bin\th05\frmdelay.obj bin\th04\cdg_load.obj bin\th05\egcrect.obj bin\th03\hfliplut.obj bin\th04\snd_pmdr.obj bin\th04\snd_mmdr.obj bin\th04\snd_mode.obj +bin\th05\maine.exe: bin\th05\maine.obj th05\cutscene.cpp bin\th04\cfg_lres.obj th05\maine011.cpp th05\regist.cpp th05\staff.cpp bin\th04\cdg_p_na.obj bin\th04\snd_se_r.obj bin\th04\snd_se.obj bin\th04\bgimage.obj bin\th04\exit.obj bin\th05\vector.obj bin\th05\bgimager.obj bin\th05\snd_load.obj bin\th05\snd_kaja.obj bin\th05\pi_cpp_1.obj bin\th05\pi_asm_1.obj bin\th05\pi_cpp_2.obj bin\th05\pi_asm_2.obj bin\th05\initmain.obj bin\th05\input_s.obj bin\th05\inp_h_w.obj bin\th05\snd_dlym.obj bin\th05\frmdelay.obj bin\th04\cdg_load.obj bin\th05\egcrect.obj bin\th03\hfliplut.obj bin\th04\snd_pmdr.obj bin\th04\snd_mmdr.obj bin\th04\snd_mode.obj $(CC) $(CFLAGS) $(LARGE_LFLAGS) -DGAME=5 -DBINARY='E' -3 -Z -nbin\th05\ -eMAINE.EXE @&&| $** | diff --git a/th03/cutscene.cpp b/th03/cutscene.cpp new file mode 100644 index 00000000..be95bcf2 --- /dev/null +++ b/th03/cutscene.cpp @@ -0,0 +1 @@ +#include "th03/cutscene/cutscene.cpp" diff --git a/th03/cutscene/cutscene.cpp b/th03/cutscene/cutscene.cpp index 6535f6d9..a18d80a5 100644 --- a/th03/cutscene/cutscene.cpp +++ b/th03/cutscene/cutscene.cpp @@ -4,11 +4,16 @@ // 1) TH03 and TH04 allocate dedicated memory for backing up the text box area // in VRAM ([box_bg]), TH05 uses the bgimage system instead. +#include #include "platform.h" #include "pc98.h" #include "planar.h" #include "shiftjis.hpp" #include "master.hpp" +extern "C" { +#include "th02/hardware/frmdelay.h" +} +#include "th03/cutscene/cutscene.hpp" // State // ----- @@ -46,3 +51,35 @@ extern int script_number_param_default; void near box_1_to_0_animate(void); #endif // ----------------------- + +bool16 pascal near cutscene_script_load(const char* fn) +{ + cutscene_script_free(); + + if(!file_ropen(fn)) { + return true; + } + size_t size = file_size(); + #if (GAME >= 4) + // PORTERS: Required for TH03 on flat memory models as well. + // ZUN bug: Missing an error check if [size] >= sizeof(script); + script_p = static_cast(script); + #else + script = reinterpret_cast(hmem_allocbyte(size)); + #endif + file_read(script_p, size); + file_close(); + return false; +} + +#if (GAME <= 4) + void near cutscene_script_free(void) + { + #if (GAME == 3) + if(script) { + HMem::free(script); + script = nullptr; + } + #endif + } +#endif diff --git a/th03/cutscene/cutscene.hpp b/th03/cutscene/cutscene.hpp index 7bc41c41..ca4daa99 100644 --- a/th03/cutscene/cutscene.hpp +++ b/th03/cutscene/cutscene.hpp @@ -37,6 +37,20 @@ extern screen_point_t cursor; extern int text_interval; +// Loads the cutscene script from the given file, returning `false` on success. +// TH03 frees the previously loaded script and allocates a new one with [fn]'s +// file size before loading it from the file. +bool16 pascal near cutscene_script_load(const char *fn); + +// Frees the cutscene script. No-op in TH04 and TH05, where it's statically +// allocated. +#if (GAME == 5) + inline void cutscene_script_free() { + } +#else + void near cutscene_script_free(); +#endif + // ZUN quirk: The cutscene system features both // 1) a top-level input sensing mechanism (for updating the fast-forward flag), // and diff --git a/th03_mainl.asm b/th03_mainl.asm index 1ad8da1f..6d695cc8 100644 --- a/th03_mainl.asm +++ b/th03_mainl.asm @@ -27,7 +27,7 @@ include th03/formats/scoredat.inc extern _execl:proc extern _tolower:proc -group_01 group CFG_LRES_TEXT, mainl_01_TEXT, SCOREDAT_TEXT, REGIST_TEXT, mainl_03_TEXT +group_01 group CFG_LRES_TEXT, CUTSCENE_TEXT, mainl_01_TEXT, SCOREDAT_TEXT, REGIST_TEXT, mainl_03_TEXT ; =========================================================================== @@ -135,7 +135,7 @@ CFG_LRES_TEXT segment byte public 'CODE' use16 CFG_LRES_TEXT ends ; Segment type: Pure code -mainl_01_TEXT segment byte public 'CODE' use16 +CUTSCENE_TEXT segment byte public 'CODE' use16 assume cs:group_01 ;org 3 assume es:nothing, ss:nothing, ds:_DATA, fs:nothing, gs:nothing @@ -998,10 +998,9 @@ loc_9EF1: graph_showpage al call graph_clear call graph_show - pushd [off_E4B6] - call sub_A12E + call @cutscene_script_load$qnxc pascal, [off_E4B6] call sub_AC6E - call sub_A174 + call @cutscene_script_free$qv call sub_990C call sub_9A2C call gaiji_restore @@ -1197,66 +1196,12 @@ loc_A12A: retn sub_9F8D endp + @CUTSCENE_SCRIPT_LOAD$QNXC procdesc pascal near \ + fn:dword + @cutscene_script_free$qv procdesc near +CUTSCENE_TEXT ends -; =============== S U B R O U T I N E ======================================= - -; Attributes: bp-based frame - -sub_A12E proc near - -arg_0 = dword ptr 4 - - push bp - mov bp, sp - push si - call sub_A174 - pushd [bp+arg_0] - call file_ropen - or ax, ax - jnz short loc_A147 - mov ax, 1 - jmp short loc_A16F -; --------------------------------------------------------------------------- - -loc_A147: - call file_size - mov si, ax - push ax - call hmem_allocbyte - mov word ptr _script+2, ax - mov word ptr _script, 0 - push ax - push word ptr _script - push si - call file_read - call file_close - xor ax, ax - -loc_A16F: - pop si - pop bp - retn 4 -sub_A12E endp - - -; =============== S U B R O U T I N E ======================================= - -; Attributes: bp-based frame - -sub_A174 proc near - push bp - mov bp, sp - cmp _script, 0 - jz short loc_A191 - push word ptr _script+2 - call hmem_free - mov _script, 0 - -loc_A191: - pop bp - retn -sub_A174 endp - +mainl_01_TEXT segment byte public 'CODE' use16 EGC_START_COPY_DEF 1, near ; =============== S U B R O U T I N E ======================================= @@ -2878,10 +2823,9 @@ loc_B9DD: graph_showpage al call graph_clear call graph_show - pushd [off_EE4E] - call sub_A12E + call @cutscene_script_load$qnxc pascal, [off_EE4E] call sub_AC6E - call sub_A174 + call @cutscene_script_free$qv call sub_C40D les bx, _resident mov es:[bx+resident_t.story_stage], STAGE_ALL @@ -2898,9 +2842,9 @@ loc_B9DD: graph_showpage 0 push ds push offset a@99ed_txt ; "@99ED.TXT" - call sub_A12E + call @cutscene_script_load$qnxc call sub_AC6E - call sub_A174 + call @cutscene_script_free$qv loc_BA66: call text_clear diff --git a/th04/cutscene.cpp b/th04/cutscene.cpp new file mode 100644 index 00000000..be95bcf2 --- /dev/null +++ b/th04/cutscene.cpp @@ -0,0 +1 @@ +#include "th03/cutscene/cutscene.cpp" diff --git a/th04_maine.asm b/th04_maine.asm index 45c35f64..5a72b023 100644 --- a/th04_maine.asm +++ b/th04_maine.asm @@ -26,7 +26,7 @@ include th04/hardware/grppsafx.inc extern _tolower:proc extern __ctype:byte -maine_01 group CFG_LRES_TEXT, maine_01_TEXT, maine_01__TEXT +maine_01 group CFG_LRES_TEXT, CUTSCENE_TEXT, maine_01_TEXT, maine_01__TEXT g_SHARED group SHARED, SHARED_ ; =========================================================================== @@ -152,7 +152,7 @@ CFG_LRES_TEXT segment byte public 'CODE' use16 CFG_LRES_TEXT ends ; Segment type: Pure code -maine_01_TEXT segment byte public 'CODE' use16 +CUTSCENE_TEXT segment byte public 'CODE' use16 assume cs:maine_01 ;org 9 assume es:nothing, ss:nothing, ds:_DATA, fs:nothing, gs:nothing @@ -205,9 +205,9 @@ sub_A0BD proc near mov es:[bx+5], al push word ptr off_E5C0+2 push bx - call sub_A292 + call @cutscene_script_load$qnxc call sub_ADFC - call sub_A2D1 + call @cutscene_script_free$qv pop bp retn sub_A0BD endp @@ -333,53 +333,12 @@ locret_A290: retf _main endp + @CUTSCENE_SCRIPT_LOAD$QNXC procdesc pascal near \ + fn:dword + @cutscene_script_free$qv procdesc near +CUTSCENE_TEXT ends -; =============== S U B R O U T I N E ======================================= - -; Attributes: bp-based frame - -sub_A292 proc near - -var_2 = word ptr -2 -arg_0 = dword ptr 4 - - enter 2, 0 - call sub_A2D1 - pushd [bp+arg_0] - call file_ropen - or ax, ax - jnz short loc_A2AD - mov ax, 1 - leave - retn 4 -; --------------------------------------------------------------------------- - -loc_A2AD: - call file_size - mov [bp+var_2], ax - mov _script_p, offset _script - push ds - push _script_p - push ax - call file_read - call file_close - xor ax, ax - leave - retn 4 -sub_A292 endp - - -; =============== S U B R O U T I N E ======================================= - -; Attributes: bp-based frame - -sub_A2D1 proc near - push bp - mov bp, sp - pop bp - retn -sub_A2D1 endp - +maine_01_TEXT segment byte public 'CODE' use16 EGC_START_COPY_DEF 1, near ; =============== S U B R O U T I N E ======================================= diff --git a/th05/cutscene.cpp b/th05/cutscene.cpp new file mode 100644 index 00000000..be95bcf2 --- /dev/null +++ b/th05/cutscene.cpp @@ -0,0 +1 @@ +#include "th03/cutscene/cutscene.cpp" diff --git a/th05_maine.asm b/th05_maine.asm index a42a0495..7f70d772 100644 --- a/th05_maine.asm +++ b/th05_maine.asm @@ -27,7 +27,7 @@ include th04/hardware/grppsafx.inc extern _tolower:proc extern __ctype:byte -maine_01 group CFG_LRES_TEXT, maine_01_TEXT, maine_01__TEXT, maine_01___TEXT +maine_01 group CFG_LRES_TEXT, CUTSCENE_TEXT, maine_01_TEXT, maine_01__TEXT, maine_01___TEXT g_SHARED group SHARED, SHARED_ ; =========================================================================== @@ -159,7 +159,7 @@ CFG_LRES_TEXT segment byte public 'CODE' use16 CFG_LRES_TEXT ends ; Segment type: Pure code -maine_01_TEXT segment byte public 'CODE' use16 +CUTSCENE_TEXT segment byte public 'CODE' use16 assume cs:maine_01 ;org 5 assume es:nothing, ss:nothing, ds:_DATA, fs:nothing, gs:nothing @@ -225,7 +225,7 @@ loc_A5DC: mov es:[bx+4], al push word ptr off_10190+2 push bx - call sub_A695 + call @cutscene_script_load$qnxc call sub_AFD6 pop bp retn @@ -301,40 +301,11 @@ loc_A693: retf _main endp + @CUTSCENE_SCRIPT_LOAD$QNXC procdesc pascal near \ + fn:dword +CUTSCENE_TEXT ends -; =============== S U B R O U T I N E ======================================= - -; Attributes: bp-based frame - -sub_A695 proc near - -var_2 = word ptr -2 -arg_0 = dword ptr 4 - - enter 2, 0 - pushd [bp+arg_0] - call file_ropen - or ax, ax - jnz short loc_A6AD - mov ax, 1 - leave - retn 4 -; --------------------------------------------------------------------------- - -loc_A6AD: - call file_size - mov [bp+var_2], ax - mov _script_p, offset _script - push ds - push _script_p - push ax - call file_read - call file_close - xor ax, ax - leave - retn 4 -sub_A695 endp - +maine_01_TEXT segment byte public 'CODE' use16 EGC_START_COPY_DEF 1, near ; =============== S U B R O U T I N E =======================================