[Decompilation] [th05] pi_put_8(), pi_put_quarter_8()

> assigning to the DI register immediately before a CALL
Yeah, no amount of comma operator trickery can get *that* out of this
compiler. Also, these TH05 .PI functions are the only place in PC-98
Touhou with a `IMUL DI, imm8` instruction, which is impossible to get
out of Turbo C++'s built-in assembler.
Well, at least the `if` branches decompile somewhat nicely.

Part of P0134, funded by [Anonymous].
This commit is contained in:
nmlgc 2021-02-14 12:51:12 +01:00
parent 25d26824a1
commit ffcc46d32f
10 changed files with 144 additions and 113 deletions

View File

@ -150,7 +150,7 @@ bin\th05\res_kso.com: th05\res_kso.cpp
$**
| masters.lib
bin\th05\op.exe: th05\op010.cpp bin\th05\op.obj th05\op011.cpp th05\m_char.cpp bin\th05\pi_asm_2.obj bin\th05\initop.obj bin\th05\input_s.obj bin\th05\inp_h_w.obj bin\th05\snd_dlym.obj th05\cdg_p_nc.cpp bin\th05\frmdelay.obj bin\th04\cdg_load.obj bin\th05\egcrect.obj bin\hfliplut.obj
bin\th05\op.exe: th05\op010.cpp bin\th05\op.obj th05\op011.cpp th05\m_char.cpp bin\th05\pi_cpp_2.obj bin\th05\pi_asm_2.obj bin\th05\initop.obj bin\th05\input_s.obj bin\th05\inp_h_w.obj bin\th05\snd_dlym.obj th05\cdg_p_nc.cpp bin\th05\frmdelay.obj bin\th04\cdg_load.obj bin\th05\egcrect.obj bin\hfliplut.obj
$(CC) $(CFLAGS) -ml -DGAME=5 -DBINARY='O' -3 -Z -nbin\th05\ -eOP.EXE @&&|
$**
|
@ -160,7 +160,7 @@ bin\th05\main.exe: bin\th05\main.obj th05\main010.cpp th05\main011.cpp th05\p_co
$**
|
bin\th05\maine.exe: bin\th05\maine.obj th05\maine011.cpp th05\regist.cpp th05\staff.cpp bin\th05\pi_asm_2.obj bin\th05\initmain.obj bin\th05\input_s.obj bin\th05\inp_h_w.obj bin\th05\snd_dlym.obj bin\th05\frmdelay.obj bin\th04\cdg_load.obj bin\th05\egcrect.obj bin\hfliplut.obj
bin\th05\maine.exe: bin\th05\maine.obj th05\maine011.cpp th05\regist.cpp th05\staff.cpp bin\th05\pi_cpp_2.obj bin\th05\pi_asm_2.obj bin\th05\initmain.obj bin\th05\input_s.obj bin\th05\inp_h_w.obj bin\th05\snd_dlym.obj bin\th05\frmdelay.obj bin\th04\cdg_load.obj bin\th05\egcrect.obj bin\hfliplut.obj
$(CC) $(CFLAGS) -ml -DGAME=5 -DBINARY='E' -Z -nbin\th05\ -eMAINE.EXE @&&|
$**
|

View File

@ -7,6 +7,8 @@ include libs/master.lib/macros.inc
GAIJI_PUTSA procdesc pascal far \
x:word, y:word, strp_seg:word, strp_off:word, atrb:word
GRAPH_PACK_PUT_8_NOCLIP procdesc pascal far \
left:word, top:word, linepat_sgm:word, linepat_off:word, len:word
GRAPH_PI_FREE procdesc pascal far \
header:far ptr, image:far ptr
PALETTE_SHOW procdesc pascal far

View File

@ -460,6 +460,11 @@ void MASTER_RET palette_white_out(unsigned speed);
void MASTER_RET graph_pack_put_8(
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.
void MASTER_RET graph_pack_put_8_noclip(
screen_x_t left, screen_y_t top, const void far *linepat, pixel_t len
);
#endif
// ---

View File

@ -16,6 +16,43 @@ include th03/arg_bx.inc
SHARED_ segment word public 'CODE' use16
assume cs:SHARED_
public PI_PUT_8_ROWLOOP
pi_put_8_rowloop proc pascal near
; Can't use ARG, because the function doesn't `PUSH BP`!
@@stride_packed = word ptr [bp+2]
@@w = word ptr [bp+4]
@@top = word ptr [bp+6]
@@left = word ptr [bp+8]
@@h equ di
mov bp, sp
@@put_row:
push es
call graph_pack_put_8_noclip pascal, @@left, @@top, es, si, @@w
pop es
inc @@top
cmp @@top, RES_Y
jb short @@next_row
sub @@top, RES_Y
@@next_row:
add si, @@stride_packed
; .PI pointer normalization, see pi_buffer_p_normalize()
mov ax, si
shr ax, 4
mov dx, es
add dx, ax
mov es, dx
and si, 0Fh
dec @@h
jnz short @@put_row
retn 8
pi_put_8_rowloop endp
public PI_PALETTE_APPLY
func pi_palette_apply
arg_bx far, @slot:word

55
th05/formats/pi_cpp_2.cpp Normal file
View File

@ -0,0 +1,55 @@
// Second TH05 .PI C++ translation unit.
#pragma codeseg SHARED_
extern "C" {
#include <stddef.h>
#include "platform.h"
#include "pc98.h"
#include "planar.h"
#include "master.hpp"
#include "th05/formats/pi.h"
#include "th05/formats/pi_impl.hpp"
// Additionally takes:
// • `void far *pi_buf` in ES:SI
// • `pixel_t h` in DI
void pascal near pi_put_8_rowloop(
screen_x_t left, vram_y_t top, pixel_t w, size_t stride_packed
);
void DEFCONV pi_put_8(screen_x_t left, vram_y_t top, int slot)
{
#define rowloop_func __asm { \
push left; /* left */ \
push top; /* top */ \
mov ax, word ptr pi_headers[di].xsize; \
push ax; /* w */ \
shr ax, 1; \
push ax; /* stride_packed */ \
mov di, word ptr pi_headers[di].ysize; \
call near ptr pi_put_8_rowloop; \
}
pi_put_impl(left, top, slot, rowloop_func);
#undef rowloop_func
}
#pragma codestring "\x90"
void pascal pi_put_quarter_8(
screen_x_t left, vram_y_t top, int slot, int quarter
)
{
#define rowloop_func __asm { \
push left; \
push top; \
push PI_QUARTER_W; \
push (PI_W / 2); \
mov di, PI_QUARTER_H; \
call near ptr pi_put_8_rowloop; \
}
pi_put_quarter_impl(left, top, slot, quarter, rowloop_func);
#undef rowloop_func
}
}

39
th05/formats/pi_impl.hpp Normal file
View File

@ -0,0 +1,39 @@
// Shared parts of the pi_put_*() functions.
#include "decomp.h"
inline void imul_di(int8_t factor) {
__emit__(0x6B, 0xFF, factor);
}
#define pi_put_impl(left, top, slot, rowloop_func) \
_SI = slot; \
_DI = _SI; \
_SI <<= 2; /* *= sizeof(void far *) */ \
__asm { les si, pi_buffers[si]; } \
imul_di(sizeof(PiHeader)); \
rowloop_func
#define buffer_offset_off _AX
#define buffer_offset_sgm _DX
#define quarter_local _CL
#define pi_put_quarter_impl(left, top, slot, quarter, rowloop_func) \
buffer_offset_off = 0; \
buffer_offset_sgm = 0; \
_SI = slot; \
\
quarter_local = quarter; \
if(quarter_local & 1) { \
buffer_offset_off = (PI_QUARTER_W / 2); \
} \
if(quarter_local & 2) { \
/* Careful! Parenthesizing this naively leads to overflows, since */ \
/* (PI_QUARTER * PI_W) doesn't fit into 16 bits. */\
buffer_offset_sgm = ((PI_QUARTER_H / 2) * (PI_W / 16)); \
} \
_SI <<= 2; /* *= sizeof(void far *) */ \
__asm { les si, pi_buffers[si]; } \
_SI += buffer_offset_off; \
_ES += buffer_offset_sgm; \
rowloop_func

View File

@ -1,109 +0,0 @@
public PI_PUT_8
pi_put_8 proc
; (PASCAL calling convention, parameter list needs to be reversed here)
arg @@slot:word, @@top:word, @@left:word
push bp
mov bp, sp
push si
push di
mov si, @@slot
mov di, si
shl si, 2
les si, _pi_buffers[si]
imul di, size PiHeader
push @@left
push @@top
mov ax, _pi_headers.PiHeader._xsize[di]
push ax
shr ax, 1
push ax
mov di, _pi_headers.PiHeader._ysize[di]
call pi_put_8_rowloop
pop di
pop si
pop bp
ret 6
pi_put_8 endp
align 2
; ---------------------------------------------------------------------------
public PI_PUT_QUARTER_8
pi_put_quarter_8 proc
; (PASCAL calling convention, parameter list needs to be reversed here)
arg @@quarter:byte, @@slot:word, @@top:word, @@left:word
push bp
mov bp, sp
push si
push di
xor ax, ax
xor dx, dx
mov si, @@slot
mov cl, @@quarter
test cl, 1
jz short @@bottom_quarter?
mov ax, 160
@@bottom_quarter?:
test cl, 2
jz short @@put
mov dx, ((640 * 200) / 2) / 16
@@put:
shl si, 2
les si, _pi_buffers[si]
add si, ax
mov ax, es
add ax, dx
mov es, ax
push @@left
push @@top
push 320
push 320
mov di, 200
call pi_put_8_rowloop
pop di
pop si
pop bp
ret 8
pi_put_quarter_8 endp
; ---------------------------------------------------------------------------
; void pascal pi_put_8_rowloop(
; void far *pi_buf<es:si>,
; pixel_t h<di>,
; screen_x_t x, vram_y_t y, pixel_t w, size_t stride_packed
; );
pi_put_8_rowloop proc near
@@stride_packed = word ptr [bp+2]
@@w = word ptr [bp+4]
@@top = word ptr [bp+6]
@@left = word ptr [bp+8]
@@h equ di
mov bp, sp
@@put_row:
push es
call graph_pack_put_8_noclip pascal, @@left, @@top, es, si, @@w
pop es
inc @@top
cmp @@top, RES_Y
jb short @@next_row
sub @@top, RES_Y
@@next_row:
add si, @@stride_packed
mov ax, si
shr ax, 4
mov dx, es
add dx, ax
mov es, dx
and si, 0Fh
dec @@h
jnz short @@put_row
retn 8
pi_put_8_rowloop endp

1
th05/pi_cpp_2.cpp Normal file
View File

@ -0,0 +1 @@
#include "th05/formats/pi_cpp_2.cpp"

View File

@ -7540,7 +7540,8 @@ include th05/snd/load.asm
include th05/snd/kajaint.asm
include th05/formats/pi_put_masked.asm
include th05/formats/pi_load.asm
include th05/formats/pi_put.asm
extern PI_PUT_8:proc
extern PI_PUT_QUARTER_8:proc
extern PI_PALETTE_APPLY:proc
extern PI_FREE:proc
extern GAME_INIT_MAIN:proc

View File

@ -2545,7 +2545,7 @@ include th05/snd/load.asm
include th05/snd/kajaint.asm
include th05/formats/pi_put_masked.asm
include th05/formats/pi_load.asm
include th05/formats/pi_put.asm
extern PI_PUT_8:proc
extern PI_PALETTE_APPLY:proc
extern PI_FREE:proc
extern _game_init_op:proc