ReC98/th05/snd/load.cpp

122 lines
2.6 KiB
C++

#pragma option -zCSHARED_ -3
#include <errno.h>
#include "platform.h"
#include "x86real.h"
#include "decomp.hpp"
#include "master.hpp"
#include "libs/kaja/kaja.h"
extern "C" {
#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], snd_load_func_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;
_DS = FP_SEG(fn);
_SI = FP_OFF(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;
_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 = snd_load_size();
geninterrupt(0x21);
// DOS file close
_AH = 0x3E;
geninterrupt(0x21);
_asm { push es; }
_asm { pop ds; }
ret:
#undef func_local
#undef ext
#undef _DI
}
}