mirror of
https://github.com/vgmstream/vgmstream.git
synced 2025-01-17 23:36:41 +01:00
commit
311eeebc1b
@ -147,7 +147,8 @@ mpeg_codec_data *init_mpeg_custom(STREAMFILE *streamFile, off_t start_offset, co
|
||||
|
||||
if (channels <= 0 || channels > 16) goto fail; /* arbitrary max */
|
||||
if (channels < data->channels_per_frame) goto fail;
|
||||
if (data->default_buffer_size > 0x8000) goto fail;
|
||||
//todo simplify/unify XVAG/P3D/SCD/LYN and just feed arbitrary chunks to the decoder
|
||||
if (data->default_buffer_size > 0x10000) goto fail; /* max for some Ubi Lyn */
|
||||
|
||||
|
||||
/* init streams */
|
||||
|
@ -259,6 +259,7 @@ static const char* extension_list[] = {
|
||||
"rak",
|
||||
"ras",
|
||||
"raw",
|
||||
"rda", //FFmpeg/reserved [Rhythm Destruction (PC)]
|
||||
"rkv",
|
||||
"rnd",
|
||||
"rof",
|
||||
@ -294,7 +295,7 @@ static const char* extension_list[] = {
|
||||
"scd",
|
||||
"sck",
|
||||
"sd9",
|
||||
"sdf",
|
||||
"sdf", //txth/reserved [Gummy Bears Mini Golf (3DS), Agent Hugo - Lemoon Twist (PS2)]
|
||||
"sdt",
|
||||
"seg",
|
||||
"sf0",
|
||||
|
@ -257,8 +257,9 @@ VGMSTREAM * init_vgmstream_riff(STREAMFILE *streamFile) {
|
||||
/* .lwav: to avoid hijacking .wav, .xwav: fake for Xbox games (unneded anymore) */
|
||||
/* .da: The Great Battle VI (PS), .cd: Exector (PS), .med: Psi Ops (PC), .snd: Layton Brothers (iOS/Android),
|
||||
* .adx: Remember11 (PC) sfx
|
||||
* .adp: Headhunter (DC) */
|
||||
if ( check_extensions(streamFile, "wav,lwav,xwav,da,cd,med,snd,adx,adp") ) {
|
||||
* .adp: Headhunter (DC)
|
||||
* .xss: Spider-Man The Movie (Xbox) */
|
||||
if ( check_extensions(streamFile, "wav,lwav,xwav,da,cd,med,snd,adx,adp,xss") ) {
|
||||
;
|
||||
}
|
||||
else if ( check_extensions(streamFile, "mwv") ) {
|
||||
|
@ -687,13 +687,15 @@ static int get_bytes_to_samples(txth_header * txth, uint32_t bytes) {
|
||||
if (!txth->interleave) return 0;
|
||||
return bytes / txth->interleave * 256 * txth->channels;
|
||||
|
||||
/* untested */
|
||||
case IMA:
|
||||
case DVI_IMA:
|
||||
return ima_bytes_to_samples(bytes, txth->channels);
|
||||
case AICA:
|
||||
return aica_bytes_to_samples(bytes, txth->channels);
|
||||
|
||||
/* untested */
|
||||
case SDX2:
|
||||
return bytes;
|
||||
case AICA:
|
||||
return bytes * 2 / txth->channels;
|
||||
case NGC_DTK:
|
||||
return bytes / 32 * 28; /* always stereo? */
|
||||
case APPLE_IMA4:
|
||||
|
@ -159,12 +159,9 @@ VGMSTREAM * init_vgmstream_ubi_lyn(STREAMFILE *streamFile) {
|
||||
mpeg_custom_config cfg = {0};
|
||||
int i;
|
||||
|
||||
if (read_32bitLE(start_offset+0x00,streamFile) != 2) /* id? */
|
||||
goto fail;
|
||||
|
||||
cfg.interleave = read_32bitLE(start_offset+0x04,streamFile);
|
||||
cfg.chunk_size = read_32bitLE(start_offset+0x08,streamFile);
|
||||
/* 0x08: frame size, 0x0c: frame per interleave, 0x10: samples per frame */
|
||||
cfg.chunk_size = read_32bitLE(start_offset+0x08,streamFile); /* frame size (not counting MPEG padding?) */
|
||||
/* 0x00: id? (2=Tintin, 3=Michael Jackson), 0x0c: frame per interleave, 0x10: samples per frame */
|
||||
|
||||
/* skip seek tables and find actual start */
|
||||
start_offset += 0x14;
|
||||
|
@ -26,7 +26,7 @@ static const int wma_block_align_index[17] = {
|
||||
};
|
||||
|
||||
|
||||
typedef enum { PCM, XBOX_ADPCM, MS_ADPCM, XMA1, XMA2, WMA, XWMA, ATRAC3, OGG, DSP } xact_codec;
|
||||
typedef enum { PCM, XBOX_ADPCM, MS_ADPCM, XMA1, XMA2, WMA, XWMA, ATRAC3, OGG, DSP, ATRAC9_RIFF } xact_codec;
|
||||
typedef struct {
|
||||
int little_endian;
|
||||
int version;
|
||||
@ -70,6 +70,7 @@ typedef struct {
|
||||
} xwb_header;
|
||||
|
||||
static void get_name(char * buf, size_t maxsize, int target_subsong, xwb_header * xwb, STREAMFILE *streamFile);
|
||||
static STREAMFILE* setup_subfile_streamfile(STREAMFILE *streamFile, off_t subfile_offset, size_t subfile_size, const char* fake_ext);
|
||||
|
||||
|
||||
/* XWB - XACT Wave Bank (Microsoft SDK format for XBOX/XBOX360/Windows) */
|
||||
@ -293,37 +294,44 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) {
|
||||
}
|
||||
}
|
||||
|
||||
/* Techland's bizarre format hijack (Nail'd, Sniper: Ghost Warrior PS3).
|
||||
* Somehow they used XWB + ATRAC3 in their PS3 games, very creative */
|
||||
|
||||
/* format hijacks from creative devs, using non-official codecs */
|
||||
if (xwb.version == XACT_TECHLAND && xwb.codec == XMA2 /* XACT_TECHLAND used in their X360 games too */
|
||||
&& (xwb.block_align == 0x60 || xwb.block_align == 0x98 || xwb.block_align == 0xc0) ) {
|
||||
xwb.codec = ATRAC3; /* standard ATRAC3 blocks sizes; no other way to identify (other than reading data) */
|
||||
&& (xwb.block_align == 0x60 || xwb.block_align == 0x98 || xwb.block_align == 0xc0) ) { /* standard ATRAC3 blocks sizes */
|
||||
/* Techland ATRAC3 [Nail'd (PS3), Sniper: Ghost Warrior (PS3)] */
|
||||
xwb.codec = ATRAC3;
|
||||
|
||||
/* num samples uses a modified entry_info format (maybe skip samples + samples? sfx use the standard format)
|
||||
* ignore for now and just calc max samples */
|
||||
xwb.num_samples = atrac3_bytes_to_samples(xwb.stream_size, xwb.block_align * xwb.channels);
|
||||
}
|
||||
|
||||
/* Oddworld: Stranger's Wrath iOS/Android format hijack, with changed meanings */
|
||||
if (xwb.codec == OGG) {
|
||||
else if (xwb.codec == OGG) {
|
||||
/* Oddworld: Stranger's Wrath (iOS/Android) */
|
||||
xwb.num_samples = xwb.stream_size / (2 * xwb.channels); /* uncompressed bytes */
|
||||
xwb.stream_size = xwb.loop_end;
|
||||
xwb.loop_start = 0;
|
||||
xwb.loop_end = 0;
|
||||
}
|
||||
|
||||
/* Stardew Valley (Switch) format hijack, with full interleaved DSPs (including headers) */
|
||||
if (xwb.version == XACT3_0_MAX && xwb.codec == XMA2
|
||||
&& xwb.bits_per_sample == 0x01 && xwb.block_align == 0x04 && xwb.data_size == 0x55951c1c) {
|
||||
else if (xwb.version == XACT3_0_MAX && xwb.codec == XMA2
|
||||
&& xwb.bits_per_sample == 0x01 && xwb.block_align == 0x04
|
||||
&& xwb.data_size == 0x55951c1c) { /* some kind of id? */
|
||||
/* Stardew Valley (Switch), full interleaved DSPs (including headers) */
|
||||
xwb.codec = DSP;
|
||||
}
|
||||
else if (xwb.version == XACT3_0_MAX && xwb.codec == XMA2
|
||||
&& xwb.bits_per_sample == 0x01 && xwb.block_align == 0x04
|
||||
&& xwb.data_size == 0x4e0a1000) { /* some kind of id? */
|
||||
/* Stardew Valley (Vita), standard RIFF with ATRAC9 */
|
||||
xwb.codec = ATRAC9_RIFF;
|
||||
}
|
||||
|
||||
|
||||
/* test loop after the above fixes */
|
||||
xwb.loop_flag = (xwb.loop_end > 0 || xwb.loop_end_sample > xwb.loop_start)
|
||||
&& !(xwb.entry_flags & WAVEBANKENTRY_FLAGS_IGNORELOOP);
|
||||
|
||||
/* Oddworld OGG the data_size value is size of uncompressed bytes instead; DSP uses some id/config as value */
|
||||
if (xwb.codec != OGG && xwb.codec != DSP) {
|
||||
if (xwb.codec != OGG && xwb.codec != DSP && xwb.codec != ATRAC9_RIFF) {
|
||||
/* some low-q rips don't remove padding, relax validation a bit */
|
||||
if (xwb.data_offset + xwb.data_size > get_streamfile_size(streamFile))
|
||||
goto fail;
|
||||
@ -516,7 +524,6 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) {
|
||||
vgmstream->layout_type = layout_none;
|
||||
break;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
case DSP: { /* Stardew Valley (Switch) extension */
|
||||
@ -530,6 +537,30 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) {
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef VGM_USE_ATRAC9
|
||||
case ATRAC9_RIFF: { /* Stardew Valley (Vita) extension */
|
||||
VGMSTREAM *temp_vgmstream = NULL;
|
||||
STREAMFILE *temp_streamFile = NULL;
|
||||
|
||||
/* standard RIFF, use subfile (seems doesn't use xwb loops) */
|
||||
VGM_ASSERT(xwb.loop_flag, "XWB: RIFF ATRAC9 loop flag found\n");
|
||||
|
||||
temp_streamFile = setup_subfile_streamfile(streamFile, xwb.stream_offset,xwb.stream_size, "at9");
|
||||
if (!temp_streamFile) goto fail;
|
||||
|
||||
temp_vgmstream = init_vgmstream_riff(temp_streamFile);
|
||||
close_streamfile(temp_streamFile);
|
||||
if (!temp_vgmstream) goto fail;
|
||||
|
||||
temp_vgmstream->num_streams = vgmstream->num_streams;
|
||||
temp_vgmstream->stream_size = vgmstream->stream_size;
|
||||
temp_vgmstream->meta_type = vgmstream->meta_type;
|
||||
|
||||
close_vgmstream(vgmstream);
|
||||
return temp_vgmstream;
|
||||
}
|
||||
#endif
|
||||
|
||||
default:
|
||||
goto fail;
|
||||
}
|
||||
@ -546,6 +577,30 @@ fail:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* ****************************************************************************** */
|
||||
|
||||
static STREAMFILE* setup_subfile_streamfile(STREAMFILE *streamFile, off_t subfile_offset, size_t subfile_size, const char* fake_ext) {
|
||||
STREAMFILE *temp_streamFile = NULL, *new_streamFile = NULL;
|
||||
|
||||
/* setup subfile */
|
||||
new_streamFile = open_wrap_streamfile(streamFile);
|
||||
if (!new_streamFile) goto fail;
|
||||
temp_streamFile = new_streamFile;
|
||||
|
||||
new_streamFile = open_clamp_streamfile(temp_streamFile, subfile_offset,subfile_size);
|
||||
if (!new_streamFile) goto fail;
|
||||
temp_streamFile = new_streamFile;
|
||||
|
||||
new_streamFile = open_fakename_streamfile(temp_streamFile, NULL,fake_ext);
|
||||
if (!new_streamFile) goto fail;
|
||||
temp_streamFile = new_streamFile;
|
||||
|
||||
return temp_streamFile;
|
||||
|
||||
fail:
|
||||
close_streamfile(temp_streamFile);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* ****************************************************************************** */
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user