diff --git a/Makefile.mak b/Makefile.mak index 9ee2f3e2..880a181a 100644 --- a/Makefile.mak +++ b/Makefile.mak @@ -59,7 +59,7 @@ bin\th01\op.exe: bin\piloadc.obj bin\th01\op.obj th01\op_01.cpp th01\op_02.c th0 $** | -bin\th01\reiiden.exe: bin\piloadc.obj bin\th01\reiiden.obj th01\main_01.cpp th01\main_01_.cpp th01\main_02.c th01\main_03.c th01\main_04.c th01\main_05.c th01\main_06.cpp th01\main_07.cpp th01\main_08.cpp th01\main_09.cpp th01\main_12.c th01\main_13.cpp th01\main_13_.cpp th01\main_14.cpp th01\main_16.c th01\main_19.cpp th01\main_25.cpp th01\main_27.cpp th01\main_30.cpp th01\main_38.cpp +bin\th01\reiiden.exe: bin\piloadc.obj bin\th01\reiiden.obj th01\main_01.cpp th01\main_01_.cpp th01\main_02.c th01\main_03.c th01\main_04.c th01\main_05.c th01\main_06.cpp th01\main_07.cpp th01\main_08.cpp th01\main_09.cpp th01\main_12.c th01\main_13.cpp th01\main_13_.cpp th01\main_14.cpp th01\main_16.c th01\main_19.cpp th01\main_23.cpp th01\main_25.cpp th01\main_27.cpp th01\main_30.cpp th01\main_38.cpp $(CC) $(CFLAGS) -ml -3 -DGAME=1 -DBINARY='M' -nbin\th01\ -eREIIDEN.EXE @&&| $** | diff --git a/Research/Borland C++ decompilation.md b/Research/Borland C++ decompilation.md index 466c1b29..e021a09c 100644 --- a/Research/Borland C++ decompilation.md +++ b/Research/Borland C++ decompilation.md @@ -110,6 +110,29 @@ as part of the same translation unit. Found nothing so far, though. Borland C++ just pushes the entire word. Will cause IDA to mis-identify certain local variables as `word`s when they aren't. +### Pushing pointers + +When passing a `near` pointer to a function that takes a `far` one, the +segment argument is sometimes `PUSH`ed immediately, before evaluating the +offset: + +```c++ +#pragma option -ml + +struct s100 { + char c[100]; +}; + +extern s100 structs[5]; + +void __cdecl process(s100 *element); + +void foo(int i) { + process((s100 near *)(&structs[i])); // PUSH DS; (AX = offset); PUSH AX; + process((s100 far *)(&structs[i])); // (AX = offset); PUSH DS; PUSH AX; +} +``` + ## Flags ### `-Z` (Suppress register reloads) diff --git a/th01/formats/grc.cpp b/th01/formats/grc.cpp new file mode 100644 index 00000000..62a79bee --- /dev/null +++ b/th01/formats/grc.cpp @@ -0,0 +1,43 @@ +#include +#include "platform.h" +#include "pc98.h" +#include "planar.h" +#include "th01/formats/pf.hpp" +#include "th01/formats/grc.hpp" + +int grc_load(int slot, const char fn[PF_FN_LEN]) +{ + union { + spriteformat_header_inner_t inner; + Palette4 pal; + int8_t space[50]; + } header; + + arc_file_load(fn); + arc_file_seek(offsetof(grc_header_t, vram_w)); + arc_file_get_near(grc_images[slot].vram_w); + arc_file_get_near(grc_images[slot].h); + + arc_file_get_far(header.inner); + grc_images[slot].image_count = header.inner.image_count; + // MODDERS: + /* if( + header.inner.image_count < 0 || + header.inner.image_count > GRC_IMAGES_PER_SLOT + ) { + return 1; + } */ + + size_t image_size = (grc_images[slot].vram_w * grc_images[slot].h); + arc_file_get_far(header.pal); // yeah, should have been a seek + + for(int image = 0; grc_images[slot].image_count > image; image++) { + if(grc_images[slot].dots[image]) { + delete[] grc_images[slot].dots[image]; + } + grc_images[slot].dots[image] = new dots8_t[image_size]; + arc_file_get(grc_images[slot].dots[image], image_size); + } + arc_file_free(); + return 0; +} diff --git a/th01/formats/grc.hpp b/th01/formats/grc.hpp index 33a13984..f766c819 100644 --- a/th01/formats/grc.hpp +++ b/th01/formats/grc.hpp @@ -1,5 +1,17 @@ /// Uncompressed monochrome 8w×h sprite format /// ------------------------------------------ +#include "th01/formats/sprfmt_h.hpp" + +#define GRC_MAGIC "GRCG" + +// On-disk per-file header. Not the same as for .BOS! +struct grc_header_t { + char magic[sizeof(GRC_MAGIC) - 1]; + int16_t vram_w; + int16_t h; + spriteformat_header_inner_t inner; +}; + static const int GRC_SLOT_COUNT = 8; static const int GRC_IMAGES_PER_SLOT = 8; @@ -12,4 +24,8 @@ struct grc_t { }; extern grc_t grc_images[GRC_SLOT_COUNT]; + +// Loads all images from the .GRC file with the given [fn] inside the +// currently active packfile into the given .GRC [slot]. Always returns 0. +int grc_load(int slot, const char fn[PF_FN_LEN]); /// ------------------------------------------ diff --git a/th01/formats/pf.hpp b/th01/formats/pf.hpp index 91745f00..4b31149c 100644 --- a/th01/formats/pf.hpp +++ b/th01/formats/pf.hpp @@ -20,6 +20,9 @@ void pascal arc_file_load(const char fn[PF_FN_LEN]); // into [buf], advancing the cursor in the process. void pascal arc_file_get(char *buf, size_t size); +#define arc_file_get_near(var) \ + arc_file_get(reinterpret_cast(&var), sizeof(var)) + #define arc_file_get_far(var) \ arc_file_get(reinterpret_cast(&var), sizeof(var)) diff --git a/th01/formats/sprfmt_h.hpp b/th01/formats/sprfmt_h.hpp new file mode 100644 index 00000000..9a817649 --- /dev/null +++ b/th01/formats/sprfmt_h.hpp @@ -0,0 +1,13 @@ +// Header structures for multi-sprite formats. Used for .BOS and .GRC. +#pragma pack(push, 1) +struct spriteformat_header_inner_t { + uint8_t image_count; + int8_t unknown[7]; +}; + +// For reference, never actually used by the game itself (unfortunately). +template struct spriteformat_header_t { + Outer outer; + Palette4 pal; +}; +#pragma pack(pop) diff --git a/th01/main_23.cpp b/th01/main_23.cpp new file mode 100644 index 00000000..c470d00c --- /dev/null +++ b/th01/main_23.cpp @@ -0,0 +1,10 @@ +/* ReC98 + * ----- + * Code segment #23 of TH01's REIIDEN.EXE + */ + +#pragma option -3 -Z + +extern "C" { +#include "th01/formats/grc.cpp" +} diff --git a/th01_reiiden.asm b/th01_reiiden.asm index bfcdc588..e90af712 100644 --- a/th01_reiiden.asm +++ b/th01_reiiden.asm @@ -73,6 +73,7 @@ BOMBS_MAX = 5 main_01 group main_01_TEXT, main_01__TEXT, main_01___TEXT main_13 group main_13_TEXT, main_13__TEXT main_19 group main_19_TEXT, main_19__TEXT +main_23 group main_23_TEXT, main_23__TEXT main_25 group main_25_TEXT, main_25__TEXT main_27 group main_27_TEXT, main_27__TEXT main_30 group main_30_TEXT, main_30__TEXT @@ -912,14 +913,8 @@ sub_BCFE endp sub_BEB1 proc far push bp mov bp, sp - push ds - push offset aKuzi1_grc ; "kuzi1.grc" - push 6 - call sub_1744B - push ds - push offset aKuzi2_grc ; "kuzi2.grc" - push 7 - call sub_1744B + call _grc_load stdcall, 6, offset aKuzi1_grc, ds + call _grc_load stdcall, 7, offset aKuzi2_grc, ds add sp, 0Ch pop bp retf @@ -12018,120 +12013,14 @@ main_22_TEXT ends ; Segment type: Pure code main_23_TEXT segment byte public 'CODE' use16 - assume cs:main_23_TEXT + extern _grc_load:proc +main_23_TEXT ends + +main_23__TEXT segment byte public 'CODE' use16 + assume cs:main_23 ;org 0Bh 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_1744B proc far - -var_36 = byte ptr -36h -var_4 = word ptr -4 -var_2 = word ptr -2 -arg_0 = word ptr 6 -@@fn = dword ptr 8 - - enter 36h, 0 - push si - push di - mov di, [bp+arg_0] - call arc_file_load pascal, large [bp+@@fn] - call arc_file_seek pascal, 4 - push ds - mov ax, di - imul ax, size grc_t - add ax, offset _grc_images.GRC_vram_w - push ax - push 2 - call arc_file_get - push ds - mov ax, di - imul ax, size grc_t - add ax, offset _grc_images.GRC_h - push ax - push 2 - call arc_file_get - push ss - lea ax, [bp+var_36] - push ax - push 8 - call arc_file_get - mov al, [bp+var_36] - mov ah, 0 - mov bx, di - imul bx, size grc_t - mov _grc_images[bx].GRC_image_count, ax - mov bx, di - imul bx, size grc_t - mov ax, _grc_images[bx].GRC_vram_w - mov bx, di - imul bx, size grc_t - imul _grc_images[bx].GRC_h - mov [bp+var_2], ax - push ss - lea ax, [bp+var_36] - push ax - push size palette_t - call arc_file_get - mov [bp+var_4], 0 - jmp short loc_17534 -; --------------------------------------------------------------------------- - -loc_174C8: - mov bx, di - imul bx, size grc_t - mov ax, [bp+var_4] - shl ax, 2 - add bx, ax - mov ax, word ptr _grc_images.GRC_dots[bx]+0 - or ax, word ptr _grc_images.GRC_dots[bx]+2 - jz short loc_174F9 - mov bx, di - imul bx, size grc_t - mov ax, [bp+var_4] - shl ax, 2 - add bx, ax - pushd _grc_images.GRC_dots[bx] ; font - call @$bdla$qnv - add sp, 4 - -loc_174F9: - push [bp+var_2] - call @$bnwa$qui - pop cx - mov bx, di - imul bx, size grc_t - mov si, [bp+var_4] - shl si, 2 - add bx, si - mov word ptr _grc_images.GRC_dots[bx]+2, dx - mov word ptr _grc_images.GRC_dots[bx]+0, ax - mov bx, di - imul bx, size grc_t - mov ax, [bp+var_4] - shl ax, 2 - add bx, ax - call arc_file_get pascal, large _grc_images.GRC_dots[bx], [bp+var_2] - inc [bp+var_4] - -loc_17534: - mov bx, di - imul bx, size grc_t - mov ax, _grc_images[bx].GRC_image_count - cmp ax, [bp+var_4] - jg short loc_174C8 - call arc_file_free - xor ax, ax - pop di - pop si - leave - retf -sub_1744B endp - - ; =============== S U B R O U T I N E ======================================= ; Attributes: bp-based frame @@ -13154,7 +13043,7 @@ loc_17CA3: retf sub_17C2F endp -main_23_TEXT ends +main_23__TEXT ends ; =========================================================================== @@ -34744,10 +34633,7 @@ sub_24F41 proc far push offset point_3988E call sub_1568F mov word_398B8, 0 - push ds - push offset aBoss5_gr_grc ; "boss5_gr.grc" - push 0 - call sub_1744B + call _grc_load stdcall, 0, offset aBoss5_gr_grc, ds call _ptn_new stdcall, (12 shl 16) or 2 call _ptn_load stdcall, 3, offset aBoss3_m_ptn_1, ds ; "boss3_m.ptn" mov byte_3A1B2, 0C0h ; '?' @@ -40657,23 +40543,11 @@ sub_28754 proc far push ds push offset word_39A1E call sub_16B56 - push ds - push offset aBoss6gr1_grc ; "boss6gr1.grc" - push 0 - call sub_1744B - push ds - push offset aBoss6gr2_grc ; "boss6gr2.grc" - push 1 - call sub_1744B - push ds - push offset aBoss6gr3_grc ; "boss6gr3.grc" - push 2 - call sub_1744B + call _grc_load stdcall, 0, offset aBoss6gr1_grc, ds + call _grc_load stdcall, 1, offset aBoss6gr2_grc, ds + call _grc_load stdcall, 2, offset aBoss6gr3_grc, ds add sp, 30h - push ds - push offset aBoss6gr4_grc ; "boss6gr4.grc" - push 3 - call sub_1744B + call _grc_load stdcall, 3, offset aBoss6gr4_grc, ds call sub_232A4 nopcall sub_287D9 call _ptn_new stdcall, (16 shl 16) or 2