From b3c5e4dcfede0132150fc46f93018943919d79a8 Mon Sep 17 00:00:00 2001 From: nmlgc Date: Sat, 15 Dec 2018 15:49:50 +0100 Subject: [PATCH] [Reverse-engineering] [th05] Rendering and hit testing for a single laser What the hell. Funded by zorg. --- th05/laser_render_hittest.asm | 174 ++++++++++++++++++++++++++++++ th05_main.asm | 197 +--------------------------------- 2 files changed, 179 insertions(+), 192 deletions(-) create mode 100644 th05/laser_render_hittest.asm diff --git a/th05/laser_render_hittest.asm b/th05/laser_render_hittest.asm new file mode 100644 index 00000000..82c946c1 --- /dev/null +++ b/th05/laser_render_hittest.asm @@ -0,0 +1,174 @@ +; Returns the Y coordinate in AX. + +; int __usercall near vector2_at_opt(int angle, int length, Point origin, Point near *ret) +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 /* (inout) */, +; Point *t /* (out) */, +; const Point *edgelength /* (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 diff --git a/th05_main.asm b/th05_main.asm index d34771f6..ed138822 100644 --- a/th05_main.asm +++ b/th05_main.asm @@ -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