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 <= 0 || channels > 16) goto fail; /* arbitrary max */
|
||||||
if (channels < data->channels_per_frame) goto fail;
|
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 */
|
/* init streams */
|
||||||
|
@ -259,6 +259,7 @@ static const char* extension_list[] = {
|
|||||||
"rak",
|
"rak",
|
||||||
"ras",
|
"ras",
|
||||||
"raw",
|
"raw",
|
||||||
|
"rda", //FFmpeg/reserved [Rhythm Destruction (PC)]
|
||||||
"rkv",
|
"rkv",
|
||||||
"rnd",
|
"rnd",
|
||||||
"rof",
|
"rof",
|
||||||
@ -294,7 +295,7 @@ static const char* extension_list[] = {
|
|||||||
"scd",
|
"scd",
|
||||||
"sck",
|
"sck",
|
||||||
"sd9",
|
"sd9",
|
||||||
"sdf",
|
"sdf", //txth/reserved [Gummy Bears Mini Golf (3DS), Agent Hugo - Lemoon Twist (PS2)]
|
||||||
"sdt",
|
"sdt",
|
||||||
"seg",
|
"seg",
|
||||||
"sf0",
|
"sf0",
|
||||||
|
@ -257,8 +257,9 @@ VGMSTREAM * init_vgmstream_riff(STREAMFILE *streamFile) {
|
|||||||
/* .lwav: to avoid hijacking .wav, .xwav: fake for Xbox games (unneded anymore) */
|
/* .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),
|
/* .da: The Great Battle VI (PS), .cd: Exector (PS), .med: Psi Ops (PC), .snd: Layton Brothers (iOS/Android),
|
||||||
* .adx: Remember11 (PC) sfx
|
* .adx: Remember11 (PC) sfx
|
||||||
* .adp: Headhunter (DC) */
|
* .adp: Headhunter (DC)
|
||||||
if ( check_extensions(streamFile, "wav,lwav,xwav,da,cd,med,snd,adx,adp") ) {
|
* .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") ) {
|
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;
|
if (!txth->interleave) return 0;
|
||||||
return bytes / txth->interleave * 256 * txth->channels;
|
return bytes / txth->interleave * 256 * txth->channels;
|
||||||
|
|
||||||
/* untested */
|
|
||||||
case IMA:
|
case IMA:
|
||||||
case DVI_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:
|
case SDX2:
|
||||||
return bytes;
|
return bytes;
|
||||||
case AICA:
|
|
||||||
return bytes * 2 / txth->channels;
|
|
||||||
case NGC_DTK:
|
case NGC_DTK:
|
||||||
return bytes / 32 * 28; /* always stereo? */
|
return bytes / 32 * 28; /* always stereo? */
|
||||||
case APPLE_IMA4:
|
case APPLE_IMA4:
|
||||||
|
@ -159,12 +159,9 @@ VGMSTREAM * init_vgmstream_ubi_lyn(STREAMFILE *streamFile) {
|
|||||||
mpeg_custom_config cfg = {0};
|
mpeg_custom_config cfg = {0};
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (read_32bitLE(start_offset+0x00,streamFile) != 2) /* id? */
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
cfg.interleave = read_32bitLE(start_offset+0x04,streamFile);
|
cfg.interleave = read_32bitLE(start_offset+0x04,streamFile);
|
||||||
cfg.chunk_size = read_32bitLE(start_offset+0x08,streamFile);
|
cfg.chunk_size = read_32bitLE(start_offset+0x08,streamFile); /* frame size (not counting MPEG padding?) */
|
||||||
/* 0x08: frame size, 0x0c: frame per interleave, 0x10: samples per frame */
|
/* 0x00: id? (2=Tintin, 3=Michael Jackson), 0x0c: frame per interleave, 0x10: samples per frame */
|
||||||
|
|
||||||
/* skip seek tables and find actual start */
|
/* skip seek tables and find actual start */
|
||||||
start_offset += 0x14;
|
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 {
|
typedef struct {
|
||||||
int little_endian;
|
int little_endian;
|
||||||
int version;
|
int version;
|
||||||
@ -70,6 +70,7 @@ typedef struct {
|
|||||||
} xwb_header;
|
} xwb_header;
|
||||||
|
|
||||||
static void get_name(char * buf, size_t maxsize, int target_subsong, xwb_header * xwb, STREAMFILE *streamFile);
|
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) */
|
/* 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 */
|
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.block_align == 0x60 || xwb.block_align == 0x98 || xwb.block_align == 0xc0) ) { /* standard ATRAC3 blocks sizes */
|
||||||
xwb.codec = ATRAC3; /* standard ATRAC3 blocks sizes; no other way to identify (other than reading data) */
|
/* 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)
|
/* 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 */
|
* ignore for now and just calc max samples */
|
||||||
xwb.num_samples = atrac3_bytes_to_samples(xwb.stream_size, xwb.block_align * xwb.channels);
|
xwb.num_samples = atrac3_bytes_to_samples(xwb.stream_size, xwb.block_align * xwb.channels);
|
||||||
}
|
}
|
||||||
|
else if (xwb.codec == OGG) {
|
||||||
/* Oddworld: Stranger's Wrath iOS/Android format hijack, with changed meanings */
|
/* Oddworld: Stranger's Wrath (iOS/Android) */
|
||||||
if (xwb.codec == OGG) {
|
|
||||||
xwb.num_samples = xwb.stream_size / (2 * xwb.channels); /* uncompressed bytes */
|
xwb.num_samples = xwb.stream_size / (2 * xwb.channels); /* uncompressed bytes */
|
||||||
xwb.stream_size = xwb.loop_end;
|
xwb.stream_size = xwb.loop_end;
|
||||||
xwb.loop_start = 0;
|
xwb.loop_start = 0;
|
||||||
xwb.loop_end = 0;
|
xwb.loop_end = 0;
|
||||||
}
|
}
|
||||||
|
else if (xwb.version == XACT3_0_MAX && xwb.codec == XMA2
|
||||||
/* Stardew Valley (Switch) format hijack, with full interleaved DSPs (including headers) */
|
&& xwb.bits_per_sample == 0x01 && xwb.block_align == 0x04
|
||||||
if (xwb.version == XACT3_0_MAX && xwb.codec == XMA2
|
&& xwb.data_size == 0x55951c1c) { /* some kind of id? */
|
||||||
&& xwb.bits_per_sample == 0x01 && xwb.block_align == 0x04 && xwb.data_size == 0x55951c1c) {
|
/* Stardew Valley (Switch), full interleaved DSPs (including headers) */
|
||||||
xwb.codec = DSP;
|
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 */
|
/* test loop after the above fixes */
|
||||||
xwb.loop_flag = (xwb.loop_end > 0 || xwb.loop_end_sample > xwb.loop_start)
|
xwb.loop_flag = (xwb.loop_end > 0 || xwb.loop_end_sample > xwb.loop_start)
|
||||||
&& !(xwb.entry_flags & WAVEBANKENTRY_FLAGS_IGNORELOOP);
|
&& !(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 */
|
/* 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 */
|
/* some low-q rips don't remove padding, relax validation a bit */
|
||||||
if (xwb.data_offset + xwb.data_size > get_streamfile_size(streamFile))
|
if (xwb.data_offset + xwb.data_size > get_streamfile_size(streamFile))
|
||||||
goto fail;
|
goto fail;
|
||||||
@ -516,7 +524,6 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) {
|
|||||||
vgmstream->layout_type = layout_none;
|
vgmstream->layout_type = layout_none;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
case DSP: { /* Stardew Valley (Switch) extension */
|
case DSP: { /* Stardew Valley (Switch) extension */
|
||||||
@ -530,6 +537,30 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) {
|
|||||||
break;
|
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:
|
default:
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
@ -546,6 +577,30 @@ fail:
|
|||||||
return NULL;
|
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