mirror of https://github.com/nmlgc/ReC98.git
[Decompilation] [th05] snd_load()
A decompilation of ZUN-written ASM that was almost worth it, for once! Too bad that those aren't the <string.h> intrinsics that the Wolfenstein 3D disassembly hinted at, though. Part of P0135, funded by [Anonymous].
This commit is contained in:
parent
903f5b55de
commit
01c92da1ac
|
@ -152,17 +152,17 @@ 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\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\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 @&&|
|
||||
$**
|
||||
|
|
||||
|
||||
bin\th05\main.exe: bin\th05\main.obj th05\main010.cpp th05\main011.cpp th05\p_common.cpp th05\p_reimu.cpp th05\p_marisa.cpp th05\p_mima.cpp th05\p_yuuka.cpp bin\th05\player.obj bin\th05\hud_bar.obj bin\th05\scoreupd.obj th05\main012.cpp th05\main013.cpp bin\hfliplut.obj bin\th05\bullet.obj bin\th05\snd_kaja.obj bin\th05\initmain.obj bin\th05\input_s.obj bin\th05\inp_h_w.obj bin\th05\frmdelay.obj bin\th04\cdg_load.obj th05\main031.cpp th05\main032.cpp th05\main033.cpp th05\main034.cpp
|
||||
bin\th05\main.exe: bin\th05\main.obj th05\main010.cpp th05\main011.cpp th05\p_common.cpp th05\p_reimu.cpp th05\p_marisa.cpp th05\p_mima.cpp th05\p_yuuka.cpp bin\th05\player.obj bin\th05\hud_bar.obj bin\th05\scoreupd.obj th05\main012.cpp th05\main013.cpp bin\hfliplut.obj bin\th05\bullet.obj bin\th05\snd_load.obj bin\th05\snd_kaja.obj bin\th05\initmain.obj bin\th05\input_s.obj bin\th05\inp_h_w.obj bin\th05\frmdelay.obj bin\th04\cdg_load.obj th05\main031.cpp th05\main032.cpp th05\main033.cpp th05\main034.cpp
|
||||
$(CC) $(CFLAGS) $(LARGE_LFLAGS) -3 -Z -DGAME=5 -DBINARY='M' -nbin\th05\ -eMAIN.EXE @&&|
|
||||
$**
|
||||
|
|
||||
|
||||
bin\th05\maine.exe: bin\th05\maine.obj th05\maine011.cpp th05\regist.cpp th05\staff.cpp 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\initmain.obj bin\th05\input_s.obj bin\th05\inp_h_w.obj bin\th05\snd_dlym.obj bin\th05\frmdelay.obj bin\th04\cdg_load.obj bin\th05\egcrect.obj bin\hfliplut.obj
|
||||
bin\th05\maine.exe: bin\th05\maine.obj th05\maine011.cpp th05\regist.cpp th05\staff.cpp 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\initmain.obj bin\th05\input_s.obj bin\th05\inp_h_w.obj bin\th05\snd_dlym.obj bin\th05\frmdelay.obj bin\th04\cdg_load.obj bin\th05\egcrect.obj bin\hfliplut.obj
|
||||
$(CC) $(CFLAGS) $(LARGE_LFLAGS) -DGAME=5 -DBINARY='E' -Z -nbin\th05\ -eMAINE.EXE @&&|
|
||||
$**
|
||||
|
|
||||
|
|
|
@ -77,6 +77,7 @@ extern "C" {
|
|||
|
||||
int MASTER_RET bgm_init(int bufsiz);
|
||||
void MASTER_RET bgm_finish(void);
|
||||
int MASTER_RET bgm_read_sdata(const char MASTER_PTR *fn);
|
||||
int MASTER_RET bgm_sound(int num);
|
||||
// ----------------------------------------
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#include "libs/kaja/kaja.h"
|
||||
#include "th02/snd/snd.h"
|
||||
|
||||
extern char snd_load_fn[13];
|
||||
extern char snd_load_fn[SND_FN_LEN];
|
||||
|
||||
void snd_load(const char *fn, kaja_func_t func)
|
||||
{
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
; Shorter symbols for the [func] parameter of snd_load()
|
||||
SND_LOAD_SONG equ (KAJA_GET_SONG_ADDRESS shl 8)
|
||||
SND_LOAD_SE equ (PMD_GET_SE_ADDRESS shl 8)
|
||||
|
||||
|
|
|
@ -49,15 +49,18 @@ void snd_delay_until_volume(uint8_t volume);
|
|||
void snd_delay_until_measure(int measure);
|
||||
#endif
|
||||
|
||||
// Shorter symbols for the [func] parameter of snd_load()
|
||||
#define SND_LOAD_SONG (kaja_func_t)(KAJA_GET_SONG_ADDRESS << 8)
|
||||
#define SND_LOAD_SE (kaja_func_t)(PMD_GET_SE_ADDRESS << 8)
|
||||
|
||||
#define SND_FN_LEN 13
|
||||
|
||||
#if defined(PMD) && (GAME <= 3) /* requires kaja.h */
|
||||
// Loads a song in .M format ([func] = SND_LOAD_SONG) or a sound effect
|
||||
// bank in EFC format ([func] = SND_LOAD_SE) into the respective work
|
||||
// buffer of the sound driver. If MIDI is used, 'md' is appended to the
|
||||
// file name.
|
||||
void DEFCONV snd_load(const char *fn, kaja_func_t func);
|
||||
void DEFCONV snd_load(const char fn[SND_FN_LEN], kaja_func_t func);
|
||||
#endif
|
||||
|
||||
void snd_se_reset(void);
|
||||
|
|
|
@ -1,14 +1,3 @@
|
|||
; Loads a song ([func] = SND_LOAD_SONG) or a sound effect bank ([func] =
|
||||
; SND_LOAD_SE) into the respective work buffer of the sound driver. [fn] must
|
||||
; not have any extension. Depending on snd_bgm_mode and snd_se_mode, the
|
||||
; following file is loaded:
|
||||
; • '[fn].m26' if SND_BGM_FM26
|
||||
; • '[fn].m86' if SND_BGM_FM86
|
||||
; • '[fn].mmd' if SND_BGM_MIDI
|
||||
; • '[fn].efc' if SND_SE_FM
|
||||
; • '[fn].efs' if SND_SE_BEEP (using master.lib's BGM driver)
|
||||
|
||||
; void __stdcall snd_load(int func, const char *fn)
|
||||
snd_load proc
|
||||
arg @@func:word, @@fn:ptr
|
||||
|
||||
|
|
|
@ -30,3 +30,25 @@ static inline bool snd_is_active() {
|
|||
// Checks the requested BGM and SE modes against the available hardware and
|
||||
// sets [snd_se_mode] and [snd_bgm_mode] accordingly. Returns [snd_bgm_mode].
|
||||
unsigned char pascal snd_determine_modes(int req_bgm_mode, int req_se_mode);
|
||||
|
||||
// Loads a song ([func] = SND_LOAD_SONG) or a sound effect bank ([func] =
|
||||
// SND_LOAD_SE) into the respective work buffer of the sound driver. [fn] must
|
||||
// not have any extension. Depending on [snd_bgm_mode], [snd_se_mode], and
|
||||
// game, the following file is loaded:
|
||||
//
|
||||
// | | TH04 | TH05 |
|
||||
// |----------------+------------+-----------|
|
||||
// | [snd_bgm_mode] | [func] = SND_LOAD_SONG |
|
||||
// |----------------+------------+-----------|
|
||||
// | SND_BGM_FM26 | [fn].m26 | [fn].m |
|
||||
// | SND_BGM_FM86 | [fn].m86 | [fn].m2 |
|
||||
// | SND_BGM_MIDI | [fn].mmd | [fn].md | (yes, see TH05's load[data].asm)
|
||||
// |----------------+------------+-----------|
|
||||
// | [snd_se_mode] | [func] = SND_LOAD_SE |
|
||||
// |----------------+------------+-----------|
|
||||
// | SND_SE_FM | [fn].efc | [fn].efc |
|
||||
// | SND_SE_BEEP | [fn].efs | [fn].efs | (using master.lib's BGM driver)
|
||||
//
|
||||
// Note that the TH05 version will infinitely loop if neither the file for the
|
||||
// current [snd_bgm_mode] nor "[fn].m" exist.
|
||||
void pascal snd_load(const char fn[SND_FN_LEN], int16_t func);
|
||||
|
|
|
@ -1,97 +0,0 @@
|
|||
; Loads a song ([func] = SND_LOAD_SONG) or a sound effect bank ([func] =
|
||||
; SND_LOAD_SE) into the respective work buffer of the sound driver. [fn] must
|
||||
; not have any extension. Depending on snd_bgm_mode and snd_se_mode, the
|
||||
; following file is loaded:
|
||||
; • '[fn].m' if SND_BGM_FM26
|
||||
; • '[fn].m2' if SND_BGM_FM86
|
||||
; • '[fn].md' if SND_BGM_MIDI (yes, see this game's snd_load[data].asm)
|
||||
; • '[fn].efc' if SND_SE_FM
|
||||
; • '[fn].efs' if SND_SE_BEEP (using master.lib's BGM driver)
|
||||
; Note that the TH05 version will infinitely loop if neither the file for the
|
||||
; current snd_bgm_mode nor '[fn].m' exist.
|
||||
|
||||
; void __stdcall snd_load(int func, const char *fn)
|
||||
snd_load proc
|
||||
arg @@func:word, @@fn:far ptr
|
||||
|
||||
push bp
|
||||
mov bp, sp
|
||||
push si
|
||||
push di
|
||||
mov dx, ds
|
||||
mov es, dx
|
||||
mov di, offset _snd_load_fn
|
||||
lds si, @@fn
|
||||
mov bp, @@func
|
||||
mov cx, SND_LOAD_FN_LEN
|
||||
rep movsb
|
||||
mov ds, dx
|
||||
mov di, offset _snd_load_fn
|
||||
dec cx
|
||||
xor ax, ax
|
||||
repne scasb
|
||||
dec di
|
||||
mov byte ptr [di], '.'
|
||||
inc di
|
||||
cmp bp, SND_LOAD_SE
|
||||
jnz short @@song
|
||||
cmp _snd_se_mode, SND_SE_OFF
|
||||
jz short @@ret
|
||||
xor bx, bx
|
||||
cmp _snd_se_mode, SND_SE_BEEP
|
||||
jnz short @@set_ext
|
||||
mov dword ptr [di], 'sfe'
|
||||
call bgm_finish
|
||||
call bgm_init pascal, 2048
|
||||
call bgm_read_sdata pascal, ds, offset _snd_load_fn
|
||||
jmp short @@ret
|
||||
|
||||
@@song:
|
||||
cmp _snd_bgm_mode, SND_BGM_OFF
|
||||
jz short @@ret
|
||||
kajacall KAJA_SONG_STOP
|
||||
movzx bx, _snd_bgm_mode
|
||||
shl bx, 2
|
||||
|
||||
@@set_ext:
|
||||
mov eax, dword ptr aSND_LOAD_EXT[bx]
|
||||
|
||||
@@open:
|
||||
mov [di], eax
|
||||
mov dx, offset _snd_load_fn
|
||||
mov ax, 3D00h
|
||||
int 21h
|
||||
jnb short @@which_driver?
|
||||
cmp ax, 2 ; ENOFILE, from <errno.h>
|
||||
jnz short @@ret
|
||||
mov eax, dword ptr aSND_LOAD_EXT_FM26
|
||||
jmp short @@open
|
||||
|
||||
@@which_driver?:
|
||||
mov bx, ax
|
||||
mov ax, bp
|
||||
cmp ah, KAJA_GET_SONG_ADDRESS
|
||||
jnz short @@PMD
|
||||
cmp _snd_bgm_mode, SND_BGM_MIDI
|
||||
jnz short @@PMD
|
||||
int 61h
|
||||
jmp short @@read
|
||||
|
||||
@@PMD:
|
||||
int 60h
|
||||
|
||||
@@read:
|
||||
mov ax, 3F00h
|
||||
mov cx, 0FFFFh
|
||||
int 21h
|
||||
mov ah, 3Eh
|
||||
int 21h
|
||||
push es
|
||||
pop ds
|
||||
|
||||
@@ret:
|
||||
pop di
|
||||
pop si
|
||||
pop bp
|
||||
ret 6
|
||||
snd_load endp
|
|
@ -0,0 +1,121 @@
|
|||
#pragma codeseg SHARED_
|
||||
#pragma option -3
|
||||
|
||||
extern "C" {
|
||||
#include <errno.h>
|
||||
#include "platform.h"
|
||||
#include "x86real.h"
|
||||
#include "decomp.h"
|
||||
#include "master.hpp"
|
||||
#include "libs/kaja/kaja.h"
|
||||
#include "th05/snd/snd.h"
|
||||
|
||||
extern char snd_load_fn[SND_FN_LEN];
|
||||
extern const char SND_LOAD_EXT[4][4];
|
||||
|
||||
void pascal snd_load(const char fn[SND_FN_LEN], int16_t func)
|
||||
{
|
||||
#define _DI reinterpret_cast<char near *>(_DI)
|
||||
#define func_local _BP
|
||||
#define ext _EAX
|
||||
|
||||
__asm { mov dx, ds; }
|
||||
|
||||
// memcpy(snd_load_fn, fn, sizeof(SND_LOAD_FN));
|
||||
_ES = _DX;
|
||||
_DI = snd_load_fn;
|
||||
__asm { lds si, fn; }
|
||||
func_local = func;
|
||||
_CX = sizeof(snd_load_fn);
|
||||
__asm { rep movsb; }
|
||||
|
||||
// _DI = strchr(str, '\0');
|
||||
_DS = _DX;
|
||||
_DI = snd_load_fn;
|
||||
_CX--; // = -1
|
||||
_AX = '\0';
|
||||
__asm { repne scasb; }
|
||||
|
||||
_DI--;
|
||||
*(_DI) = '.';
|
||||
_DI++;
|
||||
if(func_local == SND_LOAD_SE) {
|
||||
// Only not decompilable because the jump distance happens to exactly
|
||||
// be 127 bytes, for which Turbo C++ doesn't emit short jumps anymore.
|
||||
__asm {
|
||||
cmp snd_se_mode, SND_SE_OFF;
|
||||
jz short ret;
|
||||
}
|
||||
_BX = 0;
|
||||
if(snd_se_mode == SND_SE_BEEP) {
|
||||
*reinterpret_cast<uint32_t near *>(_DI) = 0x00736665; // "efs\0"
|
||||
bgm_finish();
|
||||
bgm_init(2048);
|
||||
bgm_read_sdata(snd_load_fn);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if(snd_bgm_mode == SND_BGM_OFF) {
|
||||
return;
|
||||
}
|
||||
/* TODO: Replace with the decompiled expressions
|
||||
* snd_kaja_func(KAJA_SONG_STOP, 0);
|
||||
* _BX = (snd_bgm_mode << 2);
|
||||
* Since snd_kaja_interrupt() is undecompilable, this can never work
|
||||
* with the original translation unit structure. */
|
||||
__asm {
|
||||
push (KAJA_SONG_STOP shl 8);
|
||||
push cs;
|
||||
call near ptr snd_kaja_interrupt;
|
||||
db 0x0F, 0xB6, 0x1E; // MOVZX BX,
|
||||
dw offset snd_bgm_mode; // snd_bgm_mode
|
||||
shl bx, 2
|
||||
}
|
||||
}
|
||||
ext = *reinterpret_cast<const int32_t *>(&SND_LOAD_EXT[0][_BX]);
|
||||
|
||||
// ZUN bug: Infinite loop if neither the file for the current
|
||||
// [snd_bgm_mode] nor "[fn].m" exist.
|
||||
while(1) {
|
||||
*reinterpret_cast<uint32_t near *>(_DI) = ext;
|
||||
|
||||
// DOS file open
|
||||
reinterpret_cast<char near *>(_DX) = snd_load_fn;
|
||||
_AX = 0x3D00;
|
||||
geninterrupt(0x21);
|
||||
if(!FLAGS_CARRY) {
|
||||
break;
|
||||
}
|
||||
if(_AX != ENOFILE) {
|
||||
return;
|
||||
}
|
||||
ext = *reinterpret_cast<const int32_t *>(SND_LOAD_EXT[SND_BGM_FM26]);
|
||||
}
|
||||
|
||||
_BX = _AX; // Unnecessary, just remove this line
|
||||
_AX = func_local;
|
||||
if((_AH == KAJA_GET_SONG_ADDRESS) && (snd_bgm_mode == SND_BGM_MIDI)) {
|
||||
geninterrupt(MMD);
|
||||
} else {
|
||||
geninterrupt(PMD);
|
||||
}
|
||||
|
||||
// DOS file read; song data address is in DS:DX
|
||||
_AX = 0x3F00;
|
||||
_CX = 0xFFFF;
|
||||
geninterrupt(0x21);
|
||||
|
||||
// DOS file close
|
||||
_AH = 0x3E;
|
||||
geninterrupt(0x21);
|
||||
|
||||
__asm { push es; }
|
||||
__asm { pop ds; }
|
||||
|
||||
ret:
|
||||
#undef func_local
|
||||
#undef ext
|
||||
#undef _DI
|
||||
}
|
||||
|
||||
}
|
|
@ -1,4 +1,6 @@
|
|||
aSND_LOAD_EXT db 'efc',0
|
||||
aSND_LOAD_EXT_FM26 db 'm',0,0,0
|
||||
aSND_LOAD_EXT_FM86 db 'm2',0,'m' ; Yes, that's how it's addressed.
|
||||
aSND_LOAD_EXT_MIDI db 'md',0
|
||||
public _SND_LOAD_EXT
|
||||
_SND_LOAD_EXT label dword
|
||||
db 'efc',0
|
||||
db 'm',0,0,0
|
||||
db 'm2',0,'m' ; Yes, that's how it's addressed.
|
||||
db 'md',0
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
#include "th05/snd/load.cpp"
|
|
@ -10561,7 +10561,7 @@ include th04/formats/cdg_put.asm
|
|||
include th02/exit.asm
|
||||
include th04/math/vector1_at.asm
|
||||
include th04/math/vector2_at.asm
|
||||
include th05/snd/load.asm
|
||||
extern SND_LOAD:proc
|
||||
extern SND_KAJA_INTERRUPT:proc
|
||||
extern GAME_INIT_MAIN:proc
|
||||
extern _input_reset_sense:proc
|
||||
|
|
|
@ -7536,7 +7536,7 @@ include th02/exit.asm
|
|||
include th04/math/vector1_at.asm
|
||||
include th04/math/vector2_at.asm
|
||||
include th04/bgimage_put_rect.asm
|
||||
include th05/snd/load.asm
|
||||
extern SND_LOAD:proc
|
||||
extern SND_KAJA_INTERRUPT:proc
|
||||
extern PI_PUT_QUARTER_MASKED_8:proc
|
||||
extern PI_LOAD:proc
|
||||
|
|
|
@ -2541,7 +2541,7 @@ include th05/music/piano.asm
|
|||
GRCG_SETCOLOR_DIRECT_DEF 1
|
||||
db 0
|
||||
include th04/bgimage_put_rect.asm
|
||||
include th05/snd/load.asm
|
||||
extern SND_LOAD:proc
|
||||
extern SND_KAJA_INTERRUPT:proc
|
||||
extern PI_PUT_MASKED_8:proc
|
||||
extern PI_LOAD:proc
|
||||
|
|
Loading…
Reference in New Issue