mirror of
https://github.com/vgmstream/vgmstream.git
synced 2024-11-30 17:24:31 +01:00
Merge pull request #1630 from NicknineTheEagle/sdd
Added .sdd [Piglet's Big Game (PS2/GC)]
This commit is contained in:
commit
c6284ee311
@ -499,6 +499,7 @@ static const char* extension_list[] = {
|
|||||||
"scd",
|
"scd",
|
||||||
"sch",
|
"sch",
|
||||||
"sd9",
|
"sd9",
|
||||||
|
"sdd",
|
||||||
"sdl",
|
"sdl",
|
||||||
"sdp", //txth/reserved [Metal Gear Arcade (AC)]
|
"sdp", //txth/reserved [Metal Gear Arcade (AC)]
|
||||||
"sdf",
|
"sdf",
|
||||||
@ -1446,6 +1447,7 @@ static const meta_info meta_info_list[] = {
|
|||||||
{meta_EA_SBK, "Electronic Arts SBK header"},
|
{meta_EA_SBK, "Electronic Arts SBK header"},
|
||||||
{meta_DSP_ASURA, "Rebellion DSP header"},
|
{meta_DSP_ASURA, "Rebellion DSP header"},
|
||||||
{meta_ONGAKUKAN_RIFF_ADP, "Ongakukan RIFF WAVE 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) {
|
void get_vgmstream_coding_description(VGMSTREAM* vgmstream, char* out, size_t out_size) {
|
||||||
|
@ -667,6 +667,7 @@
|
|||||||
<ClCompile Include="meta\sbk.c" />
|
<ClCompile Include="meta\sbk.c" />
|
||||||
<ClCompile Include="meta\scd_pcm.c" />
|
<ClCompile Include="meta\scd_pcm.c" />
|
||||||
<ClCompile Include="meta\sd9.c" />
|
<ClCompile Include="meta\sd9.c" />
|
||||||
|
<ClCompile Include="meta\sdd.c" />
|
||||||
<ClCompile Include="meta\sdf.c" />
|
<ClCompile Include="meta\sdf.c" />
|
||||||
<ClCompile Include="meta\sdrh.c" />
|
<ClCompile Include="meta\sdrh.c" />
|
||||||
<ClCompile Include="meta\sdt.c" />
|
<ClCompile Include="meta\sdt.c" />
|
||||||
|
@ -1831,6 +1831,9 @@
|
|||||||
<ClCompile Include="meta\sd9.c">
|
<ClCompile Include="meta\sd9.c">
|
||||||
<Filter>meta\Source Files</Filter>
|
<Filter>meta\Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="meta\sdd.c">
|
||||||
|
<Filter>meta\Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="meta\sdf.c">
|
<ClCompile Include="meta\sdf.c">
|
||||||
<Filter>meta\Source Files</Filter>
|
<Filter>meta\Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
@ -1011,4 +1011,6 @@ VGMSTREAM* init_vgmstream_dsp_asura_sfx(STREAMFILE* sf);
|
|||||||
|
|
||||||
VGMSTREAM* init_vgmstream_adp_ongakukan(STREAMFILE* sf);
|
VGMSTREAM* init_vgmstream_adp_ongakukan(STREAMFILE* sf);
|
||||||
|
|
||||||
|
VGMSTREAM* init_vgmstream_sdd(STREAMFILE* sf);
|
||||||
|
|
||||||
#endif /*_META_H*/
|
#endif /*_META_H*/
|
||||||
|
122
src/meta/sdd.c
Normal file
122
src/meta/sdd.c
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
#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) {
|
||||||
|
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 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;
|
||||||
|
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;
|
||||||
|
}
|
@ -3,83 +3,83 @@
|
|||||||
|
|
||||||
/* .APM - seen in old Ubisoft games [Rayman 2: The Great Escape (PC), Donald Duck: Goin' Quackers (PC)] */
|
/* .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* init_vgmstream_ubi_apm(STREAMFILE* sf) {
|
||||||
VGMSTREAM* vgmstream = NULL;
|
VGMSTREAM* vgmstream = NULL;
|
||||||
uint32_t channels, sample_rate, file_size, nibble_size;
|
uint32_t channels, sample_rate, file_size, nibble_size;
|
||||||
off_t start_offset;
|
off_t start_offset;
|
||||||
int loop_flag;
|
int loop_flag;
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
|
|
||||||
if (read_u16le(0x00, sf) != 0x2000 || !is_id32be(0x14, sf, "vs12"))
|
if (read_u16le(0x00, sf) != 0x2000 || !is_id32be(0x14, sf, "vs12"))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
if (!check_extensions(sf, "apm"))
|
if (!check_extensions(sf, "apm"))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
/* (info from https://github.com/Synthesis/ray2get)
|
/* (info from https://github.com/Synthesis/ray2get)
|
||||||
* 0x00(2): format tag (0x2000 for Ubisoft ADPCM)
|
* 0x00(2): format tag (0x2000 for Ubisoft ADPCM)
|
||||||
* 0x02(2): channels
|
* 0x02(2): channels
|
||||||
* 0x04(4): sample rate
|
* 0x04(4): sample rate
|
||||||
* 0x08(4): byte rate? PCM samples?
|
* 0x08(4): byte rate? PCM samples?
|
||||||
* 0x0C(2): block align
|
* 0x0C(2): block align
|
||||||
* 0x0E(2): bits per sample
|
* 0x0E(2): bits per sample
|
||||||
* 0x10(4): header size
|
* 0x10(4): header size
|
||||||
* 0x14(4): "vs12"
|
* 0x14(4): "vs12"
|
||||||
* 0x18(4): file size
|
* 0x18(4): file size
|
||||||
* 0x1C(4): nibble size
|
* 0x1C(4): nibble size
|
||||||
* 0x20(4): -1?
|
* 0x20(4): -1?
|
||||||
* 0x24(4): 0?
|
* 0x24(4): 0?
|
||||||
* 0x28(4): high/low nibble flag (when loaded in memory)
|
* 0x28(4): high/low nibble flag (when loaded in memory)
|
||||||
* 0x2C(N): ADPCM info per channel, last to first
|
* 0x2C(N): ADPCM info per channel, last to first
|
||||||
* - 0x00(4): ADPCM hist
|
* - 0x00(4): ADPCM hist
|
||||||
* - 0x04(4): ADPCM step index
|
* - 0x04(4): ADPCM step index
|
||||||
* - 0x08(4): copy of ADPCM data (after interleave, ex. R from data + 0x01)
|
* - 0x08(4): copy of ADPCM data (after interleave, ex. R from data + 0x01)
|
||||||
* 0x60(4): "DATA"
|
* 0x60(4): "DATA"
|
||||||
* 0x64(N): ADPCM data
|
* 0x64(N): ADPCM data
|
||||||
*/
|
*/
|
||||||
|
|
||||||
channels = read_u16le(0x02, sf);
|
channels = read_u16le(0x02, sf);
|
||||||
sample_rate = read_u32le(0x04, sf);
|
sample_rate = read_u32le(0x04, sf);
|
||||||
file_size = read_u32le(0x18, sf);
|
file_size = read_u32le(0x18, sf);
|
||||||
nibble_size = read_u32le(0x1c, sf);
|
nibble_size = read_u32le(0x1c, sf);
|
||||||
|
|
||||||
start_offset = 0x64;
|
start_offset = 0x64;
|
||||||
|
|
||||||
if (file_size != get_streamfile_size(sf))
|
if (file_size != get_streamfile_size(sf))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
if (nibble_size > (file_size - start_offset))
|
if (nibble_size > (file_size - start_offset))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
if (!is_id32be(0x60, sf, "DATA"))
|
if (!is_id32be(0x60, sf, "DATA"))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
loop_flag = 0;
|
loop_flag = 0;
|
||||||
|
|
||||||
/* build the VGMSTREAM */
|
/* build the VGMSTREAM */
|
||||||
vgmstream = allocate_vgmstream(channels, loop_flag);
|
vgmstream = allocate_vgmstream(channels, loop_flag);
|
||||||
if (!vgmstream) goto fail;
|
if (!vgmstream) goto fail;
|
||||||
|
|
||||||
vgmstream->meta_type = meta_UBI_APM;
|
vgmstream->meta_type = meta_UBI_APM;
|
||||||
vgmstream->coding_type = coding_DVI_IMA_int;
|
vgmstream->coding_type = coding_DVI_IMA_int;
|
||||||
vgmstream->layout_type = layout_interleave;
|
vgmstream->layout_type = layout_interleave;
|
||||||
vgmstream->interleave_block_size = 0x01;
|
vgmstream->interleave_block_size = 0x01;
|
||||||
vgmstream->sample_rate = sample_rate;
|
vgmstream->sample_rate = sample_rate;
|
||||||
vgmstream->num_samples = ima_bytes_to_samples(file_size - start_offset, channels);
|
vgmstream->num_samples = ima_bytes_to_samples(file_size - start_offset, channels);
|
||||||
|
|
||||||
/* read initial hist (last to first) */
|
/* read initial hist (last to first) */
|
||||||
for (i = 0; i < channels; i++) {
|
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_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);
|
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?):
|
//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); ...
|
// ...; step = adpcm_table[step_index]; delta = (step >> 3); step &= (~7); ...
|
||||||
|
|
||||||
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
|
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
return vgmstream;
|
return vgmstream;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
close_vgmstream(vgmstream);
|
close_vgmstream(vgmstream);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -509,6 +509,7 @@ init_vgmstream_t init_vgmstream_functions[] = {
|
|||||||
init_vgmstream_dsp_asura_ttss,
|
init_vgmstream_dsp_asura_ttss,
|
||||||
init_vgmstream_dsp_asura_sfx,
|
init_vgmstream_dsp_asura_sfx,
|
||||||
init_vgmstream_adp_ongakukan,
|
init_vgmstream_adp_ongakukan,
|
||||||
|
init_vgmstream_sdd,
|
||||||
|
|
||||||
/* lower priority metas (no clean header identity, somewhat ambiguous, or need extension/companion file to identify) */
|
/* lower priority metas (no clean header identity, somewhat ambiguous, or need extension/companion file to identify) */
|
||||||
init_vgmstream_agsc,
|
init_vgmstream_agsc,
|
||||||
|
@ -708,6 +708,7 @@ typedef enum {
|
|||||||
meta_EA_SBK,
|
meta_EA_SBK,
|
||||||
meta_DSP_ASURA,
|
meta_DSP_ASURA,
|
||||||
meta_ONGAKUKAN_RIFF_ADP,
|
meta_ONGAKUKAN_RIFF_ADP,
|
||||||
|
meta_SDD,
|
||||||
|
|
||||||
} meta_t;
|
} meta_t;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user