[Audio 5/?] Build the Samplebank Table (#1674)

* [Audio 5/?] Build the Samplebank Table

* OoT suggested changes

* Fix format specifier

* Moved linker_scripts files used in final linker to linker_scripts/final

* Populate OTHER_DIRS with linker_scripts subdirs

* Unhide the partial link command
This commit is contained in:
Tharo 2024-08-17 22:02:57 +01:00 committed by GitHub
parent 7209abbec2
commit 98d9571f51
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 339 additions and 34 deletions

View File

@ -163,6 +163,7 @@ SCHC_FLAGS :=
AUDIO_EXTRACT := $(PYTHON) tools/audio_extraction.py
SAMPLECONV := tools/audio/sampleconv/sampleconv
SBC := tools/audio/sbc
ATBLGEN := tools/audio/atblgen
SBCFLAGS := --matching
@ -281,14 +282,14 @@ OVL_RELOC_FILES := $(shell $(CPP) $(CPPFLAGS) $(SPEC) | $(BUILD_DIR_REPLACE) | g
SCHEDULE_INC_FILES := $(foreach f,$(SCHEDULE_FILES:.schl=.schl.inc),$(BUILD_DIR)/$f)
LD_FILES := $(foreach f,$(shell find linker_scripts/*.ld),$(BUILD_DIR)/$f)
LD_FINAL_FILES := $(foreach f,$(shell find linker_scripts/final/*.ld),$(BUILD_DIR)/$f)
# Automatic dependency files
# (Only asm_processor dependencies and reloc dependencies are handled for now)
DEP_FILES := $(O_FILES:.o=.asmproc.d) $(OVL_RELOC_FILES:.o=.d)
# Other directories that need to be created in the build directory
OTHER_DIRS := baserom dmadata linker_scripts
OTHER_DIRS := baserom dmadata $(shell find linker_scripts -type d)
# create build directories
$(shell mkdir -p $(foreach dir,$(OTHER_DIRS),$(BUILD_DIR)/$(dir)))
@ -382,9 +383,9 @@ $(ROMC): $(ROM) $(ELF) $(BUILD_DIR)/dmadata/compress_ranges.txt
$(PYTHON) tools/buildtools/compress.py --in $(ROM) --out $@ --dma-start `tools/buildtools/dmadata_start.sh $(NM) $(ELF)` --compress `cat $(BUILD_DIR)/dmadata/compress_ranges.txt` --threads $(N_THREADS)
$(PYTHON) -m ipl3checksum sum --cic 6105 --update $@
$(ELF): $(TEXTURE_FILES_OUT) $(ASSET_FILES_OUT) $(O_FILES) $(OVL_RELOC_FILES) $(LDSCRIPT) $(LD_FILES) \
$(ELF): $(TEXTURE_FILES_OUT) $(ASSET_FILES_OUT) $(O_FILES) $(OVL_RELOC_FILES) $(LDSCRIPT) $(LD_FINAL_FILES) \
$(SAMPLEBANK_O_FILES)
$(LD) -T $(LDSCRIPT) -T $(LD_FILES) --no-check-sections --accept-unknown-input-arch --emit-relocs -Map $(MAP) -o $@
$(LD) -T $(LDSCRIPT) -T $(LD_FINAL_FILES) --no-check-sections --accept-unknown-input-arch --emit-relocs -Map $(MAP) -o $@
## Order-only prerequisites
# These ensure e.g. the O_FILES are built before the OVL_RELOC_FILES.
@ -609,6 +610,20 @@ ifeq ($(AUDIO_BUILD_DEBUG),1)
@cmp $(@:.o=.bin) $(patsubst $(BUILD_DIR)/assets/audio/samplebanks/%,$(EXTRACTED_DIR)/baserom_audiotest/audiotable_files/%,$(@:.o=.bin)) && echo "$(<F) OK"
endif
# put together the tables
$(BUILD_DIR)/assets/audio/samplebank_table.h: $(SAMPLEBANK_BUILD_XMLS)
$(ATBLGEN) --banks $@ $^
# build the tables into objects, move data -> rodata
$(BUILD_DIR)/src/audio/tables/samplebank_table.o: src/audio/tables/samplebank_table.c $(BUILD_DIR)/assets/audio/samplebank_table.h
$(CC_CHECK_COMP) $(CC_CHECK_FLAGS) $(IINC) $(CC_CHECK_WARNINGS) $(C_DEFINES) $(MIPS_BUILTIN_DEFS) -o $(@:.o=.tmp) $<
$(CC) -c $(CFLAGS) $(IINC) $(WARNINGS) $(C_DEFINES) $(MIPS_VERSION) $(ENDIAN) $(OPTFLAGS) -o $(@:.o=.tmp) $<
$(LD) -r -T linker_scripts/audio_table_rodata.ld $(@:.o=.tmp) -o $@
@$(RM) $(@:.o=.tmp)
$(RM_MDEBUG)
-include $(DEP_FILES)
# Print target for debugging

View File

@ -11,5 +11,6 @@
#define UNUSED __attribute__((unused))
#define FALLTHROUGH __attribute__((fallthrough))
#define NORETURN __attribute__((noreturn))
#define NO_REORDER __attribute__((no_reorder))
#endif

View File

@ -17,6 +17,13 @@ typedef enum SampleBankTableType {
/* 2 */ SAMPLE_TABLE
} SampleBankTableType;
typedef struct AudioTableHeader {
/* 0x00 */ s16 numEntries;
/* 0x02 */ s16 unkMediumParam;
/* 0x04 */ uintptr_t romAddr;
/* 0x08 */ char pad[0x8];
} AudioTableHeader; // size = 0x10
typedef struct AudioTableEntry {
/* 0x0 */ uintptr_t romAddr;
/* 0x4 */ size_t size;
@ -28,10 +35,7 @@ typedef struct AudioTableEntry {
} AudioTableEntry; // size = 0x10
typedef struct AudioTable {
/* 0x00 */ s16 numEntries;
/* 0x02 */ s16 unkMediumParam;
/* 0x04 */ uintptr_t romAddr;
/* 0x08 */ char pad[0x8];
/* 0x00 */ AudioTableHeader header;
/* 0x10 */ AudioTableEntry entries[1]; // (dynamic size)
} AudioTable; // size >= 0x20

View File

@ -41,7 +41,7 @@ extern const AudioHeapInitSizes gAudioHeapInitSizes;
extern u8 gSoundFontTable[];
extern u8 gSequenceFontTable[];
extern u8 gSequenceTable[];
extern u8 gSampleBankTable[];
extern AudioTable gSampleBankTable;
// bss

View File

@ -0,0 +1,17 @@
OUTPUT_ARCH (mips)
/* Audio Table Linker Script, maps data into rodata */
SECTIONS {
.rodata :
{
*(.data*)
*(.rodata*)
}
/DISCARD/ :
{
*(*);
}
}

5
spec
View File

@ -615,7 +615,10 @@ beginseg
include "$(BUILD_DIR)/src/code/jpegdecoder.o"
include_data_with_rodata "$(BUILD_DIR)/src/code/z_game_over.o"
include "$(BUILD_DIR)/src/code/z_construct.o"
include "$(BUILD_DIR)/data/code/audio_tables.rodata.o"
include "$(BUILD_DIR)/data/code/audio_soundfont_table.rodata.o"
include "$(BUILD_DIR)/data/code/audio_sequence_font_table.rodata.o"
include "$(BUILD_DIR)/data/code/audio_sequence_table.rodata.o"
include "$(BUILD_DIR)/src/audio/tables/samplebank_table.o"
include "$(BUILD_DIR)/data/code/aspMain.rodata.o"
include "$(BUILD_DIR)/data/code/gspF3DZEX2.NoN.PosLight.fifo.rodata.o"
include "$(BUILD_DIR)/data/code/gspS2DEX2.fifo.rodata.o"

View File

@ -1302,7 +1302,7 @@ void AudioHeap_DiscardSampleCacheEntry(SampleCacheEntry* entry) {
s32 sampleBankId2;
s32 fontId;
numFonts = gAudioCtx.soundFontTable->numEntries;
numFonts = gAudioCtx.soundFontTable->header.numEntries;
for (fontId = 0; fontId < numFonts; fontId++) {
sampleBankId1 = gAudioCtx.soundFontList[fontId].sampleBankId1;
sampleBankId2 = gAudioCtx.soundFontList[fontId].sampleBankId2;
@ -1366,7 +1366,7 @@ void AudioHeap_DiscardSampleCaches(void) {
s32 fontId;
s32 j;
numFonts = gAudioCtx.soundFontTable->numEntries;
numFonts = gAudioCtx.soundFontTable->header.numEntries;
for (fontId = 0; fontId < numFonts; fontId++) {
sampleBankId1 = gAudioCtx.soundFontList[fontId].sampleBankId1;
sampleBankId2 = gAudioCtx.soundFontList[fontId].sampleBankId2;
@ -1441,7 +1441,7 @@ void AudioHeap_ApplySampleBankCacheInternal(s32 apply, s32 sampleBankId) {
s32 pad[4];
sampleBankTable = gAudioCtx.sampleBankTable;
numFonts = gAudioCtx.soundFontTable->numEntries;
numFonts = gAudioCtx.soundFontTable->header.numEntries;
change.oldAddr = (uintptr_t)AudioHeap_SearchCaches(SAMPLE_TABLE, CACHE_EITHER, sampleBankId);
if (change.oldAddr == 0) {
return;

View File

@ -367,10 +367,10 @@ void AudioLoad_SetSampleFontLoadStatus(s32 sampleBankId, s32 loadStatus) {
void AudioLoad_InitTable(AudioTable* table, uintptr_t romAddr, u16 unkMediumParam) {
s32 i;
table->unkMediumParam = unkMediumParam;
table->romAddr = romAddr;
table->header.unkMediumParam = unkMediumParam;
table->header.romAddr = romAddr;
for (i = 0; i < table->numEntries; i++) {
for (i = 0; i < table->header.numEntries; i++) {
if ((table->entries[i].size != 0) && (table->entries[i].medium == MEDIUM_CART)) {
table->entries[i].romAddr += romAddr;
}
@ -433,7 +433,7 @@ s32 AudioLoad_SyncLoadSample(Sample* sample, s32 fontId) {
if (sample->medium == MEDIUM_UNK) {
AudioLoad_SyncDmaUnkMedium((uintptr_t)sample->sampleAddr, sampleAddr, sample->size,
gAudioCtx.sampleBankTable->unkMediumParam);
gAudioCtx.sampleBankTable->header.unkMediumParam);
} else {
AudioLoad_SyncDma((uintptr_t)sample->sampleAddr, sampleAddr, sample->size, sample->medium);
}
@ -788,7 +788,7 @@ void* AudioLoad_SyncLoad(s32 tableType, u32 id, s32* didAllocate) {
bcopy((void*)romAddr, ramAddr, size);
} else if (medium2 == mediumUnk) {
AudioLoad_SyncDmaUnkMedium(romAddr, ramAddr, size, (s16)table->unkMediumParam);
AudioLoad_SyncDmaUnkMedium(romAddr, ramAddr, size, (s16)table->header.unkMediumParam);
} else {
AudioLoad_SyncDma(romAddr, ramAddr, size, medium);
}
@ -1158,8 +1158,8 @@ void* AudioLoad_AsyncLoadInner(s32 tableType, s32 id, s32 nChunks, s32 retData,
}
if (medium == MEDIUM_UNK) {
AudioLoad_StartAsyncLoadUnkMedium((s16)table->unkMediumParam, romAddr, ramAddr, size, medium, nChunks,
retQueue, MK_ASYNC_MSG(retData, tableType, realId, loadStatus));
AudioLoad_StartAsyncLoadUnkMedium((s16)table->header.unkMediumParam, romAddr, ramAddr, size, medium,
nChunks, retQueue, MK_ASYNC_MSG(retData, tableType, realId, loadStatus));
} else {
AudioLoad_StartAsyncLoad(romAddr, ramAddr, size, medium, nChunks, retQueue,
MK_ASYNC_MSG(retData, tableType, realId, loadStatus));
@ -1303,10 +1303,10 @@ void AudioLoad_Init(void* heap, size_t heapSize) {
// Connect audio tables to their tables in memory
gAudioCtx.sequenceTable = (AudioTable*)gSequenceTable;
gAudioCtx.soundFontTable = (AudioTable*)gSoundFontTable;
gAudioCtx.sampleBankTable = (AudioTable*)gSampleBankTable;
gAudioCtx.sampleBankTable = &gSampleBankTable;
gAudioCtx.sequenceFontTable = gSequenceFontTable;
gAudioCtx.numSequences = gAudioCtx.sequenceTable->numEntries;
gAudioCtx.numSequences = gAudioCtx.sequenceTable->header.numEntries;
gAudioCtx.specId = 0;
gAudioCtx.resetStatus = 1; // Set reset to immediately initialize the audio heap
@ -1317,7 +1317,7 @@ void AudioLoad_Init(void* heap, size_t heapSize) {
AudioLoad_InitTable(gAudioCtx.soundFontTable, SEGMENT_ROM_START(Audiobank), 0);
AudioLoad_InitTable(gAudioCtx.sampleBankTable, SEGMENT_ROM_START(Audiotable), 0);
numFonts = gAudioCtx.soundFontTable->numEntries;
numFonts = gAudioCtx.soundFontTable->header.numEntries;
gAudioCtx.soundFontList = AudioHeap_Alloc(&gAudioCtx.initPool, numFonts * sizeof(SoundFont));
for (i = 0; i < numFonts; i++) {
@ -1383,7 +1383,7 @@ s32 AudioLoad_SlowLoadSample(s32 fontId, s32 instId, s8* isDone) {
slowLoad->instId = instId;
if (slowLoad->medium == MEDIUM_UNK) {
slowLoad->unkMediumParam = gAudioCtx.sampleBankTable->unkMediumParam;
slowLoad->unkMediumParam = gAudioCtx.sampleBankTable->header.unkMediumParam;
}
gAudioCtx.slowLoadPos ^= 1;
@ -1527,7 +1527,7 @@ s32 AudioLoad_SlowLoadSeq(s32 seqId, u8* ramAddr, s8* isDone) {
slowLoad->seqOrFontId = seqId;
if (slowLoad->medium == MEDIUM_UNK) {
slowLoad->unkMediumParam = seqTable->unkMediumParam;
slowLoad->unkMediumParam = seqTable->header.unkMediumParam;
}
gAudioCtx.slowLoadPos ^= 1;
@ -1706,7 +1706,7 @@ void AudioLoad_ProcessAsyncLoad(AudioAsyncLoad* asyncLoad, s32 resetStatus) {
if (asyncLoad->bytesRemaining < asyncLoad->chunkSize) {
if (asyncLoad->medium == MEDIUM_UNK) {
AudioLoad_AsyncDmaUnkMedium(asyncLoad->curDevAddr, asyncLoad->curRamAddr, asyncLoad->bytesRemaining,
sampleBankTable->unkMediumParam);
sampleBankTable->header.unkMediumParam);
} else if (asyncLoad->medium == MEDIUM_RAM_UNLOADED) {
AudioLoad_AsyncDmaRamUnloaded(asyncLoad, asyncLoad->bytesRemaining);
} else {
@ -1718,7 +1718,7 @@ void AudioLoad_ProcessAsyncLoad(AudioAsyncLoad* asyncLoad, s32 resetStatus) {
if (asyncLoad->medium == MEDIUM_UNK) {
AudioLoad_AsyncDmaUnkMedium(asyncLoad->curDevAddr, asyncLoad->curRamAddr, asyncLoad->chunkSize,
sampleBankTable->unkMediumParam);
sampleBankTable->header.unkMediumParam);
} else if (asyncLoad->medium == MEDIUM_RAM_UNLOADED) {
AudioLoad_AsyncDmaRamUnloaded(asyncLoad, asyncLoad->chunkSize);
} else {
@ -1889,7 +1889,7 @@ void AudioLoad_RelocateFontAndPreloadSamples(s32 fontId, SoundFontData* fontData
case false:
if (sample->medium == MEDIUM_UNK) {
AudioLoad_SyncDmaUnkMedium((uintptr_t)sample->sampleAddr, sampleRamAddr, sample->size,
gAudioCtx.sampleBankTable->unkMediumParam);
gAudioCtx.sampleBankTable->header.unkMediumParam);
sample->sampleAddr = sampleRamAddr;
sample->medium = MEDIUM_RAM;
} else {
@ -2153,7 +2153,7 @@ void AudioLoad_PreloadSamplesForFont(s32 fontId, s32 async, SampleBankRelocInfo*
case false:
if (sample->medium == MEDIUM_UNK) {
AudioLoad_SyncDmaUnkMedium((uintptr_t)sample->sampleAddr, addr, sample->size,
gAudioCtx.sampleBankTable->unkMediumParam);
gAudioCtx.sampleBankTable->header.unkMediumParam);
sample->sampleAddr = addr;
sample->medium = MEDIUM_RAM;
} else {

View File

@ -0,0 +1,50 @@
#include "attributes.h"
#include "z64audio.h"
// Symbol definition
extern AudioTable gSampleBankTable;
#pragma weak gSampleBankTable = sSampleBankTableHeader
// Externs for table
#define DEFINE_SAMPLE_BANK(name, medium, cachePolicy) \
extern u8 name##_Start[]; \
extern u8 name##_Size[];
#define DEFINE_SAMPLE_BANK_PTR(index, medium, cachePolicy) /*empty*/
#include "assets/audio/samplebank_table.h"
#undef DEFINE_SAMPLE_BANK
#undef DEFINE_SAMPLE_BANK_PTR
// Table header
NO_REORDER AudioTableHeader sSampleBankTableHeader = {
// The table contains the number of samplebanks, count them with the preprocessor
#define DEFINE_SAMPLE_BANK(name, medium, cachePolicy) 1 +
#define DEFINE_SAMPLE_BANK_PTR(index, medium, cachePolicy) 1 +
#include "assets/audio/samplebank_table.h"
0,
#undef DEFINE_SAMPLE_BANK
#undef DEFINE_SAMPLE_BANK_PTR
0,
0x00000000,
{ 0, 0, 0, 0, 0, 0, 0, 0 },
};
// Table body
NO_REORDER AudioTableEntry sSampleBankTableEntries[] = {
#define DEFINE_SAMPLE_BANK(name, medium, cachePolicy) \
{ (u32)name##_Start, (u32)name##_Size, (medium), (cachePolicy), 0, 0, 0 },
#define DEFINE_SAMPLE_BANK_PTR(index, medium, cachePolicy) { (index), 0, (medium), (cachePolicy), 0, 0, 0 },
#include "assets/audio/samplebank_table.h"
#undef DEFINE_SAMPLE_BANK
#undef DEFINE_SAMPLE_BANK_PTR
};

View File

@ -1,3 +1,4 @@
__pycache__/
atblgen
sbc

View File

@ -1,4 +1,4 @@
PROGRAMS := sbc
PROGRAMS := atblgen sbc
ifeq ($(shell which xml2-config),)
$(error xml2-config not found. Did you install libxml2-dev?)
@ -30,11 +30,14 @@ format:
$(CLANG_FORMAT) $(FORMAT_ARGS) $(shell find . -maxdepth 1 -type f -name "*.[ch]")
$(MAKE) -C sampleconv format
sbc_SOURCES := samplebank_compiler.c samplebank.c aifc.c xml.c util.c
atblgen_SOURCES := audio_tablegen.c samplebank.c xml.c util.c
sbc_SOURCES := samplebank_compiler.c samplebank.c aifc.c xml.c util.c
sbc_CFLAGS := $(XML_CFLAGS)
atblgen_CFLAGS := $(XML_CFLAGS)
sbc_CFLAGS := $(XML_CFLAGS)
sbc_LDFLAGS := $(XML_LDFLAGS)
atblgen_LDFLAGS := $(XML_LDFLAGS)
sbc_LDFLAGS := $(XML_LDFLAGS)
define COMPILE =
$(1): $($1_SOURCES)

View File

@ -0,0 +1,208 @@
/**
* SPDX-FileCopyrightText: Copyright (C) 2024 ZeldaRET
* SPDX-License-Identifier: MPL-2.0
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include <assert.h>
#include <ctype.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "samplebank.h"
#include "xml.h"
#include "util.h"
/* Utility */
static bool
is_xml(const char *path)
{
size_t len = strlen(path);
if (len < 4)
return false;
if (path[len - 4] == '.' && tolower(path[len - 3]) == 'x' && tolower(path[len - 2]) == 'm' &&
tolower(path[len - 1]) == 'l')
return true;
return false;
}
/* Samplebanks */
static int
tablegen_samplebanks(const char *sb_hdr_out, const char **samplebanks_paths, int num_samplebank_files)
{
// Read in all samplebank xml files
samplebank *samplebanks = malloc(num_samplebank_files * sizeof(samplebank));
for (int i = 0; i < num_samplebank_files; i++) {
const char *path = samplebanks_paths[i];
if (!is_xml(path))
error("Not an xml file? (\"%s\")", path);
xmlDocPtr document = xmlReadFile(path, NULL, XML_PARSE_NONET);
if (document == NULL)
error("Could not read xml file \"%s\"\n", path);
read_samplebank_xml(&samplebanks[i], document);
}
// Find largest index, including pointer indices
size_t index_max = 0;
for (int i = 0; i < num_samplebank_files; i++) {
samplebank *sb = &samplebanks[i];
unsigned index = sb->index;
if (index > index_max)
index_max = index;
for (size_t j = 0; j < sb->num_pointers; j++) {
index = sb->pointer_indices[j];
if (index > index_max)
index_max = index;
}
}
size_t indices_len = index_max + 1;
// Classify indices and check that no two indices are the same
#define INDEX_NONE 0
#define INDEX_NOPOINTER 1
#define INDEX_POINTER 2
struct sb_index_info {
const char *name;
unsigned index_type;
unsigned ptr_index;
const char *medium;
const char *cache_policy;
};
struct sb_index_info *index_info = calloc(indices_len, sizeof(struct sb_index_info));
for (int i = 0; i < num_samplebank_files; i++) {
samplebank *sb = &samplebanks[i];
unsigned index = sb->index;
if (index_info[index].index_type != INDEX_NONE)
error("Overlapping samplebank indices, saw index %u more than once", index);
index_info[index].index_type = INDEX_NOPOINTER;
index_info[index].name = sb->name;
index_info[index].medium = sb->medium;
index_info[index].cache_policy = sb->cache_policy;
unsigned real_index = index;
// Add pointers defined for this bank
for (size_t j = 0; j < sb->num_pointers; j++) {
index = sb->pointer_indices[j];
if (index_info[index].index_type != INDEX_NONE)
error("Overlapping samplebank indices, saw index %u more than once", index);
index_info[index].index_type = INDEX_POINTER;
index_info[index].ptr_index = real_index;
index_info[index].medium = sb->medium;
index_info[index].cache_policy = sb->cache_policy;
}
}
// Check that we have no gaps in the indices
for (size_t i = 0; i < indices_len; i++) {
if (index_info[i].index_type == INDEX_NONE)
error("Missing samplebank index %lu", i);
}
// Emit the table
FILE *out = fopen(sb_hdr_out, "w");
if (out == NULL)
error("Failed to open samplebank header output");
fprintf(out,
// clang-format off
"/**" "\n"
" * DEFINE_SAMPLE_BANK(name, medium, cachePolicy)" "\n"
" * DEFINE_SAMPLE_BANK_PTR(index, medium, cachePolicy)" "\n"
" */" "\n"
// clang-format on
);
for (size_t i = 0; i < indices_len; i++) {
unsigned index_type = index_info[i].index_type;
// By this point we shouldn't have any INDEX_NONEs, since it would have been caught before this
// when we checked for gaps
assert(index_type == INDEX_NOPOINTER || index_type == INDEX_POINTER);
if (index_type == INDEX_NOPOINTER) {
fprintf(out, "DEFINE_SAMPLE_BANK (%s, %s, %s)\n", index_info[i].name, index_info[i].medium,
index_info[i].cache_policy);
} else {
fprintf(out, "DEFINE_SAMPLE_BANK_PTR(%u, %s, %s)\n", index_info[i].ptr_index, index_info[i].medium,
index_info[i].cache_policy);
}
}
fclose(out);
free(index_info);
free(samplebanks);
return EXIT_SUCCESS;
}
/* Common */
static int
usage(const char *progname)
{
fprintf(stderr,
// clang-format off
"%s: Generate code tables for audio data" "\n"
"Usage:" "\n"
" %s --banks <samplebank_table.h> <samplebank xml files...>" "\n",
// clang-format on
progname, progname);
return EXIT_FAILURE;
}
int
main(int argc, char **argv)
{
int ret = EXIT_SUCCESS;
const char *progname = argv[0];
if (argc < 2)
return usage(progname);
const char *mode = argv[1];
if (strequ(mode, "--banks")) {
if (argc < 4)
return usage(progname);
const char *sb_hdr_out = argv[2];
const char **samplebanks_paths = (const char **)&argv[3];
int num_samplebank_files = argc - 3;
ret = tablegen_samplebanks(sb_hdr_out, samplebanks_paths, num_samplebank_files);
} else {
return usage(progname);
}
return ret;
}

View File

@ -687,7 +687,10 @@
0x801E1070 : "sequence",
0x801E1100 : "session_config",
0x801E1110 : "z_game_over",
0x801E1180 : "audio_tables",
0x801E1180 : "audio_soundfont_table",
0x801E1420 : "audio_sequence_font_table",
0x801E1630 : "audio_sequence_table",
0x801E1E40 : "audio_samplebank_table",
0x801E1E80 : "aspMain",
0x801E2160 : "gspF3DZEX2.NoN.PosLight.fifo",
0x801E3BB0 : "gspS2DEX2.fifo",