diff --git a/libs/kaja/kaja.h b/libs/kaja/kaja.h index 7becf66b..9c2e984d 100644 --- a/libs/kaja/kaja.h +++ b/libs/kaja/kaja.h @@ -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; diff --git a/th02/snd/load.c b/th02/snd/load.cpp similarity index 90% rename from th02/snd/load.c rename to th02/snd/load.cpp index c9c0c17d..400b19e0 100644 --- a/th02/snd/load.c +++ b/th02/snd/load.cpp @@ -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); } + +} diff --git a/th02/snd/snd.h b/th02/snd/snd.h index f36fa348..99b4225f 100644 --- a/th02/snd/snd.h +++ b/th02/snd/snd.h @@ -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 diff --git a/th02/snd_load.c b/th02/snd_load.c deleted file mode 100644 index 54dce7e7..00000000 --- a/th02/snd_load.c +++ /dev/null @@ -1 +0,0 @@ -#include "th02/snd/load.c" diff --git a/th02/snd_load.cpp b/th02/snd_load.cpp new file mode 100644 index 00000000..1c1b2b14 --- /dev/null +++ b/th02/snd_load.cpp @@ -0,0 +1 @@ +#include "th02/snd/load.cpp" diff --git a/th04/snd/snd.h b/th04/snd/snd.h index 1daf4ba4..f1c68ab1 100644 --- a/th04/snd/snd.h +++ b/th04/snd/snd.h @@ -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 diff --git a/th05/snd/load.cpp b/th05/snd/load.cpp index 0815946c..3a1faba7 100644 --- a/th05/snd/load.cpp +++ b/th05/snd/load.cpp @@ -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