Skip to content

Commit

Permalink
[Decompilation] [th04/th05] Dialog: Script loading functions
Browse files Browse the repository at this point in the history
Part of P0186, funded by [Anonymous] and Blue Bolt.
  • Loading branch information
nmlgc committed Mar 26, 2022
1 parent b33631d commit 903d824
Show file tree
Hide file tree
Showing 9 changed files with 135 additions and 179 deletions.
4 changes: 2 additions & 2 deletions Makefile.mak
Expand Up @@ -126,7 +126,7 @@ bin\th04\op.exe: bin\th04\op.obj th04\m_char.cpp bin\th01\vplanset.obj bin\th02\
$**
|

bin\th04\main.exe: bin\th04\main.obj bin\th04\slowdown.obj th04\ems.cpp th04\playfld.cpp th04\dialog.cpp bin\th04\player_p.obj bin\th04\scoreupd.obj th04\hud_ovrl.cpp bin\th04\cfg_lres.obj bin\th01\vplanset.obj bin\th03\vector2.obj bin\th02\frmdely1.obj bin\th03\hfliplut.obj th04\mpn_free.cpp bin\th04\input_w.obj th04\mpn_l_i.cpp 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_load.obj bin\th04\cdg_put.obj bin\th04\exit.obj bin\th04\initmain.obj bin\th04\cdg_p_na.obj bin\th04\cdg_p_pr.obj bin\th04\input_s.obj bin\th04\snd_se_r.obj bin\th04\snd_se.obj bin\th04\cdg_load.obj th04\gather.cpp bin\th04\scrolly3.obj bin\th04\motion_3.obj th04\mb_dft.cpp bin\th04\it_spl_u.obj th04\bullet_u.cpp th04\bullet_a.cpp
bin\th04\main.exe: bin\th04\main.obj bin\th04\slowdown.obj th04\ems.cpp th04\playfld.cpp th04\f_dialog.cpp th04\dialog.cpp bin\th04\player_p.obj bin\th04\scoreupd.obj th04\hud_ovrl.cpp bin\th04\cfg_lres.obj bin\th01\vplanset.obj bin\th03\vector2.obj bin\th02\frmdely1.obj bin\th03\hfliplut.obj th04\mpn_free.cpp bin\th04\input_w.obj th04\mpn_l_i.cpp 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_load.obj bin\th04\cdg_put.obj bin\th04\exit.obj bin\th04\initmain.obj bin\th04\cdg_p_na.obj bin\th04\cdg_p_pr.obj bin\th04\input_s.obj bin\th04\snd_se_r.obj bin\th04\snd_se.obj bin\th04\cdg_load.obj th04\gather.cpp bin\th04\scrolly3.obj bin\th04\motion_3.obj th04\mb_dft.cpp bin\th04\it_spl_u.obj th04\bullet_u.cpp th04\bullet_a.cpp
$(CC) $(CFLAGS) $(LARGE_LFLAGS) -DGAME=4 -DBINARY='M' -3 -Z -nbin\th04\ -eMAIN.EXE @&&|
$**
|
Expand All @@ -149,7 +149,7 @@ bin\th05\op.exe: th05\op010.cpp bin\th05\op.obj th05\op011.cpp th05\m_char.cpp b
$**
|

bin\th05\main.exe: bin\th05\main.obj bin\th04\slowdown.obj th05\ems.cpp bin\th05\cfg_lres.obj th05\main010.cpp th05\dialog.cpp th05\playfld.cpp th05\main011.cpp th05\p_common.cpp th05\p_reimu.cpp th05\p_marisa.cpp th05\p_mima.cpp th05\p_yuuka.cpp bin\th05\player.obj bin\th05\hud_bar.obj bin\th05\scoreupd.obj th05\hud_ovrl.cpp bin\th04\player_p.obj th05\main014.cpp th05\player_a.cpp bin\th05\bullet_1.obj th05\bullet_c.cpp bin\th03\vector2.obj bin\th03\hfliplut.obj bin\th04\snd_pmdr.obj bin\th04\snd_mmdr.obj bin\th04\snd_mode.obj bin\th05\bullet.obj th05\bullet_t.cpp bin\th04\cdg_p_na.obj bin\th04\snd_se_r.obj bin\th04\snd_se.obj bin\th05\cdg_put.obj bin\th04\exit.obj bin\th05\vector.obj bin\th05\snd_load.obj bin\th05\snd_kaja.obj bin\th05\initmain.obj bin\th05\input_s.obj bin\th05\inp_h_w.obj bin\th05\frmdelay.obj bin\th04\cdg_load.obj bin\th04\scrolly3.obj bin\th04\motion_3.obj th05\gather.cpp th05\main032.cpp th05\mb_dft.cpp th05\laser_sc.cpp th05\curveb_u.cpp bin\th04\it_spl_u.obj th05\bullet_u.cpp th05\main034.cpp th05\main035.cpp th05\boss.cpp
bin\th05\main.exe: bin\th05\main.obj bin\th04\slowdown.obj th05\ems.cpp bin\th05\cfg_lres.obj th05\main010.cpp th05\f_dialog.cpp th05\dialog.cpp th05\playfld.cpp th05\main011.cpp th05\p_common.cpp th05\p_reimu.cpp th05\p_marisa.cpp th05\p_mima.cpp th05\p_yuuka.cpp bin\th05\player.obj bin\th05\hud_bar.obj bin\th05\scoreupd.obj th05\hud_ovrl.cpp bin\th04\player_p.obj th05\main014.cpp th05\player_a.cpp bin\th05\bullet_1.obj th05\bullet_c.cpp bin\th03\vector2.obj bin\th03\hfliplut.obj bin\th04\snd_pmdr.obj bin\th04\snd_mmdr.obj bin\th04\snd_mode.obj bin\th05\bullet.obj th05\bullet_t.cpp bin\th04\cdg_p_na.obj bin\th04\snd_se_r.obj bin\th04\snd_se.obj bin\th05\cdg_put.obj bin\th04\exit.obj bin\th05\vector.obj bin\th05\snd_load.obj bin\th05\snd_kaja.obj bin\th05\initmain.obj bin\th05\input_s.obj bin\th05\inp_h_w.obj bin\th05\frmdelay.obj bin\th04\cdg_load.obj bin\th04\scrolly3.obj bin\th04\motion_3.obj th05\gather.cpp th05\main032.cpp th05\mb_dft.cpp th05\laser_sc.cpp th05\curveb_u.cpp bin\th04\it_spl_u.obj th05\bullet_u.cpp th05\main034.cpp th05\main035.cpp th05\boss.cpp
$(CC) $(CFLAGS) $(LARGE_LFLAGS) -3 -Z -DGAME=5 -DBINARY='M' -nbin\th05\ -eMAIN.EXE @&&|
$**
|
Expand Down
1 change: 1 addition & 0 deletions th04/f_dialog.cpp
@@ -0,0 +1 @@
#include "th04/formats/dialog.cpp"
43 changes: 43 additions & 0 deletions th04/formats/dialog.cpp
@@ -0,0 +1,43 @@
#pragma option -zCmain_TEXT

#include <stddef.h>
#include "platform.h"
#include "master.hpp"
#include "th04/score.h"
#include "th04/resident.hpp"
#include "th04/formats/dialog.hpp"

void pascal near dialog_load(const char *fn)
{
size_t size;

// While hmem_free() isn't specified to perform a NULL check, it does in
// practice. So while this is *technically* fine, it's not the cleanest
// solution. Fixed in TH05.
hmem_free(reinterpret_cast<void __seg *>(dialog_p));

file_ropen(fn);
size = file_size();
dialog_p = reinterpret_cast<unsigned char far *>(hmem_allocbyte(size));
file_read(dialog_p, size);
file_close();
}

void near dialog_load(void)
{
#define fn dialog_fn
extern char *fn;
dialog_fn[3] = resident->playchar_ascii;
dialog_fn[4] = resident->stage_ascii;
dialog_load(dialog_fn);
#undef fn
}

void dialog_load_yuuka5_defeat_bad(void)
{
#define fn dialog_fn_yuuka5_defeat_bad
extern char *fn;
fn[3] = resident->playchar_ascii;
dialog_load(fn);
#undef fn
}
11 changes: 11 additions & 0 deletions th04/formats/dialog.hpp
@@ -1,2 +1,13 @@
// Script buffer pointer
extern unsigned char far *dialog_p;

// Loads a dialog script from the file with the given name. `near` in this
// game, as it's only used internally.
void pascal near dialog_load(const char *fn);

// Loads the dialog script after defeating Stage 5 Yuuka with continues or on
// Easy mode, shown before the Bad Ending.
void dialog_load_yuuka5_defeat_bad(void);

// Loads the dialog script for the current player character and stage.
void near dialog_load(void);
92 changes: 9 additions & 83 deletions th04_main.asm
Expand Up @@ -859,7 +859,7 @@ loc_B141:
loc_B144:
call main_01:map_load
call main_01:std_load
call main_01:sub_CED4
call @dialog_load$qv
call tiles_fill_initial
graph_accesspage 0

Expand Down Expand Up @@ -2212,82 +2212,11 @@ loc_CE8F:
leave
retn
midboss4_render endp
main_TEXT ends


; =============== S U B R O U T I N E =======================================

; Attributes: bp-based frame

sub_CE93 proc near

arg_0 = dword ptr 4

push bp
mov bp, sp
push si
push word ptr _dialog_p+2
call hmem_free
pushd [bp+arg_0]
call file_ropen
call file_size
mov si, ax
push ax
call hmem_allocbyte
mov word ptr _dialog_p+2, ax
mov word ptr _dialog_p, 0
push ax
push word ptr _dialog_p
push si
call file_read
call file_close
pop si
pop bp
retn 4
sub_CE93 endp


; =============== S U B R O U T I N E =======================================

; Attributes: bp-based frame

sub_CED4 proc near
push bp
mov bp, sp
les bx, _resident
assume es:nothing
mov al, es:[bx+resident_t.playchar_ascii]
les bx, off_22BAA
mov es:[bx+3], al
les bx, _resident
mov al, es:[bx+resident_t.stage_ascii]
les bx, off_22BAA
mov es:[bx+4], al
push word ptr off_22BAA+2
push bx
call main_01:sub_CE93
pop bp
retn
sub_CED4 endp


; =============== S U B R O U T I N E =======================================

; Attributes: bp-based frame

sub_CF01 proc far
push bp
mov bp, sp
les bx, _resident
mov al, es:[bx+resident_t.playchar_ascii]
les bx, off_22BAE
mov es:[bx+3], al
push word ptr off_22BAE+2
push bx
call main_01:sub_CE93
pop bp
retf
sub_CF01 endp

DIALOG_TEXT segment byte public 'CODE' use16
@dialog_load$qv procdesc near
extern @dialog_load_yuuka5_defeat_bad$qv:proc

; =============== S U B R O U T I N E =======================================

Expand Down Expand Up @@ -3170,9 +3099,7 @@ public @dialog_animate$qv
pop bp
retf
@dialog_animate$qv endp
main_TEXT ends

DIALOG_TEXT segment byte public 'CODE' use16
@dialog_init$qv procdesc near
@dialog_exit$qv procdesc near
DIALOG_TEXT ends
Expand Down Expand Up @@ -28452,7 +28379,7 @@ loc_1E7B5:
jnz short loc_1E801

loc_1E7F2:
call sub_CF01
call @dialog_load_yuuka5_defeat_bad$qv
call @dialog_animate$qv
call @end_game_bad$qv

Expand Down Expand Up @@ -32105,10 +32032,9 @@ include th04/main/playfld[data].asm
byte_22B9E db 1
db 0
include th04/main/frames[data].asm
off_22BAA dd a_dm00_txt
; "_DM00.TXT"
off_22BAE dd a_dm04b_txt
; "_DM04B.txt"
public _dialog_fn, _dialog_fn_yuuka5_defeat_bad
_dialog_fn dd a_dm00_txt
_dialog_fn_yuuka5_defeat_bad dd a_dm04b_txt
include th04/main/dialog/dialog[data].asm
public _number_of_calls_to_this_function
_number_of_calls_to_this_function db 0
Expand Down
1 change: 1 addition & 0 deletions th05/f_dialog.cpp
@@ -0,0 +1 @@
#include "th05/formats/dialog.cpp"
41 changes: 41 additions & 0 deletions th05/formats/dialog.cpp
@@ -0,0 +1,41 @@
#pragma option -zCmain_TEXT

#include <stddef.h>
#include "platform.h"
#include "master.hpp"
#include "th04/common.h"
#include "th04/score.h"
#include "th04/main/stage/stage.hpp"
#include "th05/playchar.h"
#include "th05/resident.hpp"
#include "th05/formats/dialog.hpp"

void pascal dialog_load(const char *fn)
{
size_t size;
tx2_header_t header;

if(dialog_p) {
hmem_free(reinterpret_cast<void __seg *>(dialog_p));
}
file_ropen(fn);
file_read(&header, sizeof(header));

// A sanity check here would have been particularly helpful for
// translators, who tend to start out by just blindly editing a .TX2 file.
size = (header.offset_for[playchar + 1] - header.offset_for[playchar]);

dialog_p = reinterpret_cast<unsigned char far *>(hmem_allocbyte(size));
file_seek(header.offset_for[playchar], SEEK_SET);
file_read(dialog_p, size);
file_close();
}

void near dialog_load(void)
{
#define fn dialog_fn
extern char *fn;
fn[4] = ('0' + stage_id);
dialog_load(fn);
#undef fn
}
18 changes: 18 additions & 0 deletions th05/formats/dialog.hpp
@@ -1,8 +1,26 @@
/// TH05 in-game dialog script format
/// ---------------------------------

struct tx2_header_t {
// The dialog script for player character N is stored between
// `offset_for[N]` and `offset_for[N + 1]`.
uint16_t offset_for[PLAYCHAR_COUNT + 1];
};

const uint8_t FACE_NONE = 0xFF;

// Script buffer pointer
extern unsigned char far *dialog_p;

// Loading and freeing
// -------------------

// Loads the dialog script for the current player character from the .TX2 file
// with the given name. `far` in this game, as it's also called from outside
// its segment.
void pascal dialog_load(const char *fn);

// Loads the dialog script for the current player character and stage.
void near dialog_load(void);
// -------------------
/// ---------------------------------

0 comments on commit 903d824

Please sign in to comment.