From 816ba8342c54a8aa03a9c8d908cc03bf1737a21f Mon Sep 17 00:00:00 2001 From: nmlgc Date: Thu, 6 Aug 2020 20:23:52 +0200 Subject: [PATCH] [Decompilation] [th01] Background + foreground VRAM blit functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Yes, functions! Those would have been nice earlier! Also documented another overly specific Borland C++ code generation quirk with regard to assigning expression results to elements of 16-bit arrays… Part of P0107, funded by Yanga. --- Research/Borland C++ decompilation.md | 27 ++++ th01/main/boss/entity.cpp | 25 ++++ th01_reiiden.asm | 187 ++++---------------------- 3 files changed, 81 insertions(+), 158 deletions(-) diff --git a/Research/Borland C++ decompilation.md b/Research/Borland C++ decompilation.md index e021a09c..0f8630dc 100644 --- a/Research/Borland C++ decompilation.md +++ b/Research/Borland C++ decompilation.md @@ -88,6 +88,33 @@ case it's part of an arithmetic expression that was promoted to `int`. ret = (3.14 > f); // FLD 3.14, FCOMP f + 4 ``` +## Assignments + +* When assigning to a array element at a variable or non-0 index, the array + element address is typically evaluated before the expression to be assigned. + But when assigning + * the result of any arithmetic expression of a *16-bit type* + * to an element of a `far` array of a *16-bit type*, + + the expression will be evaluated first, if its signedness differs from that + of the array: + + ```c + int far *s; + unsigned int far *u; + int s1, s2; + unsigned int u1, u2; + + s[1] = (s1 | s2); // LES BX, [s]; MOV AX, s1; OR AX, s2; MOV ES:[BX+2], AX + s[1] = (s1 | u2); // MOV AX, s1; OR AX, u2; LES BX, [s]; MOV ES:[BX+2], AX + s[1] = (u1 | u2); // MOV AX, u1; OR AX, u2; LES BX, [s]; MOV ES:[BX+2], AX + + u[1] = (s1 | s2); // MOV AX, s1; OR AX, s2; LES BX, [u]; MOV ES:[BX+2], AX + u[1] = (s1 | u2); // LES BX, [u]; MOV AX, s1; OR AX, u2; MOV ES:[BX+2], AX + u[1] = (u1 | u2); // LES BX, [u]; MOV AX, u1; OR AX, u2; MOV ES:[BX+2], AX + ``` + + ## `switch` statements * Sequence of the individual cases is identical in both C and ASM diff --git a/th01/main/boss/entity.cpp b/th01/main/boss/entity.cpp index 30603d88..884cdda5 100644 --- a/th01/main/boss/entity.cpp +++ b/th01/main/boss/entity.cpp @@ -192,4 +192,29 @@ void CBossEntity::put_1line(int left, int y, int image, int row) const bos_p++; } } +void pascal near vram_snap_masked( + dots16_t &dst, dots8_t plane[], uint16_t vram_offset, dots16_t mask +) +{ + dst = (reinterpret_cast(plane[vram_offset]) & mask); +} + +void pascal near vram_put_bg_fg( + sdots16_t fg, dots8_t plane[], uint16_t vram_offset, sdots16_t bg_masked +) +{ + reinterpret_cast(plane[vram_offset]) = (fg | bg_masked); +} + +void pascal near vram_put_unaligned_bg_fg( + sdots16_t fg, + dots8_t plane[], + uint16_t vram_offset, + uint16_t bg_masked, + char first_bit +) +{ + sdots16_t fg_shifted = (fg >> first_bit) + (fg << (16 - first_bit)); + reinterpret_cast(plane[vram_offset]) = (fg_shifted | bg_masked); +} /// -------- diff --git a/th01_reiiden.asm b/th01_reiiden.asm index 4d4cbe96..3e31712c 100644 --- a/th01_reiiden.asm +++ b/th01_reiiden.asm @@ -8877,6 +8877,11 @@ main_21_TEXT segment byte public 'CODE' use16 extern @CBossEntity@bos_metadata_get$xqmimuct1t1:proc extern @CBossEntity@put_8$xqiii:proc extern @CBossEntity@put_1line$xqiiii:proc + VRAM_SNAP_MASKED procdesc pascal near + VRAM_PUT_BG_FG procdesc pascal near \ + fg:word, plane:dword, vram_offset:word, bg_masked:word + VRAM_PUT_UNALIGNED_BG_FG procdesc pascal near \ + fg:word, plane:dword, vram_offset:word, bg_masked:word, first_bit:byte main_21_TEXT ends main_21__TEXT segment byte public 'CODE' use16 @@ -8884,88 +8889,6 @@ main_21__TEXT segment byte public 'CODE' use16 ;org 4 assume es:nothing, ss:nothing, ds:_DATA, fs:nothing, gs:nothing -; =============== S U B R O U T I N E ======================================= - -; Attributes: bp-based frame - -sub_15C80 proc near - -arg_0 = word ptr 4 -arg_2 = word ptr 6 -arg_4 = dword ptr 8 -arg_8 = dword ptr 0Ch - - push bp - mov bp, sp - les bx, [bp+arg_4] - add bx, [bp+arg_2] - mov ax, es:[bx] - and ax, [bp+arg_0] - les bx, [bp+arg_8] - mov es:[bx], ax - pop bp - retn 0Ch -sub_15C80 endp - - -; =============== S U B R O U T I N E ======================================= - -; Attributes: bp-based frame - -sub_15C99 proc near - -arg_0 = word ptr 4 -arg_2 = word ptr 6 -arg_4 = dword ptr 8 -arg_8 = word ptr 0Ch - - push bp - mov bp, sp - mov ax, [bp+arg_8] - or ax, [bp+arg_0] - les bx, [bp+arg_4] - add bx, [bp+arg_2] - mov es:[bx], ax - pop bp - retn 0Ah -sub_15C99 endp - - -; =============== S U B R O U T I N E ======================================= - -; Attributes: bp-based frame - -sub_15CAF proc near - -var_2 = word ptr -2 -arg_0 = byte ptr 4 -arg_2 = word ptr 6 -arg_4 = word ptr 8 -arg_6 = dword ptr 0Ah -arg_A = word ptr 0Eh - - enter 2, 0 - push si - mov si, [bp+arg_A] - mov ax, si - mov cl, [bp+arg_0] - sar ax, cl - mov cl, 10h - sub cl, [bp+arg_0] - mov dx, si - shl dx, cl - add ax, dx - mov [bp+var_2], ax - les bx, [bp+arg_6] - add bx, [bp+arg_4] - or ax, [bp+arg_2] - mov es:[bx], ax - pop si - leave - retn 0Ch -sub_15CAF endp - - ; =============== S U B R O U T I N E ======================================= ; Attributes: bp-based frame @@ -9107,51 +9030,35 @@ loc_15D71: pushd [_VRAM_PLANE_B] push si push [bp+var_20] - call sub_15C80 + call vram_snap_masked push ss lea ax, [bp+var_E] push ax pushd [_VRAM_PLANE_R] push si push [bp+var_20] - call sub_15C80 + call vram_snap_masked push ss lea ax, [bp+var_C] push ax pushd [_VRAM_PLANE_G] push si push [bp+var_20] - call sub_15C80 + call vram_snap_masked push ss lea ax, [bp+var_A] push ax pushd [_VRAM_PLANE_E] push si push [bp+var_20] - call sub_15C80 + call vram_snap_masked push 0 call _graph_accesspage_func add sp, 4 - push [bp+var_1E] - pushd [_VRAM_PLANE_B] - push si - push [bp+var_10] - call sub_15C99 - push [bp+var_1C] - pushd [_VRAM_PLANE_R] - push si - push [bp+var_E] - call sub_15C99 - push [bp+var_1A] - pushd [_VRAM_PLANE_G] - push si - push [bp+var_C] - call sub_15C99 - push [bp+var_18] - pushd [_VRAM_PLANE_E] - push si - push [bp+var_A] - call sub_15C99 + call vram_put_bg_fg pascal, [bp+var_1E], large [_VRAM_PLANE_B], si, [bp+var_10] + call vram_put_bg_fg pascal, [bp+var_1C], large [_VRAM_PLANE_R], si, [bp+var_E] + call vram_put_bg_fg pascal, [bp+var_1A], large [_VRAM_PLANE_G], si, [bp+var_C] + call vram_put_bg_fg pascal, [bp+var_18], large [_VRAM_PLANE_E], si, [bp+var_A] jmp loc_15F2C ; --------------------------------------------------------------------------- @@ -9172,55 +9079,35 @@ loc_15E7A: pushd [_VRAM_PLANE_B] push si push [bp+var_12] - call sub_15C80 + call vram_snap_masked push ss lea ax, [bp+var_E] push ax pushd [_VRAM_PLANE_R] push si push [bp+var_12] - call sub_15C80 + call vram_snap_masked push ss lea ax, [bp+var_C] push ax pushd [_VRAM_PLANE_G] push si push [bp+var_12] - call sub_15C80 + call vram_snap_masked push ss lea ax, [bp+var_A] push ax pushd [_VRAM_PLANE_E] push si push [bp+var_12] - call sub_15C80 + call vram_snap_masked push 0 call _graph_accesspage_func add sp, 4 - push [bp+var_1E] - pushd [_VRAM_PLANE_B] - push si - push [bp+var_10] - push [bp+var_7] - call sub_15CAF - push [bp+var_1C] - pushd [_VRAM_PLANE_R] - push si - push [bp+var_E] - push [bp+var_7] - call sub_15CAF - push [bp+var_1A] - pushd [_VRAM_PLANE_G] - push si - push [bp+var_C] - push [bp+var_7] - call sub_15CAF - push [bp+var_18] - pushd [_VRAM_PLANE_E] - push si - push [bp+var_A] - push [bp+var_7] - call sub_15CAF + call vram_put_unaligned_bg_fg pascal, [bp+var_1E], large [_VRAM_PLANE_B], si, [bp+var_10], [bp+var_7] + call vram_put_unaligned_bg_fg pascal, [bp+var_1C], large [_VRAM_PLANE_R], si, [bp+var_E], [bp+var_7] + call vram_put_unaligned_bg_fg pascal, [bp+var_1A], large [_VRAM_PLANE_G], si, [bp+var_C], [bp+var_7] + call vram_put_unaligned_bg_fg pascal, [bp+var_18], large [_VRAM_PLANE_E], si, [bp+var_A], [bp+var_7] loc_15F2C: add si, 2 @@ -10059,7 +9946,7 @@ loc_16596: add ax, ax add bx, ax push word ptr es:[bx] - call sub_15C80 + call vram_snap_masked push ss lea ax, [bp+var_E] push ax @@ -10071,7 +9958,7 @@ loc_16596: add ax, ax add bx, ax push word ptr es:[bx] - call sub_15C80 + call vram_snap_masked push ss lea ax, [bp+var_C] push ax @@ -10083,7 +9970,7 @@ loc_16596: add ax, ax add bx, ax push word ptr es:[bx] - call sub_15C80 + call vram_snap_masked push ss lea ax, [bp+var_A] push ax @@ -10095,7 +9982,7 @@ loc_16596: add ax, ax add bx, ax push word ptr es:[bx] - call sub_15C80 + call vram_snap_masked push 0 call _graph_accesspage_func add sp, 4 @@ -10104,41 +9991,25 @@ loc_16596: mov ax, di add ax, ax add bx, ax - push word ptr es:[bx+bos_image_t.BOS_B] - pushd [_VRAM_PLANE_B] - push si - push [bp+var_10] - call sub_15C99 + call vram_put_bg_fg pascal, word ptr es:[bx], large [_VRAM_PLANE_B], si, [bp+var_10] les bx, [bp+@@bos] les bx, es:[bx+bos_image_t.BOS_R] mov ax, di add ax, ax add bx, ax - push word ptr es:[bx] - pushd [_VRAM_PLANE_R] - push si - push [bp+var_E] - call sub_15C99 + call vram_put_bg_fg pascal, word ptr es:[bx], large [_VRAM_PLANE_R], si, [bp+var_E] les bx, [bp+@@bos] les bx, es:[bx+bos_image_t.BOS_G] mov ax, di add ax, ax add bx, ax - push word ptr es:[bx] - pushd [_VRAM_PLANE_G] - push si - push [bp+var_C] - call sub_15C99 + call vram_put_bg_fg pascal, word ptr es:[bx], large [_VRAM_PLANE_G], si, [bp+var_C] les bx, [bp+@@bos] les bx, es:[bx+bos_image_t.BOS_E] mov ax, di add ax, ax add bx, ax - push word ptr es:[bx] - pushd [_VRAM_PLANE_E] - push si - push [bp+var_A] - call sub_15C99 + call vram_put_bg_fg pascal, word ptr es:[bx], large [_VRAM_PLANE_E], si, [bp+var_A] add si, 2 loc_166AA: