fix some ongakukan .adp

at least one adp file from midousuji-sen was found to have a "fact" chunk at offset 0x24 instead of the usual 0x26. this caused vgmstream to not play said file at all.

not only does this commit fixes this, it also adds additional checks to the "adp_ongakukan" meta.

this includes the introduction of the "diff" variable whose purpose is to subtract the difference between expected_size and pcm_size. meta will now only proceed if diff is between 0 and 2 (sorta).

as for the "fix" itself, it required the introduction of the "fact_offset" variable.

fact_offset adds both fmt_offset and fmt_size so that "fact" chunk signature can be read (and checked against adp file within the meta) properly instead of always requiring "fact" to be at 0x26.

fact_offset is also checked if it goes below 0x24 and above 0x28.
This commit is contained in:
modusc896d352 2024-07-25 19:06:14 -03:00
parent 808a3233a8
commit 3145f7ebe4

View File

@ -9,8 +9,8 @@ VGMSTREAM* init_vgmstream_adp_ongakukan(STREAMFILE* sf) {
bool sound_is_adpcm = false;
int32_t fmt_size, fmt_offset;
int32_t sample_rate, data_size;
int16_t channels;
int16_t channels;
int32_t expected_size, pcm_size, diff, fact_offset;
/* checks */
if (!is_id32be(0x00, sf, "RIFF"))
@ -24,21 +24,22 @@ VGMSTREAM* init_vgmstream_adp_ongakukan(STREAMFILE* sf) {
data_size = get_streamfile_size(sf) - start_offset;
/* RIFF size seem to match original PCM .wav, while encoded .adp data equals or is slightly smaller that that */
uint32_t expected_size = (read_u32le(0x04, sf) - 0x24);
uint32_t pcm_size = data_size * 2 * sizeof(short); // * channels
if (pcm_size > expected_size)
expected_size = (read_u32le(0x04, sf) - 0x24);
pcm_size = data_size * 2 * sizeof(short); // * channels
diff = expected_size - pcm_size;
if (diff < 0 || diff > 2)
return NULL;
if (!is_id32be(0x08, sf, "WAVE"))
return NULL;
if (!is_id32be(0x0c, sf, "fmt "))
return NULL;
if (!is_id32be(0x0c, sf, "fmt "))
return NULL;
fmt_size = read_s32le(0x10, sf);
/* depending on the adp, fmt_size alternates between 0x10 and 0x12 */
if (fmt_size < 0x10 || fmt_size > 0x12)
goto fail;
fmt_offset = 0x14;
fmt_offset = 0x14;
if (read_s16le(fmt_offset + 0x00, sf) != 0x0001) /* PCM format */
goto fail;
@ -49,11 +50,17 @@ VGMSTREAM* init_vgmstream_adp_ongakukan(STREAMFILE* sf) {
if (read_s16le(fmt_offset + 0x0e, sf) != 16) /* PCM bit depth */
goto fail;
/* rest of fmt header is the usual header for 16-bit PCM wav files: bitrate, block size, and the like (see riff.c) */
/* if fmt_size == 0x12 there may be is an additional s16 field that's always zero, but not always. */
/* next chunk is at fixed offset, regardless of fmt_size (fmt_size 0x12 with "data" at 0x24 is possible).
* "data" has chunk size (does not match ADP size but original WAV) and "fact" chunk size 0x04 cut off) */
if (!is_id32be(0x24, sf, "data") && !is_id32be(0x26, sf, "fact"))
/* if fmt_size == 0x12 there is an additional s16 field that may or may not be zero. */
/* depending on the adp, "fact" chunk is "movable" as we'll see later. */
fact_offset = fmt_offset + fmt_size;
if (fact_offset < 0x24 || fact_offset > 0x28)
goto fail;
/* for next chunk, if "data" then it's at fixed offset (0x24), regardless of fmt_size (fmt_size 0x12 with "data" at 0x24 is possible).
* if "fact" however, offset goes AFTER fmt_size (mostly 0x26 and rarely 0x24).
* "data" has chunk size (does not match ADP size but original WAV) and "fact" chunk size is always 0x04 (whether cut off or otherwise). */
if (!is_id32be(0x24, sf, "data") && !is_id32be(fact_offset, sf, "fact"))
goto fail;
/* Ongagukan games using this format just read it by checking "ADP" extension in a provided file name,