Skip to content

Commit

Permalink
DSP: Asura engine variants
Browse files Browse the repository at this point in the history
  • Loading branch information
EdnessP committed May 24, 2024
1 parent 5e25e54 commit 69ab3d9
Show file tree
Hide file tree
Showing 9 changed files with 193 additions and 16 deletions.
1 change: 1 addition & 0 deletions src/formats.c
Original file line number Diff line number Diff line change
Expand Up @@ -1436,6 +1436,7 @@ static const meta_info meta_info_list[] = {
{meta_CBX, "Traveller's Tales CBX header"},
{meta_VAS_ROCKSTAR, "Rockstar .VAS header"},
{meta_EA_SBK, "Electronic Arts SBK header"},
{meta_DSP_ASURA, "Rebellion DSP header"},
};

void get_vgmstream_coding_description(VGMSTREAM* vgmstream, char* out, size_t out_size) {
Expand Down
1 change: 1 addition & 0 deletions src/libvgmstream.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -537,6 +537,7 @@
<ClCompile Include="meta\nds_strm.c" />
<ClCompile Include="meta\nds_strm_ffta2.c" />
<ClCompile Include="meta\ngc_adpdtk.c" />
<ClCompile Include="meta\ngc_dsp_asura.c" />
<ClCompile Include="meta\ngc_dsp_konami.c" />
<ClCompile Include="meta\ngc_dsp_mpds.c" />
<ClCompile Include="meta\ngc_dsp_std.c" />
Expand Down
3 changes: 3 additions & 0 deletions src/libvgmstream.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -1432,6 +1432,9 @@
<ClCompile Include="meta\ngc_adpdtk.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
<ClCompile Include="meta\ngc_dsp_asura.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
<ClCompile Include="meta\ngc_dsp_konami.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
Expand Down
6 changes: 5 additions & 1 deletion src/meta/meta.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ VGMSTREAM* init_vgmstream_dsp_sps_n1(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_dsp_itl_ch(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_dsp_adpy(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_dsp_adpx(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_dsp_ds2(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_dsp_lucasarts_ds2(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_dsp_itl(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_dsp_sqex(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_dsp_wiivoice(STREAMFILE* sf);
Expand All @@ -69,6 +69,8 @@ VGMSTREAM* init_vgmstream_dsp_cwac(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_idsp_tose(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_dsp_kwa(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_dsp_apex(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_dsp_asura(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_dsp_asura_ds2(STREAMFILE* sf);

VGMSTREAM * init_vgmstream_csmp(STREAMFILE *streamFile);

Expand Down Expand Up @@ -1010,4 +1012,6 @@ VGMSTREAM* init_vgmstream_vas_rockstar(STREAMFILE* sf);

VGMSTREAM* init_vgmstream_ea_sbk(STREAMFILE* sf);

VGMSTREAM* init_vgmstream_dsp_asura_sfx(STREAMFILE* sf);

#endif /*_META_H*/
77 changes: 77 additions & 0 deletions src/meta/ngc_dsp_asura.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
#include "meta.h"
#include "../coding/coding.h"


/* .sfx - Rebellion (Asura engine) games [Sniper Elite (Wii)] */
/* Despite what the extension implies it's used for music too */
/* Rebellion's other DSP variants can be found in ngc_dsp_std */
VGMSTREAM* init_vgmstream_dsp_asura_sfx(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
int channels, interleave, loop_flag;
uint32_t nibble_count, sample_rate;
off_t ch1_offset, ch2_offset;


/* checks */
if (!check_extensions(sf, "sfx"))
return NULL;

/* no clear header id, but this is how they all start */
/* the 0x02s are likely channels and codec (DSPADPCM) */
if (read_u32be(0x00, sf) != 0x00 &&
read_u32be(0x04, sf) != 0x02 &&
read_u32be(0x08, sf) != 0x02)
return NULL;


nibble_count = read_u32be(0x0C, sf);
sample_rate = read_u32be(0x10, sf); /* always 44100? */

/* this would likely be an array, but always 2ch so */
ch1_offset = read_u32be(0x14, sf); /* always 0x20? */
ch2_offset = read_u32be(0x18, sf); /* 0x10 aligned */

interleave = ch2_offset - ch1_offset;

/* channel header:
* 0x00: coefs
* 0x20: gain (0)
* 0x22: initial ps
* 0x30: stream start
*/

channels = 2;
loop_flag = 0;

/* more safety checks */
if (interleave < 0 ||
interleave < nibble_count / 2 ||
interleave > get_streamfile_size(sf) / channels)
goto fail;

if (read_u16be(ch1_offset + 0x22, sf) != read_u8(ch1_offset + 0x30, sf) ||
read_u16be(ch2_offset + 0x22, sf) != read_u8(ch2_offset + 0x30, sf))
goto fail;


/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channels, loop_flag);
if (!vgmstream) goto fail;

vgmstream->sample_rate = sample_rate;
vgmstream->meta_type = meta_DSP_ASURA;
vgmstream->coding_type = coding_NGC_DSP;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = interleave;
dsp_read_coefs_be(vgmstream, sf, ch1_offset, interleave);
vgmstream->num_samples = dsp_nibbles_to_samples(nibble_count);

if (!vgmstream_open_stream(vgmstream, sf, ch1_offset + 0x30))
goto fail;

return vgmstream;

fail:
close_vgmstream(vgmstream);
return NULL;
}
110 changes: 98 additions & 12 deletions src/meta/ngc_dsp_std.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,10 @@ static bool read_dsp_header_endian(struct dsp_header *header, off_t offset, STRE
goto fail;

header->sample_rate = get_u32(buf+0x08);
if (header->sample_rate < 8000 || header->sample_rate > 48000)
goto fail; /* validated later but fail faster (unsure of min) */
if (header->sample_rate < 5000 || header->sample_rate > 48000)
/* validated later but fail faster (unsure of min) */
/* lowest known so far is 5000 in Judge Dredd (GC) */
goto fail;

/* context */
header->loop_flag = get_u16(buf+0x0c);
Expand Down Expand Up @@ -315,8 +317,10 @@ VGMSTREAM* init_vgmstream_ngc_dsp_std(STREAMFILE* sf) {

/* .dsp: standard
* .adp: Dr. Muto/Battalion Wars (GC), Tale of Despereaux (Wii)
* (extensionless): Tony Hawk's Downhill Jam (Wii) */
if (!check_extensions(sf, "dsp,adp,"))
* (extensionless): Tony Hawk's Downhill Jam (Wii)
* .wav: PDC World Championship Darts 2009 & Pro Tour (Wii)
* .dat: The Sims: Bustin' Out (GC) (rarely, most are extensionless) */
if (!check_extensions(sf, "dsp,adp,,wav,lwav,dat,ldat"))
return NULL;

channels = 1;
Expand Down Expand Up @@ -358,7 +362,7 @@ VGMSTREAM* init_vgmstream_ngc_dsp_std(STREAMFILE* sf) {

/* ignore ddsp, that set samples/nibbles counting both channels so can't be detected
* (could check for .dsp but most files don't need this) */
if (check_extensions(sf, "adp")) {
if (check_extensions(sf, "adp,")) {
uint32_t interleave = (get_streamfile_size(sf) / 2);

ko = !read_dsp_header_be(&header2, interleave, sf);
Expand All @@ -371,7 +375,7 @@ VGMSTREAM* init_vgmstream_ngc_dsp_std(STREAMFILE* sf) {
}
}
}

if (header.loop_flag) {
off_t loop_off;
/* check loop predictor/scale */
Expand Down Expand Up @@ -846,15 +850,16 @@ VGMSTREAM* init_vgmstream_wii_wsd(STREAMFILE* sf) {
return NULL;
}

/* .ddsp - full interleaved dsp [Shark Tale (GC), The Sims 2: Pets (Wii), Wacky Races: Crash & Dash (Wii)] */
/* .ddsp - full interleaved dsp [Shark Tale (GC), The Sims series (GC/Wii), Wacky Races: Crash & Dash (Wii)] */
VGMSTREAM* init_vgmstream_dsp_ddsp(STREAMFILE* sf) {
dsp_meta dspm = {0};

/* checks */
/* .adp: Tale of Despereaux (Wii) */
/* .ddsp: fake extension (games have bigfiles without names, but has references to .wav)
* .wav: Wacky Races: Crash & Dash (Wii) */
if (!check_extensions(sf, "adp,ddsp,wav,lwav"))
* .wav: Wacky Races: Crash & Dash (Wii)
* (extensionless): The Sims series (GC/Wii) */
if (!check_extensions(sf, "adp,ddsp,wav,lwav,"))
goto fail;

dspm.channels = 2;
Expand Down Expand Up @@ -913,7 +918,7 @@ VGMSTREAM* init_vgmstream_dsp_str_ig(STREAMFILE* sf) {
dspm.header_spacing = 0x80;
dspm.start_offset = 0x800;
dspm.interleave = 0x4000;

dspm.meta_type = meta_DSP_STR_IG;
return init_vgmstream_dsp_common(sf, &dspm);
fail:
Expand Down Expand Up @@ -1271,7 +1276,7 @@ VGMSTREAM* init_vgmstream_dsp_adpx(STREAMFILE* sf) {
}

/* .ds2 - LucasArts wrapper [Star Wars: Bounty Hunter (GC)] */
VGMSTREAM* init_vgmstream_dsp_ds2(STREAMFILE* sf) {
VGMSTREAM* init_vgmstream_dsp_lucasarts_ds2(STREAMFILE* sf) {
dsp_meta dspm = {0};
size_t file_size, channel_offset;

Expand Down Expand Up @@ -1406,7 +1411,7 @@ VGMSTREAM* init_vgmstream_dsp_wiiadpcm(STREAMFILE* sf) {
goto fail;

dspm.interleave = read_u32be(0x08,sf); /* interleave offset */
/* 0x0c: NFS = 0 when RAM (2 DSP headers), interleave size when stream (2 WIIADPCM headers)
/* 0x0c: NFS = 0 when RAM (2 DSP headers), interleave size when stream (2 WIIADPCM headers)
* AB = 0 (2 WIIADPCM headers) */

dspm.channels = (dspm.interleave ? 2 : 1);
Expand Down Expand Up @@ -1556,3 +1561,84 @@ VGMSTREAM* init_vgmstream_dsp_apex(STREAMFILE* sf) {
fail:
return NULL;
}


/* DSP - Rebellion Developments (Asura engine) games */
VGMSTREAM* init_vgmstream_dsp_asura(STREAMFILE* sf) {
dsp_meta dspm = {0};
off_t start_offset;
size_t data_size;
uint8_t flag;

/* checks */
if (!is_id32be(0x00, sf, "DSP\x00") && /* GC */
!is_id32be(0x00, sf, "DSP\x01") && /* GC/Wii/WiiU */
!is_id32be(0x00, sf, "DSP\x02")) /* WiiU */
return NULL;

/* .dsp: Judge Dredd (GC)
* .wav: Judge Dredd (GC), The Simpsons Game (Wii), Sniper Elite V2 (WiiU) */
if (!check_extensions(sf, "dsp,wav,lwav"))
return NULL;

/* flag set to 0x00 so far only seen in Judge Dredd, which also uses 0x01
* at first assumed being 0 means it has a stream name at 0x48 (unlikely) */
/* flag set to 0x02 means it's ddsp-like stereo */
flag = read_u8(0x03, sf);
/* GC/Wii games are all just standard DSP with an id string */
/* Sniper Elite V2 (WiiU) added a filesize value in the header
* and has extra garbage 0xCD bytes at the end for alignment */
start_offset = 0x04;

data_size = read_u32be(start_offset, sf);
/* stereo flag should only occur on the WiiU, Wii uses .ds2 or .sfx (ngc_dsp_asura) */
if (align_size_to_block(data_size + 0x08, 0x04) == get_streamfile_size(sf) || (flag == 0x02 &&
align_size_to_block(data_size * 2 + 0x0C, 0x04) == get_streamfile_size(sf)))
start_offset = 0x08;

dspm.channels = 1;
dspm.max_channels = 1;

if (flag == 0x02) { /* channels are not aligned */
if (read_u32be(data_size + 0x08, sf) != data_size)
goto fail; /* size should match */

dspm.channels = 2;
dspm.max_channels = 2;
dspm.header_spacing = data_size + 0x04;
dspm.interleave = dspm.header_spacing;
}

dspm.header_offset = start_offset + 0x00;
dspm.start_offset = start_offset + 0x60;

dspm.meta_type = meta_DSP_ASURA;
return init_vgmstream_dsp_common(sf, &dspm);
fail:
return NULL;
}


/* .ds2 - Rebellion (Asura engine) [PDC World Championship Darts 2009 & Pro Tour (Wii)] */
VGMSTREAM* init_vgmstream_dsp_asura_ds2(STREAMFILE* sf) {
dsp_meta dspm = {0};

if (!check_extensions(sf, "ds2"))
goto fail;

dspm.channels = 2;
dspm.max_channels = 2;
dspm.interleave = 0x8000;

dspm.header_offset = 0x00;
dspm.start_offset = 0x60;

dspm.header_spacing = dspm.interleave;
dspm.interleave_first_skip = dspm.start_offset;
dspm.interleave_first = dspm.interleave - dspm.interleave_first_skip;

dspm.meta_type = meta_DSP_ASURA;
return init_vgmstream_dsp_common(sf, &dspm);
fail:
return NULL;
}
5 changes: 3 additions & 2 deletions src/meta/vag.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,9 @@ VGMSTREAM* init_vgmstream_vag(STREAMFILE* sf) {
* .xa2: Shikigami no Shiro (PS2)
* .snd: Alien Breed (Vita)
* .svg: ModernGroove: Ministry of Sound Edition (PS2)
* (extensionless): The Urbz (PS2), The Sims series (PS2) */
if (!check_extensions(sf,"vag,swag,str,vig,l,r,vas,xa2,snd,svg,"))
* (extensionless): The Urbz (PS2), The Sims series (PS2)
* .wav: Sniper Elite (PS2), The Simpsons Game (PS2/PSP) */
if (!check_extensions(sf,"vag,swag,str,vig,l,r,vas,xa2,snd,svg,,wav,lwav"))
return NULL;

file_size = get_streamfile_size(sf);
Expand Down
5 changes: 4 additions & 1 deletion src/vgmstream.c
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,7 @@ init_vgmstream_t init_vgmstream_functions[] = {
init_vgmstream_gin,
init_vgmstream_dsf,
init_vgmstream_208,
init_vgmstream_dsp_ds2,
init_vgmstream_dsp_lucasarts_ds2,
init_vgmstream_ffdl,
init_vgmstream_mus_vc,
init_vgmstream_strm_abylight,
Expand Down Expand Up @@ -527,6 +527,9 @@ init_vgmstream_t init_vgmstream_functions[] = {
init_vgmstream_cbx,
init_vgmstream_vas_rockstar,
init_vgmstream_ea_sbk,
init_vgmstream_dsp_asura,
init_vgmstream_dsp_asura_ds2,
init_vgmstream_dsp_asura_sfx,

/* lower priority metas (no clean header identity, somewhat ambiguous, or need extension/companion file to identify) */
init_vgmstream_agsc,
Expand Down
1 change: 1 addition & 0 deletions src/vgmstream_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -709,6 +709,7 @@ typedef enum {
meta_CBX,
meta_VAS_ROCKSTAR,
meta_EA_SBK,
meta_DSP_ASURA,

} meta_t;

Expand Down

0 comments on commit 69ab3d9

Please sign in to comment.