mirror of
https://github.com/n64decomp/sm64
synced 2026-05-14 10:07:41 +00:00
Experimental audio support
Special thanks to Arisotura for helping out :)
This commit is contained in:
parent
f4e7a6b4b9
commit
0453c965ec
|
|
@ -1,7 +1,7 @@
|
|||
FROM devkitpro/devkitarm:latest as build
|
||||
|
||||
RUN apt update
|
||||
RUN apt -y install build-essential bsdmainutils
|
||||
RUN apt -y install build-essential bsdmainutils sox
|
||||
RUN mkdir /sm64
|
||||
WORKDIR /sm64
|
||||
|
||||
|
|
|
|||
44
Makefile
44
Makefile
|
|
@ -236,6 +236,7 @@ ULTRA_BIN_DIRS := lib/bin
|
|||
|
||||
ifeq ($(TARGET_NDS),1)
|
||||
SRC_DIRS += src/nds
|
||||
ARM7_SRC_DIRS := src/nds/arm7
|
||||
else
|
||||
SRC_DIRS += asm
|
||||
ULTRA_SRC_DIRS += lib/asm
|
||||
|
|
@ -269,14 +270,21 @@ ifeq ($(TARGET_NDS),1)
|
|||
guScaleF.c \
|
||||
guTranslateF.c
|
||||
ULTRA_C_FILES := $(addprefix lib/src/,$(ULTRA_C_FILES))
|
||||
|
||||
ARM7_C_FILES := $(foreach dir,$(ARM7_SRC_DIRS),$(wildcard $(dir)/*.c))
|
||||
ARM7_O_FILES := $(foreach file,$(ARM7_C_FILES),$(BUILD_DIR)/arm7/$(file:.c=.o))
|
||||
endif
|
||||
|
||||
# Sound files
|
||||
SOUND_BANK_FILES := $(wildcard sound/sound_banks/*.json)
|
||||
SOUND_SAMPLE_DIRS := $(wildcard sound/samples/*)
|
||||
SOUND_SAMPLE_AIFFS := $(foreach dir,$(SOUND_SAMPLE_DIRS),$(wildcard $(dir)/*.aiff))
|
||||
ifdef TARGET_NDS
|
||||
SOUND_SAMPLE_AIFCS := $(foreach file,$(SOUND_SAMPLE_AIFFS),$(BUILD_DIR)/$(file:.aiff=.ima))
|
||||
else
|
||||
SOUND_SAMPLE_TABLES := $(foreach file,$(SOUND_SAMPLE_AIFFS),$(BUILD_DIR)/$(file:.aiff=.table))
|
||||
SOUND_SAMPLE_AIFCS := $(foreach file,$(SOUND_SAMPLE_AIFFS),$(BUILD_DIR)/$(file:.aiff=.aifc))
|
||||
endif
|
||||
SOUND_SEQUENCE_DIRS := sound/sequences sound/sequences/$(VERSION)
|
||||
# all .m64 files in SOUND_SEQUENCE_DIRS, plus all .m64 files that are generated from .s files in SOUND_SEQUENCE_DIRS
|
||||
SOUND_SEQUENCE_FILES := \
|
||||
|
|
@ -298,6 +306,10 @@ GODDARD_O_FILES := $(foreach file,$(GODDARD_C_FILES),$(BUILD_DIR)/$(file:.c=.o))
|
|||
# Automatic dependency files
|
||||
DEP_FILES := $(O_FILES:.o=.d) $(ULTRA_O_FILES:.o=.d) $(GODDARD_O_FILES:.o=.d) $(BUILD_DIR)/$(LD_SCRIPT).d
|
||||
|
||||
ifeq ($(TARGET_NDS),1)
|
||||
DEP_FILES += $(ARM7_O_FILES:.o=.d)
|
||||
endif
|
||||
|
||||
# Files with GLOBAL_ASM blocks
|
||||
ifeq ($(NON_MATCHING),0)
|
||||
ifeq ($(VERSION),sh)
|
||||
|
|
@ -381,14 +393,18 @@ ifeq ($(TARGET_NDS),1)
|
|||
|
||||
LIBDIRS := $(DEVKITPRO)/libnds
|
||||
TARGET_CFLAGS := -march=armv5te -mtune=arm946e-s -fomit-frame-pointer -ffast-math $(foreach dir,$(LIBDIRS),-I$(dir)/include) -DTARGET_NDS -DARM9 -D_LANGUAGE_C -DNO_SEGMENTED_MEMORY -DLIBFAT
|
||||
TARGET_LDFLAGS := -lfat -lnds9 -specs=dsi_arm9.specs -g -mthumb -mthumb-interwork $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
|
||||
ARM7_TARGET_CFLAGS := -mcpu=arm7tdmi -mtune=arm7tdmi -fomit-frame-pointer -ffast-math $(foreach dir,$(LIBDIRS),-I$(dir)/include) -DTARGET_NDS -DARM7
|
||||
|
||||
CC_CHECK := $(CC)
|
||||
CC_CHECK_CFLAGS := -fsyntax-only -fsigned-char $(CC_CFLAGS) $(TARGET_CFLAGS) -Wall -Wextra -Wno-format-security -DNON_MATCHING -DAVOID_UB $(DEF_INC_CFLAGS)
|
||||
ARM7_CC_CHECK_CFLAGS := -fsyntax-only -fsigned-char $(CC_CFLAGS) $(ARM7_TARGET_CFLAGS) -Wall -Wextra -Wno-format-security $(DEF_INC_CFLAGS)
|
||||
|
||||
ASFLAGS := $(foreach i,$(INCLUDE_DIRS),-I$(i)) $(foreach d,$(DEFINES),--defsym $(d))
|
||||
CFLAGS := -fno-strict-aliasing -fwrapv $(OPT_FLAGS) $(TARGET_CFLAGS) $(DEF_INC_CFLAGS)
|
||||
LDFLAGS := $(TARGET_LDFLAGS)
|
||||
LDFLAGS := -lfat -lnds9 -specs=dsi_arm9.specs -g -mthumb -mthumb-interwork $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
|
||||
|
||||
ARM7_CFLAGS := -fno-strict-aliasing -fwrapv $(OPT_FLAGS) $(ARM7_TARGET_CFLAGS) $(DEF_INC_CFLAGS)
|
||||
ARM7_LDFLAGS := -lnds7 -specs=ds_arm7.specs -g -mthumb-interwork $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
|
||||
|
||||
else
|
||||
|
||||
|
|
@ -537,6 +553,10 @@ endif
|
|||
|
||||
ALL_DIRS := $(BUILD_DIR) $(addprefix $(BUILD_DIR)/,$(SRC_DIRS) $(GODDARD_SRC_DIRS) $(ULTRA_SRC_DIRS) $(ULTRA_BIN_DIRS) $(BIN_DIRS) $(TEXTURE_DIRS) $(TEXT_DIRS) $(SOUND_SAMPLE_DIRS) $(addprefix levels/,$(LEVEL_DIRS)) rsp include) $(MIO0_DIR) $(addprefix $(MIO0_DIR)/,$(VERSION)) $(SOUND_BIN_DIR) $(SOUND_BIN_DIR)/sequences/$(VERSION)
|
||||
|
||||
ifeq ($(TARGET_NDS),1)
|
||||
ALL_DIRS += $(addprefix $(BUILD_DIR)/arm7/,$(ARM7_SRC_DIRS))
|
||||
endif
|
||||
|
||||
# Make sure build directory exists before compiling anything
|
||||
DUMMY != mkdir -p $(ALL_DIRS)
|
||||
|
||||
|
|
@ -611,6 +631,11 @@ endif
|
|||
# Sound File Generation #
|
||||
#==============================================================================#
|
||||
|
||||
ifdef TARGET_NDS
|
||||
$(BUILD_DIR)/%.ima: %.aiff
|
||||
$(call print,Encoding IMA:,$<,$@)
|
||||
$(V)sox $^ $@
|
||||
else
|
||||
$(BUILD_DIR)/%.table: %.aiff
|
||||
$(call print,Extracting codebook:,$<,$@)
|
||||
$(V)$(AIFF_EXTRACT_CODEBOOK) $< >$@
|
||||
|
|
@ -618,6 +643,7 @@ $(BUILD_DIR)/%.table: %.aiff
|
|||
$(BUILD_DIR)/%.aifc: $(BUILD_DIR)/%.table %.aiff
|
||||
$(call print,Encoding VADPCM:,$<,$@)
|
||||
$(V)$(VADPCM_ENC) -c $^ $@
|
||||
endif
|
||||
|
||||
$(ENDIAN_BITWIDTH): $(TOOLS_DIR)/determine-endian-bitwidth.c
|
||||
@$(PRINT) "$(GREEN)Generating endian-bitwidth $(NO_COL)\n"
|
||||
|
|
@ -720,6 +746,13 @@ $(BUILD_DIR)/%.o: $(BUILD_DIR)/%.c
|
|||
@$(CC_CHECK) $(CC_CHECK_CFLAGS) -MMD -MP -MT $@ -MF $(BUILD_DIR)/$*.d $<
|
||||
$(V)$(CC) -c $(CFLAGS) -o $@ $<
|
||||
|
||||
ifeq ($(TARGET_NDS),1)
|
||||
$(BUILD_DIR)/arm7/%.o: %.c
|
||||
$(call print,Compiling:,$<,$@)
|
||||
@$(CC_CHECK) $(ARM7_CC_CHECK_CFLAGS) -MMD -MP -MT $@ -MF $(BUILD_DIR)/arm7/$*.d $<
|
||||
$(V)$(CC) -c $(ARM7_CFLAGS) -o $@ $<
|
||||
endif
|
||||
|
||||
# Alternate compiler flags needed for matching
|
||||
ifeq ($(COMPILER),ido)
|
||||
$(BUILD_DIR)/levels/%/leveldata.o: OPT_FLAGS := -g
|
||||
|
|
@ -797,9 +830,10 @@ $(BUILD_DIR)/rsp/%.bin $(BUILD_DIR)/rsp/%_data.bin: rsp/%.s
|
|||
|
||||
# Build NDS ROM
|
||||
ifeq ($(TARGET_NDS),1)
|
||||
$(ROM): $(O_FILES) $(MIO0_FILES:.mio0=.o) $(ULTRA_O_FILES) $(GODDARD_O_FILES)
|
||||
$(LD) -L $(BUILD_DIR) -o $@.elf $(O_FILES) $(ULTRA_O_FILES) $(GODDARD_O_FILES) $(LDFLAGS)
|
||||
ndstool -c $@ -9 $@.elf
|
||||
$(ROM): $(O_FILES) $(ARM7_O_FILES) $(MIO0_FILES:.mio0=.o) $(ULTRA_O_FILES) $(GODDARD_O_FILES)
|
||||
$(LD) -L $(BUILD_DIR) -o $@.arm9.elf $(O_FILES) $(ULTRA_O_FILES) $(GODDARD_O_FILES) $(LDFLAGS)
|
||||
$(LD) -L $(BUILD_DIR) -o $@.arm7.elf $(ARM7_O_FILES) $(ARM7_LDFLAGS)
|
||||
ndstool -c $@ -9 $@.arm9.elf -7 $@.arm7.elf
|
||||
else
|
||||
|
||||
# Run linker script through the C preprocessor
|
||||
|
|
|
|||
|
|
@ -16,9 +16,9 @@ A prior copy of the game is required to extract the assets.
|
|||
## Linux installation
|
||||
* First follow [the guide for installing devkitPro packages](https://devkitpro.org/wiki/Getting_Started), also installing the `nds-dev` group as mentioned
|
||||
* Install the needed tools
|
||||
* Debian/Ubuntu: `sudo apt install -y build-essential git python`
|
||||
* Fedora: `sudo dnf install gcc make git python`
|
||||
* Arch/derivatives like Manjaro: `sudo pacman -S base-devel git python`
|
||||
* Debian/Ubuntu: `sudo apt install -y build-essential git python sox`
|
||||
* Fedora: `sudo dnf install gcc make git python sox`
|
||||
* Arch/derivatives like Manjaro: `sudo pacman -S base-devel git python sox`
|
||||
* Clone this repository and change to its directory
|
||||
```
|
||||
git clone https://github.com/Hydr8gon/sm64.git
|
||||
|
|
|
|||
|
|
@ -433,7 +433,6 @@ extern void func_802ad74c(u32 bits, u32 arg);
|
|||
extern void func_802ad770(u32 bits, s8 arg);
|
||||
|
||||
static void update_background_music_after_sound(u8 bank, u8 soundIndex);
|
||||
static void update_game_sound(void);
|
||||
static void fade_channel_volume_scale(u8 player, u8 channelId, u8 targetScale, u16 fadeTimer);
|
||||
void process_level_music_dynamics(void);
|
||||
static u8 begin_background_music_fade(u16 fadeDuration);
|
||||
|
|
@ -1341,7 +1340,7 @@ void audio_signal_game_loop_tick(void) {
|
|||
/**
|
||||
* Called from threads: thread4_sound, thread5_game_loop (EU and SH only)
|
||||
*/
|
||||
static void update_game_sound(void) {
|
||||
void update_game_sound(void) {
|
||||
u8 soundStatus;
|
||||
u8 i;
|
||||
u8 soundId;
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ struct SPTask *func_sh_802f5a80(void);
|
|||
#endif
|
||||
void play_sound(s32 soundBits, f32 *pos);
|
||||
void audio_signal_game_loop_tick(void);
|
||||
void update_game_sound(void);
|
||||
void seq_player_fade_out(u8 player, u16 fadeDuration);
|
||||
void fade_volume_scale(u8 player, u8 targetScale, u16 fadeDuration);
|
||||
void seq_player_lower_volume(u8 player, u16 fadeDuration, u8 percentage);
|
||||
|
|
|
|||
|
|
@ -1314,6 +1314,10 @@ void audio_reset_session(void) {
|
|||
#endif
|
||||
|
||||
gNotes = soundAlloc(&gNotesAndBuffersPool, gMaxSimultaneousNotes * sizeof(struct Note));
|
||||
#ifdef TARGET_NDS
|
||||
// Point to the uncached RAM mirror so both CPUs can access the data reliably
|
||||
gNotes = (struct Note*)((u32)gNotes + 0xA000000);
|
||||
#endif
|
||||
note_init_all();
|
||||
init_note_free_list();
|
||||
|
||||
|
|
|
|||
|
|
@ -2750,7 +2750,7 @@ void process_sequences(UNUSED s32 iterationsRemaining) {
|
|||
#endif
|
||||
}
|
||||
}
|
||||
#if defined(VERSION_JP) || defined(VERSION_US)
|
||||
#if (defined(VERSION_JP) || defined(VERSION_US)) && !defined(TARGET_NDS)
|
||||
reclaim_notes();
|
||||
#endif
|
||||
process_notes();
|
||||
|
|
|
|||
53
src/nds/arm7/main.c
Normal file
53
src/nds/arm7/main.c
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
#include "../nds_include.h"
|
||||
|
||||
#include "nds_audio.h"
|
||||
|
||||
struct Note *gNotes;
|
||||
static bool running;
|
||||
|
||||
static void send_input(void) {
|
||||
inputGetAndSend();
|
||||
}
|
||||
|
||||
static void update_audio(void) {
|
||||
// Request an audio update from the ARM9
|
||||
IPC_SendSync(0);
|
||||
swiIntrWait(0, IRQ_IPC_SYNC);
|
||||
|
||||
// Play the current notes
|
||||
play_notes(gNotes);
|
||||
}
|
||||
|
||||
static void power_down(void) {
|
||||
running = false;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
irqInit();
|
||||
fifoInit();
|
||||
touchInit();
|
||||
|
||||
readUserSettings();
|
||||
installSystemFIFO();
|
||||
setPowerButtonCB(power_down);
|
||||
|
||||
SetYtrigger(80);
|
||||
irqSet(IRQ_VCOUNT, send_input);
|
||||
irqEnable(IRQ_VCOUNT | IRQ_IPC_SYNC);
|
||||
|
||||
// Get a pointer to the audio data from the ARM9
|
||||
while (!fifoCheckValue32(FIFO_USER_01));
|
||||
gNotes = (struct Note*)fifoGetValue32(FIFO_USER_01);
|
||||
|
||||
// Prepare to update the audio at 240 Hz
|
||||
enableSound();
|
||||
timerStart(0, ClockDivider_64, TIMER_FREQ_64(240), update_audio);
|
||||
running = true;
|
||||
|
||||
// Wait idly for interrupts
|
||||
while (running) {
|
||||
swiWaitForVBlank();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
48
src/nds/arm7/nds_audio.c
Normal file
48
src/nds/arm7/nds_audio.c
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
#include "../nds_include.h"
|
||||
|
||||
#include "nds_audio.h"
|
||||
|
||||
static u32 calculate_vol_pan(struct Note *note) {
|
||||
// Calculate the DS volume and pan values for a note
|
||||
u32 vol = (note->targetVolLeft + note->targetVolRight) / 2;
|
||||
u32 pan = (vol << 14) / note->targetVolLeft;
|
||||
vol >>= 7;
|
||||
pan >>= 8;
|
||||
if (vol > 127) vol = 127;
|
||||
if (pan > 127) pan = 127;
|
||||
return SOUND_VOL(vol) | SOUND_PAN(pan);
|
||||
}
|
||||
|
||||
void play_notes(struct Note *notes) {
|
||||
// Play notes on the 16 sound channels of the DS
|
||||
// The samples are converted to DS ADPCM at compile time, so they can be played directly
|
||||
for (int i = 0; i < 16; i++) {
|
||||
struct Note *note = ¬es[i];
|
||||
|
||||
if (note->enabled && note->sound != NULL) {
|
||||
if (note->needsInit) {
|
||||
const struct AudioBankSample *sample = note->sound->sample;
|
||||
const u32 loop = (sample->loop->count ? SOUND_REPEAT : SOUND_ONE_SHOT);
|
||||
|
||||
// Ensure the channel is properly reset
|
||||
SCHANNEL_CR(i) &= ~SCHANNEL_ENABLE;
|
||||
|
||||
// Start playing a note on the current channel
|
||||
SCHANNEL_SOURCE(i) = (u32)sample->sampleAddr;
|
||||
SCHANNEL_REPEAT_POINT(i) = sample->loop->start / sizeof(u32);
|
||||
SCHANNEL_LENGTH(i) = (sample->loop->end - sample->loop->start) / sizeof(u32);
|
||||
SCHANNEL_TIMER(i) = SOUND_FREQ((u16)(note->frequency * 32768));
|
||||
SCHANNEL_CR(i) = SCHANNEL_ENABLE | SOUND_FORMAT_ADPCM | calculate_vol_pan(note) | loop;
|
||||
|
||||
note->needsInit = false;
|
||||
} else if (SCHANNEL_CR(i) & SCHANNEL_ENABLE) {
|
||||
// Update the parameters of a currently playing note
|
||||
SCHANNEL_TIMER(i) = SOUND_FREQ((u16)(note->frequency * 32768));
|
||||
SCHANNEL_CR(i) = (SCHANNEL_CR(i) & ~(SOUND_VOL(127) | SOUND_PAN(127))) | calculate_vol_pan(note);
|
||||
}
|
||||
} else {
|
||||
// Disable the channel if no note should play
|
||||
SCHANNEL_CR(i) &= ~SCHANNEL_ENABLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
8
src/nds/arm7/nds_audio.h
Normal file
8
src/nds/arm7/nds_audio.h
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
#ifndef NDS_AUDIO_H
|
||||
#define NDS_AUDIO_H
|
||||
|
||||
#include "audio/load.h"
|
||||
|
||||
extern void play_notes(struct Note *notes);
|
||||
|
||||
#endif // NDS_AUDIO_H
|
||||
86
src/nds/main.c
Normal file
86
src/nds/main.c
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
#include <stdio.h>
|
||||
|
||||
#include "nds_include.h"
|
||||
#include <fat.h>
|
||||
|
||||
#include "audio/data.h"
|
||||
#include "audio/external.h"
|
||||
#include "audio/load.h"
|
||||
#include "audio/seqplayer.h"
|
||||
#include "game/game_init.h"
|
||||
#include "nds_renderer.h"
|
||||
|
||||
OSMesg D_80339BEC;
|
||||
OSMesgQueue gSIEventMesgQueue;
|
||||
|
||||
s8 gResetTimer;
|
||||
s8 D_8032C648;
|
||||
s8 gDebugLevelSelect;
|
||||
s8 gShowProfiler;
|
||||
s8 gShowDebugText;
|
||||
|
||||
u8 audio_state;
|
||||
static u8 audio_step;
|
||||
|
||||
void set_vblank_handler(UNUSED s32 index, UNUSED struct VblankHandler *handler, UNUSED OSMesgQueue *queue, UNUSED OSMesg *msg) {
|
||||
}
|
||||
|
||||
void dispatch_audio_sptask(UNUSED struct SPTask *spTask) {
|
||||
}
|
||||
|
||||
void send_display_list(struct SPTask *spTask) {
|
||||
draw_frame((Gfx*)spTask->task.t.data_ptr);
|
||||
}
|
||||
|
||||
static void update_audio(void) {
|
||||
// Update audio at the ARM7's request
|
||||
if (audio_state == 0) {
|
||||
// Update the audio logic at 30 Hz
|
||||
if ((audio_step = (audio_step + 1) & 7) == 0) {
|
||||
update_game_sound();
|
||||
gAudioFrameCount += 2;
|
||||
gAudioRandom = ((gAudioRandom + gAudioFrameCount) * gAudioFrameCount);
|
||||
}
|
||||
|
||||
// Update the sequences at 240 Hz
|
||||
process_sequences(0);
|
||||
} else if (audio_state == 1) {
|
||||
// Disable audio
|
||||
for (int i = 0; i < 16; i++) {
|
||||
gNotes[i].enabled = false;
|
||||
}
|
||||
audio_state = 2;
|
||||
}
|
||||
|
||||
// Tell the ARM7 it can go ahead
|
||||
IPC_SendSync(0);
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
static u64 pool[0x165000 / sizeof(u64)];
|
||||
main_pool_init(pool, pool + sizeof(pool) / sizeof(pool[0]));
|
||||
gEffectsMemoryPool = mem_pool_init(0x4000, MEMORY_POOL_LEFT);
|
||||
|
||||
renderer_init();
|
||||
|
||||
#ifdef LIBFAT
|
||||
if (!fatInitDefault()) {
|
||||
printf("Failed to initialize libfat!\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
audio_init();
|
||||
sound_init();
|
||||
|
||||
// Set up audio on the ARM9 side
|
||||
irqSet(IRQ_IPC_SYNC, update_audio);
|
||||
irqEnable(IRQ_IPC_SYNC);
|
||||
|
||||
// Give the ARM7 a pointer to the audio data
|
||||
fifoSendValue32(FIFO_USER_01, (u32)gNotes);
|
||||
|
||||
// Run the game
|
||||
thread5_game_loop(NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
#include "lib/src/osContInternal.h"
|
||||
|
||||
extern u8 audio_state;
|
||||
|
||||
s32 osContInit(UNUSED OSMesgQueue *mq, u8 *controllerBits, UNUSED OSContStatus *status) {
|
||||
*controllerBits = 1;
|
||||
return 0;
|
||||
|
|
@ -59,4 +61,8 @@ void osContGetReadData(OSContPad *pad) {
|
|||
touchRead(&pos);
|
||||
pad->button |= (pos.px < 128) ? L_CBUTTONS : R_CBUTTONS;
|
||||
}
|
||||
|
||||
if (keysDown() & KEY_SELECT) {
|
||||
audio_state = !audio_state;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,48 +0,0 @@
|
|||
#include <stdio.h>
|
||||
|
||||
#include "nds_include.h"
|
||||
#include <fat.h>
|
||||
|
||||
#include "audio/external.h"
|
||||
#include "game/game_init.h"
|
||||
#include "nds_renderer.h"
|
||||
|
||||
OSMesg D_80339BEC;
|
||||
OSMesgQueue gSIEventMesgQueue;
|
||||
|
||||
s8 gResetTimer;
|
||||
s8 D_8032C648;
|
||||
s8 gDebugLevelSelect;
|
||||
s8 gShowProfiler;
|
||||
s8 gShowDebugText;
|
||||
|
||||
void set_vblank_handler(UNUSED s32 index, UNUSED struct VblankHandler *handler, UNUSED OSMesgQueue *queue, UNUSED OSMesg *msg) {
|
||||
}
|
||||
|
||||
void dispatch_audio_sptask(UNUSED struct SPTask *spTask) {
|
||||
}
|
||||
|
||||
void send_display_list(struct SPTask *spTask) {
|
||||
draw_frame((Gfx*)spTask->task.t.data_ptr);
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
static u64 pool[0x165000 / sizeof(u64)];
|
||||
main_pool_init(pool, pool + sizeof(pool) / sizeof(pool[0]));
|
||||
gEffectsMemoryPool = mem_pool_init(0x4000, MEMORY_POOL_LEFT);
|
||||
|
||||
renderer_init();
|
||||
|
||||
#ifdef LIBFAT
|
||||
if (!fatInitDefault()) {
|
||||
printf("Failed to initialize libfat!\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
audio_init();
|
||||
sound_init();
|
||||
|
||||
thread5_game_loop(NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -165,6 +165,31 @@ def parse_aifc(data, name, fname):
|
|||
loop = parse_aifc_loop(vadpcm_loops) if vadpcm_loops is not None else None
|
||||
return Aifc(name, fname, audio_data, sample_rate, book, loop)
|
||||
|
||||
def parse_ima(data, name, fname, bank_name):
|
||||
sample_rate = None
|
||||
loop = None
|
||||
|
||||
with open("sound/samples/" + bank_name + "/" + name + ".aiff", "rb") as aiff:
|
||||
aiff_data = aiff.read()
|
||||
i = 12
|
||||
sections = []
|
||||
while i < len(aiff_data):
|
||||
tp = aiff_data[i : i + 4]
|
||||
(le,) = struct.unpack(">I", aiff_data[i + 4 : i + 8])
|
||||
i += 8
|
||||
sections.append((tp, aiff_data[i : i + le]))
|
||||
i = align(i + le, 2)
|
||||
|
||||
for (tp, aiff_data) in sections:
|
||||
if tp == b"COMM":
|
||||
sample_rate = parse_f80(aiff_data[8:18])
|
||||
elif tp == b"MARK":
|
||||
start = (struct.unpack('>I', aiff_data[4:8])[0] >> 1) + 4
|
||||
end = (struct.unpack('>I', aiff_data[16:20])[0] >> 1) + 4
|
||||
loop = Loop(start, end, 1, None)
|
||||
|
||||
return Aifc(name, fname, b"\0\0\0\0" + data, sample_rate, None, loop)
|
||||
|
||||
|
||||
class ReserveSerializer:
|
||||
def __init__(self):
|
||||
|
|
@ -566,22 +591,31 @@ def serialize_ctl(bank, base_ser, is_shindou):
|
|||
|
||||
# Book
|
||||
book_addr_buf.append(pack("P", ser.size))
|
||||
ser.add(pack("ii", aifc.book.order, aifc.book.npredictors))
|
||||
for x in aifc.book.table:
|
||||
ser.add(pack("h", x))
|
||||
if aifc.book is None:
|
||||
ser.add(pack("ii", 0, 0))
|
||||
else:
|
||||
ser.add(pack("ii", aifc.book.order, aifc.book.npredictors))
|
||||
for x in aifc.book.table:
|
||||
ser.add(pack("h", x))
|
||||
ser.align(16)
|
||||
|
||||
# Loop
|
||||
loop_addr_buf.append(pack("P", ser.size))
|
||||
if aifc.loop is None:
|
||||
assert sample_len % 9 in [0, 1]
|
||||
end = sample_len // 9 * 16 + (sample_len % 2) + (sample_len % 9)
|
||||
ser.add(pack("IIiI", 0, end, 0, 0))
|
||||
if aifc.fname.endswith(".ima"):
|
||||
if aifc.loop is None:
|
||||
ser.add(pack("IIiI", 0, sample_len, 0, 0))
|
||||
else:
|
||||
ser.add(pack("IIiI", aifc.loop.start, aifc.loop.end, aifc.loop.count, 0))
|
||||
else:
|
||||
ser.add(pack("IIiI", aifc.loop.start, aifc.loop.end, aifc.loop.count, 0))
|
||||
assert aifc.loop.count != 0
|
||||
for x in aifc.loop.state:
|
||||
ser.add(pack("h", x))
|
||||
if aifc.loop is None:
|
||||
assert sample_len % 9 in [0, 1]
|
||||
end = sample_len // 9 * 16 + (sample_len % 2) + (sample_len % 9)
|
||||
ser.add(pack("IIiI", 0, end, 0, 0))
|
||||
else:
|
||||
ser.add(pack("IIiI", aifc.loop.start, aifc.loop.end, aifc.loop.count, 0))
|
||||
assert aifc.loop.count != 0
|
||||
for x in aifc.loop.state:
|
||||
ser.add(pack("h", x))
|
||||
ser.align(16)
|
||||
|
||||
env_name_to_addr = {}
|
||||
|
|
@ -992,14 +1026,15 @@ def main():
|
|||
entries = []
|
||||
for f in sorted(os.listdir(dir)):
|
||||
fname = os.path.join(dir, f)
|
||||
if not f.endswith(".aifc"):
|
||||
continue
|
||||
try:
|
||||
with open(fname, "rb") as inf:
|
||||
data = inf.read()
|
||||
entries.append(parse_aifc(data, f[:-5], fname))
|
||||
if f.endswith(".aifc"):
|
||||
entries.append(parse_aifc(data, f[:-5], fname))
|
||||
elif f.endswith(".ima"):
|
||||
entries.append(parse_ima(data, f[:-4], fname, name))
|
||||
except Exception as e:
|
||||
fail("malformed AIFC file " + fname + ": " + str(e))
|
||||
fail("malformed audio file " + fname + ": " + str(e))
|
||||
if entries:
|
||||
sample_bank = SampleBank(name, entries)
|
||||
sample_banks.append(sample_bank)
|
||||
|
|
|
|||
Loading…
Reference in a new issue