From 42842898ddecf27aa913dc0f17bf2697f8bf7660 Mon Sep 17 00:00:00 2001 From: NicknineTheEagle Date: Tue, 12 Nov 2024 23:27:48 +0300 Subject: [PATCH 1/3] Formatting --- src/meta/ubi_apm.c | 126 ++++++++++++++++++++++----------------------- 1 file changed, 63 insertions(+), 63 deletions(-) diff --git a/src/meta/ubi_apm.c b/src/meta/ubi_apm.c index a0967da6..a5bb4a75 100644 --- a/src/meta/ubi_apm.c +++ b/src/meta/ubi_apm.c @@ -3,83 +3,83 @@ /* .APM - seen in old Ubisoft games [Rayman 2: The Great Escape (PC), Donald Duck: Goin' Quackers (PC)] */ VGMSTREAM* init_vgmstream_ubi_apm(STREAMFILE* sf) { - VGMSTREAM* vgmstream = NULL; - uint32_t channels, sample_rate, file_size, nibble_size; - off_t start_offset; - int loop_flag; - uint32_t i; + VGMSTREAM* vgmstream = NULL; + uint32_t channels, sample_rate, file_size, nibble_size; + off_t start_offset; + int loop_flag; + uint32_t i; - if (read_u16le(0x00, sf) != 0x2000 || !is_id32be(0x14, sf, "vs12")) - goto fail; + if (read_u16le(0x00, sf) != 0x2000 || !is_id32be(0x14, sf, "vs12")) + goto fail; - if (!check_extensions(sf, "apm")) - goto fail; + if (!check_extensions(sf, "apm")) + goto fail; - /* (info from https://github.com/Synthesis/ray2get) - * 0x00(2): format tag (0x2000 for Ubisoft ADPCM) - * 0x02(2): channels - * 0x04(4): sample rate - * 0x08(4): byte rate? PCM samples? - * 0x0C(2): block align - * 0x0E(2): bits per sample - * 0x10(4): header size - * 0x14(4): "vs12" - * 0x18(4): file size - * 0x1C(4): nibble size - * 0x20(4): -1? - * 0x24(4): 0? - * 0x28(4): high/low nibble flag (when loaded in memory) - * 0x2C(N): ADPCM info per channel, last to first - * - 0x00(4): ADPCM hist - * - 0x04(4): ADPCM step index - * - 0x08(4): copy of ADPCM data (after interleave, ex. R from data + 0x01) - * 0x60(4): "DATA" - * 0x64(N): ADPCM data - */ + /* (info from https://github.com/Synthesis/ray2get) + * 0x00(2): format tag (0x2000 for Ubisoft ADPCM) + * 0x02(2): channels + * 0x04(4): sample rate + * 0x08(4): byte rate? PCM samples? + * 0x0C(2): block align + * 0x0E(2): bits per sample + * 0x10(4): header size + * 0x14(4): "vs12" + * 0x18(4): file size + * 0x1C(4): nibble size + * 0x20(4): -1? + * 0x24(4): 0? + * 0x28(4): high/low nibble flag (when loaded in memory) + * 0x2C(N): ADPCM info per channel, last to first + * - 0x00(4): ADPCM hist + * - 0x04(4): ADPCM step index + * - 0x08(4): copy of ADPCM data (after interleave, ex. R from data + 0x01) + * 0x60(4): "DATA" + * 0x64(N): ADPCM data + */ - channels = read_u16le(0x02, sf); - sample_rate = read_u32le(0x04, sf); - file_size = read_u32le(0x18, sf); - nibble_size = read_u32le(0x1c, sf); + channels = read_u16le(0x02, sf); + sample_rate = read_u32le(0x04, sf); + file_size = read_u32le(0x18, sf); + nibble_size = read_u32le(0x1c, sf); - start_offset = 0x64; + start_offset = 0x64; - if (file_size != get_streamfile_size(sf)) - goto fail; + if (file_size != get_streamfile_size(sf)) + goto fail; - if (nibble_size > (file_size - start_offset)) - goto fail; + if (nibble_size > (file_size - start_offset)) + goto fail; - if (!is_id32be(0x60, sf, "DATA")) - goto fail; + if (!is_id32be(0x60, sf, "DATA")) + goto fail; - loop_flag = 0; + loop_flag = 0; - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channels, loop_flag); - if (!vgmstream) goto fail; + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channels, loop_flag); + if (!vgmstream) goto fail; - vgmstream->meta_type = meta_UBI_APM; - vgmstream->coding_type = coding_DVI_IMA_int; - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = 0x01; - vgmstream->sample_rate = sample_rate; - vgmstream->num_samples = ima_bytes_to_samples(file_size - start_offset, channels); + vgmstream->meta_type = meta_UBI_APM; + vgmstream->coding_type = coding_DVI_IMA_int; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x01; + vgmstream->sample_rate = sample_rate; + vgmstream->num_samples = ima_bytes_to_samples(file_size - start_offset, channels); - /* read initial hist (last to first) */ - for (i = 0; i < channels; i++) { - vgmstream->ch[i].adpcm_history1_32 = read_s32le(0x2c + 0x0c * (channels - 1 - i) + 0x00, sf); - vgmstream->ch[i].adpcm_step_index = read_s32le(0x2c + 0x0c * (channels - 1 - i) + 0x04, sf); - } - //todo supposedly APM IMA removes lower 3b after assigning step, but wave looks a bit off (Rayman 2 only?): - // ...; step = adpcm_table[step_index]; delta = (step >> 3); step &= (~7); ... + /* read initial hist (last to first) */ + for (i = 0; i < channels; i++) { + vgmstream->ch[i].adpcm_history1_32 = read_s32le(0x2c + 0x0c * (channels - 1 - i) + 0x00, sf); + vgmstream->ch[i].adpcm_step_index = read_s32le(0x2c + 0x0c * (channels - 1 - i) + 0x04, sf); + } + //todo supposedly APM IMA removes lower 3b after assigning step, but wave looks a bit off (Rayman 2 only?): + // ...; step = adpcm_table[step_index]; delta = (step >> 3); step &= (~7); ... - if (!vgmstream_open_stream(vgmstream, sf, start_offset)) - goto fail; + if (!vgmstream_open_stream(vgmstream, sf, start_offset)) + goto fail; - return vgmstream; + return vgmstream; fail: - close_vgmstream(vgmstream); - return NULL; + close_vgmstream(vgmstream); + return NULL; } From 6fdc2025cd8b2a779164b8c40ec933ae78f3828f Mon Sep 17 00:00:00 2001 From: NicknineTheEagle Date: Wed, 13 Nov 2024 01:12:05 +0300 Subject: [PATCH 2/3] Added .sdd [Piglet's Big Game (PS2/GC)] --- src/formats.c | 2 + src/libvgmstream.vcxproj | 1 + src/libvgmstream.vcxproj.filters | 3 + src/meta/meta.h | 2 + src/meta/sdd.c | 101 +++++++++++++++++++++++++++++++ src/vgmstream_init.c | 1 + src/vgmstream_types.h | 1 + 7 files changed, 111 insertions(+) create mode 100644 src/meta/sdd.c diff --git a/src/formats.c b/src/formats.c index 33241716..8ca3e58c 100644 --- a/src/formats.c +++ b/src/formats.c @@ -499,6 +499,7 @@ static const char* extension_list[] = { "scd", "sch", "sd9", + "sdd", "sdl", "sdp", //txth/reserved [Metal Gear Arcade (AC)] "sdf", @@ -1446,6 +1447,7 @@ static const meta_info meta_info_list[] = { {meta_EA_SBK, "Electronic Arts SBK header"}, {meta_DSP_ASURA, "Rebellion DSP header"}, {meta_ONGAKUKAN_RIFF_ADP, "Ongakukan RIFF WAVE header"}, + {meta_SDD, "Doki Denki DSBH header"}, }; void get_vgmstream_coding_description(VGMSTREAM* vgmstream, char* out, size_t out_size) { diff --git a/src/libvgmstream.vcxproj b/src/libvgmstream.vcxproj index 7089e3cf..5fbf4e3a 100644 --- a/src/libvgmstream.vcxproj +++ b/src/libvgmstream.vcxproj @@ -667,6 +667,7 @@ + diff --git a/src/libvgmstream.vcxproj.filters b/src/libvgmstream.vcxproj.filters index 2ccbc970..4f79a75d 100644 --- a/src/libvgmstream.vcxproj.filters +++ b/src/libvgmstream.vcxproj.filters @@ -1831,6 +1831,9 @@ meta\Source Files + + meta\Source Files + meta\Source Files diff --git a/src/meta/meta.h b/src/meta/meta.h index 14467bea..71593e20 100644 --- a/src/meta/meta.h +++ b/src/meta/meta.h @@ -1011,4 +1011,6 @@ VGMSTREAM* init_vgmstream_dsp_asura_sfx(STREAMFILE* sf); VGMSTREAM* init_vgmstream_adp_ongakukan(STREAMFILE* sf); +VGMSTREAM* init_vgmstream_sdd(STREAMFILE* sf); + #endif /*_META_H*/ diff --git a/src/meta/sdd.c b/src/meta/sdd.c new file mode 100644 index 00000000..3570a034 --- /dev/null +++ b/src/meta/sdd.c @@ -0,0 +1,101 @@ +#include "meta.h" +#include "../coding/coding.h" + +/* .SDD - from Piglet's Big Game (PS2/GC) */ +VGMSTREAM* init_vgmstream_sdd(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + uint32_t header_size, data_size, sample_rate, sound_offset, sound_size; + uint8_t codec, channels; + off_t table_offset, data_offset, entry_offset, name_offset; + size_t name_size; + int target_subsong = sf->stream_index, total_subsongs, loop_flag; + + if (!is_id32be(0x00, sf, "DSBH")) + goto fail; + + if (!check_extensions(sf, "sdd")) + goto fail; + + /* always little endian, even on GC */ + header_size = read_u32le(0x04, sf); + table_offset = 0x20; + + /* haven't seen any filenames larger than 16 bytes so should be safe */ + total_subsongs = (header_size - table_offset) / 0x20; + + if (target_subsong == 0) target_subsong = 1; + if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) + goto fail; + + /* get name buffer size */ + name_offset = table_offset + (target_subsong - 1) * 0x20; + name_size = read_string(NULL, STREAM_NAME_SIZE, name_offset, sf) + 1; + + entry_offset = name_offset + name_size; + codec = read_u8(entry_offset + 0x00, sf); + //bps = read_u8(entry_offset + 0x01, sf); + channels = read_u8(entry_offset + 0x02, sf); + sample_rate = read_u32le(entry_offset + 0x03, sf); + sound_offset = read_u32le(entry_offset + 0x07, sf); + sound_size = read_u32le(entry_offset + 0x0b, sf); + + /* no stereo samples seen */ + if (channels > 1) + goto fail; + + data_offset = header_size; + if (!is_id32be(data_offset, sf, "DSBD")) + goto fail; + + data_size = read_u32le(data_offset + 0x04, sf); + if (data_offset + data_size > get_streamfile_size(sf)) + goto fail; + + sound_offset += data_offset + 0x20; + loop_flag = 0; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channels, loop_flag); + if (!vgmstream) goto fail; + + vgmstream->meta_type = meta_SDD; + vgmstream->sample_rate = sample_rate; + vgmstream->stream_size = sound_size; + vgmstream->num_streams = total_subsongs; + read_string(vgmstream->stream_name, STREAM_NAME_SIZE, name_offset, sf); + + switch (codec) { + case 0x01: /* DSP */ + /* starts with incomplete DSP header (nibble count not set) */ + if (sound_size < 0x60) + goto fail; + + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->layout_type = layout_none; + vgmstream->num_samples = read_u32be(sound_offset + 0x00, sf); + + /* set coefs and initial history */ + dsp_read_coefs_be(vgmstream, sf, sound_offset + 0x1c, 0x00); + vgmstream->ch[0].adpcm_history1_16 = read_u16be(sound_offset + 0x40, sf); + vgmstream->ch[0].adpcm_history2_16 = read_u16be(sound_offset + 0x42, sf); + + sound_offset += 0x60; + vgmstream->stream_size -= 0x60; + break; + case 0x03: /* PSX */ + vgmstream->coding_type = coding_PSX; + vgmstream->layout_type = layout_none; + vgmstream->num_samples = ps_bytes_to_samples(sound_size, channels); + break; + default: + goto fail; + } + + if (!vgmstream_open_stream(vgmstream, sf, sound_offset)) + goto fail; + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/src/vgmstream_init.c b/src/vgmstream_init.c index e8c4a5ab..ceef04b0 100644 --- a/src/vgmstream_init.c +++ b/src/vgmstream_init.c @@ -509,6 +509,7 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_dsp_asura_ttss, init_vgmstream_dsp_asura_sfx, init_vgmstream_adp_ongakukan, + init_vgmstream_sdd, /* lower priority metas (no clean header identity, somewhat ambiguous, or need extension/companion file to identify) */ init_vgmstream_agsc, diff --git a/src/vgmstream_types.h b/src/vgmstream_types.h index eeb21c14..96eb0586 100644 --- a/src/vgmstream_types.h +++ b/src/vgmstream_types.h @@ -708,6 +708,7 @@ typedef enum { meta_EA_SBK, meta_DSP_ASURA, meta_ONGAKUKAN_RIFF_ADP, + meta_SDD, } meta_t; From d8728320dfa3a7960cae5f81af3d1007c0067dc5 Mon Sep 17 00:00:00 2001 From: NicknineTheEagle Date: Wed, 13 Nov 2024 15:39:24 +0300 Subject: [PATCH 3/3] SDD: Added PCM codec [Winnie the Pooh's Rumbly Tumbly Adventure (PS2/GC)] --- src/meta/sdd.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/meta/sdd.c b/src/meta/sdd.c index 3570a034..e282f845 100644 --- a/src/meta/sdd.c +++ b/src/meta/sdd.c @@ -1,5 +1,6 @@ #include "meta.h" #include "../coding/coding.h" +#include "../util/chunks.h" /* .SDD - from Piglet's Big Game (PS2/GC) */ VGMSTREAM* init_vgmstream_sdd(STREAMFILE* sf) { @@ -82,6 +83,26 @@ VGMSTREAM* init_vgmstream_sdd(STREAMFILE* sf) { sound_offset += 0x60; vgmstream->stream_size -= 0x60; break; + case 0x02: { /* PCM */ + off_t chunk_offset; + size_t chunk_size; + + /* stored as RIFF */ + sound_offset += 0x0c; + sound_size -= 0x0c; + + /* find "data" chunk */ + if (!find_chunk_riff_le(sf, 0x64617461, sound_offset, sound_size, &chunk_offset, &chunk_size)) + goto fail; + + vgmstream->coding_type = coding_PCM16LE; + vgmstream->layout_type = layout_none; + vgmstream->num_samples = pcm16_bytes_to_samples(chunk_size, channels); + + sound_offset = chunk_offset; + vgmstream->stream_size = chunk_size; + break; + } case 0x03: /* PSX */ vgmstream->coding_type = coding_PSX; vgmstream->layout_type = layout_none;