2019-09-15 16:23:33 +00:00
|
|
|
; void pascal near tiles_invalidate_around(Point center);
|
|
|
|
public TILES_INVALIDATE_AROUND
|
[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
|
|
|
tiles_invalidate_around proc near
|
|
|
|
arg_bx near, @center:dword
|
2018-12-29 23:00:10 +00:00
|
|
|
|
|
|
|
mov dx, _tile_invalidate_box.x
|
|
|
|
shr dx, 1
|
[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 ax, @center.x
|
2018-12-29 23:00:10 +00:00
|
|
|
sar ax, 4
|
|
|
|
sub ax, dx
|
|
|
|
cmp ax, PLAYFIELD_W
|
|
|
|
jl short @@left_edge_left_of_playfield?
|
|
|
|
|
|
|
|
@@outside_playfield:
|
[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
|
2018-12-29 23:00:10 +00:00
|
|
|
; ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
@@left_edge_left_of_playfield?:
|
|
|
|
mov cx, ax
|
|
|
|
or ax, ax
|
|
|
|
js short @@right_edge_left_of_playfield?
|
|
|
|
and ax, (TILE_W - 1)
|
|
|
|
|
|
|
|
@@right_edge_left_of_playfield?:
|
|
|
|
add ax, _tile_invalidate_box.x
|
|
|
|
dec ax
|
|
|
|
js short @@outside_playfield
|
|
|
|
sar cx, 4
|
|
|
|
jns short @@check_y
|
|
|
|
xor cx, cx
|
|
|
|
|
|
|
|
@@check_y:
|
|
|
|
mov _invalidate_left_x_tile, cx
|
|
|
|
shr ax, 4
|
|
|
|
inc ax
|
|
|
|
mov cx, ax ; CX = number of horizontal tiles to invalidate
|
|
|
|
mov dx, _tile_invalidate_box.y
|
|
|
|
sar dx, 1
|
[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 ax, @center.y
|
2018-12-29 23:00:10 +00:00
|
|
|
sar ax, 4
|
|
|
|
add ax, TILE_H
|
|
|
|
sub ax, dx
|
|
|
|
jns short @@bottom_below_playfield?
|
|
|
|
mov dx, _tile_invalidate_box.y
|
|
|
|
add dx, ax
|
|
|
|
or dx, dx
|
|
|
|
jle short @@outside_playfield
|
|
|
|
|
|
|
|
@@bottom_below_playfield?:
|
|
|
|
cmp ax, PLAYFIELD_H + TILE_H
|
|
|
|
jge short @@outside_playfield
|
|
|
|
mov bh, 0
|
|
|
|
mov bl, _page_back
|
|
|
|
add bx, bx
|
2020-04-30 17:24:28 +00:00
|
|
|
add ax, _scroll_line_on_page[bx]
|
2018-12-29 23:00:10 +00:00
|
|
|
jns short @@scroll_wrap?
|
|
|
|
add ax, RES_Y
|
|
|
|
jmp short @@invalidate
|
|
|
|
; ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
@@scroll_wrap?:
|
|
|
|
cmp ax, RES_Y
|
|
|
|
jl short @@invalidate
|
|
|
|
sub ax, RES_Y
|
|
|
|
|
|
|
|
@@invalidate:
|
|
|
|
mov dx, ax
|
|
|
|
and dx, 7
|
|
|
|
add dx, _tile_invalidate_box.y ; DX = Invalidated height in pixels
|
|
|
|
mov bx, dx
|
|
|
|
add bx, ax
|
|
|
|
shr ax, 3
|
|
|
|
shl ax, 5 ; AX *= TILES_MEMORY_X
|
|
|
|
push si
|
|
|
|
push di
|
|
|
|
push ds
|
|
|
|
pop es
|
|
|
|
assume es:_DATA
|
|
|
|
mov di, ax
|
|
|
|
add di, _invalidate_left_x_tile
|
|
|
|
add di, offset _halftiles_dirty
|
|
|
|
mov si, TILES_MEMORY_X
|
|
|
|
sub si, cx ; SI = row stride
|
|
|
|
mov ah, cl
|
|
|
|
mov al, 1
|
|
|
|
cmp bx, RES_Y
|
|
|
|
jl short @@set_nowrap
|
|
|
|
mov bx, offset _halftiles_dirty_end
|
|
|
|
|
|
|
|
@@set_wrap:
|
|
|
|
mov cl, ah
|
|
|
|
rep stosb
|
|
|
|
sub dx, TILE_FLAG_H
|
|
|
|
add di, si
|
|
|
|
cmp di, bx
|
|
|
|
jl short @@set_wrap
|
|
|
|
sub di, size _halftiles_dirty
|
|
|
|
|
|
|
|
@@set_nowrap:
|
|
|
|
mov cl, ah
|
|
|
|
rep stosb
|
|
|
|
add di, si
|
|
|
|
sub dx, TILE_FLAG_H
|
|
|
|
jg short @@set_nowrap
|
|
|
|
pop di
|
|
|
|
pop si
|
[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
|
|
|
|
tiles_invalidate_around endp
|