[Reverse-engineering] [th02/th03/th04/th05] snd_load() buffer size

Hardcoding these *might* have been acceptable if the numbers actually
matched the sizes defined in GAME.BAT, but they don't. With PMD's
AH=22h function, there's really no excuse though.
About time I looked into this, and expressed that constant as an inline
function that can easily be replaced with a proper implementation.

Part of P0139, funded by [Anonymous].
This commit is contained in:
nmlgc 2021-05-11 23:13:35 +02:00
parent ca4bf5002a
commit 46a1674250
7 changed files with 33 additions and 3 deletions

View File

@ -24,6 +24,11 @@ typedef enum {
PMD_SE_PLAY = 0x0C,
PMD_GET_WORKAREA_ADDRESS = 0x10,
// Returns the sizes of the song (AL), instrument (AH), and sound effect
// (DL) buffers, in KiB. These can be customized on the PMD command line
// with the /M, /V and /E options respectively.
PMD_GET_BUFFER_SIZES = 0x22,
_kaja_func_t_FORCE_UINT16 = 0xFFFF
} kaja_func_t;

View File

@ -1,5 +1,6 @@
#pragma option -zCSHARED
extern "C" {
#include "platform.h"
#include "x86real.h"
#include "libs/kaja/kaja.h"
@ -47,7 +48,7 @@ void snd_load(const char fn[SND_FN_LEN], kaja_func_t func)
// DOS file read; song data address is in DS:DX
_AX = 0x3F00;
_CX = 0x5000;
_CX = snd_load_size();
geninterrupt(0x21);
__asm { pop ds; }
@ -56,3 +57,5 @@ void snd_load(const char fn[SND_FN_LEN], kaja_func_t func)
_AH = 0x3E;
geninterrupt(0x21);
}
}

View File

@ -60,6 +60,19 @@ void snd_delay_until_volume(uint8_t volume);
#define SND_FN_LEN 13
#if defined(PMD) && (GAME <= 3) /* requires kaja.h */
#if defined(__cplusplus) && (GAME <= 4)
static inline uint16_t snd_load_size() {
// ZUN bug: Should rather retrieve the maximum data size for song
// or sound effect data via PMD_GET_BUFFER_SIZES, instead of
// hardcoding a random maximum and risking overflowing PMD's data
// buffer.
// (Unfortunately, MMD lacks a similar function...)
// MODDERS: When implementing this properly, rearrange the call
// sites to make sure that AX isn't destroyed.
return 0x5000;
}
#endif
// 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

View File

@ -1 +0,0 @@
#include "th02/snd/load.c"

1
th02/snd_load.cpp Normal file
View File

@ -0,0 +1 @@
#include "th02/snd/load.cpp"

View File

@ -39,6 +39,7 @@ static inline bool16 snd_se_active() {
// sets [snd_se_mode] and [snd_bgm_mode] accordingly. Returns [snd_bgm_mode].
int pascal snd_determine_modes(int req_bgm_mode, int req_se_mode);
#if defined(PMD) /* requires kaja.h */
// 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
@ -60,3 +61,11 @@ int pascal snd_determine_modes(int req_bgm_mode, int req_se_mode);
// 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);
#if defined(__cplusplus) && (GAME == 5)
// Refer to TH02's implementation for an explanation of how wrong this is.
static inline uint16_t snd_load_size() {
return 0xFFFF;
}
#endif
#endif

View File

@ -101,7 +101,7 @@ void pascal snd_load(const char fn[SND_FN_LEN], int16_t func)
// DOS file read; song data address is in DS:DX
_AX = 0x3F00;
_CX = 0xFFFF;
_CX = snd_load_size();
geninterrupt(0x21);
// DOS file close