diff --git a/src/formats.c b/src/formats.c index 0c3fc0d3..5b388a19 100644 --- a/src/formats.c +++ b/src/formats.c @@ -806,7 +806,7 @@ static const meta_info meta_info_list[] = { {meta_OTM, "Otomedius OTM Header"}, {meta_CSTM, "Nintendo 3DS CSTM Header"}, {meta_FSTM, "Nintendo Wii U FSTM Header"}, - {meta_G1L, "Tecmo Koei G1L Header"}, + {meta_KT_WIIBGM, "Koei Tecmo WiiBGM Header"}, {meta_3DS_IDSP, "Nintendo IDSP Header"}, {meta_WIIU_BTSND, "Wii U Menu Boot Sound"}, {meta_MCA, "Capcom MCA Header"}, diff --git a/src/meta/g1l.c b/src/meta/g1l.c index 7e659fe6..7ea4efe3 100644 --- a/src/meta/g1l.c +++ b/src/meta/g1l.c @@ -1,118 +1,106 @@ #include "meta.h" #include "../util.h" -// Koei Tecmo G1L, found in the Warriors games -VGMSTREAM * init_vgmstream_g1l(STREAMFILE *streamFile) { +#include "../coding/coding.h" + +static VGMSTREAM * init_vgmstream_kt_wiibgm_offset(STREAMFILE *streamFile, off_t offset); + +/* Koei Tecmo G1L - pack format, sometimes containing a single stream + * + * It probably makes more sense to extract it externally, it's here mainly for Hyrule Warriors */ +VGMSTREAM * init_vgmstream_kt_g1l(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; + int type, num_streams, target_stream = 1; + off_t stream_offset; + int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL; - coding_t coding_type; - - /*off_t head_offset;*/ - - int channel_count; - int loop_flag; - off_t start_offset; - - /* check extension, case insensitive */ - streamFile->get_name(streamFile, filename, sizeof(filename)); - if (strcasecmp("g1l", filename_extension(filename))) + if (!check_extensions(streamFile,"g1l")) goto fail; - /* check header */ - if ((uint32_t)read_32bitBE(0, streamFile) != 0x47314C5F) /* "G1L_" */ - goto fail; - if ((uint32_t)read_32bitBE(0x1c, streamFile) != 0x57696942) /* "WiiB" */ + if ((read_32bitBE(0x0, streamFile) != 0x47314C5F /* "G1L_" (BE) */ + || read_32bitBE(0x0, streamFile) != 0x5F4C3147) /* "_L1G" (LE) */ + && read_32bitBE(0x4, streamFile) != 0x30303030) /* "0000" (version?) */ goto fail; - /* check type details */ - if (read_32bitBE(0x30, streamFile) > 0) - loop_flag = 1; - else - loop_flag = 0; - channel_count = read_8bit(0x3f, streamFile); - - - coding_type = coding_NGC_DSP; - - - if (channel_count < 1) goto fail; - - /* build the VGMSTREAM */ - - vgmstream = allocate_vgmstream(channel_count, loop_flag); - if (!vgmstream) goto fail; - - /* fill in the vital statistics */ - vgmstream->num_samples = read_32bitBE(0x2c, streamFile); - vgmstream->sample_rate = (uint16_t)read_16bitBE(0x42, streamFile); - /* channels and loop flag are set by allocate_vgmstream */ - - vgmstream->loop_start_sample = read_32bitBE(0x30, streamFile); - vgmstream->loop_end_sample = vgmstream->num_samples; - - - vgmstream->coding_type = coding_type; - if (channel_count == 1) - vgmstream->layout_type = layout_none; - - vgmstream->layout_type = layout_interleave_byte; - - vgmstream->meta_type = meta_G1L; - - vgmstream->interleave_block_size = 0x1; - - if (vgmstream->coding_type == coding_NGC_DSP) { - off_t coef_offset = 0x78; - - int i, j; - int coef_spacing = 0x60; - - for (j = 0; jchannels; j++) { - for (i = 0; i<16; i++) { - vgmstream->ch[j].adpcm_coef[i] = read_16bitBE(coef_offset + j*coef_spacing + i * 2, streamFile); - } - } - - start_offset = 0x81c; + if (read_32bitBE(0x0, streamFile) == 0x47314C5F ) { + read_32bit = read_32bitBE; + } else { + read_32bit = read_32bitLE; } -#ifdef VGM_USE_MAIATRAC3PLUS - else if (vgmstream->coding_type == coding_AT3plus) { - start_offset = 0xc4; - } -#endif - else - goto fail; + /* 0x08 filesize */ + /* 0x0c first file offset (same as 0x18) */ + type = read_32bit(0x10,streamFile); + num_streams = read_32bit(0x14,streamFile); + if (target_stream < 0 || target_stream > num_streams) goto fail; + if (target_stream==0) target_stream = 1; + stream_offset = read_32bit(0x18 + 0x4*(target_stream-1),streamFile); + /* filesize = stream_offset - stream_next_offset*/ + switch(type) { /* type may not be correct */ + case 0x09: /* DSP (WiiBGM) from Hyrule Warriors (Wii U) */ + vgmstream = init_vgmstream_kt_wiibgm_offset(streamFile, stream_offset); + break; + case 0x01: /* ATRAC3plus (RIFF) from One Piece Pirate Warriors 2 (PS3) */ + case 0x00: /* OGG (KOVS) from Romance Three Kindgoms 13 (PC)*/ + case 0x0A: /* OGG (KOVS) from Dragon Quest Heroes (PC)*/ + default: + goto fail; + } - /* open the file for reading by each channel */ - { - int i; - for (i = 0; ilayout_type == layout_interleave_shortblock) - vgmstream->ch[i].streamfile = streamFile->open(streamFile, filename, - vgmstream->interleave_block_size); - else if (vgmstream->layout_type == layout_interleave) - vgmstream->ch[i].streamfile = streamFile->open(streamFile, filename, - STREAMFILE_DEFAULT_BUFFER_SIZE); - else - vgmstream->ch[i].streamfile = streamFile->open(streamFile, filename, - 0x1000); - - if (!vgmstream->ch[i].streamfile) goto fail; - - vgmstream->ch[i].channel_start_offset = - vgmstream->ch[i].offset = - start_offset + i*vgmstream->interleave_block_size; - } - } return vgmstream; - - /* clean up anything we may have opened */ fail: - if (vgmstream) close_vgmstream(vgmstream); + close_vgmstream(vgmstream); return NULL; } + +/* Koei Tecmo "WiiBGM" DSP format - found in Hyrule Warriors, Romance of the Three Kingdoms 12 */ +VGMSTREAM * init_vgmstream_kt_wiibgm(STREAMFILE *streamFile) { + return init_vgmstream_kt_wiibgm_offset(streamFile, 0x0); +} + +static VGMSTREAM * init_vgmstream_kt_wiibgm_offset(STREAMFILE *streamFile, off_t offset) { + VGMSTREAM * vgmstream = NULL; + int loop_flag, channel_count; + off_t start_offset; + + if (!check_extensions(streamFile,"g1l,dsp")) + goto fail; + + if (read_32bitBE(offset+0x0, streamFile) != 0x57696942 && /* "WiiB" */ + read_32bitBE(offset+0x4, streamFile) != 0x474D0000) /* "GM\0\0" */ + goto fail; + + /* check type details */ + loop_flag = read_32bitBE(offset+0x14, streamFile) > 0; + channel_count = read_8bit(offset+0x23, streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count, loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->num_samples = read_32bitBE(offset+0x10, streamFile); + vgmstream->sample_rate = (uint16_t)read_16bitBE(offset+0x26, streamFile); + vgmstream->loop_start_sample = read_32bitBE(offset+0x14, streamFile); + vgmstream->loop_end_sample = vgmstream->num_samples; + + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->layout_type = layout_interleave_byte; + vgmstream->meta_type = meta_KT_WIIBGM; + + vgmstream->interleave_block_size = 0x1; + + dsp_read_coefs_be(vgmstream,streamFile, offset+0x5C, 0x60); + start_offset = offset+0x800; + + if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) + goto fail; + return vgmstream; + + fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/src/meta/meta.h b/src/meta/meta.h index b92eac68..c9f25671 100644 --- a/src/meta/meta.h +++ b/src/meta/meta.h @@ -650,7 +650,8 @@ VGMSTREAM * init_vgmstream_bfstm(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_bfwav(STREAMFILE* streamFile); -VGMSTREAM * init_vgmstream_g1l(STREAMFILE* streamFile); +VGMSTREAM * init_vgmstream_kt_g1l(STREAMFILE* streamFile); +VGMSTREAM * init_vgmstream_kt_wiibgm(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_mca(STREAMFILE* streamFile); diff --git a/src/vgmstream.c b/src/vgmstream.c index 83c4be32..3e2af74c 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -331,7 +331,8 @@ VGMSTREAM * (*init_vgmstream_fcns[])(STREAMFILE *streamFile) = { init_vgmstream_otm, init_vgmstream_bcstm, init_vgmstream_3ds_idsp, - init_vgmstream_g1l, + init_vgmstream_kt_g1l, + init_vgmstream_kt_wiibgm, init_vgmstream_hca, init_vgmstream_ps2_svag_snk, init_vgmstream_ps2_vds_vdm, diff --git a/src/vgmstream.h b/src/vgmstream.h index 5352fba5..049ec8a3 100644 --- a/src/vgmstream.h +++ b/src/vgmstream.h @@ -582,7 +582,7 @@ typedef enum { meta_CSTM, // Nintendo 3DS CSTM meta_FSTM, // Nintendo Wii U FSTM meta_3DS_IDSP, // Nintendo 3DS/Wii U IDSP - meta_G1L, // Tecmo Koei G1L + meta_KT_WIIBGM, // Koei Tecmo WiiBGM meta_MCA, // Capcom MCA "MADP" meta_XB3D_ADX, // Xenoblade Chronicles 3D ADX meta_HCA, /* CRI HCA */