[Decompilation] [th03/th04/th05] Cutscenes: Masked blitting of new pictures

Part of P0223, funded by Blue Bolt and rosenrose.
This commit is contained in:
nmlgc 2022-11-10 02:03:18 +01:00
parent 684c149bef
commit 6f8b32ca4a
11 changed files with 107 additions and 309 deletions

View File

@ -505,7 +505,8 @@ void MASTER_RET palette_white_out(unsigned speed);
int x, int y, const void far *linepat, int len
);
// Copy of graph_pack_put_8() that does not clip the Y coordinate to
// the vertical grc_setclip() coordinates.
// the vertical grc_setclip() coordinates. Necessary for temporary blits to
// the 400th VRAM row.
void MASTER_RET graph_pack_put_8_noclip(
screen_x_t left, screen_y_t top, const void far *linepat, pixel_t len
);

View File

@ -26,12 +26,22 @@
#define egc_setup_copy() \
outport2(EGC_ACTIVEPLANEREG, 0xFFF0); \
outport2(EGC_READPLANEREG, 0x00FF); \
/* EGC_COMPAREREAD | EGC_WS_PATREG | EGC_RL_MEMREAD */ \
/* EGC_COMPAREREAD | EGC_WS_PATREG | EGC_RL_MEMREAD */ \
outport2(EGC_MODE_ROP_REG, 0x3100); \
outport2(EGC_MASKREG, 0xFFFF); \
outport2(EGC_ADDRRESSREG, 0); \
outport2(EGC_BITLENGTHREG, 0xF);
// Requires the EGC to have been activated and set up for a copy before.
// ZUN bloat: Can be merged into egc_setup_copy().
#define egc_setup_copy_masked(mask) { \
outport2(EGC_READPLANEREG, 0x00ff); \
/* EGC_COMPAREREAD | EGC_WS_PATREG | EGC_RL_MEMREAD */ \
outport2(EGC_MODE_ROP_REG, 0x3100); \
outport2(EGC_BITLENGTHREG, 0xF); \
outport(EGC_MASKREG, mask); \
}
// Blits the rectangle from
// (⌊left/16⌋*16, top)
// to

View File

@ -9,6 +9,9 @@
#define PI_W RES_X
#define PI_H RES_Y
static const pixel_t PI_QUARTER_W = (PI_W / 2);
static const pixel_t PI_QUARTER_H = (PI_H / 2);
// Global PI file slots.
extern PiHeader pi_headers[PI_SLOT_COUNT];
extern void far *pi_buffers[PI_SLOT_COUNT];
@ -51,4 +54,16 @@ typedef uint8_t far *pi_buffer_p_t;
#define pi_buffer_p_next_row(p, slot) \
pi_buffer_p_offset(p, pi_headers[slot].xsize, 0);
#define pi_buffer_p_init_quarter(p, slot, quarter) { \
pi_buffer_p_init(p, slot); \
if(quarter == 1) { \
pi_buffer_p_offset(p, PI_QUARTER_W, 0); \
} else if(quarter == 2) { \
pi_buffer_p_offset(p, 0, PI_QUARTER_H); \
} else if(quarter == 3) { \
pi_buffer_p_offset(p, PI_QUARTER_W, PI_QUARTER_H); \
} \
pi_buffer_p_normalize(p); \
}
// --------------------------

View File

@ -13,8 +13,15 @@
#include "master.hpp"
extern "C" {
#include "th02/hardware/frmdelay.h"
#if (GAME == 5)
#include "th01/hardware/egc.h"
#include "th05/formats/pi.hpp"
#elif (GAME == 4)
#include "th03/formats/pi.hpp"
#else
#include "th03/formats/pi.hpp"
#endif
}
#include "th03/formats/pi.hpp"
#include "th03/cutscene/cutscene.hpp"
// Constants
@ -24,6 +31,8 @@ static const pixel_t PIC_W = PI_QUARTER_W;
static const pixel_t PIC_H = PI_QUARTER_H;
static const vram_byte_amount_t PIC_VRAM_W = (PIC_W / BYTE_DOTS);
static const int PIC_SLOT = 0;
// ---------
// State
@ -100,7 +109,20 @@ bool16 pascal near cutscene_script_load(const char* fn)
#include "th01/hardware/egcstart.cpp"
#undef egc_start_copy
#if (GAME <= 4)
#if (GAME == 5)
#define pic_copy_to_other(left, top) { \
egc_copy_rect_1_to_0_16(left, top, PIC_W, PIC_H); \
}
void pascal near pic_put_both_masked(
screen_x_t left, vram_y_t top, int quarter, int mask_id
)
{
graph_accesspage(1);
pi_put_quarter_masked_8(left, top, PIC_SLOT, quarter, mask_id);
pic_copy_to_other(left, top);
}
#else
void pascal near pic_copy_to_other(screen_x_t left, vram_y_t top)
{
vram_offset_t vo = vram_offset_shift(left, top);
@ -134,4 +156,45 @@ bool16 pascal near cutscene_script_load(const char* fn)
// changes like this one are completely redundant, thankfully.
graph_accesspage(0);
}
void pascal near pic_put_both_masked(
screen_x_t left, vram_y_t top, int quarter, int mask_id
)
{
enum {
TEMP_ROW = RES_Y,
};
vram_word_amount_t vram_word;
vram_offset_t vo_temp;
pi_buffer_p_t row_p;
pi_buffer_p_init_quarter(row_p, PIC_SLOT, quarter);
graph_showpage(1);
vram_offset_t vo = vram_offset_shift(left, top);
graph_accesspage(0);
for(pixel_t y = 0; y < PIC_H; y++) {
// This might actually be faster than clearing the masked pixels
// using the GRCG and doing an unaccelerated 4-plane VRAM OR.
graph_pack_put_8_noclip(0, TEMP_ROW, row_p, PIC_W);
egc_start_copy();
egc_setup_copy_masked(PI_MASKS[mask_id][y & (PI_MASK_COUNT - 1)]);
vo_temp = vram_offset_shift(0, TEMP_ROW);
vram_word = 0;
while(vram_word < (PIC_W / EGC_REGISTER_DOTS)) {
egc_chunk(vo) = egc_chunk(vo_temp);
vram_word++;
vo += EGC_REGISTER_SIZE;
vo_temp += EGC_REGISTER_SIZE;
}
egc_off();
vo += (ROW_SIZE - PIC_VRAM_W);
pi_buffer_p_offset(row_p, PI_W, 0);
pi_buffer_p_normalize(row_p);
}
graph_showpage(0);
pic_copy_to_other(left, top);
}
#endif

View File

@ -12,6 +12,3 @@ void pascal pi_put_interlace_8(screen_x_t left, vram_y_t top, int slot);
void pascal pi_put_quarter_8(
screen_x_t left, vram_y_t top, int slot, int quarter
);
static const pixel_t PI_QUARTER_W = (PI_W / 2);
static const pixel_t PI_QUARTER_H = (PI_H / 2);

View File

@ -14,16 +14,7 @@ void pascal pi_put_quarter_8(
{
pi_buffer_p_t row_p;
pi_buffer_p_init(row_p, slot);
if(quarter == 1) {
pi_buffer_p_offset(row_p, PI_QUARTER_W, 0);
} else if(quarter == 2) {
pi_buffer_p_offset(row_p, 0, PI_QUARTER_H);
} else if(quarter == 3) {
pi_buffer_p_offset(row_p, PI_QUARTER_W, PI_QUARTER_H);
}
pi_buffer_p_normalize(row_p);
pi_buffer_p_init_quarter(row_p, slot, quarter);
for(pixel_t y_in_quarter = 0; y_in_quarter < PI_QUARTER_H; y_in_quarter++) {
graph_pack_put_8(left, top, row_p, PI_QUARTER_W);
top++;

View File

@ -1199,133 +1199,14 @@ sub_9F8D endp
@CUTSCENE_SCRIPT_LOAD$QNXC procdesc pascal near \
fn:dword
@cutscene_script_free$qv procdesc near
@egc_start_copy$qv procdesc near
@PIC_COPY_TO_OTHER$QII procdesc pascal near \
left:word, top:word
@PIC_PUT_BOTH_MASKED$QIIII procdesc pascal near \
left_and_top:dword, quarter:word, mask_id:word
CUTSCENE_TEXT ends
mainl_01_TEXT segment byte public 'CODE' use16
; =============== S U B R O U T I N E =======================================
; Attributes: bp-based frame
sub_A23C proc near
var_8 = dword ptr -8
var_4 = word ptr -4
var_2 = word ptr -2
arg_0 = word ptr 4
arg_2 = word ptr 6
@@top = word ptr 8
@@left = word ptr 0Ah
enter 8, 0
push si
push di
mov eax, _pi_buffers
mov [bp+var_8], eax
cmp [bp+arg_2], 1
jnz short loc_A257
add word ptr [bp+var_8], 0A0h
jmp short loc_A26F
; ---------------------------------------------------------------------------
loc_A257:
cmp [bp+arg_2], 2
jnz short loc_A264
add word ptr [bp+var_8], 0FA00h
jmp short loc_A26F
; ---------------------------------------------------------------------------
loc_A264:
cmp [bp+arg_2], 3
jnz short loc_A26F
add word ptr [bp+var_8], 0FAA0h
loc_A26F:
mov eax, [bp+var_8]
shr eax, 10h
mov dx, word ptr [bp+var_8]
shr dx, 4
add ax, dx
mov dx, word ptr [bp+var_8]
and dx, 0Fh
mov word ptr [bp+var_8+2], ax
mov word ptr [bp+var_8], dx
graph_showpage 1
mov ax, [bp+@@left]
sar ax, 3
mov dx, [bp+@@top]
shl dx, 6
add ax, dx
mov dx, [bp+@@top]
shl dx, 4
add ax, dx
mov si, ax
graph_accesspage 0
xor di, di
jmp loc_A34E
; ---------------------------------------------------------------------------
loc_A2B4:
call graph_pack_put_8_noclip pascal, large 400, [bp+var_8], 320
call @egc_start_copy$qv
egc_selectpat
egc_setrop EGC_COMPAREREAD or EGC_WS_PATREG or EGC_RL_MEMREAD
outw2 EGC_BITLENGTHREG, 0Fh
mov bx, [bp+arg_0]
shl bx, 3
mov ax, di
and ax, 3
add ax, ax
add bx, ax
outw2 EGC_MASKREG, _PI_MASKS[bx]
mov [bp+var_4], 7D00h
mov [bp+var_2], 0
jmp short loc_A31E
; ---------------------------------------------------------------------------
loc_A301:
les bx, _VRAM_PLANE_B
add bx, [bp+var_4]
mov ax, es:[bx]
mov bx, word ptr _VRAM_PLANE_B
add bx, si
mov es:[bx], ax
inc [bp+var_2]
add si, 2
add [bp+var_4], 2
loc_A31E:
cmp [bp+var_2], 14h
jl short loc_A301
call egc_off
add si, 28h ; '('
add word ptr [bp+var_8], 140h
mov eax, [bp+var_8]
shr eax, 10h
mov dx, word ptr [bp+var_8]
shr dx, 4
add ax, dx
mov dx, word ptr [bp+var_8]
and dx, 0Fh
mov word ptr [bp+var_8+2], ax
mov word ptr [bp+var_8], dx
inc di
loc_A34E:
cmp di, 0C8h
jl loc_A2B4
graph_showpage 0
call @pic_copy_to_other$qii pascal, [bp+@@left], [bp+@@top]
pop di
pop si
leave
retn 8
sub_A23C endp
; =============== S U B R O U T I N E =======================================
; Attributes: bp-based frame
@ -2195,10 +2076,7 @@ loc_AAF8:
; ---------------------------------------------------------------------------
loc_AB16:
push (160 shl 16) or 64
push [bp+var_2]
push si
call sub_A23C
call @pic_put_both_masked$qiiii pascal, (160 shl 16) or 64, [bp+var_2], si
cmp _fast_forward, 0
jnz short loc_AB32
push [bp+var_4]

View File

@ -5,6 +5,7 @@
#include "decomp.hpp"
#include "shiftjis.hpp"
#include "master.hpp"
#include "th01/hardware/egc.h"
extern "C" {
#include "th02/hardware/frmdelay.h"
#if (GAME == 5)
@ -36,11 +37,7 @@ void pascal near box_1_to_0_masked(box_mask_t mask)
egc_temp_t tmp;
for(screen_y_t y = BOX_TOP; y < BOX_BOTTOM; y++) {
outport2(EGC_READPLANEREG, 0x00ff);
// EGC_COMPAREREAD | EGC_WS_PATREG | EGC_RL_MEMREAD
outport2(EGC_MODE_ROP_REG, 0x3100);
outport2(EGC_BITLENGTHREG, 0xF);
outport(EGC_MASKREG, BOX_MASKS[mask][y & 3]);
egc_setup_copy_masked(BOX_MASKS[mask][y & 3]);
vram_offset_t vram_offset = vram_offset_shift(BOX_LEFT, y);
pixel_t x = 0;

View File

@ -336,133 +336,14 @@ _main endp
@CUTSCENE_SCRIPT_LOAD$QNXC procdesc pascal near \
fn:dword
@cutscene_script_free$qv procdesc near
@egc_start_copy$qv procdesc near
@PIC_COPY_TO_OTHER$QII procdesc pascal near \
left:word, top:word
@PIC_PUT_BOTH_MASKED$QIIII procdesc pascal near \
left_and_top:dword, quarter:word, mask_id:word
CUTSCENE_TEXT ends
maine_01_TEXT segment byte public 'CODE' use16
; =============== S U B R O U T I N E =======================================
; Attributes: bp-based frame
sub_A37F proc near
var_8 = dword ptr -8
var_4 = word ptr -4
var_2 = word ptr -2
arg_0 = word ptr 4
arg_2 = word ptr 6
@@top = word ptr 8
@@left = word ptr 0Ah
enter 8, 0
push si
push di
mov eax, _pi_buffers
mov [bp+var_8], eax
cmp [bp+arg_2], 1
jnz short loc_A39A
add word ptr [bp+var_8], 0A0h
jmp short loc_A3B2
; ---------------------------------------------------------------------------
loc_A39A:
cmp [bp+arg_2], 2
jnz short loc_A3A7
add word ptr [bp+var_8], 0FA00h
jmp short loc_A3B2
; ---------------------------------------------------------------------------
loc_A3A7:
cmp [bp+arg_2], 3
jnz short loc_A3B2
add word ptr [bp+var_8], 0FAA0h
loc_A3B2:
mov eax, [bp+var_8]
shr eax, 10h
mov dx, word ptr [bp+var_8]
shr dx, 4
add ax, dx
mov dx, word ptr [bp+var_8]
and dx, 0Fh
mov word ptr [bp+var_8+2], ax
mov word ptr [bp+var_8], dx
graph_showpage 1
mov ax, [bp+arg_6]
sar ax, 3
mov dx, [bp+arg_4]
shl dx, 6
add ax, dx
mov dx, [bp+arg_4]
shl dx, 4
add ax, dx
mov si, ax
graph_accesspage 0
xor di, di
jmp loc_A491
; ---------------------------------------------------------------------------
loc_A3F7:
call graph_pack_put_8_noclip pascal, large 400, [bp+var_8], 320
call @egc_start_copy$qv
egc_selectpat
egc_setrop EGC_COMPAREREAD or EGC_WS_PATREG or EGC_RL_MEMREAD
outw2 EGC_BITLENGTHREG, 0Fh
mov bx, [bp+arg_0]
shl bx, 3
mov ax, di
and ax, 3
add ax, ax
add bx, ax
outw2 EGC_MASKREG, _PI_MASKS[bx]
mov [bp+var_4], 7D00h
mov [bp+var_2], 0
jmp short loc_A461
; ---------------------------------------------------------------------------
loc_A444:
les bx, _VRAM_PLANE_B
add bx, [bp+var_4]
mov ax, es:[bx]
mov bx, word ptr _VRAM_PLANE_B
add bx, si
mov es:[bx], ax
inc [bp+var_2]
add si, 2
add [bp+var_4], 2
loc_A461:
cmp [bp+var_2], 14h
jl short loc_A444
call egc_off
add si, 28h ; '('
add word ptr [bp+var_8], 140h
mov eax, [bp+var_8]
shr eax, 10h
mov dx, word ptr [bp+var_8]
shr dx, 4
add ax, dx
mov dx, word ptr [bp+var_8]
and dx, 0Fh
mov word ptr [bp+var_8+2], ax
mov word ptr [bp+var_8], dx
inc di
loc_A491:
cmp di, 0C8h
jl loc_A3F7
graph_showpage 0
call @pic_copy_to_other$qii pascal, [bp+@@left], [bp+@@top]
pop di
pop si
leave
retn 8
sub_A37F endp
; =============== S U B R O U T I N E =======================================
; Attributes: bp-based frame
@ -1294,10 +1175,7 @@ loc_AC94:
; ---------------------------------------------------------------------------
loc_ACB2:
push 0A00040h
push [bp+var_2]
push si
call sub_A37F
call @pic_put_both_masked$qiiii pascal, (160 shl 16) or 64, [bp+var_2], si
cmp _fast_forward, 0
jnz short loc_ACCE
push [bp+var_4]

View File

@ -4,7 +4,8 @@
void pascal pi_free(int slot);
// Like pi_put_8() and pi_put_quarter_8(), but applying the mask with the given
// ID while blitting.
// ID while blitting. See TH03's and TH04's pic_put_both_masked() for a C++
// implementation of the same functionality.
void pascal pi_put_masked_8(
screen_x_t left, vram_y_t top, int slot, int mask_id
);

View File

@ -303,42 +303,12 @@ _main endp
@CUTSCENE_SCRIPT_LOAD$QNXC procdesc pascal near \
fn:dword
@PIC_PUT_BOTH_MASKED$QIIII procdesc pascal near \
left_and_top:dword, quarter:word, mask_id:word
CUTSCENE_TEXT ends
maine_01_TEXT segment byte public 'CODE' use16
; =============== S U B R O U T I N E =======================================
; Attributes: bp-based frame
sub_A705 proc near
arg_0 = word ptr 4
arg_2 = word ptr 6
arg_4 = word ptr 8
arg_6 = word ptr 0Ah
push bp
mov bp, sp
push si
push di
mov si, [bp+arg_6]
mov di, [bp+arg_4]
graph_accesspage 1
push si
push di
push 0
push [bp+arg_2]
push [bp+arg_0]
call pi_put_quarter_masked_8
call egc_copy_rect_1_to_0_16 pascal, si, di, (320 shl 16) or 200
pop di
pop si
pop bp
retn 8
sub_A705 endp
; =============== S U B R O U T I N E =======================================
; Attributes: bp-based frame
@ -963,10 +933,7 @@ loc_AE1A:
; ---------------------------------------------------------------------------
loc_AE25:
push 0A00040h
push [bp+var_2]
push si
call sub_A705
call @pic_put_both_masked$qiiii pascal, (160 shl 16) or 64, [bp+var_2], si
cmp _fast_forward, 0
jnz short loc_AE41
push [bp+var_4]