[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.
2019-09-24 18:54:32 +00:00
|
|
|
.386
|
2019-09-21 09:04:39 +00:00
|
|
|
locals
|
|
|
|
|
[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.
2019-09-24 18:54:32 +00:00
|
|
|
include libs/master.lib/master.inc
|
[Maintenance] Reimplement TASM's ARG directive for `MOV BX, SP` functions
`cPtrSize` is simply the wrong constant for calculating parameter
offsets on the stack, because it corresponds to the memory model's
default distance, not the function's distance. Luckily, ARG has a
RETURNS clause, and if you declare all parameters in there, ARG won't
emit that pesky and unnecessary `ENTER 0, 0` instruction. Big discovery
right there!
Sadly, ARG is unusable for ZUN's silly functions that keep the base
pointer in BX. TASM declares the resulting equates as `[BP+offset]`,
and it's apparently impossible to only get `offset` out of such an
equate later.
So, rather than staying with numbers, let's reimplement ARG for these
functions instead. This way, we can even abstract away the stack clear
size for the `RET` instructions.
It's a bit rough around the edges though, forcing you to explicitly
specify the function distance, and to pass the parameters in reverse
order compared to the C declaration (thankfully, all of these use the
PASCAL calling convention). It also doesn't work with more complex
types yet. But certainly better than numbers.
Part of P0134, funded by [Anonymous].
2021-02-10 11:51:14 +00:00
|
|
|
include th03/arg_bx.inc
|
2020-04-05 14:17:33 +00:00
|
|
|
include th02/main/playfld.inc
|
2019-09-21 09:04:39 +00:00
|
|
|
include th04/math/motion.inc
|
|
|
|
include th04/hardware/input.inc
|
2020-04-05 14:17:33 +00:00
|
|
|
include th04/main/player/player.inc
|
[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.
2019-09-24 18:54:32 +00:00
|
|
|
|
|
|
|
VECTOR2_AT procdesc pascal far \
|
|
|
|
ret:ptr Point, origin_x:word, origin_y:word, length:word, angle:byte
|
|
|
|
|
2020-04-28 16:10:07 +00:00
|
|
|
MAIN_01 group MAIN_0_TEXT, MAIN_01_TEXT
|
|
|
|
MAIN_0_TEXT segment byte public 'CODE' use16
|
2020-04-23 19:11:04 +00:00
|
|
|
TILES_INVALIDATE_AROUND procdesc pascal near \
|
|
|
|
center:Point
|
2020-04-28 16:10:07 +00:00
|
|
|
MAIN_0_TEXT ends
|
[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.
2019-09-24 18:54:32 +00:00
|
|
|
|
|
|
|
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
|
2019-09-21 09:04:39 +00:00
|
|
|
|
2019-11-15 19:54:33 +00:00
|
|
|
extrn _player_pos:motion_t
|
2019-09-21 09:04:39 +00:00
|
|
|
extrn _playchar_speed_aligned:word
|
|
|
|
extrn _playchar_speed_diagonal:word
|
|
|
|
|
|
|
|
; ----------------------------------------------------------------------------
|
|
|
|
|
2020-04-28 16:10:07 +00:00
|
|
|
MAIN_01_TEXT segment word public 'CODE' use16
|
|
|
|
assume cs:MAIN_01
|
2019-09-21 09:04:39 +00:00
|
|
|
|
[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.
2019-09-24 18:54:32 +00:00
|
|
|
; void pascal near player_invalidate(void);
|
|
|
|
public PLAYER_INVALIDATE
|
2020-04-28 16:10:07 +00:00
|
|
|
PLAYER_INVALIDATE proc pascal near
|
[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.
2019-09-24 18:54:32 +00:00
|
|
|
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
|
2020-04-28 16:10:07 +00:00
|
|
|
call VECTOR2_AT pascal, offset _drawpoint, _player_pos.cur.x, _player_pos.cur.y, di, ax
|
[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.
2019-09-24 18:54:32 +00:00
|
|
|
MISS_EXPLOSION_CLIP @@next
|
2020-04-28 16:10:07 +00:00
|
|
|
call TILES_INVALIDATE_AROUND pascal, large [_drawpoint]
|
[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.
2019-09-24 18:54:32 +00:00
|
|
|
|
|
|
|
@@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
|
2020-04-28 16:10:07 +00:00
|
|
|
call TILES_INVALIDATE_AROUND pascal, large [_player_pos.prev]
|
[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.
2019-09-24 18:54:32 +00:00
|
|
|
mov _tile_invalidate_box.x, PLAYER_OPTION_W + PLAYER_W + PLAYER_OPTION_W
|
|
|
|
mov _tile_invalidate_box.y, PLAYER_OPTION_H
|
2020-04-28 16:10:07 +00:00
|
|
|
call TILES_INVALIDATE_AROUND pascal, large [_player_option_pos_prev]
|
[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.
2019-09-24 18:54:32 +00:00
|
|
|
|
|
|
|
@@ret:
|
|
|
|
retn
|
2020-04-28 16:10:07 +00:00
|
|
|
PLAYER_INVALIDATE endp
|
[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.
2019-09-24 18:54:32 +00:00
|
|
|
|
|
|
|
|
|
|
|
even
|
|
|
|
|
|
|
|
|
2019-09-21 09:04:39 +00:00
|
|
|
; move_ret_t pascal near player_move(int input);
|
|
|
|
public PLAYER_MOVE
|
2020-04-28 16:10:07 +00:00
|
|
|
PLAYER_MOVE proc near
|
[Maintenance] Reimplement TASM's ARG directive for `MOV BX, SP` functions
`cPtrSize` is simply the wrong constant for calculating parameter
offsets on the stack, because it corresponds to the memory model's
default distance, not the function's distance. Luckily, ARG has a
RETURNS clause, and if you declare all parameters in there, ARG won't
emit that pesky and unnecessary `ENTER 0, 0` instruction. Big discovery
right there!
Sadly, ARG is unusable for ZUN's silly functions that keep the base
pointer in BX. TASM declares the resulting equates as `[BP+offset]`,
and it's apparently impossible to only get `offset` out of such an
equate later.
So, rather than staying with numbers, let's reimplement ARG for these
functions instead. This way, we can even abstract away the stack clear
size for the `RET` instructions.
It's a bit rough around the edges though, forcing you to explicitly
specify the function distance, and to pass the parameters in reverse
order compared to the C declaration (thankfully, all of these use the
PASCAL calling convention). It also doesn't work with more complex
types yet. But certainly better than numbers.
Part of P0134, funded by [Anonymous].
2021-02-10 11:51:14 +00:00
|
|
|
arg_bx near, @input:word
|
2019-09-21 09:04:39 +00:00
|
|
|
|
|
|
|
@@diagonal_x equ ax
|
|
|
|
@@diagonal_y equ cx
|
|
|
|
@@aligned equ dx
|
|
|
|
|
[Maintenance] Reimplement TASM's ARG directive for `MOV BX, SP` functions
`cPtrSize` is simply the wrong constant for calculating parameter
offsets on the stack, because it corresponds to the memory model's
default distance, not the function's distance. Luckily, ARG has a
RETURNS clause, and if you declare all parameters in there, ARG won't
emit that pesky and unnecessary `ENTER 0, 0` instruction. Big discovery
right there!
Sadly, ARG is unusable for ZUN's silly functions that keep the base
pointer in BX. TASM declares the resulting equates as `[BP+offset]`,
and it's apparently impossible to only get `offset` out of such an
equate later.
So, rather than staying with numbers, let's reimplement ARG for these
functions instead. This way, we can even abstract away the stack clear
size for the `RET` instructions.
It's a bit rough around the edges though, forcing you to explicitly
specify the function distance, and to pass the parameters in reverse
order compared to the C declaration (thankfully, all of these use the
PASCAL calling convention). It also doesn't work with more complex
types yet. But certainly better than numbers.
Part of P0134, funded by [Anonymous].
2021-02-10 11:51:14 +00:00
|
|
|
mov bx, @input
|
2019-09-21 09:04:39 +00:00
|
|
|
cmp bl, INPUT_RIGHT or INPUT_DOWN
|
|
|
|
ja short @@invalid
|
|
|
|
mov @@diagonal_y, _playchar_speed_diagonal
|
|
|
|
mov @@diagonal_x, @@diagonal_y
|
|
|
|
mov @@aligned, _playchar_speed_aligned
|
|
|
|
and bh, low INPUT_MOVEMENT
|
|
|
|
jz short @@switch
|
|
|
|
or bl, bl
|
|
|
|
jnz short @@invalid
|
|
|
|
shr bx, 8
|
|
|
|
cmp bl, 8
|
|
|
|
ja short @@invalid
|
|
|
|
add bl, 11
|
|
|
|
|
|
|
|
@@switch:
|
|
|
|
add bx, bx
|
|
|
|
jmp word ptr cs:@@switch_table[bx]
|
|
|
|
|
|
|
|
@@up:
|
|
|
|
neg @@aligned
|
|
|
|
|
|
|
|
@@down:
|
2019-11-15 19:54:33 +00:00
|
|
|
mov _player_pos.velocity.y, @@aligned
|
2019-09-21 09:04:39 +00:00
|
|
|
jmp short @@moved
|
|
|
|
; ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
@@left:
|
|
|
|
neg @@aligned
|
|
|
|
|
|
|
|
@@right:
|
2019-11-15 19:54:33 +00:00
|
|
|
mov _player_pos.velocity.x, @@aligned
|
2019-09-21 09:04:39 +00:00
|
|
|
jmp short @@moved
|
|
|
|
; ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
@@up_right:
|
|
|
|
neg @@diagonal_y
|
|
|
|
jmp short @@down_right
|
|
|
|
; ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
@@up_left:
|
|
|
|
neg @@diagonal_y
|
|
|
|
|
|
|
|
@@down_left:
|
|
|
|
neg @@diagonal_x
|
|
|
|
|
|
|
|
@@down_right:
|
2019-11-15 19:54:33 +00:00
|
|
|
mov _player_pos.velocity.x, @@diagonal_x
|
|
|
|
mov _player_pos.velocity.y, @@diagonal_y
|
2019-09-21 09:04:39 +00:00
|
|
|
jmp short @@moved
|
|
|
|
; ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
@@standing_still:
|
|
|
|
mov al, MOVE_NOINPUT
|
|
|
|
jmp short @@ret
|
|
|
|
; ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
@@invalid:
|
|
|
|
xor al, al
|
|
|
|
jmp short @@ret
|
|
|
|
; ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
@@moved:
|
|
|
|
mov al, MOVE_VALID
|
|
|
|
|
|
|
|
@@ret:
|
[Maintenance] Reimplement TASM's ARG directive for `MOV BX, SP` functions
`cPtrSize` is simply the wrong constant for calculating parameter
offsets on the stack, because it corresponds to the memory model's
default distance, not the function's distance. Luckily, ARG has a
RETURNS clause, and if you declare all parameters in there, ARG won't
emit that pesky and unnecessary `ENTER 0, 0` instruction. Big discovery
right there!
Sadly, ARG is unusable for ZUN's silly functions that keep the base
pointer in BX. TASM declares the resulting equates as `[BP+offset]`,
and it's apparently impossible to only get `offset` out of such an
equate later.
So, rather than staying with numbers, let's reimplement ARG for these
functions instead. This way, we can even abstract away the stack clear
size for the `RET` instructions.
It's a bit rough around the edges though, forcing you to explicitly
specify the function distance, and to pass the parameters in reverse
order compared to the C declaration (thankfully, all of these use the
PASCAL calling convention). It also doesn't work with more complex
types yet. But certainly better than numbers.
Part of P0134, funded by [Anonymous].
2021-02-10 11:51:14 +00:00
|
|
|
ret_bx
|
2019-09-21 09:04:39 +00:00
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
|
|
@@switch_table label word
|
|
|
|
dw @@standing_still
|
|
|
|
dw @@up
|
|
|
|
dw @@down
|
|
|
|
dw @@invalid
|
|
|
|
dw @@left
|
|
|
|
dw @@up_left
|
|
|
|
dw @@down_left
|
|
|
|
dw @@invalid
|
|
|
|
dw @@right
|
|
|
|
dw @@up_right
|
|
|
|
dw @@down_right
|
|
|
|
dw @@invalid
|
|
|
|
dw @@up_left
|
|
|
|
dw @@up_right
|
|
|
|
dw @@invalid
|
|
|
|
dw @@down_left
|
|
|
|
dw @@invalid
|
|
|
|
dw @@invalid
|
|
|
|
dw @@invalid
|
|
|
|
dw @@down_right
|
2020-04-28 16:10:07 +00:00
|
|
|
PLAYER_MOVE endp
|
|
|
|
MAIN_01_TEXT ends
|
2019-09-21 09:04:39 +00:00
|
|
|
|
|
|
|
end
|