diff --git a/src/meta/hca_keys.h b/src/meta/hca_keys.h index e77da08e..2b294df7 100644 --- a/src/meta/hca_keys.h +++ b/src/meta/hca_keys.h @@ -229,6 +229,7 @@ static const hcakey_info hcakey_list[] = { {5047159794308}, // 00000497222AAA84 // Shin Tennis no Ouji-sama: Rising Beat (iOS/Android) voices? + // UNI'S ON AIR (iOS/Android) {4902201417679}, // 0000047561F95FCF // Kai-ri-Sei Million Arthur (Vita) diff --git a/src/meta/nps.c b/src/meta/nps.c index bc89cd81..7f2a1ef5 100644 --- a/src/meta/nps.c +++ b/src/meta/nps.c @@ -1,44 +1,56 @@ #include "meta.h" #include "../coding/coding.h" -/* NPFS - found in Namco PS2/PSP games [Tekken 5 (PS2), Venus & Braves (PS2), Ridge Racer (PSP)] */ -VGMSTREAM * init_vgmstream_nps(STREAMFILE *streamFile) { +/* NPFS - found in Namco NuSound v1 games [Tekken 5 (PS2), Venus & Braves (PS2), Ridge Racer (PSP)] */ +VGMSTREAM* init_vgmstream_nps(STREAMFILE* sf) { VGMSTREAM * vgmstream = NULL; off_t start_offset; - int loop_flag, channel_count; + uint32_t channel_size; + int loop_flag, channel_count, loop_start, sample_rate; + /* checks */ - /* .nps: referenced extension (ex. Venus & Braves data files) + /* .nps: referenced extension (ex. Venus & Braves, Ridge Racer data files) * .npsf: header id (Namco Production Sound File?) */ - if ( !check_extensions(streamFile,"nps,npsf")) + if ( !check_extensions(sf,"nps,npsf")) goto fail; - if (read_32bitBE(0x00,streamFile) != 0x4E505346) /* "NPSF" */ + if (read_u32be(0x00, sf) != 0x4E505346) /* "NPSF" */ goto fail; - loop_flag = (read_32bitLE(0x14,streamFile) != 0xFFFFFFFF); - channel_count = read_32bitLE(0x0C,streamFile); - start_offset = (off_t)read_32bitLE(0x10,streamFile); + /* 0x04: version? (0x00001000 = 1.00?) */ + channel_size = read_s32le(0x08, sf); + channel_count = read_s32le(0x0C, sf); + start_offset = read_s32le(0x10, sf); /* interleave? */ + loop_start = read_s32le(0x14, sf); + sample_rate = read_s32le(0x18, sf); + /* 0x1c: volume? (0x3e8 = 1000 = max) */ + /* 0x20: flags? (varies between sound types in a game, but no clear pattern vs other games) */ + /* 0x24: flag? (0/1) */ + /* 0x28: null */ + /* 0x2c: null */ + /* 0x30: always 0x40 */ + /* 0x34: name (usually null terminated but may contain garbage) */ + /* rest: null or 0xFF until start */ + loop_flag = loop_start != -1; + /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); + vgmstream = allocate_vgmstream(channel_count, loop_flag); if (!vgmstream) goto fail; - vgmstream->channels = read_32bitLE(0x0C,streamFile); - vgmstream->sample_rate = read_32bitLE(0x18,streamFile); - vgmstream->num_samples = ps_bytes_to_samples(read_32bitLE(0x08,streamFile), 1); /* single channel data */ - if(vgmstream->loop_flag) { - vgmstream->loop_start_sample = read_32bitLE(0x14,streamFile); - vgmstream->loop_end_sample = ps_bytes_to_samples(read_32bitLE(0x08,streamFile), 1); - } + vgmstream->sample_rate = sample_rate; + vgmstream->num_samples = ps_bytes_to_samples(channel_size, 1); + vgmstream->loop_start_sample = loop_start; + vgmstream->loop_end_sample = vgmstream->num_samples; vgmstream->coding_type = coding_PSX; vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = read_32bitLE(0x04,streamFile) / 2; + vgmstream->interleave_block_size = 0x800; vgmstream->meta_type = meta_NPS; - read_string(vgmstream->stream_name,STREAM_NAME_SIZE, 0x34,streamFile); + read_string(vgmstream->stream_name, STREAM_NAME_SIZE, 0x34, sf); - if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) ) + if (!vgmstream_open_stream(vgmstream, sf, start_offset)) goto fail; return vgmstream; diff --git a/src/meta/riff.c b/src/meta/riff.c index efd6e9d8..e96939a5 100644 --- a/src/meta/riff.c +++ b/src/meta/riff.c @@ -509,20 +509,21 @@ VGMSTREAM * init_vgmstream_riff(STREAMFILE *streamFile) { } break; - case 0x4E584246: /* "NXBF" (Namco NUS v1) [R:Racing Evolution (Xbox)] */ - /* 0x00: "NXBF" again */ - /* 0x04: always 0x1000? */ + case 0x4E584246: /* "NXBF" (Namco NuSound v1) [R:Racing Evolution (Xbox)] */ + /* very similar to NUS's NPSF, but not quite like Cstr */ + /* 0x00: "NXBF" id */ + /* 0x04: version? (0x00001000 = 1.00?) */ /* 0x08: data size */ /* 0x0c: channels */ /* 0x10: null */ loop_start_nxbf = read_32bitLE(current_chunk + 0x08 + 0x14, streamFile); /* 0x18: sample rate */ - /* 0x1c: volume? */ + /* 0x1c: volume? (0x3e8 = 1000 = max) */ /* 0x20: type/flags? */ - /* 0x24: codec? */ + /* 0x24: flag? */ /* 0x28: null */ /* 0x2c: null */ - /* 0x30: type/flags? */ + /* 0x30: always 0x40 */ loop_flag = (loop_start_nxbf >= 0); break; diff --git a/src/vgmstream.c b/src/vgmstream.c index c37f3077..befa8be3 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -2445,12 +2445,12 @@ void describe_vgmstream(VGMSTREAM * vgmstream, char * desc, int length) { snprintf(temp,TEMPSIZE, "interleave: %#x bytes\n", (int32_t)vgmstream->interleave_block_size); concatn(length,desc,temp); - if (vgmstream->interleave_first_block_size) { + if (vgmstream->interleave_first_block_size && vgmstream->interleave_first_block_size != vgmstream->interleave_block_size) { snprintf(temp,TEMPSIZE, "interleave first block: %#x bytes\n", (int32_t)vgmstream->interleave_first_block_size); concatn(length,desc,temp); } - if (vgmstream->interleave_last_block_size) { + if (vgmstream->interleave_last_block_size && vgmstream->interleave_last_block_size != vgmstream->interleave_block_size) { snprintf(temp,TEMPSIZE, "interleave last block: %#x bytes\n", (int32_t)vgmstream->interleave_last_block_size); concatn(length,desc,temp); }