From 6f8b32ca4a2bcf9a4775a203871207c8c80d5762 Mon Sep 17 00:00:00 2001 From: nmlgc Date: Thu, 10 Nov 2022 02:03:18 +0100 Subject: [PATCH] [Decompilation] [th03/th04/th05] Cutscenes: Masked blitting of new pictures Part of P0223, funded by Blue Bolt and rosenrose. --- master.hpp | 3 +- th01/hardware/egc.h | 12 +++- th02/formats/pi.h | 15 +++++ th03/cutscene/cutscene.cpp | 67 ++++++++++++++++++- th03/formats/pi.hpp | 3 - th03/formats/pi_put_q.cpp | 11 +--- th03_mainl.asm | 128 +------------------------------------ th04/cutscene/box.cpp | 7 +- th04_maine.asm | 128 +------------------------------------ th05/formats/pi.hpp | 3 +- th05_maine.asm | 39 +---------- 11 files changed, 107 insertions(+), 309 deletions(-) diff --git a/master.hpp b/master.hpp index 588a96f9..308490fc 100644 --- a/master.hpp +++ b/master.hpp @@ -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 ); diff --git a/th01/hardware/egc.h b/th01/hardware/egc.h index 689d2558..6eaf3e93 100644 --- a/th01/hardware/egc.h +++ b/th01/hardware/egc.h @@ -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 diff --git a/th02/formats/pi.h b/th02/formats/pi.h index 5ed38806..ea977059 100644 --- a/th02/formats/pi.h +++ b/th02/formats/pi.h @@ -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); \ +} // -------------------------- diff --git a/th03/cutscene/cutscene.cpp b/th03/cutscene/cutscene.cpp index 895ca67d..e2208d3a 100644 --- a/th03/cutscene/cutscene.cpp +++ b/th03/cutscene/cutscene.cpp @@ -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 diff --git a/th03/formats/pi.hpp b/th03/formats/pi.hpp index c5a0cec1..c785ae10 100644 --- a/th03/formats/pi.hpp +++ b/th03/formats/pi.hpp @@ -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); diff --git a/th03/formats/pi_put_q.cpp b/th03/formats/pi_put_q.cpp index e155c328..774e6c13 100644 --- a/th03/formats/pi_put_q.cpp +++ b/th03/formats/pi_put_q.cpp @@ -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++; diff --git a/th03_mainl.asm b/th03_mainl.asm index 4028fb8d..243c2d10 100644 --- a/th03_mainl.asm +++ b/th03_mainl.asm @@ -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] diff --git a/th04/cutscene/box.cpp b/th04/cutscene/box.cpp index a87b46a1..f238833b 100644 --- a/th04/cutscene/box.cpp +++ b/th04/cutscene/box.cpp @@ -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; diff --git a/th04_maine.asm b/th04_maine.asm index dfca3ade..6a2bd428 100644 --- a/th04_maine.asm +++ b/th04_maine.asm @@ -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] diff --git a/th05/formats/pi.hpp b/th05/formats/pi.hpp index ad59e99e..01e81dd0 100644 --- a/th05/formats/pi.hpp +++ b/th05/formats/pi.hpp @@ -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 ); diff --git a/th05_maine.asm b/th05_maine.asm index 3a5fb531..2d38edf2 100644 --- a/th05_maine.asm +++ b/th05_maine.asm @@ -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]