From 252c13d3831b898ae4a4120ac30999418985039c Mon Sep 17 00:00:00 2001 From: nmlgc Date: Sun, 28 Feb 2021 19:10:51 +0100 Subject: [PATCH] [Decompilation] [th05] Music Room piano (decompilable functions) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If anything, these decompilations of barely decompilable functions can at least indicate that I tried. 🤷 Nice __fastcall abuse though, which allows us to least formalize *some* of the implicit state passed between those functions. Completes P0135, funded by [Anonymous]. --- Makefile.mak | 2 +- th05/music/piano.h | 59 +------------ th05/music/piano.inc | 21 ----- th05/music/piano_a.asm | 12 +++ th05/music/piano_c.asm | 112 ------------------------- th05/music/piano_c.cpp | 182 ++++++++++++++++++++++++++++++++++++++++- th05/musicp_c.cpp | 1 + th05_op.asm | 5 +- 8 files changed, 202 insertions(+), 192 deletions(-) delete mode 100644 th05/music/piano_c.asm create mode 100644 th05/musicp_c.cpp diff --git a/Makefile.mak b/Makefile.mak index 92ccfc6e..e195e139 100644 --- a/Makefile.mak +++ b/Makefile.mak @@ -152,7 +152,7 @@ bin\th05\res_kso.com: th05\res_kso.cpp $** | masters.lib -bin\th05\op.exe: th05\op010.cpp bin\th05\op.obj th05\op011.cpp th05\m_char.cpp bin\th05\musicp_a.obj bin\th05\bgimager.obj bin\th05\snd_load.obj bin\th05\snd_kaja.obj bin\th05\pi_cpp_1.obj bin\th05\pi_asm_1.obj bin\th05\pi_cpp_2.obj bin\th05\pi_asm_2.obj bin\th05\initop.obj bin\th05\input_s.obj bin\th05\inp_h_w.obj bin\th05\snd_dlym.obj th05\cdg_p_nc.cpp bin\th05\frmdelay.obj bin\th04\cdg_load.obj bin\th05\egcrect.obj bin\hfliplut.obj +bin\th05\op.exe: th05\op010.cpp bin\th05\op.obj th05\op011.cpp th05\m_char.cpp bin\th05\musicp_c.obj bin\th05\musicp_a.obj bin\th05\bgimager.obj bin\th05\snd_load.obj bin\th05\snd_kaja.obj bin\th05\pi_cpp_1.obj bin\th05\pi_asm_1.obj bin\th05\pi_cpp_2.obj bin\th05\pi_asm_2.obj bin\th05\initop.obj bin\th05\input_s.obj bin\th05\inp_h_w.obj bin\th05\snd_dlym.obj th05\cdg_p_nc.cpp bin\th05\frmdelay.obj bin\th04\cdg_load.obj bin\th05\egcrect.obj bin\hfliplut.obj $(CC) $(CFLAGS) $(LARGE_LFLAGS) -DGAME=5 -DBINARY='O' -3 -Z -nbin\th05\ -eOP.EXE @&&| $** | diff --git a/th05/music/piano.h b/th05/music/piano.h index e1bf2586..4e341e18 100644 --- a/th05/music/piano.h +++ b/th05/music/piano.h @@ -1,57 +1,6 @@ -/// Graphics -/// -------- -#define PIANO_LEFT 384 -#define PIANO_TOP 64 -#define PIANO_H 15 -#define PIANO_KEY_W 4 -#define PIANO_BLACK_H 9 -#define PIANO_BLACK_PRESSED_H 8 -#define PIANO_PADDING_BOTTOM 3 -#define PIANO_H_PADDED (PIANO_H + PIANO_PADDING_BOTTOM) +// Initializes note rendering and draws blank pianos for all monitored PMD +// channels. +void piano_setup_and_put_initial(void); -#define PIANO_OCTAVES 8 -#define PIANO_OCTAVE_W (7 * PIANO_KEY_W) - -#define PIANO_VRAM_LEFT (PIANO_LEFT / BYTE_DOTS) -#define PIANO_VRAM_W ((PIANO_OCTAVES * PIANO_OCTAVE_W) / BYTE_DOTS) - -// Sprite data -extern const dots8_t PIANO_KEYS_BLACK[PIANO_VRAM_W]; -/// -------- - -#define PIANO_LABEL_DIST_X 32 -#define PIANO_LABEL_DIST_Y 4 - -#define PIANO_LABEL_LEFT(col) \ - (PIANO_LEFT - PIANO_LABEL_DIST_X + (col * PIANO_LABEL_FONT_W)) -#define PIANO_LABEL_TOP(row) \ - (PIANO_TOP + PIANO_LABEL_DIST_Y + (row * PIANO_H_PADDED)) - -// Assumes that the GRCG is active. -#define piano_label_puts(row, chr1, chr2, chr3) \ - piano_label_putc(0, row, chr1); \ - piano_label_putc(1, row, chr2); \ - piano_label_putc(2, row, chr3); \ - -#define piano_label_putc(col, row, chr) \ - _AL = chr; \ - _DI = vram_offset_muldiv(PIANO_LABEL_LEFT(col), PIANO_LABEL_TOP(row)); \ - piano_label_put_raw(); - -void pascal piano_label_put_raw(); - -// Note data -// --------- -extern OPEN_WORK *pmd_workadr; - -typedef struct { - char fm[5]; - char unused[3]; // SSG? -} piano_notes_t; - -extern piano_notes_t piano_notes_cur; -extern piano_notes_t piano_notes_prev; -// --------- - -void piano_setup(void); +// Renders the currently played PMD notes. void piano_render(void); diff --git a/th05/music/piano.inc b/th05/music/piano.inc index b4a91737..94e4f45d 100644 --- a/th05/music/piano.inc +++ b/th05/music/piano.inc @@ -1,25 +1,4 @@ -PIANO_LEFT = 384 -PIANO_TOP = 64 -PIANO_H = 15 -PIANO_KEY_W = 4 -PIANO_BLACK_H = 9 -PIANO_BLACK_PRESSED_H = 8 -PIANO_PADDING_BOTTOM = 3 -PIANO_H_PADDED = (PIANO_H + PIANO_PADDING_BOTTOM) - -PIANO_OCTAVES = 8 -PIANO_OCTAVE_W = (7 * PIANO_KEY_W) - -PIANO_VRAM_LEFT = (PIANO_LEFT / 8) -PIANO_VRAM_W = ((PIANO_OCTAVES * PIANO_OCTAVE_W) / 8) - piano_notes_t struc fm db 5 dup(?) db 3 dup(?) piano_notes_t ends - -PIANO_LABEL_DIST_X = 32 -PIANO_LABEL_DIST_Y = 4 - -PIANO_LABEL_LEFT = PIANO_LEFT - PIANO_LABEL_DIST_X -PIANO_LABEL_TOP = PIANO_TOP + PIANO_LABEL_DIST_Y diff --git a/th05/music/piano_a.asm b/th05/music/piano_a.asm index 1ddc9d5d..467837e6 100644 --- a/th05/music/piano_a.asm +++ b/th05/music/piano_a.asm @@ -7,6 +7,18 @@ include libs/kaja/kaja.inc include th04/hardware/grcg.inc include th05/music/piano.inc +PIANO_LEFT = 384 +PIANO_H = 15 +PIANO_KEY_W = 4 +PIANO_BLACK_H = 9 +PIANO_BLACK_PRESSED_H = 8 + +PIANO_OCTAVES = 8 +PIANO_OCTAVE_W = (7 * PIANO_KEY_W) + +PIANO_VRAM_LEFT = (PIANO_LEFT / 8) +PIANO_VRAM_W = ((PIANO_OCTAVES * PIANO_OCTAVE_W) / 8) + extern _sPIANO_LABEL_FONT:byte extern _PIANO_KEYS_BLACK:byte:PIANO_VRAM_W extern _piano_notes_cur:piano_notes_t diff --git a/th05/music/piano_c.asm b/th05/music/piano_c.asm deleted file mode 100644 index 6d3e97c6..00000000 --- a/th05/music/piano_c.asm +++ /dev/null @@ -1,112 +0,0 @@ - @piano_fm_part_put_raw procdesc near - @piano_current_note_from procdesc near - _piano_part_keys_put_raw procdesc near - @piano_pressed_key_put procdesc near - @piano_label_put_raw procdesc near - _grcg_setcolor_direct_seg1_raw procdesc near - - PIANO_LABEL_FONT_W = 8 - PIANO_LABEL_FONT_H = 8 - -piano_label_puts macro row:req, chr1:req, chr2:req, chr3:req - piano_label_putc 0, row, chr1 - piano_label_putc 1, row, chr2 - piano_label_putc 2, row, chr3 -endm - -piano_label_putc macro col:req, row:req, chr:req - mov al, chr - mov di, ((PIANO_LABEL_TOP + (row * PIANO_H_PADDED)) * ROW_SIZE) + ((PIANO_LABEL_LEFT + (col * PIANO_LABEL_FONT_W)) / 8) - call @piano_label_put_raw -endm - - -public _piano_setup -_piano_setup proc far - push si - push di - GRCG_SETMODE_VIA_MOV al, GC_RMW - mov ax, GRAM_400 - mov es, ax - assume es:nothing - mov di, (PIANO_TOP + (0 * PIANO_H_PADDED)) * ROW_SIZE - call _piano_part_keys_put_raw - mov di, (PIANO_TOP + (1 * PIANO_H_PADDED)) * ROW_SIZE - call _piano_part_keys_put_raw - mov di, (PIANO_TOP + (2 * PIANO_H_PADDED)) * ROW_SIZE - call _piano_part_keys_put_raw - mov di, (PIANO_TOP + (3 * PIANO_H_PADDED)) * ROW_SIZE - call _piano_part_keys_put_raw - mov di, (PIANO_TOP + (4 * PIANO_H_PADDED)) * ROW_SIZE - call _piano_part_keys_put_raw - mov di, (PIANO_TOP + (5 * PIANO_H_PADDED)) * ROW_SIZE - call _piano_part_keys_put_raw - mov ah, GC_RI - call _grcg_setcolor_direct_seg1_raw - piano_label_puts 0, pl_F, pl_M, pl_1 - piano_label_puts 1, pl_F, pl_M, pl_2 - piano_label_puts 2, pl_F, pl_M, pl_3 - piano_label_puts 3, pl_F, pl_M, pl_4 - piano_label_puts 4, pl_F, pl_M, pl_5 - piano_label_puts 5, pl_S, pl_S, pl_G - GRCG_OFF_VIA_XOR al - push ds - mov ah, PMD_GET_WORKAREA_ADDRESS - int PMD - mov ax, ds - pop ds - mov word ptr _pmd_workadr, dx - mov word ptr _pmd_workadr+2, ax - pop di - pop si - retf -_piano_setup endp - - -public _piano_render -_piano_render proc far - push si - push di - push ds - push ds - pop fs - GRCG_SETMODE_VIA_MOV al, GC_RMW - mov ax, GRAM_400 - mov es, ax - mov di, (PIANO_TOP + (5 * PIANO_H_PADDED)) * ROW_SIZE - call _piano_part_keys_put_raw - lds bx, _pmd_workadr ; FMPart[0] - mov di, (PIANO_TOP + (0 * PIANO_H_PADDED)) * ROW_SIZE - mov si, offset piano_notes_t.fm[0] - call @piano_fm_part_put_raw - add bx, 2 ; FMPart[1] - mov di, (PIANO_TOP + (1 * PIANO_H_PADDED)) * ROW_SIZE - mov si, offset piano_notes_t.fm[1] - call @piano_fm_part_put_raw - add bx, 2 ; FMPart[2] - mov di, (PIANO_TOP + (2 * PIANO_H_PADDED)) * ROW_SIZE - mov si, offset piano_notes_t.fm[2] - call @piano_fm_part_put_raw - add bx, 2 ; FMPart[3] - mov di, (PIANO_TOP + (3 * PIANO_H_PADDED)) * ROW_SIZE - mov si, offset piano_notes_t.fm[3] - call @piano_fm_part_put_raw - add bx, 2 ; FMPart[4] - mov di, (PIANO_TOP + (4 * PIANO_H_PADDED)) * ROW_SIZE - mov si, offset piano_notes_t.fm[4] - call @piano_fm_part_put_raw - mov ah, GC_RI - call _grcg_setcolor_direct_seg1_raw - mov di, (PIANO_TOP + (5 * PIANO_H_PADDED)) * ROW_SIZE - add bx, 4 ; SSGPart[0] - call @piano_current_note_from - call @piano_pressed_key_put - add bx, 2 ; SSGPart[1] - call @piano_current_note_from - call @piano_pressed_key_put - GRCG_OFF_VIA_XOR al - pop ds - pop di - pop si - retf -_piano_render endp diff --git a/th05/music/piano_c.cpp b/th05/music/piano_c.cpp index 7423c3cd..7bec50a9 100644 --- a/th05/music/piano_c.cpp +++ b/th05/music/piano_c.cpp @@ -1,3 +1,94 @@ +#pragma codeseg SHARED_ +#pragma option -k- + +extern "C" { +#include "platform.h" +#include "x86real.h" +#include "pc98.h" +#include "planar.h" +#include "decomp.h" +#include "master.hpp" +#include "libs/kaja/kaja.h" +#include "th05/music/piano.h" +#include "th05/sprites/piano_l.h" + +/// Coordinates +/// ----------- + +static const screen_x_t PIANO_LEFT = 384; +static const vram_y_t PIANO_TOP = 64; +static const pixel_t PIANO_H = 15; +static const pixel_t PIANO_KEY_W = 4; +static const pixel_t PIANO_BLACK_H = 9; +static const pixel_t PIANO_BLACK_PRESSED_H = 8; +static const pixel_t PIANO_PADDING_BOTTOM = 3; +static const pixel_t PIANO_H_PADDED = (PIANO_H + PIANO_PADDING_BOTTOM); + +static const int PIANO_OCTAVES = 8; +static const pixel_t PIANO_OCTAVE_W = (7 * PIANO_KEY_W); + +static const vram_x_t PIANO_VRAM_LEFT = (PIANO_LEFT / BYTE_DOTS); +static const vram_byte_amount_t PIANO_VRAM_W = ( + (PIANO_OCTAVES * PIANO_OCTAVE_W) / BYTE_DOTS +); + +static const pixel_t PIANO_LABEL_DIST_X = 32; +static const pixel_t PIANO_LABEL_DIST_Y = 4; + +static inline screen_x_t label_left(int col) { + return (PIANO_LEFT - PIANO_LABEL_DIST_X + (col * PIANO_LABEL_FONT_W)); +} + +static inline screen_x_t label_top(int row) { + return (PIANO_TOP + PIANO_LABEL_DIST_Y + (row * PIANO_H_PADDED)); +} + +static inline vram_y_t part_top(int part_id) { + return (PIANO_TOP + (part_id * PIANO_H_PADDED)); +} +/// ----------- + +// Sprite data +extern const dots8_t PIANO_KEYS_BLACK[PIANO_VRAM_W]; + +/// Note data +/// --------- + +// Actually a single `OPEN_WORK far *`. +extern uint16_t pmd_workadr[2]; + +typedef struct { + char fm[5]; + char unused[3]; // SSG? +} piano_notes_t; + +extern piano_notes_t piano_notes_cur; +extern piano_notes_t piano_notes_prev; +/// --------- + +/// Redundant garbage +/// ----------------- + +#undef grcg_setmode +#undef grcg_off + +#define grcg_setmode(mode) __asm { \ + mov al, mode; \ + out 0x7C, al; \ +} + +#define grcg_off() __asm { \ + db 0x32, 0xC0; /* XOR AL, AL (alternate encoding) */ \ + out 0x7C, al; \ +} + +void near grcg_setcolor_direct_seg1_raw(); +#define grcg_setcolor(col) { \ + _AH = col; \ + grcg_setcolor_direct_seg1_raw(); \ +} +/// ----------------- + /// Helper functions /// ---------------- @@ -11,18 +102,26 @@ void __fastcall near piano_fm_part_put_raw( int16_t ax_unused, int16_t dx_unused, QQ near *near *qq ); +#define piano_fm_part_put(part_id, qq) \ + _DI = vram_offset_shift(0, part_top(part_id)); \ + __asm { mov si, part_id; } \ + piano_fm_part_put_raw(_AX, _DX, qq); // Returns the currently played note from [qq] as a KAJA onkai value, or // ONKAI_REST if none is played. char __fastcall near piano_current_note_from( int16_t ax_unused, int16_t dx_unused, QQ near *near *qq - ); +); // Additionally takes: // • `void far *vram_at_x0_and_top_of_part` // Draws a blank piano, for the part is indicated through the VRAM offset in // ES:DI. void near piano_part_keys_put_raw(); +inline void piano_part_keys_put(int part_id) { + _DI = vram_offset_shift(0, part_top(part_id)); + piano_part_keys_put_raw(); +} // Additionally takes: // • `void far *vram_at_x0_and_top_of_part` @@ -35,4 +134,85 @@ void __fastcall near piano_pressed_key_put(char onkai); // Blits a piano label character to the top-left VRAM position indicated in // ES:DI. Assumes that the GRCG is active. void __fastcall near piano_label_put_raw(piano_label_t label_char); +inline void piano_label_putc(int col, int row, piano_label_t chr) { + _AL = chr; + _DI = vram_offset_muldiv(label_left(col), label_top(row)); + piano_label_put_raw(static_cast(_AL)); +} +#define piano_label_puts(row, chr1, chr2, chr3) \ + piano_label_putc(0, row, pl_##chr1); \ + piano_label_putc(1, row, pl_##chr2); \ + piano_label_putc(2, row, pl_##chr3); /// ---------------- + +void piano_setup_and_put_initial(void) +{ + grcg_setmode(GC_RMW); + _ES = SEG_PLANE_B; + // Thanks, Turbo C++, for indicating that SI actually didn't need to be + // saved in this function! + _SI = _SI; + + piano_part_keys_put(0); + piano_part_keys_put(1); + piano_part_keys_put(2); + piano_part_keys_put(3); + piano_part_keys_put(4); + piano_part_keys_put(5); + + grcg_setcolor(GC_RI); + piano_label_puts(0, F, M, 1); + piano_label_puts(1, F, M, 2); + piano_label_puts(2, F, M, 3); + piano_label_puts(3, F, M, 4); + piano_label_puts(4, F, M, 5); + piano_label_puts(5, S, S, G); + grcg_off(); + + __asm { push ds; } + _AH = PMD_GET_WORKAREA_ADDRESS; + geninterrupt(PMD); + _AX = _DS; + __asm { pop ds; } + + // pmd_workadr = reinterpret_cast(MK_FP(_DX, _AX)); + pmd_workadr[0] = _DX; + pmd_workadr[1] = _AX; +} + +void piano_render(void) +{ + __asm { push ds; } + __asm { push ds; } + __emit__(0x0F, 0xA1); // POP FS + + grcg_setmode(GC_RMW); + _ES = SEG_PLANE_B; + + piano_part_keys_put(5); + + __asm { lds bx, dword ptr pmd_workadr; } // BX = FMPart[0] + + #define _BX reinterpret_cast(_BX) + + piano_fm_part_put(0, _BX); _BX++; // BX = FMPart[1] + piano_fm_part_put(1, _BX); _BX++; // BX = FMPart[2] + piano_fm_part_put(2, _BX); _BX++; // BX = FMPart[3] + piano_fm_part_put(3, _BX); _BX++; // BX = FMPart[4] + piano_fm_part_put(4, _BX); + + grcg_setcolor(GC_RI); + _DI = vram_offset_shift(0, part_top(5)); + _BX += 2; // BX = SSGPart[0] + piano_pressed_key_put(piano_current_note_from(_AX, _DX, _BX)); + _BX++; // BX = SSGPart[1] + piano_pressed_key_put(piano_current_note_from(_AX, _DX, _BX)); + + #undef _BX + + grcg_off(); + + __asm { pop ds; } +} + +} diff --git a/th05/musicp_c.cpp b/th05/musicp_c.cpp new file mode 100644 index 00000000..aee4dd08 --- /dev/null +++ b/th05/musicp_c.cpp @@ -0,0 +1 @@ +#include "th05/music/piano_c.cpp" diff --git a/th05_op.asm b/th05_op.asm index 2cfee879..9c996108 100644 --- a/th05_op.asm +++ b/th05_op.asm @@ -1924,7 +1924,7 @@ _musicroom proc near call pi_palette_apply pascal, 0 call pi_put_8 pascal, large 0, 0 call pi_free pascal, 0 - call _piano_setup + call _piano_setup_and_put_initial call screen_back_B_snap call bgimage_snap call draw_tracks pascal, word ptr _music_sel @@ -2537,7 +2537,8 @@ include th04/formats/cdg_put.asm include th02/exit.asm include th04/math/vector1_at.asm include th04/math/vector2_at.asm -include th05/music/piano_c.asm + extern _piano_render:proc + extern _piano_setup_and_put_initial:proc extern BGIMAGE_PUT_RECT:proc extern SND_LOAD:proc extern SND_KAJA_INTERRUPT:proc