mirror of
https://github.com/vgmstream/vgmstream.git
synced 2025-01-22 11:43:41 +01:00
Merge pull request #1387 from EdnessP/master
Sony BNK (v3): Bank/sound name support
This commit is contained in:
commit
73a4f6b879
@ -8,7 +8,8 @@ typedef enum { PSX, PCM16, ATRAC9, HEVAG } bnk_codec;
|
|||||||
/* .BNK - Sony's SCREAM bank format [The Sly Collection (PS3), Puyo Puyo Tetris (PS4), NekoBuro: Cats Block (Vita)] */
|
/* .BNK - Sony's SCREAM bank format [The Sly Collection (PS3), Puyo Puyo Tetris (PS4), NekoBuro: Cats Block (Vita)] */
|
||||||
VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) {
|
VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) {
|
||||||
VGMSTREAM* vgmstream = NULL;
|
VGMSTREAM* vgmstream = NULL;
|
||||||
uint32_t start_offset, stream_offset, name_offset = 0;
|
char bank_name[STREAM_NAME_SIZE] /*[8]*/, stream_name[STREAM_NAME_SIZE] /*[16]*/;
|
||||||
|
uint32_t start_offset, stream_offset, bank_name_offset = 0, stream_name_offset = 0;
|
||||||
uint32_t stream_size, interleave = 0;
|
uint32_t stream_size, interleave = 0;
|
||||||
int channels = 0, loop_flag, sample_rate, big_endian;
|
int channels = 0, loop_flag, sample_rate, big_endian;
|
||||||
int32_t loop_start = 0, loop_end = 0;
|
int32_t loop_start = 0, loop_end = 0;
|
||||||
@ -96,7 +97,8 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) {
|
|||||||
uint32_t table1_suboffset, table2_suboffset;
|
uint32_t table1_suboffset, table2_suboffset;
|
||||||
uint32_t table2_entry_offset = 0, table3_entry_offset = 0;
|
uint32_t table2_entry_offset = 0, table3_entry_offset = 0;
|
||||||
int table4_entry_id = -1;
|
int table4_entry_id = -1;
|
||||||
uint32_t table4_entries_offset, table4_names_offset;
|
uint32_t table4_entry_idx, table4_entries_offset, table4_names_offset;
|
||||||
|
uint32_t entry_offset, entry_count;
|
||||||
|
|
||||||
|
|
||||||
switch(sblk_version) {
|
switch(sblk_version) {
|
||||||
@ -332,8 +334,56 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) {
|
|||||||
|
|
||||||
/* parse names */
|
/* parse names */
|
||||||
switch(sblk_version) {
|
switch(sblk_version) {
|
||||||
//case 0x03: /* different format? */
|
case 0x03:
|
||||||
|
for (i = 0; i < section_entries; i++) {
|
||||||
|
entry_offset = read_u32(table1_offset + (i * table1_entry_size) + table1_suboffset, sf);
|
||||||
|
entry_count = read_u8(table1_offset + (i * table1_entry_size) + 0x04, sf);
|
||||||
|
|
||||||
|
/* is table2_entry_offset in the range of the expected section */
|
||||||
|
if (table2_entry_offset >= entry_offset && table2_entry_offset < entry_offset + (entry_count * 0x08))
|
||||||
|
table4_entry_id = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* table4:
|
||||||
|
* 0x00: bank name (optional)
|
||||||
|
* 0x08: name section offset
|
||||||
|
* 0x0C-0x14: 3 null pointers (reserved?)
|
||||||
|
* 0x18: 32 name chunk offsets (shorts)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Name chunks are organised as
|
||||||
|
* (name[0] + name[4] + name[8] + name[12]) & 0x1F;
|
||||||
|
* and using that as the index for the chunk offsets
|
||||||
|
* name_sect_offset + (chunk_idx[result] * 0x14);
|
||||||
|
*/
|
||||||
|
if (read_u8(table4_offset, sf))
|
||||||
|
bank_name_offset = table4_offset;
|
||||||
|
|
||||||
|
table4_entries_offset = table4_offset + 0x18;
|
||||||
|
table4_names_offset = table4_offset + read_u32(table4_offset + 0x08, sf);
|
||||||
|
|
||||||
|
for (i = 0; i < 32; i++) {
|
||||||
|
table4_entry_idx = read_u16(table4_entries_offset + (i * 2), sf);
|
||||||
|
stream_name_offset = table4_names_offset + (table4_entry_idx * 0x14);
|
||||||
|
/* searches the chunk until it finds the target name/index, or breaks at empty name */
|
||||||
|
while (read_u8(stream_name_offset, sf)) {
|
||||||
|
/* in case it goes somewhere out of bounds unexpectedly */
|
||||||
|
//if ((read_u8(stream_name_offset + 0x00, sf) + read_u8(stream_name_offset + 0x04, sf) +
|
||||||
|
// read_u8(stream_name_offset + 0x08, sf) + read_u8(stream_name_offset + 0x0C, sf)) & 0x1F != i)
|
||||||
|
// goto fail;
|
||||||
|
if (read_u16(stream_name_offset + 0x10, sf) == table4_entry_id)
|
||||||
|
goto loop_break; /* to break out of the for+while loop simultaneously */
|
||||||
|
//break;
|
||||||
|
stream_name_offset += 0x14;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//goto fail; /* didn't find any valid index? */
|
||||||
|
loop_break:
|
||||||
|
break;
|
||||||
|
|
||||||
//case 0x04: /* different format? */
|
//case 0x04: /* different format? */
|
||||||
|
//case 0x05: /* different format? */
|
||||||
|
|
||||||
case 0x08:
|
case 0x08:
|
||||||
case 0x09:
|
case 0x09:
|
||||||
case 0x0d:
|
case 0x0d:
|
||||||
@ -342,7 +392,7 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) {
|
|||||||
case 0x10:
|
case 0x10:
|
||||||
/* find if this sound has an assigned name in table1 */
|
/* find if this sound has an assigned name in table1 */
|
||||||
for (i = 0; i < section_entries; i++) {
|
for (i = 0; i < section_entries; i++) {
|
||||||
uint32_t entry_offset = read_u16(table1_offset+(i*table1_entry_size)+table1_suboffset+0x00,sf);
|
entry_offset = read_u16(table1_offset+(i*table1_entry_size)+table1_suboffset+0x00,sf);
|
||||||
|
|
||||||
/* rarely (ex. Polara sfx) one name applies to multiple materials,
|
/* rarely (ex. Polara sfx) one name applies to multiple materials,
|
||||||
* from current entry_offset to next entry_offset (section offsets should be in order) */
|
* from current entry_offset to next entry_offset (section offsets should be in order) */
|
||||||
@ -358,6 +408,9 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) {
|
|||||||
/* 0x0c: table4 size */
|
/* 0x0c: table4 size */
|
||||||
/* variable: entries */
|
/* variable: entries */
|
||||||
/* variable: names (null terminated) */
|
/* variable: names (null terminated) */
|
||||||
|
if (read_u8(table4_offset, sf))
|
||||||
|
bank_name_offset = table4_offset;
|
||||||
|
|
||||||
table4_entries_offset = table4_offset + read_u32(table4_offset+0x08, sf);
|
table4_entries_offset = table4_offset + read_u32(table4_offset+0x08, sf);
|
||||||
table4_names_offset = table4_entries_offset + (0x10*section_entries);
|
table4_names_offset = table4_entries_offset + (0x10*section_entries);
|
||||||
//;VGM_LOG("BNK: t4_entries=%lx, t4_names=%lx\n", table4_entries_offset, table4_names_offset);
|
//;VGM_LOG("BNK: t4_entries=%lx, t4_names=%lx\n", table4_entries_offset, table4_names_offset);
|
||||||
@ -366,7 +419,7 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) {
|
|||||||
for (i = 0; i < section_entries; i++) {
|
for (i = 0; i < section_entries; i++) {
|
||||||
int entry_id = read_u32(table4_entries_offset+(i*0x10)+0x0c, sf);
|
int entry_id = read_u32(table4_entries_offset+(i*0x10)+0x0c, sf);
|
||||||
if (entry_id == table4_entry_id) {
|
if (entry_id == table4_entry_id) {
|
||||||
name_offset = table4_names_offset + read_u32(table4_entries_offset+(i*0x10)+0x00, sf);
|
stream_name_offset = table4_names_offset + read_u32(table4_entries_offset+(i*0x10)+0x00, sf);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -376,7 +429,7 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
//;VGM_LOG("BNK: stream_offset=%lx, stream_size=%x, name_offset=%lx\n", stream_offset, stream_size, name_offset);
|
//;VGM_LOG("BNK: stream_offset=%lx, stream_size=%x, stream_name_offset=%lx\n", stream_offset, stream_size, stream_name_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -635,9 +688,13 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) {
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (name_offset)
|
if (!bank_name_offset && stream_name_offset)
|
||||||
read_string(vgmstream->stream_name,STREAM_NAME_SIZE, name_offset,sf);
|
read_string(vgmstream->stream_name, STREAM_NAME_SIZE, stream_name_offset, sf);
|
||||||
|
else if (bank_name_offset && stream_name_offset) {
|
||||||
|
read_string(bank_name, STREAM_NAME_SIZE, bank_name_offset, sf);
|
||||||
|
read_string(stream_name, STREAM_NAME_SIZE, stream_name_offset, sf);
|
||||||
|
snprintf(vgmstream->stream_name, STREAM_NAME_SIZE, "%s/%s", bank_name, stream_name);
|
||||||
|
}
|
||||||
|
|
||||||
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
|
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -81,25 +81,24 @@ VGMSTREAM* init_vgmstream_vag(STREAMFILE* sf) {
|
|||||||
loop_flag = 0;
|
loop_flag = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x70474156: /* pGAV (little endian / stereo) [Jak 3 (PS2), Jak X (PS2)] */
|
case 0x70474156: /* pGAV (little endian / stereo) [Jak II, Jak 3, Jak X (PS2)] */
|
||||||
meta_type = meta_VAG_custom;
|
meta_type = meta_VAG_custom;
|
||||||
start_offset = 0x30;
|
start_offset = 0x30;
|
||||||
|
|
||||||
if (is_id32be(0x20,sf, "Ster")) {
|
if (is_id32be(0x2000,sf, "pGAV"))
|
||||||
channels = 2;
|
interleave = 0x2000; /* Jak II & Jak 3 interleave, includes header */
|
||||||
|
else if (is_id32be(0x1000,sf, "pGAV"))
|
||||||
|
interleave = 0x1000; /* Jak X interleave, includes header */
|
||||||
|
else
|
||||||
|
interleave = 0;
|
||||||
|
|
||||||
if (is_id32be(0x2000,sf, "pGAV"))
|
if (interleave) {
|
||||||
interleave = 0x2000; /* Jak 3 interleave, includes header */
|
channels = 2;
|
||||||
else if (is_id32be(0x1000,sf, "pGAV"))
|
|
||||||
interleave = 0x1000; /* Jak X interleave, includes header */
|
|
||||||
else
|
|
||||||
goto fail;
|
|
||||||
interleave_first = interleave - start_offset; /* interleave includes header */
|
interleave_first = interleave - start_offset; /* interleave includes header */
|
||||||
interleave_first_skip = start_offset;
|
interleave_first_skip = start_offset;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
channels = 1;
|
channels = 1;
|
||||||
interleave = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
channel_size = read_u32le(0x0C,sf) / channels;
|
channel_size = read_u32le(0x0C,sf) / channels;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user