mirror of
https://github.com/vgmstream/vgmstream.git
synced 2025-02-21 04:48:21 +01:00
Fix .srsa names
This commit is contained in:
parent
0c90f4842b
commit
b88d1914ae
@ -12,8 +12,12 @@ typedef struct {
|
||||
int target_subsong;
|
||||
ktsr_codec codec;
|
||||
|
||||
uint32_t audio_id;
|
||||
int platform;
|
||||
int format;
|
||||
uint32_t sound_id;
|
||||
uint32_t sound_flags;
|
||||
uint32_t config_flags;
|
||||
|
||||
int channels;
|
||||
int sample_rate;
|
||||
@ -99,7 +103,8 @@ static VGMSTREAM* init_vgmstream_ktsr_internal(STREAMFILE* sf, bool is_srsa) {
|
||||
|
||||
/* KTSR can be a memory file (ktsl2asbin), streams (ktsl2stbin) and global config (ktsl2gcbin)
|
||||
* This accepts .ktsl2asbin with internal data or external streams as subsongs.
|
||||
* Hashes are meant to be read LE, but here are BE for easier comparison. Some info from KTSR.bt */
|
||||
* Hashes are meant to be read LE, but here are BE for easier comparison (they probably correspond
|
||||
* to some text but are pre-hashed in exes). Some info from KTSR.bt */
|
||||
|
||||
if (target_subsong == 0) target_subsong = 1;
|
||||
ktsr.target_subsong = target_subsong;
|
||||
@ -468,16 +473,52 @@ fail:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ktsr engine reads+decrypts in the same func based on passed flag tho (reversed from exe) */
|
||||
static void decrypt_string_ktsr(char* buf, size_t buf_size, uint32_t seed) {
|
||||
for (int i = 0; i < buf_size - 1; i++) {
|
||||
if (!buf[i]) /* just in case */
|
||||
break;
|
||||
|
||||
seed = 0x343FD * seed + 0x269EC3; /* classic rand */
|
||||
buf[i] ^= (seed >> 16) & 0xFF; /* 3rd byte */
|
||||
if (!buf[i]) /* end null is also encrypted (but there are extra nulls after it anyway) */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* like read_string but allow any value since it can be encrypted */
|
||||
static size_t read_string_ktsr(char* buf, size_t buf_size, off_t offset, STREAMFILE* sf) {
|
||||
int pos;
|
||||
|
||||
for (pos = 0; pos < buf_size; pos++) {
|
||||
uint8_t byte = read_u8(offset + pos, sf);
|
||||
char c = (char)byte;
|
||||
if (buf) buf[pos] = c;
|
||||
if (c == '\0')
|
||||
return pos;
|
||||
if (pos+1 == buf_size) {
|
||||
if (buf) buf[pos] = '\0';
|
||||
return buf_size;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void build_name(ktsr_header* ktsr, STREAMFILE* sf) {
|
||||
char sound_name[255] = {0};
|
||||
char config_name[255] = {0};
|
||||
|
||||
/* names can be different or same but usually config is better */
|
||||
if (ktsr->sound_name_offset) {
|
||||
read_string(sound_name, sizeof(sound_name), ktsr->sound_name_offset, sf);
|
||||
read_string_ktsr(sound_name, sizeof(sound_name), ktsr->sound_name_offset, sf);
|
||||
if (ktsr->sound_flags & 0x0008)
|
||||
decrypt_string_ktsr(sound_name, sizeof(sound_name), ktsr->audio_id);
|
||||
}
|
||||
if (ktsr->config_name_offset) {
|
||||
read_string(config_name, sizeof(config_name), ktsr->config_name_offset, sf);
|
||||
read_string_ktsr(config_name, sizeof(config_name), ktsr->config_name_offset, sf);
|
||||
if (ktsr->config_flags & 0x0200)
|
||||
decrypt_string_ktsr(config_name, sizeof(config_name), ktsr->audio_id);
|
||||
}
|
||||
|
||||
//if (longname[0] && shortname[0]) {
|
||||
@ -493,7 +534,7 @@ static void build_name(ktsr_header* ktsr, STREAMFILE* sf) {
|
||||
|
||||
}
|
||||
|
||||
static void parse_longname(ktsr_header* ktsr, STREAMFILE* sf, uint32_t target_id) {
|
||||
static void parse_longname(ktsr_header* ktsr, STREAMFILE* sf) {
|
||||
/* more configs than sounds is possible so we need target_id first */
|
||||
uint32_t offset, end, name_offset;
|
||||
uint32_t stream_id;
|
||||
@ -505,10 +546,12 @@ static void parse_longname(ktsr_header* ktsr, STREAMFILE* sf, uint32_t target_id
|
||||
uint32_t size = read_u32le(offset + 0x04, sf);
|
||||
switch(type) {
|
||||
case 0xBD888C36: /* config */
|
||||
stream_id = read_u32be(offset + 0x08, sf);
|
||||
if (stream_id != target_id)
|
||||
stream_id = read_u32le(offset + 0x08, sf);
|
||||
if (stream_id != ktsr->sound_id)
|
||||
break;
|
||||
|
||||
ktsr->config_flags = read_u32le(offset + 0x0c, sf);
|
||||
|
||||
name_offset = read_u32le(offset + 0x28, sf);
|
||||
if (name_offset > 0)
|
||||
ktsr->config_name_offset = offset + name_offset;
|
||||
@ -524,7 +567,7 @@ static void parse_longname(ktsr_header* ktsr, STREAMFILE* sf, uint32_t target_id
|
||||
|
||||
static int parse_ktsr(ktsr_header* ktsr, STREAMFILE* sf) {
|
||||
uint32_t offset, end, header_offset, name_offset;
|
||||
uint32_t stream_id = 0, stream_count;
|
||||
uint32_t stream_count;
|
||||
|
||||
/* 00: KTSR
|
||||
* 04: type
|
||||
@ -540,11 +583,14 @@ static int parse_ktsr(ktsr_header* ktsr, STREAMFILE* sf) {
|
||||
* until end: entries (totals not defined) */
|
||||
|
||||
ktsr->platform = read_u8(0x0b,sf);
|
||||
ktsr->audio_id = read_u32le(0x0c,sf);
|
||||
|
||||
if (read_u32le(0x18, sf) != read_u32le(0x1c, sf))
|
||||
goto fail;
|
||||
if (read_u32le(0x1c, sf) != get_streamfile_size(sf))
|
||||
if (read_u32le(0x1c, sf) != get_streamfile_size(sf)) {
|
||||
vgm_logi("KTSR: incorrect file size (bad rip?)\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
offset = 0x40;
|
||||
end = get_streamfile_size(sf);
|
||||
@ -557,7 +603,7 @@ static int parse_ktsr(ktsr_header* ktsr, STREAMFILE* sf) {
|
||||
case 0x6172DBA8: /* ? (mostly empty) */
|
||||
case 0xBD888C36: /* cue? (floats, stream id, etc, may have extended name; can have sub-chunks)-appears N times */
|
||||
case 0xC9C48EC1: /* unknown (has some string inside like "boss") */
|
||||
case 0xA9D23BF1: /* "state container", some kind of config/floats, witgh names like 'State_bgm01'..N */
|
||||
case 0xA9D23BF1: /* "state container", some kind of config/floats, with names like 'State_bgm01'..N */
|
||||
case 0x836FBECA: /* unknown (~0x300, encrypted? table + data) */
|
||||
break;
|
||||
|
||||
@ -565,9 +611,10 @@ static int parse_ktsr(ktsr_header* ktsr, STREAMFILE* sf) {
|
||||
ktsr->total_subsongs++;
|
||||
|
||||
/* sound table:
|
||||
* 08: stream id (used in several places)
|
||||
* 0c: unknown (low number but not version?)
|
||||
* 0e: external flag
|
||||
* 08: current/stream id (used in several places)
|
||||
* 0c: flags (sounds only; other types are similar but different bits)
|
||||
* 0x08: encrypted names (only used after ASRS was introduced?)
|
||||
* 0x10000: external flag
|
||||
* 10: sub-streams?
|
||||
* 14: offset to header offset
|
||||
* 18: offset to name
|
||||
@ -576,11 +623,10 @@ static int parse_ktsr(ktsr_header* ktsr, STREAMFILE* sf) {
|
||||
* --: header
|
||||
* --: subheader (varies) */
|
||||
|
||||
|
||||
if (ktsr->total_subsongs == ktsr->target_subsong) {
|
||||
|
||||
stream_id = read_u32be(offset + 0x08,sf);
|
||||
//ktsr->is_external = read_u16le(offset + 0x0e,sf);
|
||||
ktsr->sound_id = read_u32le(offset + 0x08,sf);
|
||||
ktsr->sound_flags = read_u32le(offset + 0x0c,sf);
|
||||
stream_count = read_u32le(offset + 0x10,sf);
|
||||
if (stream_count != 1) {
|
||||
VGM_LOG("ktsr: unknown stream count\n");
|
||||
@ -611,7 +657,7 @@ static int parse_ktsr(ktsr_header* ktsr, STREAMFILE* sf) {
|
||||
if (ktsr->target_subsong > ktsr->total_subsongs)
|
||||
goto fail;
|
||||
|
||||
parse_longname(ktsr, sf, stream_id);
|
||||
parse_longname(ktsr, sf);
|
||||
build_name(ktsr, sf);
|
||||
|
||||
/* skip TSRS header */
|
||||
|
Loading…
x
Reference in New Issue
Block a user