Merge pull request #1431 from bnnm/asrs

- Add/fix some .srsa [Fate/Samurai Remnant (PC)]
- Add FSB key
This commit is contained in:
bnnm 2023-10-08 12:44:22 +02:00 committed by GitHub
commit 9073e90aaa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 70 additions and 9 deletions

View File

@ -317,7 +317,7 @@ class App:
with open(file, 'r', encoding='utf-8') as f:
is_updating = False
for line in f:
line = line.strip()
line = line.strip('\n')
# find list section, add all current lines and ignore old ones until next section
if line.startswith('### List'):
@ -334,6 +334,8 @@ class App:
if not is_updating:
doc_lines.append(line)
doc_lines.append('')
with open(file, 'w', encoding='utf-8', newline='\n') as f:
f.write('\n'.join(doc_lines))

View File

@ -523,6 +523,7 @@ static const char* extension_list[] = {
"sps",
"spsd",
"spw",
"srsa",
"ss2",
"ssd", //txth/reserved [Zack & Wiki (Wii)]
"ssm",

View File

@ -71,6 +71,7 @@ static const fsbkey_info fsbkey_list[] = {
{ MODE_FSB5_STD, FSBKEY_ADD("Aurogon666") }, // Afterimage demo (PC)
{ MODE_FSB5_STD, FSBKEY_ADD("IfYouLikeThosesSoundsWhyNotRenumerateTheir2Authors?") }, // Blanc (PC/Switch)
{ MODE_FSB5_STD, FSBKEY_ADD("L36nshM520") }, // Nishuihan Mobile (Android)
{ MODE_FSB5_STD, FSBKEY_ADD("Forza2!") }, // Forza Motorsport (PC)
/* these games use a key per file, seemingly generated from the filename; could be possible to add them but there is a lot of songs,
so external .fsbkey may be better (use guessfsb 3.1 with --write-key-file) */

View File

@ -7,6 +7,7 @@ typedef enum { NONE, MSADPCM, DSP, GCADPCM, ATRAC9, RIFF_ATRAC9, KOVS, KTSS, } k
#define MAX_CHANNELS 8
typedef struct {
bool is_srsa;
int total_subsongs;
int target_subsong;
ktsr_codec codec;
@ -31,12 +32,53 @@ typedef struct {
char name[255+1];
} ktsr_header;
static VGMSTREAM* init_vgmstream_ktsr_internal(STREAMFILE* sf, bool is_srsa);
static int parse_ktsr(ktsr_header* ktsr, STREAMFILE* sf);
static layered_layout_data* build_layered_atrac9(ktsr_header* ktsr, STREAMFILE *sf, uint32_t config_data);
static VGMSTREAM* init_vgmstream_ktsr_sub(STREAMFILE* sf_b, ktsr_header* ktsr, VGMSTREAM* (*init_vgmstream)(STREAMFILE* sf), const char* ext);
/* KTSR - Koei Tecmo sound resource container */
VGMSTREAM* init_vgmstream_ktsr(STREAMFILE* sf) {
return init_vgmstream_ktsr_internal(sf, false) ;
}
/* ASRS - container of KTSR found in newer games */
VGMSTREAM* init_vgmstream_asrs(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
STREAMFILE* temp_sf = NULL;
/* checks */
if (!is_id32be(0x00, sf, "ASRS"))
return NULL;
/* 0x04: null */
/* 0x08: file size */
/* 0x0c: null */
/* .srsa: header id (as generated by common tools) */
if (!check_extensions(sf, "srsa"))
return NULL;
/* mini-container of memory-KTSR (streams also have a "TSRS" for stream-KTSR).
* .srsa/srst usually have hashed filenames, so it isn't easy to match them, so this is mainly useful
* for .srsa with internal streams. */
uint32_t subfile_offset = 0x10;
uint32_t subfile_size = get_streamfile_size(sf) - subfile_offset;
/* use a subfile b/c it's a pain to change all the offsets below and it's also how engine would do it */
temp_sf = setup_subfile_streamfile(sf, subfile_offset,subfile_size, "ktsl2asbin");
if (!temp_sf) goto fail;
vgmstream = init_vgmstream_ktsr_internal(temp_sf, true);
close_streamfile(temp_sf);
return vgmstream;
fail:
close_streamfile(temp_sf);
return NULL;
}
static VGMSTREAM* init_vgmstream_ktsr_internal(STREAMFILE* sf, bool is_srsa) {
VGMSTREAM* vgmstream = NULL;
STREAMFILE* sf_b = NULL;
ktsr_header ktsr = {0};
@ -46,20 +88,22 @@ VGMSTREAM* init_vgmstream_ktsr(STREAMFILE* sf) {
/* checks */
if (!is_id32be(0x00, sf, "KTSR"))
goto fail;
if (read_u32be(0x04, sf) != 0x777B481A) /* hash(?) id: 0x777B481A=as, 0x0294DDFC=st, 0xC638E69E=gc */
goto fail;
return NULL;
if (read_u32be(0x04, sf) != 0x777B481A) /* hash id: 0x777B481A=as, 0x0294DDFC=st, 0xC638E69E=gc */
return NULL;
/* .ktsl2asbin: common [Atelier Ryza (PC/Switch), Nioh (PC)]
* .asbin: Warriors Orochi 4 (PC) */
if (!check_extensions(sf, "ktsl2asbin,asbin"))
goto fail;
return NULL;
/* KTSR can be a memory file (ktsl2asbin), streams (ktsl2stbin) and global config (ktsl2gcbin)
* This accepts .ktsl2asbin with internal data or external streams as subsongs.
* Some info from KTSR.bt */
* Hashes are meant to be read LE, but here are BE for easier comparison. Some info from KTSR.bt */
if (target_subsong == 0) target_subsong = 1;
ktsr.target_subsong = target_subsong;
ktsr.is_srsa = is_srsa;
if (!parse_ktsr(&ktsr, sf))
goto fail;
@ -67,6 +111,9 @@ VGMSTREAM* init_vgmstream_ktsr(STREAMFILE* sf) {
/* open companion body */
if (ktsr.is_external) {
const char* companion_ext = check_extensions(sf, "asbin") ? "stbin" : "ktsl2stbin";
if (ktsr.is_srsa)
companion_ext = "srst";
sf_b = open_streamfile_by_ext(sf, companion_ext);
if (!sf_b) {
vgm_logi("KTSR: companion file '*.%s' not found\n", companion_ext);
@ -253,6 +300,7 @@ static int parse_codec(ktsr_header* ktsr) {
/* platform + format to codec, simplified until more codec combos are found */
switch(ktsr->platform) {
case 0x01: /* PC */
case 0x05: /* PC/Steam [Fate/Samurai Remnant (PC)] */
if (ktsr->is_external) {
if (ktsr->format == 0x0005)
ktsr->codec = KOVS; // Atelier Ryza (PC)
@ -483,7 +531,7 @@ static int parse_ktsr(ktsr_header* ktsr, STREAMFILE* sf) {
* 08: version?
* 0a: unknown (usually 00, 02/03 seen in Vita)
* 0b: platform (01=PC, 03=Vita, 04=Switch)
* 0c: game id?
* 0c: audio id? (seen in multiple files/games and used as Ogg stream IDs)
* 10: null
* 14: null
* 18: file size
@ -506,8 +554,8 @@ static int parse_ktsr(ktsr_header* ktsr, STREAMFILE* sf) {
/* parse chunk-like subfiles, usually N configs then N songs */
switch(type) {
case 0x6172DBA8: /* padding (empty) */
case 0xBD888C36: /* config (floats, stream id, etc, may have extended name) */
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 0x836FBECA: /* unknown (~0x300, encrypted? table + data) */
@ -566,6 +614,13 @@ static int parse_ktsr(ktsr_header* ktsr, STREAMFILE* sf) {
parse_longname(ktsr, sf, stream_id);
build_name(ktsr, sf);
/* skip TSRS header */
if (ktsr->is_external && ktsr->is_srsa) {
for (int i = 0; i < ktsr->channels; i++) {
ktsr->stream_offsets[i] += 0x10;
}
}
return 1;
fail:
vgm_logi("KTSR: unknown variation (report)\n");

View File

@ -884,6 +884,7 @@ VGMSTREAM* init_vgmstream_diva(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_imuse(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_ktsr(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_asrs(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_mups(STREAMFILE* sf);

View File

@ -458,6 +458,7 @@ init_vgmstream_t init_vgmstream_functions[] = {
init_vgmstream_diva,
init_vgmstream_imuse,
init_vgmstream_ktsr,
init_vgmstream_asrs,
init_vgmstream_mups,
init_vgmstream_kat,
init_vgmstream_pcm_success,