From 466c77362ebffa6d5f871b0a1a6488a07af936d3 Mon Sep 17 00:00:00 2001 From: fgsfds Date: Thu, 28 Sep 2023 00:55:14 +0200 Subject: [PATCH] port: mod: add support for sequence replacements --- port/include/mod.h | 2 ++ port/src/mod.c | 25 +++++++++++++++++++ src/lib/snd.c | 61 ++++++++++++++++++++++++++++++++++++---------- 3 files changed, 75 insertions(+), 13 deletions(-) diff --git a/port/include/mod.h b/port/include/mod.h index 5ebac5615..7d33b82ce 100644 --- a/port/include/mod.h +++ b/port/include/mod.h @@ -14,4 +14,6 @@ s32 modTextureLoad(u16 num, void *dst, u32 dstSize); s32 modAnimationLoadDescriptor(u16 num, struct animtableentry *anim); void *modAnimationLoadData(u16 num); +void *modSequenceLoad(u16 num, u32 *outSize); + #endif diff --git a/port/src/mod.c b/port/src/mod.c index 0cfeb19d2..681fb7503 100644 --- a/port/src/mod.c +++ b/port/src/mod.c @@ -12,6 +12,7 @@ #define MOD_TEXTURES_DIR "textures" #define MOD_ANIMATIONS_DIR "animations" +#define MOD_SEQUENCES_DIR "sequences" extern struct stagemusic g_StageTracks[]; extern struct stageallocation g_StageAllocations8Mb[]; @@ -437,6 +438,30 @@ s32 modTextureLoad(u16 num, void *dst, u32 dstSize) return ret; } +void *modSequenceLoad(u16 num, u32 *outSize) +{ + static s32 dirExists = -1; + if (dirExists < 0) { + dirExists = (fsFileSize(MOD_SEQUENCES_DIR "/") >= 0); + } + + if (!dirExists) { + return NULL; + } + + char path[FS_MAXPATH + 1]; + snprintf(path, sizeof(path), MOD_SEQUENCES_DIR "/%04x.bin", num); + if (fsFileSize(path) > 0) { + void *ret = fsFileLoad(path, outSize); + if (ret) { + sysLogPrintf(LOG_NOTE, "mod: loaded external sequence %04x", num); + return ret; + } + } + + return NULL; +} + void *modAnimationLoadData(u16 num) { char path[FS_MAXPATH + 1]; diff --git a/src/lib/snd.c b/src/lib/snd.c index 908859d54..997f868b5 100644 --- a/src/lib/snd.c +++ b/src/lib/snd.c @@ -23,7 +23,9 @@ #include "data.h" #include "types.h" #ifndef PLATFORM_N64 +#include "system.h" #include "preprocess.h" +#include "mod.h" #endif #define MAX_SEQ_SIZE_4MB 1024 * 14 @@ -1637,22 +1639,55 @@ bool seqPlay(struct seqinstance *seq, s32 tracknum) return false; } - binlen = ALIGN16(g_SeqTable->entries[seq->tracknum].binlen) + 0x40; +#ifndef PLATFORM_N64 + // try to load external replacement, which can be either compressed or not + u32 extlen = 0; + u8 *extseq = modSequenceLoad(seq->tracknum, &extlen); + if (extseq) { + if (extlen > 2 && rzipIs1173(extseq)) { + // sequence is compressed; uncompress + binlen = ((u32)extseq[2] << 16) | ((u32)extseq[3] << 8) | (u32)extseq[4]; + binlen = ALIGN16(binlen) + 0x40; + if (binlen >= g_SeqBufferSize) { + return false; + } + ziplen = ALIGN16(extlen); + binstart = seq->data; + zipstart = binstart + binlen - ziplen; + ziplen = rzipInflate(zipstart, binstart, scratch); + } else { + // sequence is uncompressed; just load as is + binlen = ALIGN16(extlen) + 0x40; + if (binlen >= g_SeqBufferSize) { + return false; + } + ziplen = extlen; + binstart = seq->data; + zipstart = NULL; + dmaExec(binstart, (romptr_t)extseq, extlen); + } + sysMemFree(extseq); + } else +#endif + { + binlen = ALIGN16(g_SeqTable->entries[seq->tracknum].binlen) + 0x40; - if (binlen >= g_SeqBufferSize) { - return false; + if (binlen >= g_SeqBufferSize) { + return false; + } + + ziplen = ALIGN16(g_SeqTable->entries[seq->tracknum].ziplen); +#if VERSION < VERSION_NTSC_1_0 + if (seq->data); +#endif + + binstart = seq->data; + zipstart = binstart + binlen - ziplen; + + dmaExec(zipstart, g_SeqTable->entries[seq->tracknum].romaddr, ziplen); + ziplen = rzipInflate(zipstart, binstart, scratch); } - ziplen = ALIGN16(g_SeqTable->entries[seq->tracknum].ziplen); -#if VERSION < VERSION_NTSC_1_0 - if (seq->data); -#endif - binstart = seq->data; - zipstart = binstart + binlen - ziplen; - - dmaExec(zipstart, g_SeqTable->entries[seq->tracknum].romaddr, ziplen); - - ziplen = rzipInflate(zipstart, binstart, scratch); #ifndef PLATFORM_N64 preprocessALCMidiHdr(binstart, ziplen); #endif