diff --git a/Frameworks/vgmstream/vgmstream/src/formats.c b/Frameworks/vgmstream/vgmstream/src/formats.c index 946d4100e..9e8c970a3 100644 --- a/Frameworks/vgmstream/vgmstream/src/formats.c +++ b/Frameworks/vgmstream/vgmstream/src/formats.c @@ -259,6 +259,7 @@ static const char* extension_list[] = { "ktsl2asbin", "ktss", //fake extension/header id for .kns "kvs", + "kwa", "l", "l00", //txth/reserved [Disney's Dinosaur (PS2)] @@ -1344,6 +1345,8 @@ static const meta_info meta_info_list[] = { {meta_MJB_MJH, "Sony MultiStream MJH+MJB header"}, {meta_BSNF, "id Software BSNF header"}, {meta_TAC, "tri-Ace Codec header"}, + {meta_IDSP_TOSE, "TOSE .IDSP header"}, + {meta_DSP_KWA, "Kuju London .KWA header"}, }; void get_vgmstream_coding_description(VGMSTREAM* vgmstream, char* out, size_t out_size) { diff --git a/Frameworks/vgmstream/vgmstream/src/layout/blocked_ea_1snh.c b/Frameworks/vgmstream/vgmstream/src/layout/blocked_ea_1snh.c index 5e34c6158..3c7b25db0 100644 --- a/Frameworks/vgmstream/vgmstream/src/layout/blocked_ea_1snh.c +++ b/Frameworks/vgmstream/vgmstream/src/layout/blocked_ea_1snh.c @@ -1,107 +1,107 @@ -#include "layout.h" -#include "../coding/coding.h" -#include "../vgmstream.h" - -/* set up for the block at the given offset */ -void block_update_ea_1snh(off_t block_offset, VGMSTREAM * vgmstream) { - STREAMFILE* streamFile = vgmstream->ch[0].streamfile; - int i; - uint32_t block_id; - size_t block_size = 0, block_header = 0, audio_size = 0; - int32_t (*read_32bit)(off_t,STREAMFILE*) = vgmstream->codec_endian ? read_32bitBE : read_32bitLE; - - - /* EOF reads: signal we have nothing and let the layout fail */ - if (block_offset >= get_streamfile_size(streamFile)) { - vgmstream->current_block_offset = block_offset; - vgmstream->next_block_offset = block_offset; - vgmstream->current_block_samples = -1; - return; - } - - block_id = read_32bitBE(block_offset + 0x00, streamFile); - - /* BE in SAT, but one file may have both BE and LE chunks [FIFA 98 (SAT): movie LE, audio BE] */ - if (guess_endianness32bit(block_offset + 0x04, streamFile)) - block_size = read_32bitBE(block_offset + 0x04, streamFile); - else - block_size = read_32bitLE(block_offset + 0x04, streamFile); - - block_header = 0; - - if (block_id == 0x31534E68 || block_id == 0x53454144) { /* "1SNh" "SEAD" audio header */ - int is_sead = (block_id == 0x53454144); - int is_eacs = read_32bitBE(block_offset + 0x08, streamFile) == 0x45414353; - int is_zero = read_32bitBE(block_offset + 0x08, streamFile) == 0x00; - - block_header = (is_eacs || is_zero) ? 0x28 : (is_sead ? 0x14 : 0x2c); - if (block_header >= block_size) /* sometimes has audio data after header */ - block_header = 0; - } else if (block_id == 0x31534E64 || block_id == 0x534E4443) { /* "1SNd" "SNDC" audio data */ - block_header = 0x08; - } else if (block_id == 0x00000000 || block_id == 0xFFFFFFFF || block_id == 0x31534E65) { /* EOF or "1SNe" */ - vgmstream->current_block_samples = -1; - return; - } - - vgmstream->current_block_offset = block_offset; - vgmstream->next_block_offset = block_offset + block_size; - if (block_header == 0) { - /* no audio data, skip this block */ - vgmstream->current_block_samples = 0; - return; - } - - audio_size = block_size - block_header; - - /* set new channel offsets and block sizes */ - switch(vgmstream->coding_type) { - case coding_PCM8_int: - case coding_ULAW_int: - vgmstream->current_block_samples = pcm_bytes_to_samples(audio_size, vgmstream->channels, 8); - for (i=0;ichannels;i++) { - vgmstream->ch[i].offset = block_offset + block_header + i; - } - break; - - case coding_PCM16_int: - vgmstream->current_block_samples = pcm_bytes_to_samples(audio_size, vgmstream->channels, 16); - for (i=0;ichannels;i++) { - vgmstream->ch[i].offset = block_offset + block_header + (i*2); - } - break; - - case coding_PSX: - vgmstream->current_block_samples = ps_bytes_to_samples(audio_size, vgmstream->channels); - for (i=0;ichannels;i++) { - vgmstream->ch[i].offset = block_offset + block_header + i*(audio_size/vgmstream->channels); - } - break; - - case coding_DVI_IMA: - if (vgmstream->codec_config == 1) { /* ADPCM hist */ - vgmstream->current_block_samples = read_32bit(block_offset + block_header, streamFile); - - for(i = 0; i < vgmstream->channels; i++) { - off_t adpcm_offset = block_offset + block_header + 0x04; - vgmstream->ch[i].adpcm_step_index = read_32bit(adpcm_offset + i*0x04 + 0x00*vgmstream->channels, streamFile); - vgmstream->ch[i].adpcm_history1_32 = read_32bit(adpcm_offset + i*0x04 + 0x04*vgmstream->channels, streamFile); - vgmstream->ch[i].offset = adpcm_offset + 0x08*vgmstream->channels; - } - - //VGM_ASSERT(vgmstream->current_block_samples != (block_size - block_header - 0x04 - 0x08*vgmstream->channels) * 2 / vgmstream->channels, - // "EA 1SHN blocked: different expected vs block num samples at %lx\n", block_offset); - } - else { - vgmstream->current_block_samples = ima_bytes_to_samples(audio_size, vgmstream->channels); - for(i = 0; i < vgmstream->channels; i++) { - vgmstream->ch[i].offset = block_offset + block_header; - } - } - break; - - default: - break; - } - -} +#include "layout.h" +#include "../coding/coding.h" +#include "../vgmstream.h" + +/* set up for the block at the given offset */ +void block_update_ea_1snh(off_t block_offset, VGMSTREAM* vgmstream) { + STREAMFILE* sf = vgmstream->ch[0].streamfile; + int i; + uint32_t block_id; + size_t block_size = 0, block_header = 0, audio_size = 0; + int32_t (*read_32bit)(off_t,STREAMFILE*) = vgmstream->codec_endian ? read_32bitBE : read_32bitLE; + + + /* EOF reads: signal we have nothing and let the layout fail */ + if (block_offset >= get_streamfile_size(sf)) { + vgmstream->current_block_offset = block_offset; + vgmstream->next_block_offset = block_offset; + vgmstream->current_block_samples = -1; + return; + } + + block_id = read_32bitBE(block_offset + 0x00, sf); + + /* BE in SAT, but one file may have both BE and LE chunks [FIFA 98 (SAT): movie LE, audio BE] */ + if (guess_endianness32bit(block_offset + 0x04, sf)) + block_size = read_32bitBE(block_offset + 0x04, sf); + else + block_size = read_32bitLE(block_offset + 0x04, sf); + + block_header = 0; + + if (block_id == 0x31534E68 || block_id == 0x53454144) { /* "1SNh" "SEAD" audio header */ + int is_sead = (block_id == 0x53454144); + int is_eacs = read_32bitBE(block_offset + 0x08, sf) == 0x45414353; + int is_zero = read_32bitBE(block_offset + 0x08, sf) == 0x00; + + block_header = (is_eacs || is_zero) ? 0x28 : (is_sead ? 0x14 : 0x2c); + if (block_header >= block_size) /* sometimes has audio data after header */ + block_header = 0; + } else if (block_id == 0x31534E64 || block_id == 0x534E4443) { /* "1SNd" "SNDC" audio data */ + block_header = 0x08; + } else if (block_id == 0x00000000 || block_id == 0xFFFFFFFF || block_id == 0x31534E65) { /* EOF or "1SNe" */ + vgmstream->current_block_samples = -1; + return; + } + + vgmstream->current_block_offset = block_offset; + vgmstream->next_block_offset = block_offset + block_size; + if (block_header == 0) { + /* no audio data, skip this block */ + vgmstream->current_block_samples = 0; + return; + } + + audio_size = block_size - block_header; + + /* set new channel offsets and block sizes */ + switch(vgmstream->coding_type) { + case coding_PCM8_int: + case coding_ULAW_int: + vgmstream->current_block_samples = pcm_bytes_to_samples(audio_size, vgmstream->channels, 8); + for (i=0;ichannels;i++) { + vgmstream->ch[i].offset = block_offset + block_header + i; + } + break; + + case coding_PCM16_int: + vgmstream->current_block_samples = pcm_bytes_to_samples(audio_size, vgmstream->channels, 16); + for (i=0;ichannels;i++) { + vgmstream->ch[i].offset = block_offset + block_header + (i*2); + } + break; + + case coding_PSX: + vgmstream->current_block_samples = ps_bytes_to_samples(audio_size, vgmstream->channels); + for (i=0;ichannels;i++) { + vgmstream->ch[i].offset = block_offset + block_header + i*(audio_size/vgmstream->channels); + } + break; + + case coding_DVI_IMA: + if (vgmstream->codec_config == 1) { /* ADPCM hist */ + vgmstream->current_block_samples = read_32bit(block_offset + block_header, sf); + + for(i = 0; i < vgmstream->channels; i++) { + off_t adpcm_offset = block_offset + block_header + 0x04; + vgmstream->ch[i].adpcm_step_index = read_32bit(adpcm_offset + i*0x04 + 0x00*vgmstream->channels, sf); + vgmstream->ch[i].adpcm_history1_32 = read_32bit(adpcm_offset + i*0x04 + 0x04*vgmstream->channels, sf); + vgmstream->ch[i].offset = adpcm_offset + 0x08*vgmstream->channels; + } + + //VGM_ASSERT(vgmstream->current_block_samples != (block_size - block_header - 0x04 - 0x08*vgmstream->channels) * 2 / vgmstream->channels, + // "EA 1SHN blocked: different expected vs block num samples at %lx\n", block_offset); + } + else { + vgmstream->current_block_samples = ima_bytes_to_samples(audio_size, vgmstream->channels); + for(i = 0; i < vgmstream->channels; i++) { + vgmstream->ch[i].offset = block_offset + block_header; + } + } + break; + + default: + break; + } + +} diff --git a/Frameworks/vgmstream/vgmstream/src/layout/blocked_ea_sns.c b/Frameworks/vgmstream/vgmstream/src/layout/blocked_ea_sns.c index cbb90e7fa..ba7a576be 100644 --- a/Frameworks/vgmstream/vgmstream/src/layout/blocked_ea_sns.c +++ b/Frameworks/vgmstream/vgmstream/src/layout/blocked_ea_sns.c @@ -1,70 +1,70 @@ -#include "layout.h" -#include "../coding/coding.h" -#include "../vgmstream.h" - -/* EA SNS/SPS blocks */ -void block_update_ea_sns(off_t block_offset, VGMSTREAM * vgmstream) { - STREAMFILE* streamFile = vgmstream->ch[0].streamfile; - uint32_t block_id, block_size, block_samples; - off_t channel_start; - size_t channel_interleave; - int i; - - /* EOF reads: signal we have nothing and let the layout fail */ - if (block_offset >= get_streamfile_size(streamFile)) { - vgmstream->current_block_offset = block_offset; - vgmstream->next_block_offset = block_offset; - vgmstream->current_block_samples = -1; - return; - } - - /* always BE */ - block_size = read_32bitBE(block_offset + 0x00,streamFile); - - /* At 0x00(1): block flag - * - in SNS: 0x00=normal block, 0x80=last block (not mandatory) - * - in SPS: 0x48=header, 0x44=normal block, 0x45=last block (empty) */ - block_id = (block_size & 0xFF000000) >> 24; - block_size &= 0x00FFFFFF; - - if (block_id == 0x00 || block_id == 0x80 || block_id == 0x44) { - block_samples = read_32bitBE(block_offset + 0x04, streamFile); - } else { - block_samples = 0; - } - - vgmstream->current_block_offset = block_offset; - vgmstream->next_block_offset = block_offset + block_size; - vgmstream->current_block_samples = block_samples; - - /* no need to setup offsets (plus could read over filesize near EOF) */ - if (block_samples == 0) - return; - - switch (vgmstream->coding_type) { - case coding_NGC_DSP: - /* 0x04: unknown (0x00/02), 0x08: some size?, 0x34: null? */ - channel_start = read_32bitBE(block_offset + 0x08 + 0x00, streamFile); - channel_interleave = read_32bitBE(block_offset + 0x08 + 0x0c, streamFile); - /* guessed as all known EA DSP only have one block with subheader (maybe changes coefs every block?) */ - if (channel_start >= 0x40) { - dsp_read_coefs_be(vgmstream, streamFile, block_offset + 0x08 + 0x10, 0x28); - dsp_read_hist_be(vgmstream, streamFile, block_offset + 0x08 + 0x30, 0x28);//todo guessed and doesn't fix clicks in full loops - } - break; - - default: - channel_start = 0x00; - channel_interleave = 0x00; - break; - } - - for (i = 0; i < vgmstream->channels; i++) { - vgmstream->ch[i].offset = block_offset + 0x08 + channel_start + i * channel_interleave; - - /* also fix first offset (for EALayer3) */ - if (block_offset == vgmstream->ch[i].channel_start_offset) { - vgmstream->ch[i].channel_start_offset = vgmstream->ch[i].offset; - } - } -} +#include "layout.h" +#include "../coding/coding.h" +#include "../vgmstream.h" + +/* EA SNS/SPS blocks */ +void block_update_ea_sns(off_t block_offset, VGMSTREAM* vgmstream) { + STREAMFILE* sf = vgmstream->ch[0].streamfile; + uint32_t block_id, block_size, block_samples; + off_t channel_start; + size_t channel_interleave; + int i; + + /* EOF reads: signal we have nothing and let the layout fail */ + if (block_offset >= get_streamfile_size(sf)) { + vgmstream->current_block_offset = block_offset; + vgmstream->next_block_offset = block_offset; + vgmstream->current_block_samples = -1; + return; + } + + /* always BE */ + block_size = read_32bitBE(block_offset + 0x00,sf); + + /* At 0x00(1): block flag + * - in SNS: 0x00=normal block, 0x80=last block (not mandatory) + * - in SPS: 0x48=header, 0x44=normal block, 0x45=last block (empty) */ + block_id = (block_size & 0xFF000000) >> 24; + block_size &= 0x00FFFFFF; + + if (block_id == 0x00 || block_id == 0x80 || block_id == 0x44) { + block_samples = read_32bitBE(block_offset + 0x04, sf); + } else { + block_samples = 0; + } + + vgmstream->current_block_offset = block_offset; + vgmstream->next_block_offset = block_offset + block_size; + vgmstream->current_block_samples = block_samples; + + /* no need to setup offsets (plus could read over filesize near EOF) */ + if (block_samples == 0) + return; + + switch (vgmstream->coding_type) { + case coding_NGC_DSP: + /* 0x04: unknown (0x00/02), 0x08: some size?, 0x34: null? */ + channel_start = read_32bitBE(block_offset + 0x08 + 0x00, sf); + channel_interleave = read_32bitBE(block_offset + 0x08 + 0x0c, sf); + /* guessed as all known EA DSP only have one block with subheader (maybe changes coefs every block?) */ + if (channel_start >= 0x40) { + dsp_read_coefs_be(vgmstream, sf, block_offset + 0x08 + 0x10, 0x28); + dsp_read_hist_be(vgmstream, sf, block_offset + 0x08 + 0x30, 0x28);//todo guessed and doesn't fix clicks in full loops + } + break; + + default: + channel_start = 0x00; + channel_interleave = 0x00; + break; + } + + for (i = 0; i < vgmstream->channels; i++) { + vgmstream->ch[i].offset = block_offset + 0x08 + channel_start + i * channel_interleave; + + /* also fix first offset (for EALayer3) */ + if (block_offset == vgmstream->ch[i].channel_start_offset) { + vgmstream->ch[i].channel_start_offset = vgmstream->ch[i].offset; + } + } +} diff --git a/Frameworks/vgmstream/vgmstream/src/layout/blocked_ea_wve_ad10.c b/Frameworks/vgmstream/vgmstream/src/layout/blocked_ea_wve_ad10.c index 705fd49f3..4a680a35a 100644 --- a/Frameworks/vgmstream/vgmstream/src/layout/blocked_ea_wve_ad10.c +++ b/Frameworks/vgmstream/vgmstream/src/layout/blocked_ea_wve_ad10.c @@ -1,30 +1,30 @@ -#include "layout.h" -#include "../coding/coding.h" - - -/* EA style blocks, one block per channel when stereo */ -void block_update_ea_wve_ad10(off_t block_offset, VGMSTREAM * vgmstream) { - STREAMFILE* streamFile = vgmstream->ch[0].streamfile; - int i; - size_t block_size, channel_size = 0, interleave = 0; - uint32_t block_id; - - block_id = read_32bitBE(block_offset+0x00, streamFile); - block_size = read_32bitBE(block_offset+0x04, streamFile); - - /* accept "Ad10/Ad11" audio block/footer */ - if (block_id == 0x41643130 || block_id == 0x41643131) { - channel_size = block_size - 0x08; /* one block per channel */ - interleave = block_size; - block_size = block_size*vgmstream->channels; - } - /* rest could be "MDEC" video blocks with 0 size/samples */ - - vgmstream->current_block_size = channel_size; - vgmstream->current_block_offset = block_offset; - vgmstream->next_block_offset = block_offset + block_size; - - for (i = 0; i < vgmstream->channels; i++) { - vgmstream->ch[i].offset = (block_offset + 0x08) + interleave*i; - } -} +#include "layout.h" +#include "../coding/coding.h" + + +/* EA style blocks, one block per channel when stereo */ +void block_update_ea_wve_ad10(off_t block_offset, VGMSTREAM* vgmstream) { + STREAMFILE* sf = vgmstream->ch[0].streamfile; + int i; + size_t block_size, channel_size = 0, interleave = 0; + uint32_t block_id; + + block_id = read_32bitBE(block_offset+0x00, sf); + block_size = read_32bitBE(block_offset+0x04, sf); + + /* accept "Ad10/Ad11" audio block/footer */ + if (block_id == 0x41643130 || block_id == 0x41643131) { + channel_size = block_size - 0x08; /* one block per channel */ + interleave = block_size; + block_size = block_size*vgmstream->channels; + } + /* rest could be "MDEC" video blocks with 0 size/samples */ + + vgmstream->current_block_size = channel_size; + vgmstream->current_block_offset = block_offset; + vgmstream->next_block_offset = block_offset + block_size; + + for (i = 0; i < vgmstream->channels; i++) { + vgmstream->ch[i].offset = (block_offset + 0x08) + interleave*i; + } +} diff --git a/Frameworks/vgmstream/vgmstream/src/layout/blocked_ea_wve_au00.c b/Frameworks/vgmstream/vgmstream/src/layout/blocked_ea_wve_au00.c index 038cf5cc8..a216736be 100644 --- a/Frameworks/vgmstream/vgmstream/src/layout/blocked_ea_wve_au00.c +++ b/Frameworks/vgmstream/vgmstream/src/layout/blocked_ea_wve_au00.c @@ -1,29 +1,29 @@ -#include "layout.h" -#include "../coding/coding.h" - - -/* EA style blocks */ -void block_update_ea_wve_au00(off_t block_offset, VGMSTREAM * vgmstream) { - STREAMFILE* streamFile = vgmstream->ch[0].streamfile; - int i; - size_t block_size, channel_size = 0; - uint32_t block_id; - - block_id = read_32bitBE(block_offset+0x00, streamFile); - block_size = read_32bitBE(block_offset+0x04, streamFile); - - /* accept "au00/au01" audio block/footer */ - if (block_id == 0x61753030 || block_id == 0x61753031) { - /* adjusted to frame boundaries as blocks have padding */ - channel_size = ((block_size - 0x10) / vgmstream->interleave_block_size * vgmstream->interleave_block_size) / vgmstream->channels; - } - /* rest could be "MDEC" video blocks with 0 size/samples */ - - vgmstream->current_block_size = channel_size; - vgmstream->current_block_offset = block_offset; - vgmstream->next_block_offset = block_offset + block_size; - - for (i = 0; i < vgmstream->channels; i++) { - vgmstream->ch[i].offset = (block_offset + 0x10) + channel_size*i; - } -} +#include "layout.h" +#include "../coding/coding.h" + + +/* EA style blocks */ +void block_update_ea_wve_au00(off_t block_offset, VGMSTREAM * vgmstream) { + STREAMFILE* sf = vgmstream->ch[0].streamfile; + int i; + size_t block_size, channel_size = 0; + uint32_t block_id; + + block_id = read_32bitBE(block_offset+0x00, sf); + block_size = read_32bitBE(block_offset+0x04, sf); + + /* accept "au00/au01" audio block/footer */ + if (block_id == 0x61753030 || block_id == 0x61753031) { + /* adjusted to frame boundaries as blocks have padding */ + channel_size = ((block_size - 0x10) / vgmstream->interleave_block_size * vgmstream->interleave_block_size) / vgmstream->channels; + } + /* rest could be "MDEC" video blocks with 0 size/samples */ + + vgmstream->current_block_size = channel_size; + vgmstream->current_block_offset = block_offset; + vgmstream->next_block_offset = block_offset + block_size; + + for (i = 0; i < vgmstream->channels; i++) { + vgmstream->ch[i].offset = (block_offset + 0x10) + channel_size*i; + } +} diff --git a/Frameworks/vgmstream/vgmstream/src/layout/blocked_h4m.c b/Frameworks/vgmstream/vgmstream/src/layout/blocked_h4m.c index 38a17adfd..fa9ab8c55 100644 --- a/Frameworks/vgmstream/vgmstream/src/layout/blocked_h4m.c +++ b/Frameworks/vgmstream/vgmstream/src/layout/blocked_h4m.c @@ -1,83 +1,83 @@ -#include "layout.h" -#include "../coding/coding.h" - - -/* H4M video blocks with audio frames, based on h4m_audio_decode */ -void block_update_h4m(off_t block_offset, VGMSTREAM * vgmstream) { - STREAMFILE* streamFile = vgmstream->ch[0].streamfile; - int i; - size_t block_size, block_samples; - - - /* use full_block_size as counter (a bit hacky but whatevs) */ - if (vgmstream->full_block_size <= 0) { - /* new full block */ - /* 0x00: last_full_block_size */ - uint32_t full_block_size = read_32bitBE(block_offset+0x04, streamFile); - /* 0x08: vid_frame_count */ - /* 0x0c: aud_frame_count */ - /* 0x10: block_header_unk (0x01000000, except 0 in a couple of Bomberman Jetters files) */ - - vgmstream->full_block_size = full_block_size; /* not including 0x14 block header */ - block_size = 0x14; /* skip header and point to first frame in full block */ - block_samples = 0; /* signal new block_update_h4m */ - } - else { - /* new audio or video frames in the current full block */ - uint16_t frame_type = read_16bitBE(block_offset+0x00, streamFile); - uint16_t frame_format = read_16bitBE(block_offset+0x02, streamFile); - uint32_t frame_size = read_32bitBE(block_offset+0x04, streamFile); /* not including 0x08 frame header */ - - - if (frame_type == 0x00) { - /* HVQM4_AUDIO (there are more checks with frame_format but not too relevant for vgmstream) */ - uint32_t frame_samples = read_32bitBE(block_offset+0x08, streamFile); - size_t block_skip; - - if (vgmstream->codec_config & 0x80) { - frame_samples /= 2; /* ??? */ - } - - block_skip = 0x08 + 0x04; - block_size = 0x08 + frame_size; - block_samples = frame_samples; - - /* skip data from other audio tracks */ - if (vgmstream->num_streams > 1 && vgmstream->stream_index > 1) { - uint32_t audio_bytes = frame_size - 0x04; - block_skip += (audio_bytes / vgmstream->num_streams) * (vgmstream->stream_index-1); - } - - VGM_ASSERT(frame_format == 1, "H4M: unknown frame_format %x at %x\n", frame_format, (uint32_t)block_offset); - - /* pass current mode to the decoder */ - vgmstream->codec_config = (frame_format << 8) | (vgmstream->codec_config & 0xFF); - - for (i = 0; i < vgmstream->channels; i++) { - vgmstream->ch[i].offset = block_offset + block_skip; - } - } - else { - block_size = 0x08 + frame_size; - block_samples = 0; /* signal new block_update_h4m */ - } - - vgmstream->full_block_size -= block_size; - } - - /* EOF check, there is some footer/garbage at the end */ - if (block_offset == get_streamfile_size(streamFile) - || block_offset + block_size > get_streamfile_size(streamFile)) { - //block_samples = -1; /* signal end block */ - vgmstream->full_block_size = 0; - vgmstream->current_block_samples = 0; - vgmstream->current_block_offset = get_streamfile_size(streamFile); - vgmstream->next_block_offset = get_streamfile_size(streamFile); - return; - } - - vgmstream->current_block_samples = block_samples; - vgmstream->current_block_offset = block_offset; - vgmstream->next_block_offset = block_offset + block_size; -} - +#include "layout.h" +#include "../coding/coding.h" + + +/* H4M video blocks with audio frames, based on h4m_audio_decode */ +void block_update_h4m(off_t block_offset, VGMSTREAM* vgmstream) { + STREAMFILE* sf = vgmstream->ch[0].streamfile; + int i; + size_t block_size, block_samples; + + + /* use full_block_size as counter (a bit hacky but whatevs) */ + if (vgmstream->full_block_size <= 0) { + /* new full block */ + /* 0x00: last_full_block_size */ + uint32_t full_block_size = read_32bitBE(block_offset+0x04, sf); + /* 0x08: vid_frame_count */ + /* 0x0c: aud_frame_count */ + /* 0x10: block_header_unk (0x01000000, except 0 in a couple of Bomberman Jetters files) */ + + vgmstream->full_block_size = full_block_size; /* not including 0x14 block header */ + block_size = 0x14; /* skip header and point to first frame in full block */ + block_samples = 0; /* signal new block_update_h4m */ + } + else { + /* new audio or video frames in the current full block */ + uint16_t frame_type = read_16bitBE(block_offset+0x00, sf); + uint16_t frame_format = read_16bitBE(block_offset+0x02, sf); + uint32_t frame_size = read_32bitBE(block_offset+0x04, sf); /* not including 0x08 frame header */ + + + if (frame_type == 0x00) { + /* HVQM4_AUDIO (there are more checks with frame_format but not too relevant for vgmstream) */ + uint32_t frame_samples = read_32bitBE(block_offset+0x08, sf); + size_t block_skip; + + if (vgmstream->codec_config & 0x80) { + frame_samples /= 2; /* ??? */ + } + + block_skip = 0x08 + 0x04; + block_size = 0x08 + frame_size; + block_samples = frame_samples; + + /* skip data from other audio tracks */ + if (vgmstream->num_streams > 1 && vgmstream->stream_index > 1) { + uint32_t audio_bytes = frame_size - 0x04; + block_skip += (audio_bytes / vgmstream->num_streams) * (vgmstream->stream_index-1); + } + + VGM_ASSERT(frame_format == 1, "H4M: unknown frame_format %x at %x\n", frame_format, (uint32_t)block_offset); + + /* pass current mode to the decoder */ + vgmstream->codec_config = (frame_format << 8) | (vgmstream->codec_config & 0xFF); + + for (i = 0; i < vgmstream->channels; i++) { + vgmstream->ch[i].offset = block_offset + block_skip; + } + } + else { + block_size = 0x08 + frame_size; + block_samples = 0; /* signal new block_update_h4m */ + } + + vgmstream->full_block_size -= block_size; + } + + /* EOF check, there is some footer/garbage at the end */ + if (block_offset == get_streamfile_size(sf) + || block_offset + block_size > get_streamfile_size(sf)) { + //block_samples = -1; /* signal end block */ + vgmstream->full_block_size = 0; + vgmstream->current_block_samples = 0; + vgmstream->current_block_offset = get_streamfile_size(sf); + vgmstream->next_block_offset = get_streamfile_size(sf); + return; + } + + vgmstream->current_block_samples = block_samples; + vgmstream->current_block_offset = block_offset; + vgmstream->next_block_offset = block_offset + block_size; +} + diff --git a/Frameworks/vgmstream/vgmstream/src/layout/blocked_hwas.c b/Frameworks/vgmstream/vgmstream/src/layout/blocked_hwas.c index dbd4fd700..10cef5db4 100644 --- a/Frameworks/vgmstream/vgmstream/src/layout/blocked_hwas.c +++ b/Frameworks/vgmstream/vgmstream/src/layout/blocked_hwas.c @@ -1,24 +1,24 @@ -#include "layout.h" -#include "../vgmstream.h" - -/* a simple headerless block with special adpcm history handling */ -void block_update_hwas(off_t block_offset, VGMSTREAM * vgmstream) { - int i; - size_t block_size; - - /* no header */ - block_size = vgmstream->full_block_size; - - vgmstream->current_block_offset = block_offset; - vgmstream->next_block_offset = block_offset - + block_size; - vgmstream->current_block_size = block_size; - - /* reset ADPCM history every block (no header with hist or anything) */ - /* probably not 100% exact but good enough to get something decently playable (otherwise there are wild volume swings) */ - for (i=0;ichannels;i++) { - vgmstream->ch[i].adpcm_history1_32 = 0; - vgmstream->ch[i].adpcm_step_index = 0; - vgmstream->ch[i].offset = block_offset; - } -} +#include "layout.h" +#include "../vgmstream.h" + +/* a simple headerless block with special adpcm history handling */ +void block_update_hwas(off_t block_offset, VGMSTREAM* vgmstream) { + int i; + size_t block_size; + + /* no header */ + block_size = vgmstream->full_block_size; + + vgmstream->current_block_offset = block_offset; + vgmstream->next_block_offset = block_offset + + block_size; + vgmstream->current_block_size = block_size; + + /* reset ADPCM history every block (no header with hist or anything) */ + /* probably not 100% exact but good enough to get something decently playable (otherwise there are wild volume swings) */ + for (i=0;ichannels;i++) { + vgmstream->ch[i].adpcm_history1_32 = 0; + vgmstream->ch[i].adpcm_step_index = 0; + vgmstream->ch[i].offset = block_offset; + } +} diff --git a/Frameworks/vgmstream/vgmstream/src/layout/blocked_rws.c b/Frameworks/vgmstream/vgmstream/src/layout/blocked_rws.c index 7d3fee2a5..f702a4602 100644 --- a/Frameworks/vgmstream/vgmstream/src/layout/blocked_rws.c +++ b/Frameworks/vgmstream/vgmstream/src/layout/blocked_rws.c @@ -1,21 +1,20 @@ -#include "layout.h" -#include "../vgmstream.h" - -/* a simple headerless block with padding; configured in the main header */ -void block_update_rws(off_t block_offset, VGMSTREAM * vgmstream) { - int i; - size_t block_size; - size_t interleave; - - /* no header; size is configured in the main header */ - block_size = vgmstream->full_block_size; - interleave = vgmstream->interleave_block_size; - - vgmstream->current_block_offset = block_offset; - vgmstream->next_block_offset = block_offset - + block_size; - - for (i=0;ichannels;i++) { - vgmstream->ch[i].offset = block_offset + interleave*i; - } -} +#include "layout.h" +#include "../vgmstream.h" + +/* a simple headerless block with padding; configured in the main header */ +void block_update_rws(off_t block_offset, VGMSTREAM* vgmstream) { + int i; + size_t block_size; + size_t interleave; + + /* no header; size is configured in the main header */ + block_size = vgmstream->full_block_size; + interleave = vgmstream->interleave_block_size; + + vgmstream->current_block_offset = block_offset; + vgmstream->next_block_offset = block_offset + block_size; + + for (i = 0; i < vgmstream->channels; i++) { + vgmstream->ch[i].offset = block_offset + interleave * i; + } +} diff --git a/Frameworks/vgmstream/vgmstream/src/layout/blocked_sthd.c b/Frameworks/vgmstream/vgmstream/src/layout/blocked_sthd.c index 2d9d9fbcf..c42e969b2 100644 --- a/Frameworks/vgmstream/vgmstream/src/layout/blocked_sthd.c +++ b/Frameworks/vgmstream/vgmstream/src/layout/blocked_sthd.c @@ -1,22 +1,22 @@ -#include "layout.h" - -/* Dream Factory STHD blocks */ -void block_update_sthd(off_t block_offset, VGMSTREAM * vgmstream) { - STREAMFILE* streamFile = vgmstream->ch[0].streamfile; - size_t block_size, channel_size; - off_t data_offset; - int i; - - block_size = 0x800; - data_offset = read_16bitLE(block_offset + 0x04, streamFile); - channel_size = read_16bitLE(block_offset + 0x16, streamFile); - /* 0x06: num channels, 0x10: total blocks, 0x12: block count, 0x14(2): null, 0x18: block count + 1 */ - - vgmstream->current_block_offset = block_offset; - vgmstream->current_block_size = channel_size; - vgmstream->next_block_offset = block_offset + block_size; - - for (i = 0; i < vgmstream->channels; i++) { - vgmstream->ch[i].offset = block_offset + data_offset + channel_size*i; - } -} +#include "layout.h" + +/* Dream Factory STHD blocks */ +void block_update_sthd(off_t block_offset, VGMSTREAM* vgmstream) { + STREAMFILE* sf = vgmstream->ch[0].streamfile; + size_t block_size, channel_size; + off_t data_offset; + int i; + + block_size = 0x800; + data_offset = read_16bitLE(block_offset + 0x04, sf); + channel_size = read_16bitLE(block_offset + 0x16, sf); + /* 0x06: num channels, 0x10: total blocks, 0x12: block count, 0x14(2): null, 0x18: block count + 1 */ + + vgmstream->current_block_offset = block_offset; + vgmstream->current_block_size = channel_size; + vgmstream->next_block_offset = block_offset + block_size; + + for (i = 0; i < vgmstream->channels; i++) { + vgmstream->ch[i].offset = block_offset + data_offset + channel_size*i; + } +} diff --git a/Frameworks/vgmstream/vgmstream/src/layout/blocked_vgs.c b/Frameworks/vgmstream/vgmstream/src/layout/blocked_vgs.c index de5c0e5a5..bd8eef55e 100644 --- a/Frameworks/vgmstream/vgmstream/src/layout/blocked_vgs.c +++ b/Frameworks/vgmstream/vgmstream/src/layout/blocked_vgs.c @@ -1,32 +1,32 @@ -#include "layout.h" -#include "../coding/coding.h" -#include "../layout/layout.h" -#include "../vgmstream.h" - - -/* VGS multistream frames */ -void block_update_vgs(off_t block_offset, VGMSTREAM * vgmstream) { - STREAMFILE* streamFile = vgmstream->ch[0].streamfile; - size_t file_size = get_streamfile_size(vgmstream->ch[0].streamfile); - int i; - size_t channel_size = 0x10; - - - /* set offsets */ - for (i = 0; i < vgmstream->channels; i++) { - vgmstream->ch[i].offset = block_offset + channel_size*i; - } - - vgmstream->current_block_size = channel_size; - vgmstream->current_block_offset = block_offset; - vgmstream->next_block_offset = block_offset + channel_size*vgmstream->channels; - - /* skip unhandled tracks: flag can be 0x0n per track, of 0x8x for last frame */ - while (vgmstream->next_block_offset < file_size) { - if ((read_8bit(vgmstream->next_block_offset + 0x01, streamFile) & 0x0F) == 0x00) - break; - - vgmstream->next_block_offset += channel_size; - } - -} +#include "layout.h" +#include "../coding/coding.h" +#include "../layout/layout.h" +#include "../vgmstream.h" + + +/* VGS multistream frames */ +void block_update_vgs(off_t block_offset, VGMSTREAM* vgmstream) { + STREAMFILE* sf = vgmstream->ch[0].streamfile; + size_t file_size = get_streamfile_size(vgmstream->ch[0].streamfile); + int i; + size_t channel_size = 0x10; + + + /* set offsets */ + for (i = 0; i < vgmstream->channels; i++) { + vgmstream->ch[i].offset = block_offset + channel_size*i; + } + + vgmstream->current_block_size = channel_size; + vgmstream->current_block_offset = block_offset; + vgmstream->next_block_offset = block_offset + channel_size*vgmstream->channels; + + /* skip unhandled tracks: flag can be 0x0n per track, of 0x8x for last frame */ + while (vgmstream->next_block_offset < file_size) { + if ((read_8bit(vgmstream->next_block_offset + 0x01, sf) & 0x0F) == 0x00) + break; + + vgmstream->next_block_offset += channel_size; + } + +} diff --git a/Frameworks/vgmstream/vgmstream/src/layout/blocked_xa_aiff.c b/Frameworks/vgmstream/vgmstream/src/layout/blocked_xa_aiff.c index ab4811f68..4af8b9124 100644 --- a/Frameworks/vgmstream/vgmstream/src/layout/blocked_xa_aiff.c +++ b/Frameworks/vgmstream/vgmstream/src/layout/blocked_xa_aiff.c @@ -1,19 +1,19 @@ -#include "layout.h" -#include "../coding/coding.h" -#include "../vgmstream.h" - -/* parse a XA AIFF block (CD sector without the 0x18 subheader) */ -void block_update_xa_aiff(off_t block_offset, VGMSTREAM * vgmstream) { - int i; - size_t block_samples; - - block_samples = (28*8 / vgmstream->channels) * 18; /* size 0x900, 18 frames of size 0x80 with 8 subframes of 28 samples */ - - vgmstream->current_block_offset = block_offset; - vgmstream->current_block_samples = block_samples; - vgmstream->next_block_offset = block_offset + 0x914; - - for (i = 0; i < vgmstream->channels; i++) { - vgmstream->ch[i].offset = block_offset; - } -} +#include "layout.h" +#include "../coding/coding.h" +#include "../vgmstream.h" + +/* parse a XA AIFF block (CD sector without the 0x18 subheader) */ +void block_update_xa_aiff(off_t block_offset, VGMSTREAM* vgmstream) { + int i; + size_t block_samples; + + block_samples = (28*8 / vgmstream->channels) * 18; /* size 0x900, 18 frames of size 0x80 with 8 subframes of 28 samples */ + + vgmstream->current_block_offset = block_offset; + vgmstream->current_block_samples = block_samples; + vgmstream->next_block_offset = block_offset + 0x914; + + for (i = 0; i < vgmstream->channels; i++) { + vgmstream->ch[i].offset = block_offset; + } +} diff --git a/Frameworks/vgmstream/vgmstream/src/layout/blocked_xwav.c b/Frameworks/vgmstream/vgmstream/src/layout/blocked_xwav.c index ddd5dafb1..c353e292e 100644 --- a/Frameworks/vgmstream/vgmstream/src/layout/blocked_xwav.c +++ b/Frameworks/vgmstream/vgmstream/src/layout/blocked_xwav.c @@ -1,25 +1,25 @@ -#include "layout.h" -#include "../vgmstream.h" - -/* pseudo-blocks that must skip last 0x20 every 0x8000 */ -void block_update_xwav(off_t block_offset, VGMSTREAM * vgmstream) { - int i; - size_t block_size; - - /* no header */ - block_size = vgmstream->channels * 0x10; - - vgmstream->current_block_offset = block_offset; - vgmstream->next_block_offset = block_offset + block_size; - vgmstream->current_block_size = block_size / vgmstream->channels; - - if ((vgmstream->next_block_offset - 0x800) > 0 - && ((vgmstream->next_block_offset - 0x800 + 0x20) % 0x8000) == 0) { - vgmstream->next_block_offset += 0x20; - } - - - for (i=0;ichannels;i++) { - vgmstream->ch[i].offset = block_offset + 0x10*i; - } -} +#include "layout.h" +#include "../vgmstream.h" + +/* pseudo-blocks that must skip last 0x20 every 0x8000 */ +void block_update_xwav(off_t block_offset, VGMSTREAM* vgmstream) { + int i; + size_t block_size; + + /* no header */ + block_size = vgmstream->channels * 0x10; + + vgmstream->current_block_offset = block_offset; + vgmstream->next_block_offset = block_offset + block_size; + vgmstream->current_block_size = block_size / vgmstream->channels; + + if ((vgmstream->next_block_offset - 0x800) > 0 + && ((vgmstream->next_block_offset - 0x800 + 0x20) % 0x8000) == 0) { + vgmstream->next_block_offset += 0x20; + } + + + for (i = 0; i < vgmstream->channels; i++) { + vgmstream->ch[i].offset = block_offset + 0x10*i; + } +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/hca_keys.h b/Frameworks/vgmstream/vgmstream/src/meta/hca_keys.h index 96c971aba..6300ecb98 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/hca_keys.h +++ b/Frameworks/vgmstream/vgmstream/src/meta/hca_keys.h @@ -392,6 +392,9 @@ static const hcakey_info hcakey_list[] = { /* Uma Musume (Android) */ {75923756697503}, // 0000450D608C479F + /* Fantasia Re: Build (Android) */ + {8430978314079461325}, // 7500DA1B7FBA5FCD + /* D4DJ Groovy Mix (Android) [base files] */ {393410674916959300}, // 0575ACECA945A444 /* D4DJ Groovy Mix (Android) [music_* files, per-song later mixed with subkey] */ @@ -606,6 +609,15 @@ static const hcakey_info hcakey_list[] = { {0x1980271cfe0da9bd}, {0x945cdb3cf1f29e52}, {0x7f0feac6be7def5b}, + {0xc9f159f60b065f91}, + {0xdd9ca800a7123d6f}, + {0x0a90c8ebf8463d05}, + {0xa5c1adeb7919845f}, + {0x58d97e6f3d1aee86}, + {0x71b5fa3761d6726d}, + {0x1980271cfe0da9bd}, + {0x945cdb3cf1f29e52}, + {0x7f0feac6be7def5b}, /* Dragalia Lost (iOS/Android) */ {2967411924141, subkeys_dgl, sizeof(subkeys_dgl) / sizeof(subkeys_dgl[0]) }, // 000002B2E7889CAD diff --git a/Frameworks/vgmstream/vgmstream/src/meta/meta.h b/Frameworks/vgmstream/vgmstream/src/meta/meta.h index 7506315f0..049eb55ed 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/meta.h +++ b/Frameworks/vgmstream/vgmstream/src/meta/meta.h @@ -59,6 +59,8 @@ VGMSTREAM* init_vgmstream_dsp_sqex(STREAMFILE* sf); VGMSTREAM* init_vgmstream_dsp_wiivoice(STREAMFILE* sf); VGMSTREAM* init_vgmstream_dsp_wiiadpcm(STREAMFILE* sf); VGMSTREAM* init_vgmstream_dsp_cwac(STREAMFILE* sf); +VGMSTREAM* init_vgmstream_idsp_tose(STREAMFILE* sf); +VGMSTREAM* init_vgmstream_dsp_kwa(STREAMFILE* sf); VGMSTREAM * init_vgmstream_csmp(STREAMFILE *streamFile); diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ngc_dsp_std.c b/Frameworks/vgmstream/vgmstream/src/meta/ngc_dsp_std.c index 6b5155a15..9e8390f0b 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ngc_dsp_std.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ngc_dsp_std.c @@ -72,7 +72,7 @@ static int read_dsp_header_le(struct dsp_header *header, off_t offset, STREAMFIL typedef struct { /* basic config */ int little_endian; - int channel_count; + int channels; int max_channels; off_t header_offset; /* standard DSP header */ @@ -100,21 +100,21 @@ typedef struct { /* Common parser for most DSPs that are basically the same with minor changes. * Custom variants will just concatenate or interleave standard DSP headers and data, * so we make sure to validate read vs expected values, based on dsp_meta config. */ -static VGMSTREAM* init_vgmstream_dsp_common(STREAMFILE* sf, dsp_meta *dspm) { +static VGMSTREAM* init_vgmstream_dsp_common(STREAMFILE* sf, dsp_meta* dspm) { VGMSTREAM* vgmstream = NULL; int i, j; int loop_flag; struct dsp_header ch_header[COMMON_DSP_MAX_CHANNELS]; - if (dspm->channel_count > dspm->max_channels) + if (dspm->channels > dspm->max_channels) goto fail; - if (dspm->channel_count > COMMON_DSP_MAX_CHANNELS) + if (dspm->channels > COMMON_DSP_MAX_CHANNELS) goto fail; /* load standard DSP header per channel */ { - for (i = 0; i < dspm->channel_count; i++) { + for (i = 0; i < dspm->channels; i++) { if (read_dsp_header_endian(&ch_header[i], dspm->header_offset + i*dspm->header_spacing, sf, !dspm->little_endian)) { //;VGM_LOG("DSP: bad header\n"); goto fail; @@ -124,7 +124,7 @@ static VGMSTREAM* init_vgmstream_dsp_common(STREAMFILE* sf, dsp_meta *dspm) { /* fix bad/fixed value in loop start */ if (dspm->fix_loop_start) { - for (i = 0; i < dspm->channel_count; i++) { + for (i = 0; i < dspm->channels; i++) { if (ch_header[i].loop_flag) ch_header[i].loop_start_offset = 0x00; } @@ -132,7 +132,7 @@ static VGMSTREAM* init_vgmstream_dsp_common(STREAMFILE* sf, dsp_meta *dspm) { /* check type==0 and gain==0 */ { - for (i = 0; i < dspm->channel_count; i++) { + for (i = 0; i < dspm->channels; i++) { if (ch_header[i].format || ch_header[i].gain) { //;VGM_LOG("DSP: bad type/gain\n"); goto fail; @@ -142,13 +142,14 @@ static VGMSTREAM* init_vgmstream_dsp_common(STREAMFILE* sf, dsp_meta *dspm) { /* check for agreement between channels */ if (!dspm->ignore_header_agreement) { - for (i = 0; i < dspm->channel_count - 1; i++) { + for (i = 0; i < dspm->channels - 1; i++) { if (ch_header[i].sample_count != ch_header[i+1].sample_count || ch_header[i].nibble_count != ch_header[i+1].nibble_count || ch_header[i].sample_rate != ch_header[i+1].sample_rate || ch_header[i].loop_flag != ch_header[i+1].loop_flag || ch_header[i].loop_start_offset != ch_header[i+1].loop_start_offset || ch_header[i].loop_end_offset != ch_header[i+1].loop_end_offset) { + //;VGM_LOG("DSP: bad header agreement\n"); goto fail; } } @@ -156,7 +157,7 @@ static VGMSTREAM* init_vgmstream_dsp_common(STREAMFILE* sf, dsp_meta *dspm) { /* check expected initial predictor/scale */ { - int channels = dspm->channel_count; + int channels = dspm->channels; if (dspm->single_header) channels = 1; @@ -171,7 +172,7 @@ static VGMSTREAM* init_vgmstream_dsp_common(STREAMFILE* sf, dsp_meta *dspm) { /* check expected loop predictor/scale */ if (ch_header[0].loop_flag && !dspm->ignore_loop_ps) { - int channels = dspm->channel_count; + int channels = dspm->channels; if (dspm->single_header) channels = 1; @@ -209,7 +210,7 @@ static VGMSTREAM* init_vgmstream_dsp_common(STREAMFILE* sf, dsp_meta *dspm) { /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(dspm->channel_count,loop_flag); + vgmstream = allocate_vgmstream(dspm->channels,loop_flag); if (!vgmstream) goto fail; vgmstream->sample_rate = ch_header[0].sample_rate; @@ -245,9 +246,9 @@ static VGMSTREAM* init_vgmstream_dsp_common(STREAMFILE* sf, dsp_meta *dspm) { vgmstream->loop_end_sample = vgmstream->num_samples; if (dspm->single_header == 2) { /* double the samples */ - vgmstream->num_samples /= dspm->channel_count; - vgmstream->loop_start_sample /= dspm->channel_count; - vgmstream->loop_end_sample /= dspm->channel_count; + vgmstream->num_samples /= dspm->channels; + vgmstream->loop_start_sample /= dspm->channels; + vgmstream->loop_end_sample /= dspm->channels; } @@ -531,7 +532,7 @@ VGMSTREAM* init_vgmstream_ngc_dsp_stm(STREAMFILE* sf) { goto fail; /* 0x02(2): sample rate, 0x08+: channel sizes/loop offsets? */ - dspm.channel_count = read_32bitBE(0x04, sf); + dspm.channels = read_32bitBE(0x04, sf); dspm.max_channels = 2; dspm.fix_looping = 1; @@ -559,7 +560,7 @@ VGMSTREAM* init_vgmstream_ngc_mpdsp(STREAMFILE* sf) { * memory garbage created by the encoder that other games also have */ /* 0x02(2): sample rate, 0x08+: channel sizes/loop offsets? */ - dspm.channel_count = 2; + dspm.channels = 2; dspm.max_channels = 2; dspm.single_header = 2; @@ -583,7 +584,7 @@ VGMSTREAM* init_vgmstream_ngc_dsp_std_int(STREAMFILE* sf) { if (!check_extensions(sf, "dsp,mss,gcm")) goto fail; - dspm.channel_count = 2; + dspm.channels = 2; dspm.max_channels = 2; dspm.fix_looping = 1; @@ -628,7 +629,7 @@ VGMSTREAM* init_vgmstream_idsp_namco(STREAMFILE* sf) { dspm.fix_looping = 1; /* 0x04: null */ - dspm.channel_count = read_32bitBE(0x08, sf); + dspm.channels = read_32bitBE(0x08, sf); /* 0x0c: sample rate */ /* 0x10: num_samples */ /* 0x14: loop start */ @@ -657,7 +658,7 @@ VGMSTREAM* init_vgmstream_sadb(STREAMFILE* sf) { if (read_32bitBE(0x00,sf) != 0x73616462) /* "sadb" */ goto fail; - dspm.channel_count = read_8bit(0x32, sf); + dspm.channels = read_8bit(0x32, sf); dspm.max_channels = 2; dspm.header_offset = 0x80; @@ -691,7 +692,7 @@ VGMSTREAM* init_vgmstream_idsp_tt(STREAMFILE* sf) { version_sub = read_32bitBE(0x08, sf); /* extra check since there are other IDSPs */ if (version_main == 0x01 && version_sub == 0xc8) { /* Transformers: The Game (Wii) */ - dspm.channel_count = 2; + dspm.channels = 2; dspm.max_channels = 2; dspm.header_offset = 0x10; } @@ -702,7 +703,7 @@ VGMSTREAM* init_vgmstream_idsp_tt(STREAMFILE* sf) { * Lego Star Wars: The Complete Saga (Wii) * Lego Pirates of the Caribbean (Wii) * Lego Harry Potter: Years 1-4 (Wii) */ - dspm.channel_count = 2; + dspm.channels = 2; dspm.max_channels = 2; dspm.header_offset = 0x20; /* 0x10+: null */ @@ -710,7 +711,7 @@ VGMSTREAM* init_vgmstream_idsp_tt(STREAMFILE* sf) { else if (version_main == 0x03 && version_sub == 0x12c) { /* Lego The Lord of the Rings (Wii) */ /* Lego Dimensions (Wii U) */ - dspm.channel_count = read_32bitBE(0x10, sf); + dspm.channels = read_32bitBE(0x10, sf); dspm.max_channels = 2; dspm.header_offset = 0x20; /* 0x14+: "I_AM_PADDING" */ @@ -720,7 +721,7 @@ VGMSTREAM* init_vgmstream_idsp_tt(STREAMFILE* sf) { } dspm.header_spacing = 0x60; - dspm.start_offset = dspm.header_offset + 0x60 * dspm.channel_count; + dspm.start_offset = dspm.header_offset + 0x60 * dspm.channels; dspm.interleave = read_32bitBE(0x0c, sf); dspm.meta_type = meta_IDSP_TT; @@ -739,12 +740,12 @@ VGMSTREAM* init_vgmstream_idsp_nl(STREAMFILE* sf) { if (read_32bitBE(0x00,sf) != 0x49445350) /* "IDSP" */ goto fail; - dspm.channel_count = 2; + dspm.channels = 2; dspm.max_channels = 2; dspm.header_offset = 0x0c; dspm.header_spacing = 0x60; - dspm.start_offset = dspm.header_offset + dspm.header_spacing*dspm.channel_count; + dspm.start_offset = dspm.header_offset + dspm.header_spacing*dspm.channels; dspm.interleave = read_32bitBE(0x04,sf); /* 0x08: usable channel size */ { @@ -754,7 +755,7 @@ VGMSTREAM* init_vgmstream_idsp_nl(STREAMFILE* sf) { stream_size -= dspm.start_offset; if (dspm.interleave) - dspm.interleave_last = (stream_size / dspm.channel_count) % dspm.interleave; + dspm.interleave_last = (stream_size / dspm.channels) % dspm.interleave; } dspm.fix_looping = 1; @@ -777,7 +778,7 @@ VGMSTREAM* init_vgmstream_wii_wsd(STREAMFILE* sf) { if (read_32bitBE(0x08,sf) != read_32bitBE(0x0c,sf)) /* channel sizes */ goto fail; - dspm.channel_count = 2; + dspm.channels = 2; dspm.max_channels = 2; dspm.header_offset = read_32bitBE(0x00,sf); @@ -799,11 +800,11 @@ VGMSTREAM* init_vgmstream_dsp_ddsp(STREAMFILE* sf) { if (!check_extensions(sf, "ddsp")) goto fail; - dspm.channel_count = 2; + dspm.channels = 2; dspm.max_channels = 2; dspm.header_offset = 0x00; - dspm.header_spacing = (get_streamfile_size(sf) / dspm.channel_count); + dspm.header_spacing = (get_streamfile_size(sf) / dspm.channels); dspm.start_offset = 0x60; dspm.interleave = dspm.header_spacing; @@ -823,12 +824,12 @@ VGMSTREAM* init_vgmstream_wii_was(STREAMFILE* sf) { if (read_32bitBE(0x00,sf) != 0x69535753) /* "iSWS" */ goto fail; - dspm.channel_count = read_32bitBE(0x08,sf); + dspm.channels = read_32bitBE(0x08,sf); dspm.max_channels = 2; dspm.header_offset = 0x08 + read_32bitBE(0x04,sf); dspm.header_spacing = 0x60; - dspm.start_offset = dspm.header_offset + dspm.channel_count*dspm.header_spacing; + dspm.start_offset = dspm.header_offset + dspm.channels*dspm.header_spacing; dspm.interleave = read_32bitBE(0x10,sf); dspm.meta_type = meta_WII_WAS; @@ -845,7 +846,7 @@ VGMSTREAM* init_vgmstream_dsp_str_ig(STREAMFILE* sf) { if (!check_extensions(sf, "str")) goto fail; - dspm.channel_count = 2; + dspm.channels = 2; dspm.max_channels = 2; dspm.header_offset = 0x00; @@ -867,13 +868,13 @@ VGMSTREAM* init_vgmstream_dsp_xiii(STREAMFILE* sf) { if (!check_extensions(sf, "dsp")) goto fail; - dspm.channel_count = 2; + dspm.channels = 2; dspm.max_channels = 2; dspm.fix_loop_start = 1; /* loop flag but strange loop start instead of 0 (maybe shouldn't loop) */ dspm.header_offset = 0x00; dspm.header_spacing = 0x60; - dspm.start_offset = dspm.header_offset + dspm.header_spacing * dspm.channel_count; + dspm.start_offset = dspm.header_offset + dspm.header_spacing * dspm.channels; dspm.interleave = 0x08; dspm.meta_type = meta_DSP_XIII; @@ -897,12 +898,12 @@ VGMSTREAM* init_vgmstream_dsp_ndp(STREAMFILE* sf) { goto fail; /* 0x0c: sample rate */ - dspm.channel_count = read_u32le(0x10,sf); + dspm.channels = read_u32le(0x10,sf); dspm.max_channels = 2; dspm.header_offset = 0x18; dspm.header_spacing = 0x60; - dspm.start_offset = dspm.header_offset + dspm.channel_count*dspm.header_spacing; + dspm.start_offset = dspm.header_offset + dspm.channels*dspm.header_spacing; dspm.interleave = 0x04; dspm.ignore_loop_ps = 1; /* some files loops from 0 but loop ps is null */ @@ -925,13 +926,13 @@ VGMSTREAM* init_vgmstream_dsp_cabelas(STREAMFILE* sf) { goto fail; /* sfx are mono, but standard dsp will catch them tho */ - dspm.channel_count = read_32bitBE(0x00,sf) == read_32bitBE(0x60,sf) ? 2 : 1; + dspm.channels = read_32bitBE(0x00,sf) == read_32bitBE(0x60,sf) ? 2 : 1; dspm.max_channels = 2; - dspm.force_loop = (dspm.channel_count > 1); + dspm.force_loop = (dspm.channels > 1); dspm.header_offset = 0x00; dspm.header_spacing = 0x60; - dspm.start_offset = dspm.header_offset + dspm.channel_count*dspm.header_spacing; + dspm.start_offset = dspm.header_offset + dspm.channels*dspm.header_spacing; dspm.interleave = 0x10; dspm.meta_type = meta_DSP_CABELAS; @@ -950,12 +951,12 @@ VGMSTREAM* init_vgmstream_ngc_dsp_aaap(STREAMFILE* sf) { if (read_32bitBE(0x00,sf) != 0x41414170) /* "AAAp" */ goto fail; - dspm.channel_count = read_16bitBE(0x06,sf); + dspm.channels = read_16bitBE(0x06,sf); dspm.max_channels = 2; dspm.header_offset = 0x08; dspm.header_spacing = 0x60; - dspm.start_offset = dspm.header_offset + dspm.channel_count*dspm.header_spacing; + dspm.start_offset = dspm.header_offset + dspm.channels*dspm.header_spacing; dspm.interleave = (uint16_t)read_16bitBE(0x04,sf); dspm.meta_type = meta_NGC_DSP_AAAP; @@ -996,13 +997,13 @@ VGMSTREAM* init_vgmstream_dsp_dspw(STREAMFILE* sf) { data_size -= 0x20; /* header size */ /* 0x10: loop start, 0x14: loop end, 0x1c: num_samples */ - dspm.channel_count = read_32bitBE(0x18, sf); + dspm.channels = read_32bitBE(0x18, sf); dspm.max_channels = 6; /* 6ch in Monster Hunter 3 Ultimate */ dspm.header_offset = 0x20; - dspm.header_spacing = data_size / dspm.channel_count; + dspm.header_spacing = data_size / dspm.channels; dspm.start_offset = dspm.header_offset + 0x60; - dspm.interleave = data_size / dspm.channel_count; + dspm.interleave = data_size / dspm.channels; dspm.meta_type = meta_DSP_DSPW; return init_vgmstream_dsp_common(sf, &dspm); @@ -1021,7 +1022,7 @@ VGMSTREAM* init_vgmstream_ngc_dsp_iadp(STREAMFILE* sf) { if (read_32bitBE(0x00,sf) != 0x69616470) /* "iadp" */ goto fail; - dspm.channel_count = read_32bitBE(0x04,sf); + dspm.channels = read_32bitBE(0x04,sf); dspm.max_channels = 2; dspm.header_offset = 0x20; @@ -1046,12 +1047,12 @@ VGMSTREAM* init_vgmstream_dsp_mcadpcm(STREAMFILE* sf) { //if (read_32bitLE(0x08,sf) != read_32bitLE(0x10,sf)) // goto fail; - dspm.channel_count = read_32bitLE(0x00,sf); + dspm.channels = read_32bitLE(0x00,sf); dspm.max_channels = 2; dspm.little_endian = 1; dspm.header_offset = read_32bitLE(0x04,sf); - dspm.header_spacing = dspm.channel_count == 1 ? 0 : + dspm.header_spacing = dspm.channels == 1 ? 0 : read_32bitLE(0x0c,sf) - dspm.header_offset; /* channel 2 start, only with Nch */ dspm.start_offset = dspm.header_offset + 0x60; dspm.interleave = dspm.header_spacing; @@ -1073,14 +1074,14 @@ VGMSTREAM* init_vgmstream_dsp_switch_audio(STREAMFILE* sf) { /* manual double header test */ if (read_32bitLE(0x00, sf) == read_32bitLE(get_streamfile_size(sf) / 2, sf)) - dspm.channel_count = 2; + dspm.channels = 2; else - dspm.channel_count = 1; + dspm.channels = 1; dspm.max_channels = 2; dspm.little_endian = 1; dspm.header_offset = 0x00; - dspm.header_spacing = get_streamfile_size(sf) / dspm.channel_count; + dspm.header_spacing = get_streamfile_size(sf) / dspm.channels; dspm.start_offset = dspm.header_offset + 0x60; dspm.interleave = dspm.header_spacing; @@ -1104,13 +1105,13 @@ VGMSTREAM* init_vgmstream_dsp_sps_n1(STREAMFILE* sf) { if ((uint16_t)read_16bitLE(0x08,sf) != read_32bitLE(0x24,sf)) /* header has various repeated values */ goto fail; - dspm.channel_count = 1; + dspm.channels = 1; dspm.max_channels = 1; dspm.little_endian = 1; dspm.header_offset = 0x1c; dspm.header_spacing = 0x60; - dspm.start_offset = dspm.header_offset + dspm.header_spacing*dspm.channel_count; + dspm.start_offset = dspm.header_offset + dspm.header_spacing*dspm.channels; dspm.interleave = 0; dspm.meta_type = meta_DSP_VAG; @@ -1127,12 +1128,12 @@ VGMSTREAM* init_vgmstream_dsp_itl_ch(STREAMFILE* sf) { if (!check_extensions(sf, "itl")) goto fail; - dspm.channel_count = 2; + dspm.channels = 2; dspm.max_channels = 2; dspm.header_offset = 0x00; dspm.header_spacing = 0x60; - dspm.start_offset = dspm.header_offset + dspm.header_spacing*dspm.channel_count; + dspm.start_offset = dspm.header_offset + dspm.header_spacing*dspm.channels; dspm.interleave = 0x23C0; dspm.fix_looping = 1; @@ -1157,13 +1158,13 @@ VGMSTREAM* init_vgmstream_dsp_adpy(STREAMFILE* sf) { /* 0x08: some size? */ /* 0x0c: null */ - dspm.channel_count = read_16bitLE(0x06,sf); + dspm.channels = read_16bitLE(0x06,sf); dspm.max_channels = 2; dspm.little_endian = 1; dspm.header_offset = 0x10; dspm.header_spacing = 0x60; - dspm.start_offset = dspm.header_offset + dspm.header_spacing*dspm.channel_count; + dspm.start_offset = dspm.header_offset + dspm.header_spacing*dspm.channels; dspm.interleave = 0x08; dspm.meta_type = meta_DSP_ADPY; @@ -1186,7 +1187,7 @@ VGMSTREAM* init_vgmstream_dsp_adpx(STREAMFILE* sf) { if (read_32bitLE(0x04,sf) != read_32bitLE(0x08,sf) && read_32bitLE(0x0c,sf) != 0) goto fail; - dspm.channel_count = 2; + dspm.channels = 2; dspm.max_channels = 2; dspm.little_endian = 1; @@ -1220,7 +1221,7 @@ VGMSTREAM* init_vgmstream_dsp_ds2(STREAMFILE* sf) { if (channel_offset < file_size / 2 || channel_offset > file_size) /* just to make sure */ goto fail; - dspm.channel_count = 2; + dspm.channels = 2; dspm.max_channels = 2; dspm.single_header = 1; @@ -1247,14 +1248,14 @@ VGMSTREAM* init_vgmstream_dsp_itl(STREAMFILE* sf) { goto fail; stream_size = get_streamfile_size(sf); - dspm.channel_count = 2; + dspm.channels = 2; dspm.max_channels = 2; dspm.start_offset = 0x60; dspm.interleave = 0x10000; dspm.interleave_first_skip = dspm.start_offset; dspm.interleave_first = dspm.interleave - dspm.interleave_first_skip; - dspm.interleave_last = (stream_size / dspm.channel_count) % dspm.interleave; + dspm.interleave_last = (stream_size / dspm.channels) % dspm.interleave; dspm.header_offset = 0x00; dspm.header_spacing = dspm.interleave; @@ -1276,12 +1277,12 @@ VGMSTREAM* init_vgmstream_dsp_sqex(STREAMFILE* sf) { if (read_u32be(0x00,sf) != 0x00000000) goto fail; - dspm.channel_count = read_u32le(0x04,sf); + dspm.channels = read_u32le(0x04,sf); dspm.header_offset = read_u32le(0x08,sf); /* 0x0c: channel size */ dspm.start_offset = dspm.header_offset + 0x60; - if (dspm.channel_count > 1) { + if (dspm.channels > 1) { dspm.interleave = read_u32le(0x10,sf) - dspm.header_offset; dspm.header_spacing = dspm.interleave; } @@ -1309,14 +1310,14 @@ VGMSTREAM* init_vgmstream_dsp_wiivoice(STREAMFILE* sf) { read_u32be(0x04,sf) != 0x6F696365) /* "oice" */ goto fail; - dspm.channel_count = 1; + dspm.channels = 1; dspm.max_channels = 1; dspm.header_offset = read_u32be(0x08,sf); /* 0x10: file size */ /* 0x14: data size */ dspm.header_spacing = 0x60; - dspm.start_offset = dspm.header_offset + dspm.header_spacing*dspm.channel_count; + dspm.start_offset = dspm.header_offset + dspm.header_spacing*dspm.channels; dspm.meta_type = meta_DSP_WIIVOICE; return init_vgmstream_dsp_common(sf, &dspm); @@ -1341,7 +1342,7 @@ VGMSTREAM* init_vgmstream_dsp_wiiadpcm(STREAMFILE* sf) { } /* 0x0c: 0 when RAM (2 DSP headers), interleave size when stream (2 WIIADPCM headers) */ - dspm.channel_count = (dspm.interleave ? 2 : 1); + dspm.channels = (dspm.interleave ? 2 : 1); dspm.max_channels = 2; dspm.header_offset = 0x10; @@ -1366,7 +1367,7 @@ VGMSTREAM* init_vgmstream_dsp_cwac(STREAMFILE* sf) { if (!is_id32be(0x00,sf, "CWAC")) goto fail; - dspm.channel_count = read_u16be(0x04,sf); + dspm.channels = read_u16be(0x04,sf); dspm.header_offset = read_u32be(0x08,sf); dspm.interleave = read_u32be(0x0c,sf) - dspm.header_offset; @@ -1379,3 +1380,67 @@ VGMSTREAM* init_vgmstream_dsp_cwac(STREAMFILE* sf) { fail: return NULL; } + + +/* .idsp - interleaved dsp [Harvest Moon: Another Wonderful Life (GC)] */ +VGMSTREAM* init_vgmstream_idsp_tose(STREAMFILE* sf) { + dsp_meta dspm = {0}; + uint32_t blocks; + + /* checks */ + if (!check_extensions(sf, "idsp")) + goto fail; + if (read_u32be(0x00,sf) != 0) + goto fail; + + dspm.max_channels = 4; /* mainly stereo */ + + /* 0x04: format? */ + dspm.channels = read_u16be(0x06,sf); + dspm.interleave = read_u32be(0x08,sf); + blocks = read_u32be(0x0c,sf); + + dspm.header_offset = 0x40; + dspm.header_spacing = 0x60; + dspm.start_offset = dspm.header_offset + dspm.header_spacing * dspm.channels; + + if (dspm.start_offset + dspm.interleave * dspm.channels * blocks != get_streamfile_size(sf)) + goto fail; + + dspm.meta_type = meta_IDSP_TOSE; + return init_vgmstream_dsp_common(sf, &dspm); +fail: + return NULL; +} + + +/* .KWA - interleaved dsp [Knight Wars prototype (Wii)] */ +VGMSTREAM* init_vgmstream_dsp_kwa(STREAMFILE* sf) { + dsp_meta dspm = {0}; + + /* checks */ + /* .dsp: assumed */ + if (!check_extensions(sf, "kwa")) + goto fail; + if (read_u32be(0x00,sf) != 3) + goto fail; + + dspm.max_channels = 4; + + dspm.channels = read_u32be(0x04,sf); + dspm.interleave = read_u32be(0x0c,sf); + + dspm.header_offset = 0x20; + dspm.header_spacing = dspm.interleave; + dspm.start_offset = dspm.header_offset + 0x60; + + dspm.interleave_first_skip = 0x60; + dspm.interleave_first = dspm.interleave - dspm.interleave_first_skip; + + dspm.ignore_header_agreement = 1; /* Reus_2.kwa has a few more samples in channels 3+4 */ + + dspm.meta_type = meta_DSP_KWA; + return init_vgmstream_dsp_common(sf, &dspm); +fail: + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/txth.c b/Frameworks/vgmstream/vgmstream/src/meta/txth.c index 4d3b0dbdc..93474ac5b 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/txth.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/txth.c @@ -1552,7 +1552,7 @@ static int parse_name_table(txth_header* txth, char* name_list) { txt_offset = 0x03; } - /* in case of repeated name_lists */ + /* in case of repeated name tables */ memset(txth->name_values, 0, sizeof(txth->name_values)); txth->name_values_count = 0; @@ -1572,7 +1572,7 @@ static int parse_name_table(txth_header* txth, char* name_list) { txt_offset += bytes_read; /* get key/val (ignores lead spaces, stops at space/comment/separator) */ - ok = sscanf(line, " %[^ \t#:] : %[^\t#\r\n] ", key,val); + ok = sscanf(line, " %[^\t#:] : %[^\t#\r\n] ", key,val); if (ok != 2) { /* ignore line if no key=val (comment or garbage) */ /* try again with " (empty): (val)) */ key[0] = '\0'; diff --git a/Frameworks/vgmstream/vgmstream/src/streamfile.c b/Frameworks/vgmstream/vgmstream/src/streamfile.c index 84530db1b..9dd5e736e 100644 --- a/Frameworks/vgmstream/vgmstream/src/streamfile.c +++ b/Frameworks/vgmstream/vgmstream/src/streamfile.c @@ -1154,8 +1154,8 @@ STREAMFILE* read_filemap_file(STREAMFILE* sf, int file_num) { txt_offset += bytes_read; - /* get key/val (ignores lead spaces, stops at space/comment/separator) */ - ok = sscanf(line, " %[^ \t#:] : %[^\t#\r\n] ", key, val); + /* get key/val (ignores lead/trailing spaces, stops at comment/separator) */ + ok = sscanf(line, " %[^\t#:] : %[^\t#\r\n] ", key, val); if (ok != 2) { /* ignore line if no key=val (comment or garbage) */ continue; } diff --git a/Frameworks/vgmstream/vgmstream/src/vgmstream.c b/Frameworks/vgmstream/vgmstream/src/vgmstream.c index 79fc614ef..0942da714 100644 --- a/Frameworks/vgmstream/vgmstream/src/vgmstream.c +++ b/Frameworks/vgmstream/vgmstream/src/vgmstream.c @@ -523,6 +523,8 @@ VGMSTREAM* (*init_vgmstream_functions[])(STREAMFILE* sf) = { init_vgmstream_mzrt_v1, init_vgmstream_bsnf, init_vgmstream_tac, + init_vgmstream_idsp_tose, + init_vgmstream_dsp_kwa, /* lowest priority metas (should go after all metas, and TXTH should go before raw formats) */ init_vgmstream_txth, /* proper parsers should supersede TXTH, once added */ diff --git a/Frameworks/vgmstream/vgmstream/src/vgmstream.h b/Frameworks/vgmstream/vgmstream/src/vgmstream.h index 9cb5dfdeb..4dde34e59 100644 --- a/Frameworks/vgmstream/vgmstream/src/vgmstream.h +++ b/Frameworks/vgmstream/vgmstream/src/vgmstream.h @@ -762,6 +762,8 @@ typedef enum { meta_MJB_MJH, meta_BSNF, meta_TAC, + meta_IDSP_TOSE, + meta_DSP_KWA, } meta_t; /* standard WAVEFORMATEXTENSIBLE speaker positions */