[Reverse-engineering] [th04/th05] Player sprite area invalidation

And once again, the TH05 version is un-decompilable. :/ It was pretty
close this time, though, as the entire block between PUSH DI and POP DI
kind of resembles a separate inlined function, in accordance with Turbo
C++'s  automatic backup of the DI register, as researched in 7f971a0.

Except that it contains a loop, and Turbo C++ refuses to inline any
function with `do`, `while`, `for`, or `goto`. If it didn't, it would
have totally worked.

Also, yes, C++ class methods are treated identically in this regard.

Oh well. Shot type control functions next, finally!

Completes P0035, funded by zorg.
This commit is contained in:
nmlgc 2019-09-24 20:54:32 +02:00
parent 7887f53ea8
commit a533b5d3ea
10 changed files with 171 additions and 156 deletions

View File

@ -92,10 +92,10 @@ bin\th04\main.exe: bin\th04\main.obj bin\th04\scoreupd.obj
$**
|
bin\th05\playermv.obj: th05\playermv.asm
bin\th05\player.obj: th05\player.asm
bin\th05\hud_bar.obj: th05\hud_bar.asm
bin\th05\scoreupd.obj: th04\scoreupd.asm
bin\th05\main.exe: bin\th05\main.obj bin\th05\playermv.obj bin\th05\hud_bar.obj bin\th05\scoreupd.obj th05\main012.cpp
bin\th05\main.exe: bin\th05\main.obj bin\th05\player.obj bin\th05\hud_bar.obj bin\th05\scoreupd.obj th05\main012.cpp
$(CC) $(CFLAGS) -ml -3 -Z -DGAME=5 -nbin\th05\ -eMAIN.EXE @&&|
$**
|

View File

@ -1,6 +1,20 @@
## C++
* Every class method that returns `*this` inlines to the ideal representation.
**Certainty**: See the examples in `9d121c7`. This is what allows us to use
custom types with overloaded assignment operators, with the resulting code
generation being indistinguishable from equivalent C preprocessor macros.
* Returning *anything else* will first store that result in `AX`, leading any
branches at the call site to then refer to `AX`.
**Certainty**: Maybe Borland (not Turbo) C++ has an optimization option
against it?
## Limits of decompilability
### `MOV BX, SP`-style functions, no stack frame
### `MOV BX, SP`-style functions, or others with no standard stack frame
These almost certainly weren't compiled from C. By disabling stack frames
using `#pragma option -k-`, it *might* be possible to still get the exact same

View File

@ -1,3 +1,3 @@
; A random shared point variable used for drawing various things.
public _drawpoint
public _DRAWPOINT
_drawpoint Point <?>

View File

@ -1,4 +1,7 @@
; int pascal far vector2_at(int angle, int length, int origin_y, int origin_x, Point *ret)
; int pascal far vector2_at(
; Point *ret, int origin_x, int origin_y, int length, int angle
; );
public VECTOR2_AT
vector2_at proc far
@@angle = word ptr 6

View File

@ -0,0 +1,70 @@
; void pascal near player_invalidate(void);
public PLAYER_INVALIDATE
player_invalidate proc near
@@angle = byte ptr [bp-1]
enter 2, 0
push si
push di
mov _tile_invalidate_box.y, PLAYER_H
cmp _miss_time, 0
jz short @@alive
mov _tile_invalidate_box.x, MISS_EXPLOSION_W
mov ax, _miss_explosion_radius
; Go back a frame
add ax, -MISS_EXPLOSION_RADIUS_VELOCITY
mov di, ax
xor si, si
mov al, _miss_explosion_angle
add al, -MISS_EXPLOSION_ANGLE_VELOCITY
jmp short @@more?
@@loop:
cmp si, MISS_EXPLOSION_COUNT / 2
jnz short @@invalidate
mov ax, di
cwd
sub ax, dx
sar ax, 1
mov di, ax
mov al, @@angle
neg al
mov @@angle, al
@@invalidate:
push offset _drawpoint
push player_pos.cur.x
push player_pos.cur.y
push di
mov al, @@angle
mov ah, 0
push ax
call vector2_at
MISS_EXPLOSION_CLIP @@next
call main_01:tiles_invalidate_around pascal, _drawpoint.y, _drawpoint.x
@@next:
inc si
mov al, @@angle
add al, 256 / (MISS_EXPLOSION_COUNT / 2)
@@more?:
mov @@angle, al
cmp si, MISS_EXPLOSION_COUNT
jl short @@loop
jmp short @@ret
; ---------------------------------------------------------------------------
@@alive:
mov _tile_invalidate_box.x, PLAYER_W
call main_01:tiles_invalidate_around pascal, large [player_pos.prev]
mov _tile_invalidate_box.x, PLAYER_OPTION_W + PLAYER_W + PLAYER_OPTION_W
mov _tile_invalidate_box.y, PLAYER_OPTION_H
call main_01:tiles_invalidate_around pascal, large [_player_option_pos_prev]
@@ret:
pop di
pop si
leave
retn
player_invalidate endp

View File

@ -9,6 +9,8 @@ MISS_ANIM_EXPLODE_UNTIL = 31
MISS_EXPLOSION_COUNT = 8
MISS_EXPLOSION_W = 48
MISS_EXPLOSION_H = 48
MISS_EXPLOSION_RADIUS_VELOCITY = (7 shl 4)
MISS_EXPLOSION_ANGLE_VELOCITY = 8
MISS_EXPLOSION_CLIP macro clip_label
cmp _drawpoint.y, ((PLAYFIELD_TOP - (MISS_EXPLOSION_H / 2)) shl 4)

View File

@ -1,4 +1,4 @@
public _scroll_line_on_plane, _tile_invalidate_box
public _SCROLL_LINE_ON_PLANE, _TILE_INVALIDATE_BOX
_scroll_line_on_plane dw 2 dup(?)
; Width and height, in screen pixels, of a box around the center passed to
; tiles_invalidate_around(). *Not* the radius.

View File

@ -3469,7 +3469,7 @@ sub_CB58 proc near
push bp
mov bp, sp
call main_01:sub_10EED
call main_01:sub_107E2
call main_01:player_invalidate
call main_01:sub_10444
call main_01:sub_C74C
call main_01:sub_CA98
@ -11012,88 +11012,7 @@ loc_107D6:
retn
sub_10713 endp
; =============== S U B R O U T I N E =======================================
; Attributes: bp-based frame
sub_107E2 proc near
var_1 = byte ptr -1
enter 2, 0
push si
push di
mov _tile_invalidate_box.y, 48
cmp _miss_time, 0
jz short loc_10872
mov _tile_invalidate_box.x, 48
mov ax, _miss_explosion_radius
add ax, (-7 shl 4)
mov di, ax
xor si, si
mov al, _miss_explosion_angle
add al, -8
jmp short loc_10868
; ---------------------------------------------------------------------------
loc_1080C:
cmp si, 4
jnz short loc_10822
mov ax, di
cwd
sub ax, dx
sar ax, 1
mov di, ax
mov al, [bp+var_1]
neg al
mov [bp+var_1], al
loc_10822:
push offset _drawpoint
push player_pos.cur.x
push player_pos.cur.y
push di
mov al, [bp+var_1]
mov ah, 0
push ax
call vector2_at
cmp _drawpoint.y, (-8 shl 4)
jl short loc_10862
cmp _drawpoint.y, (376 shl 4)
jge short loc_10862
cmp _drawpoint.x, (-8 shl 4)
jl short loc_10862
cmp _drawpoint.x, (392 shl 4)
jge short loc_10862
call main_01:tiles_invalidate_around pascal, _drawpoint.y, _drawpoint.x
loc_10862:
inc si
mov al, [bp+var_1]
add al, 40h
loc_10868:
mov [bp+var_1], al
cmp si, 8
jl short loc_1080C
jmp short loc_10894
; ---------------------------------------------------------------------------
loc_10872:
mov _tile_invalidate_box.x, 32
call main_01:tiles_invalidate_around pascal, large [player_pos.prev]
mov _tile_invalidate_box.x, 64
mov _tile_invalidate_box.y, 16
call main_01:tiles_invalidate_around pascal, large [_player_option_pos_prev]
loc_10894:
pop di
pop si
leave
retn
sub_107E2 endp
include th04/player/invalidate.asm
include th04/player/move.asm
; =============== S U B R O U T I N E =======================================
@ -11194,9 +11113,9 @@ loc_10A16:
inc byte ptr es:[bx+31h]
loc_10A25:
add _miss_explosion_radius, (7 shl 4)
add _miss_explosion_radius, MISS_EXPLOSION_RADIUS_VELOCITY
mov al, _miss_explosion_angle
add al, 8
add al, MISS_EXPLOSION_ANGLE_VELOCITY
mov _miss_explosion_angle, al
cmp _miss_time, MISS_ANIM_FRAMES - MISS_ANIM_FLASH_AT
jnb locret_10ABD

View File

@ -1,9 +1,24 @@
.186
.386
locals
include libs/master.lib/macros.inc
include libs/master.lib/master.inc
include th02/playfld.inc
include th04/math/motion.inc
include th04/hardware/input.inc
include th04/player/player.inc
VECTOR2_AT procdesc pascal far \
ret:ptr Point, origin_x:word, origin_y:word, length:word, angle:byte
TILES_INVALIDATE_AROUND procdesc pascal near \
center:Point
extrn _tile_invalidate_box:Point
extrn _miss_time:byte
extrn _miss_explosion_angle:byte
extrn _miss_explosion_radius:word
extrn _drawpoint:Point
extrn _player_option_pos_prev:Point
extrn player_pos:motion_t
extrn _playchar_speed_aligned:word
@ -14,6 +29,57 @@ extrn _playchar_speed_diagonal:word
main_01_TEXT segment word public 'CODE' use16
assume cs:main_01_TEXT
; void pascal near player_invalidate(void);
public PLAYER_INVALIDATE
player_invalidate proc pascal near
mov _tile_invalidate_box.y, PLAYER_H
cmp _miss_time, 0
jz short @@alive
push di
mov _tile_invalidate_box.x, MISS_EXPLOSION_W
mov di, _miss_explosion_radius
; Go back a frame
add di, -MISS_EXPLOSION_RADIUS_VELOCITY
mov al, _miss_explosion_angle
add al, -MISS_EXPLOSION_ANGLE_VELOCITY
mov ah, MISS_EXPLOSION_COUNT
@@loop:
cmp ah, MISS_EXPLOSION_COUNT / 2
jnz short @@invalidate
shr di, 1
neg al
@@invalidate:
push ax
call vector2_at pascal, offset _drawpoint, player_pos.cur.x, player_pos.cur.y, di, ax
MISS_EXPLOSION_CLIP @@next
call tiles_invalidate_around pascal, large [_drawpoint]
@@next:
pop ax
add al, 256 / (MISS_EXPLOSION_COUNT / 2)
dec ah
jnz short @@loop
pop di
jmp short @@ret
; ---------------------------------------------------------------------------
@@alive:
mov _tile_invalidate_box.x, PLAYER_W
call tiles_invalidate_around pascal, large [player_pos.prev]
mov _tile_invalidate_box.x, PLAYER_OPTION_W + PLAYER_W + PLAYER_OPTION_W
mov _tile_invalidate_box.y, PLAYER_OPTION_H
call tiles_invalidate_around pascal, large [_player_option_pos_prev]
@@ret:
retn
player_invalidate endp
even
; move_ret_t pascal near player_move(int input);
public PLAYER_MOVE
player_move proc near

View File

@ -2017,7 +2017,7 @@ sub_BEE6 proc near
push bp
mov bp, sp
call sub_11A65
call sub_14266
call player_invalidate
call sub_123AD
call sub_E41C
call sub_E5EE
@ -12830,9 +12830,9 @@ loc_120B1:
loc_120B6:
nopcall sub_1059D
add _miss_explosion_radius, (7 shl 4)
add _miss_explosion_radius, MISS_EXPLOSION_RADIUS_VELOCITY
mov al, _miss_explosion_angle
add al, 8
add al, MISS_EXPLOSION_ANGLE_VELOCITY
mov _miss_explosion_angle, al
cmp _miss_time, MISS_ANIM_FRAMES - MISS_ANIM_FLASH_AT
jnb short locret_12148
@ -17287,66 +17287,7 @@ table_1425B dw loc_14187
dw loc_1419F
db 0
; =============== S U B R O U T I N E =======================================
sub_14266 proc near
mov _tile_invalidate_box.y, 48
cmp _miss_time, 0
jz short loc_142D4
push di
mov _tile_invalidate_box.x, 48
mov di, _miss_explosion_radius
add di, (-7 shl 4)
mov al, _miss_explosion_angle
add al, -8
mov ah, 8
loc_14288:
cmp ah, 4
jnz short loc_14291
shr di, 1
neg al
loc_14291:
push ax
push offset _drawpoint
push player_pos.cur.x
push player_pos.cur.y
push di
push ax
call vector2_at
cmp _drawpoint.y, (-8 shl 4)
jl short loc_142CA
cmp _drawpoint.y, (376 shl 4)
jge short loc_142CA
cmp _drawpoint.x, (-8 shl 4)
jl short loc_142CA
cmp _drawpoint.x, (392 shl 4)
jge short loc_142CA
call tiles_invalidate_around pascal, large [_drawpoint]
loc_142CA:
pop ax
add al, 40h
dec ah
jnz short loc_14288
pop di
jmp short locret_142F6
; ---------------------------------------------------------------------------
loc_142D4:
mov _tile_invalidate_box.x, 32
call tiles_invalidate_around pascal, large [player_pos.prev]
mov _tile_invalidate_box.x, 64
mov _tile_invalidate_box.y, 16
call tiles_invalidate_around pascal, large [_player_option_pos_prev]
locret_142F6:
retn
sub_14266 endp
nop
PLAYER_INVALIDATE procdesc pascal near
PLAYER_MOVE procdesc pascal near \
input:word
HUD_BAR_PUT procdesc near