[Decompilation] [th05] EMS / Dialog: Face loading and rendering

Aha! TH05 actually loads every single rendered dialog image
individually before rendering it, either from the EMS area or disk.
That's one way to save memory, I guess?

Part of P0169, funded by Blue Bolt.
This commit is contained in:
nmlgc 2021-11-25 15:58:22 +01:00
parent 90a2e367bc
commit 9ae4f7726e
9 changed files with 114 additions and 111 deletions

View File

@ -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\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\main013.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 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\main031.cpp th05\gather.cpp th05\main032.cpp th05\bullet_u.cpp th05\main034.cpp th05\main035.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\dialog.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\main013.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 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\main031.cpp th05\gather.cpp th05\main032.cpp th05\bullet_u.cpp th05\main034.cpp th05\main035.cpp
$(CC) $(CFLAGS) $(LARGE_LFLAGS) -3 -Z -DGAME=5 -DBINARY='M' -nbin\th05\ -eMAIN.EXE @&&| $(CC) $(CFLAGS) $(LARGE_LFLAGS) -3 -Z -DGAME=5 -DBINARY='M' -nbin\th05\ -eMAIN.EXE @&&|
$** $**
| |

View File

@ -27,6 +27,14 @@ typedef enum {
CDG_PER_STAGE, CDG_PER_STAGE,
CDG_FACESET_PLAYCHAR, CDG_FACESET_PLAYCHAR,
#if (GAME == 5)
// TH05 only uses the CDG_FACESET_PLAYCHAR and CDG_FACESET_BOSS ranges
// as temporary storage for EMS area preloading. During in-game dialog,
// every single rendered face image is individually loaded to this one
// slot, either from the EMS area or from disk, and then immediately
// freed.
CDG_DIALOG_FACE = CDG_FACESET_PLAYCHAR,
#endif
CDG_FACESET_PLAYCHAR_last = (CDG_FACESET_PLAYCHAR + (FACESET_PLAYCHAR_COUNT - 1)), CDG_FACESET_PLAYCHAR_last = (CDG_FACESET_PLAYCHAR + (FACESET_PLAYCHAR_COUNT - 1)),
CDG_FACESET_BOSS, CDG_FACESET_BOSS,
CDG_FACESET_BOSS_last = (CDG_FACESET_BOSS + (FACESET_BOSS_COUNT - 1)), CDG_FACESET_BOSS_last = (CDG_FACESET_BOSS + (FACESET_BOSS_COUNT - 1)),

View File

@ -10,8 +10,6 @@ FACE_H = 128
CDG_BG_PLAYCHAR_BOMB = 0 CDG_BG_PLAYCHAR_BOMB = 0
CDG_PER_STAGE = 1 CDG_PER_STAGE = 1
CDG_FACESET_PLAYCHAR = 2
CDG_FACESET_PLAYCHAR_last = (CDG_FACESET_PLAYCHAR + (FACESET_PLAYCHAR_COUNT - 1))
CDG_FACESET_BOSS = 8 CDG_FACESET_BOSS = 8
CDG_FACESET_BOSS_last = (CDG_FACESET_BOSS + (FACESET_BOSS_COUNT - 1)) CDG_FACESET_BOSS_last = (CDG_FACESET_BOSS + (FACESET_BOSS_COUNT - 1))
CDG_BG_BOSS = 16 CDG_BG_BOSS = 16

1
th05/dialog.cpp Normal file
View File

@ -0,0 +1 @@
#include "th05/main/dialog/dialog.cpp"

5
th05/formats/tx2.hpp Normal file
View File

@ -0,0 +1,5 @@
/// TH05 in-game dialog script format
/// ---------------------------------
const uint8_t FACE_NONE = 0xFF;
/// ---------------------------------

View File

@ -0,0 +1,67 @@
#pragma option -zPmain_01
extern "C" {
#include <stddef.h>
#include "platform.h"
#include "pc98.h"
#include "planar.h"
#include "master.hpp"
#include "th02/hardware/frmdelay.h"
#include "th03/formats/cdg.h"
#include "th04/main/playfld.hpp"
}
#include "th04/main/stage/stage.hpp"
#include "th04/sprites/main_cdg.h"
#include "th04/main/ems.hpp"
#include "th05/chars.h"
#include "th05/formats/tx2.hpp"
#include "th05/shiftjis/fns.hpp"
#include "th05/main/dialog/dialog.hpp"
extern char faceset_boss_format[];
extern char faceset_playchar_format[];
void pascal near dialog_face_load_unput_put_free_8(
screen_x_t left, vram_y_t top, int face_id
)
{
size_t size;
uint32_t offset;
char near *faceset_fn = faceset_boss_format;
char near *faceset_playchar_fn = faceset_playchar_format;
if(face_id != FACE_NONE) {
if(Ems) {
if(dialog_side == DIALOG_SIDE_PLAYCHAR) {
offset = EMS_FACESET_PLAYCHAR_OFFSET;
} else {
offset = EMS_FACESET_BOSS_OFFSET;
}
size = cdg_slots[CDG_DIALOG_FACE].bitplane_size;
offset += (face_id * size * (PLANE_COUNT + 1));
allocate_and_load_from_ems(
cdg_slots[CDG_DIALOG_FACE].seg_alpha(), offset, size
);
offset += size;
size *= PLANE_COUNT;
allocate_and_load_from_ems(
cdg_slots[CDG_DIALOG_FACE].seg_colors(), offset, size
);
offset += size;
} else {
if(dialog_side != DIALOG_SIDE_PLAYCHAR) {
faceset_fn[3] = ('0' + stage_id);
} else {
faceset_fn = faceset_playchar_fn;
faceset_fn[3] = ('0' + playchar);
}
cdg_load_single(CDG_DIALOG_FACE, faceset_fn, face_id);
}
}
frame_delay(1);
dialog_face_unput_8(left, top);
if(face_id != FACE_NONE) {
cdg_put_8(left, top, CDG_DIALOG_FACE);
cdg_free(CDG_DIALOG_FACE);
}
}

View File

@ -0,0 +1,15 @@
#include "th04/main/dialog/dialog.hpp"
// Dialog-related image functions with optional EMS support
// --------------------------------------------------------
// Loads the face image at the given ID for the current [dialog_side] from
// either the EMS area or disk, then calls dialog_face_unput_8([left], [top]),
// blits the loaded image to the same position, and frees it again.
// Can also just unblit the face image without blitting a new one by setting
// [face_id] to FACE_NONE, if you don't like calling dialog_face_unput_8()
// directly for whatever reason.
void pascal near dialog_face_load_unput_put_free_8(
screen_x_t left, vram_y_t top, int face_id
);
// --------------------------------------------------------

View File

@ -1,5 +1,6 @@
#define EYECATCH_FN "eye.cdg" #define EYECATCH_FN "eye.cdg"
#define FACESET_PLAYCHAR_FORMAT "KaO0.cD2"
#define FACESET_REIMU_FN "KAO0.cd2" #define FACESET_REIMU_FN "KAO0.cd2"
#define FACESET_MARISA_FN "KAO1.cd2" #define FACESET_MARISA_FN "KAO1.cd2"
#define FACESET_MIMA_FN "KAO2.cd2" #define FACESET_MIMA_FN "KAO2.cd2"
@ -21,3 +22,5 @@
break; \ break; \
} \ } \
} }
#define FACESET_BOSS_FORMAT "BsS0.cD2"

View File

@ -38,7 +38,7 @@ include th05/main/enemy/enemy.inc
extern _strlen:proc extern _strlen:proc
.seq .seq
main_01 group SLOWDOWN_TEXT, ma_TEXT, EMS_TEXT, mai_TEXT, CFG_LRES_TEXT, main_TEXT, main__TEXT, main_0_TEXT, PLAYER_P_TEXT, main_01_TEXT main_01 group SLOWDOWN_TEXT, ma_TEXT, EMS_TEXT, mai_TEXT, CFG_LRES_TEXT, main_TEXT, main__TEXT, main_0_TEXT, DIALOG_TEXT, PLAYER_P_TEXT, main_01_TEXT
g_SHARED group SHARED, SHARED_ g_SHARED group SHARED, SHARED_
main_03 group SCROLLY3_TEXT, MOTION_3_TEXT, main_031_TEXT, main_032_TEXT, main_033_TEXT, main_034_TEXT, main_035_TEXT, main_036_TEXT main_03 group SCROLLY3_TEXT, MOTION_3_TEXT, main_031_TEXT, main_032_TEXT, main_033_TEXT, main_034_TEXT, main_035_TEXT, main_036_TEXT
@ -3994,7 +3994,7 @@ loc_F04B:
mov al, [bp+arg_0] mov al, [bp+arg_0]
mov ah, 0 mov ah, 0
push ax push ax
call sub_F36B call @dialog_face_load_unput_put_free_$qiii
jmp loc_F0ED jmp loc_F0ED
; --------------------------------------------------------------------------- ; ---------------------------------------------------------------------------
@ -4316,108 +4316,13 @@ loc_F333:
sub_F2B4 endp sub_F2B4 endp
main__TEXT ends main__TEXT ends
DIALOG_TEXT segment byte public 'CODE' use16
@DIALOG_FACE_LOAD_UNPUT_PUT_FREE_$QIII procdesc pascal near \
left:word, top:word, cel:word
DIALOG_TEXT ends
main_0_TEXT segment byte public 'CODE' use16 main_0_TEXT segment byte public 'CODE' use16
; =============== S U B R O U T I N E =======================================
; Attributes: bp-based frame
sub_F36B proc near
var_6 = word ptr -6
var_4 = dword ptr -4
arg_0 = word ptr 4
@@top = word ptr 6
@@left = word ptr 8
enter 6, 0
push si
push di
mov di, offset aBss0_cd2_0
mov [bp+var_6], offset aKao0_cd2_0
cmp [bp+arg_0], (-1 and 255)
jz loc_F432
cmp _Ems, 0
jz loc_F40F
cmp _dialog_side, DIALOG_SIDE_PLAYCHAR
jnz short loc_F39C
mov [bp+var_4], 100000
jmp short loc_F3A4
; ---------------------------------------------------------------------------
loc_F39C:
mov [bp+var_4], 200000
loc_F3A4:
mov si, _cdg_slots.CDG_plane_size + (size cdg_t * 2)
mov ax, [bp+arg_0]
imul si
imul ax, 5
movzx eax, ax
add [bp+var_4], eax
push si
call hmem_allocbyte
mov _cdg_slots.seg_alpha + (size cdg_t * 2), ax
push _Ems
pushd [bp+var_4]
push ax
push 0
movzx eax, si
push eax
call ems_read
movzx eax, si
add [bp+var_4], eax
mov ax, 4
imul si
mov si, ax
push si
call hmem_allocbyte
mov _cdg_slots.seg_colors + (size cdg_t * 2), ax
push _Ems
pushd [bp+var_4]
push ax
push 0
movzx eax, si
push eax
call ems_read
movzx eax, si
add [bp+var_4], eax
jmp short loc_F432
; ---------------------------------------------------------------------------
loc_F40F:
cmp _dialog_side, DIALOG_SIDE_PLAYCHAR
jz short loc_F41B
mov al, _stage_id
jmp short loc_F421
; ---------------------------------------------------------------------------
loc_F41B:
mov di, [bp+var_6]
mov al, _playchar
loc_F421:
add al, 30h ; '0'
mov [di+3], al
call cdg_load_single pascal, CDG_FACESET_PLAYCHAR, ds, di, [bp+arg_0]
loc_F432:
push 1
call frame_delay
call @dialog_face_unput_8$quiui pascal, [bp+@@left], [bp+@@top]
cmp [bp+arg_0], (-1 and 255)
jz short loc_F45D
call cdg_put_8 pascal, [bp+@@left], [bp+@@top], CDG_FACESET_PLAYCHAR
call cdg_free pascal, CDG_FACESET_PLAYCHAR
loc_F45D:
pop di
pop si
leave
retn 6
sub_F36B endp
; =============== S U B R O U T I N E ======================================= ; =============== S U B R O U T I N E =======================================
; Attributes: bp-based frame ; Attributes: bp-based frame
@ -24929,8 +24834,9 @@ aSt06b db 'st06b',0
aDemo5_rec db 'DEMO5.REC',0 aDemo5_rec db 'DEMO5.REC',0
; char aOp_0[] ; char aOp_0[]
aOp_0 db 'op',0 aOp_0 db 'op',0
aBss0_cd2_0 db 'BsS0.cD2',0 public _faceset_boss_format, _faceset_playchar_format
aKao0_cd2_0 db 'KaO0.cD2',0 _faceset_boss_format db 'BsS0.cD2',0
_faceset_playchar_format db 'KaO0.cD2',0
aBb0_cdg db 'bb0.cdg',0 aBb0_cdg db 'bb0.cdg',0
aBb1_cdg db 'bb1.cdg',0 aBb1_cdg db 'bb1.cdg',0
aBb2_cdg db 'bb2.cdg',0 aBb2_cdg db 'bb2.cdg',0