diff --git a/src/formats.c b/src/formats.c index 1057c62d..d73b4a36 100644 --- a/src/formats.c +++ b/src/formats.c @@ -146,6 +146,7 @@ static const char* extension_list[] = { "cpk", "cps", "csa", //txth/reserved [LEGO Racers 2 (PS2)] + "csb", "csmp", "cvs", //txth/reserved [Aladdin in Nasira's Revenge (PS1)] "cwav", @@ -264,6 +265,7 @@ static const char* extension_list[] = { "kces", "kcey", //fake extension/header id for .pcm (renamed, to be removed) "km9", + "kma", //txth/reserved [Dynasty Warriors 7: Empires (PS3)] "kmx", "kovs", //fake extension/header id for .kvs "kno", diff --git a/src/meta/aax.c b/src/meta/aax.c index 3e509faa..f2ae7814 100644 --- a/src/meta/aax.c +++ b/src/meta/aax.c @@ -133,91 +133,3 @@ fail: free_layout_segmented(data); return NULL; } - - -/* CRI's UTF wrapper around DSP [Sonic Colors sfx (Wii), NiGHTS: Journey of Dreams sfx (Wii)] */ -VGMSTREAM* init_vgmstream_utf_dsp(STREAMFILE* sf) { - VGMSTREAM* vgmstream = NULL; - off_t start_offset; - uint8_t loop_flag = 0, channels; - uint32_t sample_rate, num_samples, loop_start, loop_end, interleave; - uint32_t data_offset, data_size, header_offset, header_size; - utf_context* utf = NULL; - - - /* checks */ - if (!is_id32be(0x00,sf, "@UTF")) - goto fail; - - /* .aax: assumed - * (extensionless): extracted names inside csb/cpk often don't have extensions */ - if (!check_extensions(sf, "aax,")) - goto fail; - - /* .aax contains a simple UTF table with one row and various columns being header info */ - { - int rows; - const char* name; - uint32_t table_offset = 0x00; - - - utf = utf_open(sf, table_offset, &rows, &name); - if (!utf) goto fail; - - if (strcmp(name, "ADPCM_WII") != 0) - goto fail; - - if (rows != 1) - goto fail; - - if (!utf_query_u32(utf, 0, "sfreq", &sample_rate)) - goto fail; - if (!utf_query_u32(utf, 0, "nsmpl", &num_samples)) - goto fail; - if (!utf_query_u8(utf, 0, "nch", &channels)) - goto fail; - if (!utf_query_u8(utf, 0, "lpflg", &loop_flag)) /* full loops */ - goto fail; - /* for some reason data is stored before header */ - if (!utf_query_data(utf, 0, "data", &data_offset, &data_size)) - goto fail; - if (!utf_query_data(utf, 0, "header", &header_offset, &header_size)) - goto fail; - - if (channels < 1 || channels > 2) - goto fail; - if (header_size != channels * 0x60) - goto fail; - - start_offset = data_offset; - interleave = (data_size+7) / 8 * 8 / channels; - - loop_start = read_32bitBE(header_offset + 0x10, sf); - loop_end = read_32bitBE(header_offset + 0x14, sf); - } - - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channels, loop_flag); - if (!vgmstream) goto fail; - - vgmstream->sample_rate = sample_rate; - vgmstream->num_samples = num_samples; - vgmstream->loop_start_sample = dsp_nibbles_to_samples(loop_start); - vgmstream->loop_end_sample = dsp_nibbles_to_samples(loop_end) + 1; - - vgmstream->coding_type = coding_NGC_DSP; - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = interleave; - vgmstream->meta_type = meta_UTF_DSP; - - dsp_read_coefs_be(vgmstream, sf, header_offset+0x1c, 0x60); - - if (!vgmstream_open_stream(vgmstream, sf, start_offset)) - goto fail; - return vgmstream; - -fail: - close_vgmstream(vgmstream); - return NULL; -} diff --git a/src/meta/csb.c b/src/meta/csb.c index 83211750..75f79408 100644 --- a/src/meta/csb.c +++ b/src/meta/csb.c @@ -7,8 +7,7 @@ VGMSTREAM* init_vgmstream_csb(STREAMFILE* sf) { VGMSTREAM* vgmstream = NULL; STREAMFILE* temp_sf = NULL; - off_t subfile_offset; - size_t subfile_size; + uint32_t subfile_offset, subfile_size; utf_context* utf = NULL; utf_context* utf_sdl = NULL; int total_subsongs, target_subsong = sf->stream_index; @@ -17,10 +16,10 @@ VGMSTREAM* init_vgmstream_csb(STREAMFILE* sf) { /* checks */ - if (!check_extensions(sf, "csb")) - goto fail; if (!is_id32be(0x00,sf, "@UTF")) goto fail; + if (!check_extensions(sf, "csb")) + goto fail; /* .csb is an early, simpler version of .acb+awk (see acb.c) used until ~2013? * Can stream from .cpk but this only loads memory data. */ @@ -115,9 +114,7 @@ VGMSTREAM* init_vgmstream_csb(STREAMFILE* sf) { goto fail; } - //;VGM_LOG("CSB: subfile offset=%lx + %x\n", subfile_offset, subfile_size); - - + //;VGM_LOG("CSB: subfile offset=%x + %x\n", subfile_offset, subfile_size); temp_sf = setup_subfile_streamfile(sf, subfile_offset, subfile_size, "aax"); if (!temp_sf) goto fail; @@ -128,6 +125,11 @@ VGMSTREAM* init_vgmstream_csb(STREAMFILE* sf) { if (!vgmstream) goto fail; break; + case 2: /* AHX */ + vgmstream = init_vgmstream_utf_ahx(temp_sf); + if (!vgmstream) goto fail; + break; + case 4: /* ADPCM_WII */ vgmstream = init_vgmstream_utf_dsp(temp_sf); if (!vgmstream) goto fail; @@ -153,3 +155,147 @@ fail: close_vgmstream(vgmstream); return NULL; } + + +/* CRI's UTF wrapper around DSP [Sonic Colors (Wii)-sfx, NiGHTS: Journey of Dreams (Wii)-sfx] */ +VGMSTREAM* init_vgmstream_utf_dsp(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + off_t start_offset; + uint8_t loop_flag = 0, channels; + uint32_t sample_rate, num_samples, loop_start, loop_end, interleave; + uint32_t data_offset, data_size, header_offset, header_size; + utf_context* utf = NULL; + + + /* checks */ + if (!is_id32be(0x00,sf, "@UTF")) + goto fail; + + /* .aax: assumed + * (extensionless): extracted names inside csb/cpk often don't have extensions */ + if (!check_extensions(sf, "aax,")) + goto fail; + + /* contains a simple UTF table with one row and various columns being header info */ + { + int rows; + const char* name; + uint32_t table_offset = 0x00; + + + utf = utf_open(sf, table_offset, &rows, &name); + if (!utf) goto fail; + + if (strcmp(name, "ADPCM_WII") != 0) + goto fail; + + if (rows != 1) + goto fail; + + if (!utf_query_u32(utf, 0, "sfreq", &sample_rate)) + goto fail; + if (!utf_query_u32(utf, 0, "nsmpl", &num_samples)) + goto fail; + if (!utf_query_u8(utf, 0, "nch", &channels)) + goto fail; + if (!utf_query_u8(utf, 0, "lpflg", &loop_flag)) /* full loops */ + goto fail; + /* for some reason data is stored before header */ + if (!utf_query_data(utf, 0, "data", &data_offset, &data_size)) + goto fail; + if (!utf_query_data(utf, 0, "header", &header_offset, &header_size)) + goto fail; + + if (channels < 1 || channels > 2) + goto fail; + if (header_size != channels * 0x60) + goto fail; + + start_offset = data_offset; + interleave = (data_size+7) / 8 * 8 / channels; + + loop_start = read_32bitBE(header_offset + 0x10, sf); + loop_end = read_32bitBE(header_offset + 0x14, sf); + } + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channels, loop_flag); + if (!vgmstream) goto fail; + + vgmstream->sample_rate = sample_rate; + vgmstream->num_samples = num_samples; + vgmstream->loop_start_sample = dsp_nibbles_to_samples(loop_start); + vgmstream->loop_end_sample = dsp_nibbles_to_samples(loop_end) + 1; + + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = interleave; + vgmstream->meta_type = meta_UTF_DSP; + + dsp_read_coefs_be(vgmstream, sf, header_offset+0x1c, 0x60); + + if (!vgmstream_open_stream(vgmstream, sf, start_offset)) + goto fail; + utf_close(utf); + return vgmstream; + +fail: + utf_close(utf); + close_vgmstream(vgmstream); + return NULL; +} + +/* CRI's UTF wrapper around AHX [Yakuza: Dead Souls (PS3)-voices] */ +VGMSTREAM* init_vgmstream_utf_ahx(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + STREAMFILE* temp_sf = NULL; + uint32_t subfile_offset, subfile_size; + utf_context* utf = NULL; + + + /* checks */ + if (!is_id32be(0x00,sf, "@UTF")) + goto fail; + + /* .aax: assumed + * (extensionless): extracted names inside csb/cpk often don't have extensions */ + if (!check_extensions(sf, "aax,")) + goto fail; + + /* contains a simple UTF table with one row and offset+size info */ + { + int rows; + const char* name; + uint32_t table_offset = 0x00; + + utf = utf_open(sf, table_offset, &rows, &name); + if (!utf) goto fail; + + if (strcmp(name, "AHX") != 0) + goto fail; + + if (rows != 1) + goto fail; + + if (!utf_query_data(utf, 0, "data", &subfile_offset, &subfile_size)) + goto fail; + } + + //;VGM_LOG("UTF_AHX: subfile offset=%x + %x\n", subfile_offset, subfile_size); + temp_sf = setup_subfile_streamfile(sf, subfile_offset, subfile_size, "ahx"); + if (!temp_sf) goto fail; + + vgmstream = init_vgmstream_ahx(temp_sf); + if (!vgmstream) goto fail; + + utf_close(utf); + close_streamfile(temp_sf); + return vgmstream; + +fail: + utf_close(utf); + close_streamfile(temp_sf); + close_vgmstream(vgmstream); + return NULL; +} diff --git a/src/meta/meta.h b/src/meta/meta.h index fe608631..44b722bd 100644 --- a/src/meta/meta.h +++ b/src/meta/meta.h @@ -359,8 +359,6 @@ VGMSTREAM * init_vgmstream_wii_sng(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_aax(STREAMFILE *streamFile); -VGMSTREAM * init_vgmstream_utf_dsp(STREAMFILE *streamFile); - VGMSTREAM * init_vgmstream_ngc_ffcc_str(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_sat_baka(STREAMFILE *streamFile); @@ -880,7 +878,9 @@ VGMSTREAM* init_vgmstream_xssb(STREAMFILE *sf); VGMSTREAM* init_vgmstream_xma_ue3(STREAMFILE *sf); -VGMSTREAM* init_vgmstream_csb(STREAMFILE *sf); +VGMSTREAM* init_vgmstream_csb(STREAMFILE* sf); +VGMSTREAM* init_vgmstream_utf_dsp(STREAMFILE* sf); +VGMSTREAM* init_vgmstream_utf_ahx(STREAMFILE* sf); VGMSTREAM *init_vgmstream_fwse(STREAMFILE *streamFile); diff --git a/src/meta/swav.c b/src/meta/swav.c index f487e4cb..6fdaa5a4 100644 --- a/src/meta/swav.c +++ b/src/meta/swav.c @@ -16,8 +16,8 @@ VGMSTREAM* init_vgmstream_swav(STREAMFILE* sf) { if (!is_id32be(0x00,sf, "SWAV")) goto fail; - /* .swav: standard - * .adpcm: Merlin - A Servant of Two Masters (DS) */ + /* .swav: standard [found inside .sdat but SDK can create them] + * .adpcm: Merlin - A Servant of Two Masters (DS) [external] */ if (!check_extensions(sf, "swav,adpcm")) goto fail; diff --git a/src/vgmstream.c b/src/vgmstream.c index c4478df0..c284b4b4 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -525,6 +525,7 @@ VGMSTREAM* (*init_vgmstream_functions[])(STREAMFILE* sf) = { init_vgmstream_bigrp, init_vgmstream_sscf_encrypted, init_vgmstream_s_p_sth, + init_vgmstream_utf_ahx, /* lower priority metas (no clean header identity, somewhat ambiguous, or need extension/companion file to identify) */ init_vgmstream_scd_pcm,