[Decompilation] [th04/th05] EGC-powered page 1→0 rectangle blitting

Actually fairly average, as far as unreasonable decompilations are
concerned. No `goto`, at least! Another place that would benefit from
EGC raster op documentation, though.

Also, got one more padding byte in TH05's MAINE.EXE correct. 🙂

Part of P0126, funded by [Anonymous] and Blue Bolt.
This commit is contained in:
nmlgc 2020-11-06 14:37:10 +01:00
parent b504d72301
commit baac3f7682
11 changed files with 151 additions and 29 deletions

View File

@ -10,6 +10,7 @@
// these assemble into the single given instruction. Apply the ! operator to
// get the N versions.
#define FLAGS_ZERO (_FLAGS & 0x40) /* JZ */
#define FLAGS_SIGN (_FLAGS & 0x80) /* JS */
// ----------------
// Alternate version that doesn't spill the port number to DX
@ -24,3 +25,6 @@
mov dx, port; \
out dx, ax; \
}
// Versions that actually inline with pseudoregisters
#define pokew(sgm, off, val) { *(uint16_t far *)(MK_FP(sgm, off)) = val; }

View File

@ -32,10 +32,13 @@
outport2(EGC_ADDRRESSREG, 0); \
outport2(EGC_BITLENGTHREG, 0xF);
// Blits the rectangle from (⌊x/16⌋*16, y) to (⌈((x + w)/16)*16⌉, (y + h))
// Blits the rectangle from
// (⌊left/16⌋*16, top)
// to
// (⌈((left + w)/16)*16⌉, (top + h))
// from VRAM page 1 to the same position on VRAM page 0.
void DEFCONV egc_copy_rect_1_to_0_16(
screen_x_t x, vram_y_t y, pixel_t w, pixel_t h
screen_x_t left, vram_y_t top, pixel_t w, pixel_t h
);
// Blits [h] rows starting at [top] from VRAM page 1 to the same position on

1
th04/egcrect.cpp Normal file
View File

@ -0,0 +1 @@
#include "th04/hardware/egcrect.cpp"

View File

@ -1,2 +0,0 @@
public _egccopyr_width_words
_egccopyr_width_words dw ?

View File

@ -1,3 +1,4 @@
; (TH04 version only, until that one gets linked in)
public EGC_COPY_RECT_1_TO_0_16
egc_copy_rect_1_to_0_16 proc far
@ -12,9 +13,7 @@ egc_copy_rect_1_to_0_16 proc far
push bp
mov bp, sp
push di
if GAME eq 4
cld
endif
call egc_start_copy
outw EGC_MODE_ROP_REG, EGC_COMPAREREAD or EGC_WS_ROP or EGC_RL_MEMREAD or 0F0h
mov ax, @@x
@ -36,7 +35,7 @@ endif
inc ax
@@x_on_word_boundary:
mov _egccopyr_width_words, ax
mov _egcrect_w, ax
mov cx, (ROW_SIZE / 2)
sub cx, ax
shl cx, 1
@ -47,29 +46,16 @@ endif
assume es:nothing
@@next_row:
mov cx, _egccopyr_width_words
mov cx, _egcrect_w
@@next_word:
if GAME eq 5
or di, di
js short @@skip
cmp di, PLANE_SIZE
jnb short @@skip
endif
mov al, 1
out 0A6h, al
mov dx, es:[di]
xor ax, ax
out 0A6h, al
if GAME eq 5
mov es:[di], dx
@@skip:
add di, 2
else
mov ax, dx
stosw
endif
loop @@next_word
add di, @@stride
dec @@row
@ -104,3 +90,4 @@ egc_start_copy proc near
outw EGC_BITLENGTHREG, 0Fh
retn
egc_start_copy endp
even

128
th04/hardware/egcrect.cpp Normal file
View File

@ -0,0 +1,128 @@
#pragma codeseg SHARED_
extern "C" {
#include <dos.h>
#include "platform.h"
#include "pc98.h"
#include "planar.h"
#include "decomp.h"
#include "master.hpp"
#include "th01/hardware/egc.h"
#define graph_accesspage_1() \
outportb2(0xA6, 1);
#define graph_accesspage_0() \
_AX ^= _AX; \
__asm out 0xA6, al;
extern vram_word_amount_t egcrect_w;
static void near egc_start_copy(void);
void DEFCONV egc_copy_rect_1_to_0_16(
screen_x_t left, vram_y_t top, pixel_t w, pixel_t h
)
{
#define vo_tmp _BX // vram_offset_t
#define first_bit _CX
#define stride static_cast<vram_byte_amount_t>(_BP)
#define w_tmp static_cast<vram_word_amount_t>(_AX)
#define rows_remaining static_cast<pixel_t>(_BX)
#define dots static_cast<dots16_t>(_DX)
#if (GAME == 4)
// TH04 wants to blit using a forward STOSW (DF = 0)
__asm { cld; }
#endif
egc_start_copy();
egc_setrop(EGC_COMPAREREAD | EGC_WS_ROP | EGC_RL_MEMREAD | 0xF0);
// Using inline assembly rather than register pseudovariables to prevent
// parameters from being moved to the SI register
__asm mov ax, left;
__asm mov dx, top;
vo_tmp = _AX;
static_cast<vram_offset_t>(vo_tmp) >>= 4;
__asm shl bx, 1;
_DX <<= 6;
vo_tmp += _DX;
_DX >>= 2;
vo_tmp += _DX;
_DI = vo_tmp;
_AX &= ((BYTE_DOTS * 2) - 1);
first_bit = _AX;
w_tmp = ((_AX + w) >> 4);
if(first_bit) {
w_tmp++;
}
egcrect_w = w_tmp;
_CX = (ROW_SIZE / 2);
_CX -= w_tmp;
__asm shl cx, 1;
rows_remaining = h;
stride = _CX;
_ES = SEG_PLANE_B;
do {
_CX = egcrect_w;
put_loop: {
#if (GAME == 5)
_DI |= _DI;
if((!FLAGS_SIGN) && (_DI < PLANE_SIZE)) {
graph_accesspage_1(); dots = peek(_ES, _DI);
graph_accesspage_0(); pokew(_ES, _DI, dots);
}
_DI += 2;
#else
graph_accesspage_1(); dots = peek(_ES, _DI);
graph_accesspage_0(); _AX = dots; __asm { stosw; }
#endif
__asm { loop put_loop; }
}
_DI += stride;
rows_remaining--;
} while(!FLAGS_SIGN);
egc_off();
}
#pragma codestring "\x90"
#pragma option -k-
static void near egc_start_copy(void)
{
__asm {
push es
push 0
pop es
pushf
cli
// The EGC does in fact require an active GRCG in TDW mode.
// (See PC-9801 Programmers' Bible, p. 456)
mov al, GC_TDW
out 0x7C, al // grcg_setmode()
// According to MEMSYS.TXT, GRCG mode changes should always be
// reflected in this memory location, for compatibility with interrupt
// routines?
mov byte ptr es:[0x495], al
popf
pop es
}
graph_egc_on();
outport(EGC_ACTIVEPLANEREG, 0xFFF0);
egc_selectpat();
outport(EGC_MASKREG, 0xFFFF);
_DX = EGC_ADDRRESSREG;
outport(_DX, (_AX - _AX)); // :zunpet:
outport(EGC_BITLENGTHREG, 0xF);
}
#pragma codestring "\x90"
}

View File

@ -0,0 +1,2 @@
public _egcrect_w
_egcrect_w dw ?

View File

@ -2664,8 +2664,7 @@ include th02/initop.asm
include th04/formats/cdg_put_noalpha.asm
include th04/hardware/input_sense.asm
include th04/snd/se.asm
include th04/hardware/egccopyr.asm
even
include th04/hardware/egcrect.asm
include th04/bgimage.asm
include th04/bgimage_put_rect.asm
include th04/formats/cdg_load.asm
@ -2933,7 +2932,7 @@ include libs/master.lib/bgm[bss].asm
include th02/snd/load[bss].asm
include th04/mem[bss].asm
include th04/hardware/input[bss].asm
include th04/hardware/egccopyr[bss].asm
include th04/hardware/egcrect[bss].asm
include th04/formats/cdg[bss].asm
include th04/setup[bss].asm
include th04/zunsoft[bss].asm

1
th05/egcrect.cpp Normal file
View File

@ -0,0 +1 @@
#include "th04/hardware/egcrect.cpp"

View File

@ -7554,7 +7554,7 @@ include th05/snd/delaymea.asm
include th05/hardware/frame_delay.asm
db 0
include th04/formats/cdg_load.asm
include th04/hardware/egccopyr.asm
extern EGC_COPY_RECT_1_TO_0_16:proc
SHARED_ ends
.data
@ -7887,7 +7887,7 @@ include th05/formats/pi_headers[bss].asm
include th04/hardware/input[bss].asm
include th04/formats/cdg[bss].asm
include libs/master.lib/pfint21[bss].asm
include th04/hardware/egccopyr[bss].asm
include th04/hardware/egcrect[bss].asm
include th04/end/cutscene_script[bss].asm
db 4 dup(?)
byte_14F8E db ?

View File

@ -2562,8 +2562,7 @@ include th04/formats/cdg_put_nocolors.asm
include th05/hardware/frame_delay.asm
db 0
include th04/formats/cdg_load.asm
include th04/hardware/egccopyr.asm
even
extern EGC_COPY_RECT_1_TO_0_16:proc
SHARED_ ends
.data
@ -3260,7 +3259,7 @@ include th05/formats/pi_headers[bss].asm
include th04/hardware/input[bss].asm
include th04/formats/cdg[bss].asm
include libs/master.lib/pfint21[bss].asm
include th04/hardware/egccopyr[bss].asm
include th04/hardware/egcrect[bss].asm
include th04/setup[bss].asm
include th04/zunsoft[bss].asm
db 104 dup(?)