diff --git a/README.md b/README.md index 9693768e..1b7be0c1 100644 --- a/README.md +++ b/README.md @@ -424,6 +424,11 @@ willow.mpf:willow.mus,willow_o.mus # Metal Gear Solid: Snake Eater 3D (3DS) names for .awb bgm_2_streamfiles.awb: bgm_2.acb ``` +``` +# Snack World (Switch) names for .awb (single .acb for all .awb, order matters) +bgm.awb: bgm.acb +bgm_DLC1.awb: bgm.acb +``` ### Plugin conflicts diff --git a/src/meta/acb.c b/src/meta/acb.c index e5fbf35b..0acad0a8 100644 --- a/src/meta/acb.c +++ b/src/meta/acb.c @@ -132,6 +132,7 @@ typedef struct { /* config */ int is_memory; int target_waveid; + int target_port; int has_TrackEventTable; int has_CommandTable; @@ -221,7 +222,7 @@ static void add_acb_name(acb_header* acb, int8_t Streaming) { /* OBJECT HANDLERS */ static int load_acb_waveform(acb_header* acb, int16_t Index) { - uint16_t Id; + uint16_t Id, PortNo; uint8_t Streaming; /* read Waveform[Index] */ @@ -231,18 +232,30 @@ static int load_acb_waveform(acb_header* acb, int16_t Index) { if (acb->is_memory) { if (!utf_query_u16(acb->WaveformTable, Index, "MemoryAwbId", &Id)) goto fail; + PortNo = 0xFFFF; } else { if (!utf_query_u16(acb->WaveformTable, Index, "StreamAwbId", &Id)) goto fail; + if (!utf_query_u16(acb->WaveformTable, Index, "StreamAwbPortNo", &PortNo)) + PortNo = 0; /* assumed */ } } + else { + PortNo = 0xFFFF; + } + if (!utf_query_u8(acb->WaveformTable, Index, "Streaming", &Streaming)) goto fail; - //;VGM_LOG("ACB: Waveform[%i]: Id=%i, Streaming=%i\n", Index, Id, Streaming); + //;VGM_LOG("ACB: Waveform[%i]: Id=%i, PortNo=%i, Streaming=%i\n", Index, Id, PortNo, Streaming); /* not found but valid */ if (Id != acb->target_waveid) return 1; + + /* correct AWB port (check ignored if set to -1) */ + if (acb->target_port >= 0 && PortNo != 0xFFFF && PortNo != acb->target_port) + return 1; + /* must match our target's (0=memory, 1=streaming, 2=memory (prefetch)+stream) */ if ((acb->is_memory && Streaming == 1) || (!acb->is_memory && Streaming == 0)) return 1; @@ -694,7 +707,7 @@ fail: } -void load_acb_wave_name(STREAMFILE* sf, VGMSTREAM* vgmstream, int waveid, int is_memory) { +void load_acb_wave_name(STREAMFILE* sf, VGMSTREAM* vgmstream, int waveid, int port, int is_memory) { acb_header acb = {0}; int i, CueName_rows; @@ -722,9 +735,12 @@ void load_acb_wave_name(STREAMFILE* sf, VGMSTREAM* vgmstream, int waveid, int is * Atom Craft may only target certain .acb versions so some links are later removed * Not all cues to point to Waveforms, some are just config events/commands. * .acb link to .awb by name (loaded manually), though they have a checksum/hash/header to validate. + * + * .acb can contain info for multiple .awb, that are loaded sequentially and assigned "port numbers" (0 to N). + * Both Wave ID and port number must be passed externally to find appropriate song name. */ - //;VGM_LOG("ACB: find waveid=%i\n", waveid); + //;VGM_LOG("ACB: find waveid=%i, port=%i\n", waveid, port); acb.acbFile = sf; @@ -732,6 +748,7 @@ void load_acb_wave_name(STREAMFILE* sf, VGMSTREAM* vgmstream, int waveid, int is if (!acb.Header) goto fail; acb.target_waveid = waveid; + acb.target_port = port; acb.is_memory = is_memory; acb.has_TrackEventTable = utf_query_data(acb.Header, 0, "TrackEventTable", NULL,NULL); acb.has_CommandTable = utf_query_data(acb.Header, 0, "CommandTable", NULL,NULL); diff --git a/src/meta/awb.c b/src/meta/awb.c index ece4b8f4..9b8c2e94 100644 --- a/src/meta/awb.c +++ b/src/meta/awb.c @@ -190,6 +190,7 @@ fail: static void load_awb_name(STREAMFILE* sf, STREAMFILE* sf_acb, VGMSTREAM* vgmstream, int waveid) { int is_memory = (sf_acb != NULL); + int port = 0; /* .acb is passed when loading memory .awb inside .acb */ if (!is_memory) { @@ -198,7 +199,7 @@ static void load_awb_name(STREAMFILE* sf, STREAMFILE* sf_acb, VGMSTREAM* vgmstre int len_name, len_cmp; /* try parsing TXTM if present */ - sf_acb = read_filemap_file(sf, 0); + sf_acb = read_filemap_file_pos(sf, 0, &port); /* try (name).awb + (name).awb */ if (!sf_acb) { @@ -249,11 +250,11 @@ static void load_awb_name(STREAMFILE* sf, STREAMFILE* sf_acb, VGMSTREAM* vgmstre } /* probably loaded */ - load_acb_wave_name(sf_acb, vgmstream, waveid, is_memory); + load_acb_wave_name(sf_acb, vgmstream, waveid, port, is_memory); close_streamfile(sf_acb); } else { - load_acb_wave_name(sf_acb, vgmstream, waveid, is_memory); + load_acb_wave_name(sf_acb, vgmstream, waveid, port, is_memory); } } diff --git a/src/meta/cpk.c b/src/meta/cpk.c index 22dcccd6..3e59c8ac 100644 --- a/src/meta/cpk.c +++ b/src/meta/cpk.c @@ -222,6 +222,7 @@ fail: static void load_cpk_name(STREAMFILE* sf, STREAMFILE* sf_acb, VGMSTREAM* vgmstream, int waveid) { int is_memory = (sf_acb != NULL); + int port = -1; /* cpk has no port numbers */ /* .acb is passed when loading memory .awb inside .acb */ if (!is_memory) { @@ -238,11 +239,11 @@ static void load_cpk_name(STREAMFILE* sf, STREAMFILE* sf_acb, VGMSTREAM* vgmstre return; /* companion .acb probably loaded */ - load_acb_wave_name(sf_acb, vgmstream, waveid, is_memory); + load_acb_wave_name(sf_acb, vgmstream, waveid, port, is_memory); close_streamfile(sf_acb); } else { - load_acb_wave_name(sf_acb, vgmstream, waveid, is_memory); + load_acb_wave_name(sf_acb, vgmstream, waveid, port, is_memory); } } diff --git a/src/meta/meta.h b/src/meta/meta.h index e7fffc51..8c7077f6 100644 --- a/src/meta/meta.h +++ b/src/meta/meta.h @@ -846,7 +846,7 @@ VGMSTREAM * init_vgmstream_awb(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_awb_memory(STREAMFILE * streamFile, STREAMFILE *acbFile); VGMSTREAM * init_vgmstream_acb(STREAMFILE * streamFile); -void load_acb_wave_name(STREAMFILE *acbFile, VGMSTREAM* vgmstream, int waveid, int is_memory); +void load_acb_wave_name(STREAMFILE *acbFile, VGMSTREAM* vgmstream, int waveid, int port, int is_memory); VGMSTREAM * init_vgmstream_rad(STREAMFILE * streamFile);