[Decompilation] [th05] Music Room piano (decompilable functions)

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].
This commit is contained in:
nmlgc 2021-02-28 19:10:51 +01:00
parent 152ecaa496
commit 252c13d383
8 changed files with 202 additions and 192 deletions

View File

@ -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 @&&|
$**
|

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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<es:di>`
// 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<es:di>`
@ -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<piano_label_t>(_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<OPEN_WORK far *>(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<QQ near *near *>(_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; }
}
}

1
th05/musicp_c.cpp Normal file
View File

@ -0,0 +1 @@
#include "th05/music/piano_c.cpp"

View File

@ -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