[Reverse-engineering] [th05] Rendering and hit testing for a single laser

What the hell.

Funded by zorg.
This commit is contained in:
nmlgc 2018-12-15 15:49:50 +01:00
parent 9d79c1413c
commit b3c5e4dcfe
2 changed files with 179 additions and 192 deletions

View File

@ -0,0 +1,174 @@
; Returns the Y coordinate in AX.
; int __usercall near vector2_at_opt(int angle<cx>, int length<bx>, Point origin<ss:bp>, Point near *ret<ss:di>)
vector2_at_opt proc near
push si
mov si, cx
add si, si
movsx eax, bx
movsx edx, _CosTable8[si]
imul eax, edx
sar eax, 8
add ax, [bp+Point.x]
mov ss:[di+Point.x], ax
movsx eax, bx
movsx edx, _SinTable8[si]
imul eax, edx
sar eax, 8
add ax, [bp+Point.y]
mov ss:[di+Point.y], ax
pop si
retn
vector2_at_opt endp
; Builds a line starting at [s], with [t] being [edgelength] 1/16th pixel
; units away from [s]. [s] and [t] are returned in pixel units.
; void __usercall build_line_in_pixels(
; Point *s<ss:di> /* (inout) */,
; Point *t<ss:bx> /* (out) */,
; const Point *edgelength<ss:bp-4> /* (out) */
; )
build_line_in_pixels proc near
mov ax, [bp+size Point+Point.x]
mov dx, ss:[di+Point.x]
add ax, dx
sar ax, 4
sar dx, 4
mov ss:[bx+Point.x], ax
mov ss:[di+Point.x], dx
mov ax, [bp+size Point+Point.y]
mov dx, ss:[di+Point.y]
add ax, dx
sar ax, 4
sar dx, 4
mov ss:[bx+Point.y], ax
mov ss:[di+Point.y], dx
retn
build_line_in_pixels endp
; Returns 1 if the laser is entirely off-screen.
; int pascal laser_render_ray(laser_coords_t near *coords)
public laser_render_ray
laser_render_ray proc near
point0 = Point ptr -20h
point1 = Point ptr -1Ch
point2 = Point ptr -18h
point3 = Point ptr -14h
point4 = Point ptr -10h
point5 = Point ptr -0Ch
point6 = Point ptr -8
point7 = Point ptr -4
@@coords = word ptr 4
enter 20h, 0
push si
push di
mov si, [bp+@@coords]
mov bl, [si+laser_coords_t.LASER_width]
mov bh, 0
shl bx, 3
mov ax, [si.laser_coords_t.origin.x]
add ax, (32 shl 4) ; Translate playfield space to screen space (X)
mov [bp+point7.x], ax
mov ax, [si+laser_coords_t.origin.y]
add ax, (16 shl 4) ; Translate playfield space to screen space (Y)
mov [bp+point7.y], ax
mov cl, [si+laser_coords_t.angle]
add cl, 64
mov ch, 0
lea di, [bp+point6]
sub bp, size Point ; bp = point7
call vector2_at_opt
add cl, 128
sub di, 4 ; di = point5
call vector2_at_opt
sub [bp-(size Point)+Point.y], ax ; bp = line edge length (Y)
mov ax, [bp-(size Point * 2).Point.x]
sub [bp-(size Point)+Point.x], ax ; bp = line edge length (X)
mov cl, [si+laser_coords_t.angle]
mov bx, [si+laser_coords_t.starts_at_distance]
sub di, size Point * 5 ; di = point0
sub bp, size Point * 2 ; bp = point5
call vector2_at_opt
mov bx, [si+laser_coords_t.ends_at_distance]
add di, size Point * 3 ; di = point3
call vector2_at_opt
lea di, [bp-(size Point * 5)] ; di = point0
lea bx, [bp-(size Point * 4)] ; bx = point1
call build_line_in_pixels
add di, size Point * 3 ; di = point3
add bx, size Point ; bx = point2
call build_line_in_pixels
add bp, size Point * 3 ; bp = (what you'd actually expect it to be)
lea di, [bp+point0]
call grc_clip_polygon_n pascal, ss, di, 8, ss, di, 4
or ax, ax
jz short @@offscreen
jge short @@draw
mov ax, 4
@@draw:
call grcg_polygon_cx pascal, ss, di, ax
xor ax, ax
jmp short @@ret
@@offscreen:
mov ax, 1
@@ret:
pop di
pop si
leave
retn 2
laser_render_ray endp
; void pascal laser_hittest(laser_t near *laser);
public laser_hittest
laser_hittest proc near
testrect_center = byte ptr -4
laser = word ptr 4
enter 8, 0
push di
push si
mov di, [bp+laser]
mov bx, [di+laser_t.coords.ends_at_distance]
mov si, [di+laser_t.coords.starts_at_distance]
sub bp, size Point
mov eax, dword ptr [di+laser_t.coords.origin]
mov [bp+0], eax
mov cl, [di+laser_t.coords.angle]
xor ch, ch
lea di, [bp+testrect_center]
@@loop:
call vector2_at_opt
add ax, (6 shl 4)
sub ax, player_pos.cur.y
cmp ax, (12 shl 4)
jnb short @@testrect_move_up
mov ax, ss:[di+Point.x]
add ax, (6 shl 4)
sub ax, player_pos.cur.x
cmp ax, (12 shl 4)
jnb short @@testrect_move_up
mov _player_is_hit, 1
jmp short @@ret
@@testrect_move_up:
sub bx, (16 shl 4)
cmp bx, si
jge short @@loop
@@ret:
add bp, 4
pop si
pop di
leave
ret 2
laser_hittest endp

View File

@ -8232,190 +8232,7 @@ sub_E950 proc near
retn
sub_E950 endp
; =============== S U B R O U T I N E =======================================
vector2_at_opt proc near
push si
mov si, cx
add si, si
movsx eax, bx
movsx edx, _CosTable8[si]
imul eax, edx
sar eax, 8
add ax, [bp+0]
mov ss:[di], ax
movsx eax, bx
movsx edx, _SinTable8[si]
imul eax, edx
sar eax, 8
add ax, [bp+2]
mov ss:[di+2], ax
pop si
retn
vector2_at_opt endp
; =============== S U B R O U T I N E =======================================
sub_E9AA proc near
mov ax, [bp+4]
mov dx, ss:[di]
add ax, dx
sar ax, 4
sar dx, 4
mov ss:[bx], ax
mov ss:[di], dx
mov ax, [bp+6]
mov dx, ss:[di+2]
add ax, dx
sar ax, 4
sar dx, 4
mov ss:[bx+2], ax
mov ss:[di+2], dx
retn
sub_E9AA endp
; =============== S U B R O U T I N E =======================================
; Attributes: bp-based frame
sub_E9D6 proc near
var_20 = byte ptr -20h
var_14 = byte ptr -14h
var_10 = byte ptr -10h
var_8 = word ptr -8
var_4 = word ptr -4
var_2 = word ptr -2
arg_0 = word ptr 4
enter 20h, 0
push si
push di
mov si, [bp+arg_0]
mov bl, [si+9]
mov bh, 0
shl bx, 3
mov ax, [si]
add ax, 200h
mov [bp+var_4], ax
mov ax, [si+2]
add ax, 100h
mov [bp+var_2], ax
mov cl, [si+8]
add cl, 40h
mov ch, 0
lea di, [bp+var_8]
sub bp, 4
call vector2_at_opt
add cl, 80h
sub di, 4
call vector2_at_opt
sub [bp+var_2], ax
mov ax, [bp+var_8]
sub [bp+var_4], ax
mov cl, [si+8]
mov bx, [si+4]
sub di, 14h
sub bp, 8
call vector2_at_opt
mov bx, [si+6]
add di, 0Ch
call vector2_at_opt
lea di, [bp+var_14]
lea bx, [bp+var_10]
call sub_E9AA
add di, 0Ch
add bx, 4
call sub_E9AA
add bp, 0Ch
lea di, [bp+var_20]
push ss
push di
push 8
push ss
push di
push 4
call grc_clip_polygon_n
or ax, ax
jz short loc_EA6D
jge short loc_EA61
mov ax, 4
loc_EA61:
push ss
push di
push ax
call grcg_polygon_cx
xor ax, ax
jmp short loc_EA70
; ---------------------------------------------------------------------------
loc_EA6D:
mov ax, 1
loc_EA70:
pop di
pop si
leave
retn 2
sub_E9D6 endp
; =============== S U B R O U T I N E =======================================
; Attributes: bp-based frame
sub_EA76 proc near
var_4 = byte ptr -4
arg_0 = word ptr 4
enter 8, 0
push di
push si
mov di, [bp+arg_0]
mov bx, [di+8]
mov si, [di+6]
sub bp, 4
mov eax, [di+2]
mov [bp+0], eax
mov cl, [di+0Ah]
xor ch, ch
lea di, [bp+var_4]
loc_EA98:
call vector2_at_opt
add ax, 60h
sub ax, player_pos.cur.y
cmp ax, 0C0h
jnb short loc_EABD
mov ax, ss:[di]
add ax, 60h
sub ax, player_pos.cur.x
cmp ax, 0C0h
jnb short loc_EABD
mov _player_is_hit, 1
jmp short loc_EAC5
; ---------------------------------------------------------------------------
loc_EABD:
sub bx, 100h
cmp bx, si
jge short loc_EA98
loc_EAC5:
add bp, 4
pop si
pop di
leave
retn 2
sub_EA76 endp
include th05/laser_render_hittest.asm
; =============== S U B R O U T I N E =======================================
@ -10471,8 +10288,7 @@ loc_FC52:
add [si+6], ax
loc_FC60:
push si
call sub_EA76
call laser_hittest pascal, si
jmp loc_FD13
; ---------------------------------------------------------------------------
@ -10502,8 +10318,7 @@ loc_FC93:
; ---------------------------------------------------------------------------
loc_FC9D:
push si
call sub_EA76
call laser_hittest pascal, si
cmp word ptr [si+12h], 0
jle short loc_FD13
mov ax, [si+0Eh]
@ -10666,8 +10481,7 @@ loc_FDC2:
mov [bp+var_8], ax
sub word ptr [si+8], 20h ; ' '
lea ax, [si+2]
push ax
call sub_E9D6
call laser_render_ray pascal, ax
mov ax, [bp+var_8]
mov [si+8], ax
@ -10743,8 +10557,7 @@ loc_FE11:
loc_FE8A:
lea ax, [si+2]
push ax
call sub_E9D6
call laser_render_ray pascal, ax
or ax, ax
jz loc_FF61
mov byte ptr [si], 0