diff --git a/src/libvgmstream.vcproj b/src/libvgmstream.vcproj index 8fb8e091..6af1b153 100644 --- a/src/libvgmstream.vcproj +++ b/src/libvgmstream.vcproj @@ -556,6 +556,10 @@ RelativePath=".\meta\cri_utf.c" > + + diff --git a/src/libvgmstream.vcxproj b/src/libvgmstream.vcxproj index 5e2841b6..05622f46 100644 --- a/src/libvgmstream.vcxproj +++ b/src/libvgmstream.vcxproj @@ -268,6 +268,7 @@ + diff --git a/src/libvgmstream.vcxproj.filters b/src/libvgmstream.vcxproj.filters index 81d3200d..4e827b52 100644 --- a/src/libvgmstream.vcxproj.filters +++ b/src/libvgmstream.vcxproj.filters @@ -355,6 +355,9 @@ meta\Source Files + + meta\Source Files + meta\Source Files diff --git a/src/meta/aax.c b/src/meta/aax.c index 4e3511f6..542899f5 100644 --- a/src/meta/aax.c +++ b/src/meta/aax.c @@ -21,7 +21,9 @@ VGMSTREAM * init_vgmstream_aax(STREAMFILE *streamFile) { /* checks */ - if (!check_extensions(streamFile, "aax")) + /* .aax: often with extension (with either HCA or AAX tables) + * (extensionless): sometimes without [PES 2013 (PC)] */ + if (!check_extensions(streamFile, "aax,")) goto fail; if (read_32bitBE(0x00,streamFile) != 0x40555446) /* "@UTF" */ goto fail; @@ -143,8 +145,8 @@ VGMSTREAM * init_vgmstream_utf_dsp(STREAMFILE *streamFile) { /* checks */ - /* aax: assumed - * (extensionless): default (extracted names inside csb/cpk don't have extensions) */ + /* .aax: assumed + * (extensionless): extracted names inside csb/cpk often don't have extensions */ if (!check_extensions(streamFile, "aax,")) goto fail; if (read_32bitBE(0x00,streamFile) != 0x40555446) /* "@UTF" */ diff --git a/src/meta/csb.c b/src/meta/csb.c new file mode 100644 index 00000000..bd429694 --- /dev/null +++ b/src/meta/csb.c @@ -0,0 +1,151 @@ +#include "meta.h" +#include "../coding/coding.h" +#include "cri_utf.h" + + +/* CSB (Cue Sheet Binary?) - CRI container of memory audio, often together with a .cpk wave bank */ +VGMSTREAM * init_vgmstream_csb(STREAMFILE *streamFile) { + VGMSTREAM *vgmstream = NULL; + STREAMFILE *temp_sf = NULL; + off_t subfile_offset; + size_t subfile_size; + utf_context *utf = NULL; + utf_context *utf_sdl = NULL; + int total_subsongs, target_subsong = streamFile->stream_index; + int8_t fmt = 0; + const char *stream_name; + + + /* checks */ + if (!check_extensions(streamFile, "csb")) + goto fail; + if (read_32bitBE(0x00,streamFile) != 0x40555446) /* "@UTF" */ + 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. */ + { + int rows, sdl_rows, sdl_row, i; + const char *name; + const char *row_name; + const char *sdl_name; + uint32_t sdl_offset, sdl_size, offset, size; + uint32_t table_offset = 0x00; + int8_t ttype; + int found = 0; + + + utf = utf_open(streamFile, table_offset, &rows, &name); + if (!utf) goto fail; + + if (strcmp(name, "TBLCSB") != 0) + goto fail; + + /* each TBLCSB row has a name and subtable with actual things: + * - INFO (TBL_INFO): table type/version + * - CUE (TBLCUE): base cues + * - SYNTH (TBLSYN): cue configs + * - SOUND_ELEMENT (TBLSDL): audio info/data (usually AAX) + * - ISAAC (TBLISC): 3D config + * - VOICE_LIMIT_GROUP (TBLVLG): system info? + * Subtable can be empty but must still appear (0 rows). + */ + sdl_row = 3; /* should use fixed order */ + + /* get SOUND_ELEMENT and table */ + if (!utf_query_string(utf, sdl_row, "name", &row_name) || strcmp(row_name, "SOUND_ELEMENT") != 0) + goto fail; + if (!utf_query_s8(utf, sdl_row, "ttype", &ttype) || ttype != 4) + goto fail; + if (!utf_query_data(utf, sdl_row, "utf", &sdl_offset, &sdl_size)) + goto fail; + + utf_sdl = utf_open(streamFile, sdl_offset, &sdl_rows, &sdl_name); + if (!utf_sdl) goto fail; + + if (strcmp(sdl_name, "TBLSDL") != 0) + goto fail; + + total_subsongs = 0; + if (target_subsong == 0) target_subsong = 1; + + /* get target subsong */ + for (i = 0; i < sdl_rows; i++) { + int8_t stmflg; + + if (!utf_query_s8(utf_sdl, i, "stmflg", &stmflg)) + goto fail; + + /* only internal data for now (when 1 this refers to a .cpk subfile probably using "name", has size 0) */ + if (stmflg) + continue; + + total_subsongs++; + if (total_subsongs == target_subsong && !found) { + + if (!utf_query_string(utf_sdl, i, "name", &stream_name)) + goto fail; + if (!utf_query_data(utf_sdl, i, "data", &offset, &size)) + goto fail; + if (!utf_query_s8(utf_sdl, i, "fmt", &fmt)) + goto fail; + VGM_LOG("fmt=%i\n", fmt); + /* also nch/sfreq/nsmpl info */ + + found = 1; + } + } + + if (!found) goto fail; + if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail; +VGM_LOG("5: %x, %x\n", sdl_offset, offset); + subfile_offset = /*sdl_offset +*/ offset; + subfile_size = size; + + /* column exists but can be empty */ + if (subfile_size == 0) + goto fail; + } + + ;VGM_LOG("CSB: subfile offset=%lx + %x\n", subfile_offset, subfile_size); + + + temp_sf = setup_subfile_streamfile(streamFile, subfile_offset, subfile_size, "aax"); + if (!temp_sf) goto fail; + + VGM_LOG("7: %i\n", fmt); + + switch(fmt) { + case 0: /* AAX */ + case 6: /* HCA */ + vgmstream = init_vgmstream_aax(temp_sf); + if (!vgmstream) goto fail; + break; + + case 4: /* ADPCM_WII */ + vgmstream = init_vgmstream_utf_dsp(temp_sf); + if (!vgmstream) goto fail; + break; + + default: + VGM_LOG("CSB: unknown format %i\n", fmt); + goto fail; + } + + VGM_LOG("8\n"); + + vgmstream->num_streams = total_subsongs; + strncpy(vgmstream->stream_name, stream_name, STREAM_NAME_SIZE-1); + + utf_close(utf); + utf_close(utf_sdl); + close_streamfile(temp_sf); + return vgmstream; + +fail: + utf_close(utf); + utf_close(utf_sdl); + close_streamfile(temp_sf); + close_vgmstream(vgmstream); + return NULL; +} diff --git a/src/meta/meta.h b/src/meta/meta.h index 45c22ca5..e9f5aa75 100644 --- a/src/meta/meta.h +++ b/src/meta/meta.h @@ -875,4 +875,6 @@ VGMSTREAM* init_vgmstream_xssb(STREAMFILE *sf); VGMSTREAM* init_vgmstream_xma_ue3(STREAMFILE *sf); +VGMSTREAM* init_vgmstream_csb(STREAMFILE *sf); + #endif /*_META_H*/ diff --git a/src/vgmstream.c b/src/vgmstream.c index 71a95f90..22be6fb5 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -485,6 +485,7 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = { init_vgmstream_isb, init_vgmstream_xssb, init_vgmstream_xma_ue3, + init_vgmstream_csb, /* 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 */