diff --git a/Makefile b/Makefile index 30c99c92..8173eb1b 100644 --- a/Makefile +++ b/Makefile @@ -157,12 +157,12 @@ LINK_LIBRARIES = $(foreach i,$(LIBRARIES),-l$(i)) ifeq ($(COMPILER),gcc) NON_MATCHING := 1 MIPSISET := -mips3 - OPT_FLAGS := -Ofast + OPT_FLAGS := -Os else ifeq ($(COMPILER),clang) NON_MATCHING := 1 # clang doesn't support ABI 'o32' for 'mips3' MIPSISET := -mips2 - OPT_FLAGS := -Ofast + OPT_FLAGS := -Os endif @@ -398,8 +398,8 @@ export LD_LIBRARY_PATH=./tools AS := $(CROSS)as ifeq ($(COMPILER),gcc) CC := $(CROSS)gcc - $(BUILD_DIR)/actors/%.o: OPT_FLAGS := -Ofast -mlong-calls - $(BUILD_DIR)/levels/%.o: OPT_FLAGS := -Ofast -mlong-calls + $(BUILD_DIR)/actors/%.o: OPT_FLAGS := -Os -mlong-calls + $(BUILD_DIR)/levels/%.o: OPT_FLAGS := -Os -mlong-calls else ifeq ($(COMPILER),clang) CC := clang endif diff --git a/asm/rom_header.s b/asm/rom_header.s index 4ce1ab32..1ed6540d 100644 --- a/asm/rom_header.s +++ b/asm/rom_header.s @@ -26,13 +26,13 @@ .ascii "E" /* NTSC-U (North America) */ #endif #if defined(SRAM) - .byte 0x30 /* Version */ + .byte 0x32 /* Version */ #elif defined(EEP16K) - .byte 0x20 /* Version */ + .byte 0x22 /* Version */ #elif defined(SRAM768K) - .byte 0x40 /* Version */ + .byte 0x42 /* Version */ #elif defined(FLASHRAM) - .byte 0x50 /* Version */ + .byte 0x52 /* Version */ #else - .byte 0x10 /* Version */ + .byte 0x12 /* Version */ #endif diff --git a/include/config.h b/include/config.h index 0f499d6b..3661ec8b 100644 --- a/include/config.h +++ b/include/config.h @@ -113,7 +113,7 @@ #define LONGER_POLES // Number of possible unique model ID's (keep it higher than 256) #define MODEL_ID_COUNT 256 -// Increase audio heap size to allow for more concurrent notes to be played and for more custom sequences/banks to be imported (does nothing with EU and SH versions) +// Increase audio heap size to allow for more concurrent notes to be played and for more custom sequences/banks to be imported (not supported for SH) #define EXPAND_AUDIO_HEAP // Allow all surfaces types to have force, (doesn't require setting force, just allows it to be optional). #define ALL_SURFACES_HAVE_FORCE diff --git a/include/macros.h b/include/macros.h index 3c171faf..cfa3a6d3 100644 --- a/include/macros.h +++ b/include/macros.h @@ -69,4 +69,8 @@ #define VIRTUAL_TO_PHYSICAL2(addr) ((void *)(addr)) #endif +#define MODE_NTSC 0 +#define MODE_MPAL 1 +#define MODE_PAL 2 + #endif // MACROS_H diff --git a/include/types.h b/include/types.h index b77762e7..15ff15b7 100644 --- a/include/types.h +++ b/include/types.h @@ -19,6 +19,14 @@ #define BAD_RETURN(cmd) cmd #endif +struct Config +{ + f32 audioFrequency; +#ifdef WIDE + s16 widescreen; +#endif + u8 tvType; +}; struct Controller { diff --git a/sound/sequences/00_sound_player.s b/sound/sequences/00_sound_player.s index 1d1e0173..4bbc9d6e 100644 --- a/sound/sequences/00_sound_player.s +++ b/sound/sequences/00_sound_player.s @@ -2113,9 +2113,6 @@ chan_setlayer 0, .layer_C6C chan_end .layer_C6C: -#if defined(VERSION_EU) || defined(VERSION_SH) - layer_transpose 1 -#endif layer_portamento 0x82, 44, 200 layer_note1 39, 0x30, 127 layer_end diff --git a/src/audio/data.c b/src/audio/data.c index cb110405..d012cb68 100644 --- a/src/audio/data.c +++ b/src/audio/data.c @@ -8,32 +8,40 @@ extern struct OSMesgQueue OSMesgQueue1; extern struct OSMesgQueue OSMesgQueue2; extern struct OSMesgQueue OSMesgQueue3; +//Since the audio session is just one now, the reverb settings are duplicated to match the original audio setting scenario. +//It's a bit hacky but whatever lol. Index range must be defined, since it's needed by the compiler. +//To increase reverb window sizes beyond 64, please increase the REVERB_WINDOW_SIZE_MAX in heap.c by a factor of 0x40 and update AUDIO_HEAP_SIZE by 4x the same amount. #ifdef VERSION_EU -struct ReverbSettingsEU sReverbSettings[] = { - { 0x04, 0x0c, 0x2fff }, - { 0x04, 0x0a, 0x47ff }, - { 0x04, 0x10, 0x2fff }, - { 0x04, 0x0e, 0x3fff }, - { 0x04, 0x0c, 0x4fff }, - { 0x04, 0x0a, 0x37ff } +struct ReverbSettingsEU sReverbSettings[8] = { + {/*Downsample Rate*/ 1,/*Window Size*/ 64,/*Gain*/ 0x2FFF }, + {/*Downsample Rate*/ 1,/*Window Size*/ 40,/*Gain*/ 0x47FF }, + {/*Downsample Rate*/ 1,/*Window Size*/ 64,/*Gain*/ 0x2FFF }, + {/*Downsample Rate*/ 1,/*Window Size*/ 60,/*Gain*/ 0x3FFF }, + {/*Downsample Rate*/ 1,/*Window Size*/ 48,/*Gain*/ 0x4FFF }, + {/*Downsample Rate*/ 1,/*Window Size*/ 64,/*Gain*/ 0x2FFF }, //Duplicate of the first index + {/*Downsample Rate*/ 1,/*Window Size*/ 40,/*Gain*/ 0x47FF }, //Duplicate of the second index + {/*Downsample Rate*/ 1,/*Window Size*/ 40,/*Gain*/ 0x37FF }, }; +/** +1: Frequency +2: Unk1 - Should be 1 +3: Simultaneous Notes +4: Number of Reverberations +5: Unk2 - Should be 0 +6: Volume +7: Unk3 - Should be 0 +8: Persistent Sequence Memory +9: Persistent Bank Memory +10: Temporary Sequence Memory +11: Temporary Bank Memory +*/ + struct AudioSessionSettingsEU gAudioSessionPresets[] = { - { 0x00007d00, 0x01, 0x10, 0x01, 0x00, &sReverbSettings[0], 0x7fff, 0x0000, 0x00003a40, 0x00006d00, - 0x00004400, 0x00002a00 }, - { 0x00007d00, 0x01, 0x10, 0x01, 0x00, &sReverbSettings[1], 0x7fff, 0x0000, 0x00003a40, 0x00006d00, - 0x00004400, 0x00002a00 }, - { 0x00007d00, 0x01, 0x10, 0x01, 0x00, &sReverbSettings[2], 0x7fff, 0x0000, 0x00003a40, 0x00006d00, - 0x00004400, 0x00002a00 }, - { 0x00007d00, 0x01, 0x10, 0x01, 0x00, &sReverbSettings[3], 0x7fff, 0x0000, 0x00003a40, 0x00006d00, - 0x00004400, 0x00002a00 }, - { 0x00007d00, 0x01, 0x10, 0x01, 0x00, &sReverbSettings[4], 0x7fff, 0x0000, 0x00003a40, 0x00006d00, - 0x00004400, 0x00002a00 }, - { 0x00007d00, 0x01, 0x10, 0x01, 0x00, &sReverbSettings[0], 0x7fff, 0x0000, 0x00004000, 0x00006e00, - 0x00003f00, 0x00002a00 }, - { 0x00007d00, 0x01, 0x10, 0x01, 0x00, &sReverbSettings[1], 0x7fff, 0x0000, 0x00004100, 0x00006e00, - 0x00004400, 0x00002a80 }, - { 0x00007d00, 0x01, 0x14, 0x01, 0x00, &sReverbSettings[5], 0x7fff, 0x0000, 0x00003500, 0x00006280, - 0x00004000, 0x00001b00 } +#ifdef EXPAND_AUDIO_HEAP + {/*1*/ 32000,/*2*/ 1,/*3*/ 40,/*4*/ 1,/*5*/ 0, &sReverbSettings[0],/*6*/ 0x7FFF,/*7*/ 0,/*8*/ 0x8200,/*9*/ 0xDC00,/*10*/ 0xE800,/*11*/ 0x5500 }, +#else + {/*1*/ 32000,/*2*/ 1,/*3*/ 20,/*4*/ 1,/*5*/ 0, &sReverbSettings[0],/*6*/ 0x7FFF,/*7*/ 0,/*8*/ 0x4100,/*9*/ 0x6E00,/*10*/ 0x7400,/*11*/ 0x2A80 }, +#endif }; #endif @@ -48,70 +56,39 @@ struct AudioSessionSettingsEU gAudioSessionPresets[] = { // - memory used for persistent banks // - memory used for temporary sequences // - memory used for temporary banks + +// To increase reverb window sizes beyond 0x1000, please increase the REVERB_WINDOW_SIZE_MAX in heap.c and update AUDIO_HEAP_SIZE by the same amount. #if defined(VERSION_JP) || defined(VERSION_US) +struct ReverbSettingsUS gReverbSettings[18] = +{ + {1, 0x0C00, 0x2FFF}, + {1, 0x0A00, 0x47FF}, + {1, 0x1000, 0x2FFF}, + {1, 0x0E00, 0x3FFF}, + {1, 0x0C00, 0x4FFF}, + {1, 0x0C00, 0x2FFF}, + {1, 0x0A00, 0x47FF}, + {1, 0x0800, 0x37FF}, + {1, 0x0800, 0x2FFF}, + {1, 0x0800, 0x3FFF}, + {1, 0x1000, 0x3FFF}, + {1, 0x1000, 0x2FFF}, + {1, 0x0C00, 0x3FFF}, + {1, 0x0800, 0x4FFF}, + {1, 0x0800, 0x2FFF}, + {1, 0x0800, 0x2FFF}, + {1, 0x0800, 0x2FFF}, + {1, 0x0800, 0x2FFF}, +}; + +// TODO: Does using 40/20 instead of 32/16 for gMaxSimultaneousNotes cause memory problems at high capacities or is it good as is? #ifdef EXPAND_AUDIO_HEAP -struct AudioSessionSettings gAudioSessionPresets[18] = { -#ifdef VERSION_JP - { 32000, 32, 1, 0x0800, 0x2FFF, 0x7FFF, 0x7200, 0xC000, 0x8800, 0x5400 }, - { 32000, 32, 1, 0x0A00, 0x47FF, 0x7FFF, 0x7200, 0xC000, 0x8800, 0x5400 }, - { 32000, 32, 1, 0x1000, 0x2FFF, 0x7FFF, 0x7200, 0xC000, 0x8800, 0x5400 }, - { 32000, 32, 1, 0x0E00, 0x3FFF, 0x7FFF, 0x7200, 0xC000, 0x8800, 0x5400 }, - { 32000, 32, 1, 0x0C00, 0x4FFF, 0x7FFF, 0x7200, 0xC000, 0x8800, 0x5400 }, - { 32000, 32, 1, 0x0800, 0x2FFF, 0x7FFF, 0x7C00, 0xC400, 0x7E00, 0x5400 }, - { 32000, 32, 1, 0x0A00, 0x47FF, 0x7FFF, 0x7E00, 0xC400, 0x8800, 0x5500 }, - { 32000, 40, 1, 0x0800, 0x37FF, 0x7FFF, 0x6600, 0xAA00, 0x8000, 0x3600 }, -#else - { 32000, 32, 1, 0x0C00, 0x2FFF, 0x7FFF, 0x7400, 0xDA00, 0x8800, 0x5400 }, - { 32000, 32, 1, 0x0A00, 0x47FF, 0x7FFF, 0x7400, 0xDA00, 0x8800, 0x5400 }, - { 32000, 32, 1, 0x1000, 0x2FFF, 0x7FFF, 0x7400, 0xDA00, 0x8800, 0x5400 }, - { 32000, 32, 1, 0x0E00, 0x3FFF, 0x7FFF, 0x7400, 0xDA00, 0x8800, 0x5400 }, - { 32000, 32, 1, 0x0C00, 0x4FFF, 0x7FFF, 0x7400, 0xDA00, 0x8800, 0x5400 }, - { 32000, 32, 1, 0x0C00, 0x2FFF, 0x7FFF, 0x8000, 0xDC00, 0x7E00, 0x5400 }, - { 32000, 32, 1, 0x0A00, 0x47FF, 0x7FFF, 0x8200, 0xDC00, 0x8800, 0x5500 }, - { 32000, 40, 1, 0x0800, 0x37FF, 0x7FFF, 0x6980, 0xC500, 0x8000, 0x3600 }, -#endif - { 27000, 32, 1, 0x0800, 0x2FFF, 0x7FFF, 0x4A00, 0xAA00, 0xE800, 0x4800 }, - { 27000, 32, 1, 0x0800, 0x3FFF, 0x7FFF, 0x4A00, 0xAA00, 0xE800, 0x4800 }, - { 27000, 32, 1, 0x1000, 0x2FFF, 0x7FFF, 0x4A00, 0xAA00, 0xE800, 0x4800 }, - { 27000, 32, 1, 0x1000, 0x3FFF, 0x7FFF, 0x4A00, 0xAA00, 0xE800, 0x4800 }, - { 27000, 32, 1, 0x0C00, 0x4FFF, 0x7FFF, 0x4A00, 0xAA00, 0xE800, 0x4800 }, - { 32000, 28, 1, 0x0800, 0x2FFF, 0x7FFF, 0x4A00, 0xAA00, 0xE800, 0x4800 }, - { 32000, 24, 1, 0x0800, 0x2FFF, 0x7FFF, 0x4A00, 0xAA00, 0xE800, 0x4800 }, - { 32000, 20, 1, 0x0800, 0x2FFF, 0x7FFF, 0x4A00, 0xAA00, 0xE800, 0x4800 }, - { 32000, 16, 1, 0x0800, 0x2FFF, 0x7FFF, 0x4A00, 0xAA00, 0xE800, 0x4800 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } +struct AudioSessionSettings gAudioSessionPresets[1] = { + { 32000, 40, 1, 0x1000, 0x2FFF, 0x7FFF, 0x8200, 0xDC00, 0xE800, 0x5500 }, }; #else -struct AudioSessionSettings gAudioSessionPresets[18] = { -#ifdef VERSION_JP - { 32000, 16, 1, 0x0800, 0x2FFF, 0x7FFF, 0x3900, 0x6000, 0x4400, 0x2A00 }, - { 32000, 16, 1, 0x0A00, 0x47FF, 0x7FFF, 0x3900, 0x6000, 0x4400, 0x2A00 }, - { 32000, 16, 1, 0x1000, 0x2FFF, 0x7FFF, 0x3900, 0x6000, 0x4400, 0x2A00 }, - { 32000, 16, 1, 0x0E00, 0x3FFF, 0x7FFF, 0x3900, 0x6000, 0x4400, 0x2A00 }, - { 32000, 16, 1, 0x0C00, 0x4FFF, 0x7FFF, 0x3900, 0x6000, 0x4400, 0x2A00 }, - { 32000, 16, 1, 0x0800, 0x2FFF, 0x7FFF, 0x3E00, 0x6200, 0x3F00, 0x2A00 }, - { 32000, 16, 1, 0x0A00, 0x47FF, 0x7FFF, 0x3F00, 0x6200, 0x4400, 0x2A80 }, - { 32000, 20, 1, 0x0800, 0x37FF, 0x7FFF, 0x3300, 0x5500, 0x4000, 0x1B00 }, -#else - { 32000, 16, 1, 0x0C00, 0x2FFF, 0x7FFF, 0x3A00, 0x6D00, 0x4400, 0x2A00 }, - { 32000, 16, 1, 0x0A00, 0x47FF, 0x7FFF, 0x3A00, 0x6D00, 0x4400, 0x2A00 }, - { 32000, 16, 1, 0x1000, 0x2FFF, 0x7FFF, 0x3A00, 0x6D00, 0x4400, 0x2A00 }, - { 32000, 16, 1, 0x0E00, 0x3FFF, 0x7FFF, 0x3A00, 0x6D00, 0x4400, 0x2A00 }, - { 32000, 16, 1, 0x0C00, 0x4FFF, 0x7FFF, 0x3A00, 0x6D00, 0x4400, 0x2A00 }, - { 32000, 16, 1, 0x0C00, 0x2FFF, 0x7FFF, 0x4000, 0x6E00, 0x3F00, 0x2A00 }, - { 32000, 16, 1, 0x0A00, 0x47FF, 0x7FFF, 0x4100, 0x6E00, 0x4400, 0x2A80 }, - { 32000, 20, 1, 0x0800, 0x37FF, 0x7FFF, 0x34C0, 0x6280, 0x4000, 0x1B00 }, -#endif - { 27000, 16, 1, 0x0800, 0x2FFF, 0x7FFF, 0x2500, 0x5500, 0x7400, 0x2400 }, - { 27000, 16, 1, 0x0800, 0x3FFF, 0x7FFF, 0x2500, 0x5500, 0x7400, 0x2400 }, - { 27000, 16, 1, 0x1000, 0x2FFF, 0x7FFF, 0x2500, 0x5500, 0x7400, 0x2400 }, - { 27000, 16, 1, 0x1000, 0x3FFF, 0x7FFF, 0x2500, 0x5500, 0x7400, 0x2400 }, - { 27000, 16, 1, 0x0C00, 0x4FFF, 0x7FFF, 0x2500, 0x5500, 0x7400, 0x2400 }, - { 32000, 14, 1, 0x0800, 0x2FFF, 0x7FFF, 0x2500, 0x5500, 0x7400, 0x2400 }, - { 32000, 12, 1, 0x0800, 0x2FFF, 0x7FFF, 0x2500, 0x5500, 0x7400, 0x2400 }, - { 32000, 10, 1, 0x0800, 0x2FFF, 0x7FFF, 0x2500, 0x5500, 0x7400, 0x2400 }, - { 32000, 8, 1, 0x0800, 0x2FFF, 0x7FFF, 0x2500, 0x5500, 0x7400, 0x2400 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } +struct AudioSessionSettings gAudioSessionPresets[1] = { + { 32000, 20, 1, 0x1000, 0x2FFF, 0x7FFF, 0x4100, 0x6E00, 0x7400, 0x2A80 }, }; #endif #endif diff --git a/src/audio/data.h b/src/audio/data.h index e0f7b1cd..80bc9581 100644 --- a/src/audio/data.h +++ b/src/audio/data.h @@ -16,8 +16,10 @@ // constant .data #if defined(VERSION_EU) || defined(VERSION_SH) extern struct AudioSessionSettingsEU gAudioSessionPresets[]; +extern struct ReverbSettingsEU sReverbSettings[8]; #else -extern struct AudioSessionSettings gAudioSessionPresets[18]; +extern struct AudioSessionSettings gAudioSessionPresets[1]; +extern struct ReverbSettingsUS gReverbSettings[18]; #endif extern u16 D_80332388[128]; // unused @@ -111,13 +113,13 @@ extern u16 gUnused80226E98[0x10]; extern u32 gAudioRandom; #ifdef EXPAND_AUDIO_HEAP -#if defined(VERSION_US) || defined(VERSION_JP) -#define EXT_AUDIO_HEAP_SIZE 0x24400 +#if defined(VERSION_US) || defined(VERSION_JP) || defined(VERSION_EU) +#define EXT_AUDIO_HEAP_SIZE 0x27400 #define EXT_AUDIO_INIT_POOL_SIZE 0x8000 #else -// EU and SH versions not yet supported for extended audio heap -#define EXT_AUDIO_HEAP_SIZE 0x24400 -#define EXT_AUDIO_INIT_POOL_SIZE 0x8000 +// SH not yet supported for expanded audio heap +#define EXT_AUDIO_HEAP_SIZE 0x0 +#define EXT_AUDIO_INIT_POOL_SIZE 0x0 #endif #else #define EXT_AUDIO_HEAP_SIZE 0x0 @@ -151,11 +153,11 @@ extern OSMesgQueue *D_SH_80350FA8; #if defined(VERSION_EU) || defined(VERSION_SH) #define UNUSED_COUNT_80333EE8 24 -#define AUDIO_HEAP_SIZE (0x2c500 + EXT_AUDIO_HEAP_SIZE + EXT_AUDIO_INIT_POOL_SIZE + BETTER_REVERB_SIZE) -#define AUDIO_INIT_POOL_SIZE (0x2c00 + EXT_AUDIO_INIT_POOL_SIZE) +#define AUDIO_HEAP_SIZE (0x3AB00 + EXT_AUDIO_HEAP_SIZE + EXT_AUDIO_INIT_POOL_SIZE + BETTER_REVERB_SIZE) +#define AUDIO_INIT_POOL_SIZE (0x2C00 + EXT_AUDIO_INIT_POOL_SIZE) #else #define UNUSED_COUNT_80333EE8 16 -#define AUDIO_HEAP_SIZE (0x31150 + EXT_AUDIO_HEAP_SIZE + EXT_AUDIO_INIT_POOL_SIZE + BETTER_REVERB_SIZE) +#define AUDIO_HEAP_SIZE (0x34750 + EXT_AUDIO_HEAP_SIZE + EXT_AUDIO_INIT_POOL_SIZE + BETTER_REVERB_SIZE) #define AUDIO_INIT_POOL_SIZE (0x2500 + EXT_AUDIO_INIT_POOL_SIZE) #endif diff --git a/src/audio/effects.c b/src/audio/effects.c index 71065168..f18af4af 100644 --- a/src/audio/effects.c +++ b/src/audio/effects.c @@ -4,6 +4,7 @@ #include "load.h" #include "data.h" #include "seqplayer.h" +#include "game/main.h" #ifdef VERSION_JP #define US_FLOAT2(x) x##.0 @@ -73,7 +74,7 @@ static void sequence_channel_process_sound(struct SequenceChannel *seqChannel) { for (i = 0; i < 4; i++) { struct SequenceChannelLayer *layer = seqChannel->layers[i]; if (layer != NULL && layer->enabled && layer->note != NULL) { - layer->noteFreqScale = layer->freqScale * seqChannel->freqScale; + layer->noteFreqScale = layer->freqScale * seqChannel->freqScale * gConfig.audioFrequency; layer->noteVelocity = layer->velocitySquare * channelVolume; layer->notePan = (layer->pan * panLayerWeight) + panFromChannel; } @@ -402,7 +403,7 @@ s32 adsr_update(struct AdsrState *adsr) { restart: #endif // fall through - + case ADSR_STATE_LOOP: adsr->delay = BSWAP16(adsr->envelope[adsr->envIndex].delay); switch (adsr->delay) { diff --git a/src/audio/external.c b/src/audio/external.c index 33e7f98c..a228607c 100644 --- a/src/audio/external.c +++ b/src/audio/external.c @@ -57,11 +57,6 @@ struct SoundCharacteristics { // Also the number of frames a discrete sound can be in the WAITING state before being deleted #define SOUND_MAX_FRESHNESS 10 -struct SequenceQueueItem { - u8 seqId; - u8 priority; -}; // size = 0x2 - // data #if defined(VERSION_EU) || defined(VERSION_SH) // moved to bss in data.c @@ -2355,7 +2350,10 @@ void play_music(u8 player, u16 seqArgs, u16 fadeTimer) { } // Abort if the queue is already full. - if (sBackgroundMusicQueueSize == MAX_BACKGROUND_MUSIC_QUEUE_SIZE) { + if (sBackgroundMusicQueueSize >= MAX_BACKGROUND_MUSIC_QUEUE_SIZE) { +#if PUPPYPRINT_DEBUG + append_puppyprint_log("Sequence queue full, aborting."); +#endif return; } @@ -2686,7 +2684,7 @@ void sound_reset(u8 presetId) { func_802ad74c(0xF2000000, 0); #endif #if defined(VERSION_JP) || defined(VERSION_US) - audio_reset_session(&gAudioSessionPresets[presetId]); + audio_reset_session(&gAudioSessionPresets[0], presetId); #else audio_reset_session_eu(presetId); #endif diff --git a/src/audio/external.h b/src/audio/external.h index 96dbc104..0a802a0e 100644 --- a/src/audio/external.h +++ b/src/audio/external.h @@ -18,6 +18,11 @@ #define SEQ_PLAYER_ENV 1 // Misc music like the puzzle jingle #define SEQ_PLAYER_SFX 2 // Sound effects +struct SequenceQueueItem { + u8 seqId; + u8 priority; +}; // size = 0x2 + extern s32 gAudioErrorFlags; extern f32 gGlobalSoundSource[3]; diff --git a/src/audio/heap.c b/src/audio/heap.c index 424df28e..78fc9fbb 100644 --- a/src/audio/heap.c +++ b/src/audio/heap.c @@ -9,6 +9,13 @@ #include "game/game_init.h" #include "game/puppyprint.h" #include "game/vc_check.h" +#include "string.h" + +#ifdef VERSION_EU +#define REVERB_WINDOW_SIZE_MAX 0x1000 +#else +#define REVERB_WINDOW_SIZE_MAX 0x1000 +#endif #define ALIGN16(val) (((val) + 0xF) & ~0xF) @@ -168,34 +175,13 @@ void build_vol_rampings_table(s32 UNUSED unused, s32 len) { #endif void reset_bank_and_seq_load_status(void) { - s32 i; - #ifdef VERSION_SH - for (i = 0; i < 64; i++) { - if (gBankLoadStatus[i] != SOUND_LOAD_STATUS_5) { - gBankLoadStatus[i] = SOUND_LOAD_STATUS_NOT_LOADED; - } - } - - for (i = 0; i < 64; i++) { - if (gUnkLoadStatus[i] != SOUND_LOAD_STATUS_5) { - gUnkLoadStatus[i] = SOUND_LOAD_STATUS_NOT_LOADED; - } - } - - for (i = 0; i < 256; i++) { - if (gSeqLoadStatus[i] != SOUND_LOAD_STATUS_5) { - gSeqLoadStatus[i] = SOUND_LOAD_STATUS_NOT_LOADED; - } - } + bzero(&gBankLoadStatus, sizeof(gBankLoadStatus)); + bzero(&gUnkLoadStatus, sizeof(gUnkLoadStatus)); + bzero(&gSeqLoadStatus, sizeof(gBankLoadStatus)); #else - for (i = 0; i < 64; i++) { - gBankLoadStatus[i] = SOUND_LOAD_STATUS_NOT_LOADED; - } - - for (i = 0; i < 256; i++) { - gSeqLoadStatus[i] = SOUND_LOAD_STATUS_NOT_LOADED; - } + bzero(&gBankLoadStatus, sizeof(gBankLoadStatus)); //Setting this array to zero is equivilent to SOUND_LOAD_STATUS_NOT_LOADED + bzero(&gSeqLoadStatus, sizeof(gSeqLoadStatus)); //Same dealio #endif } @@ -249,35 +235,26 @@ void discard_sequence(s32 seqId) { void *soundAlloc(struct SoundAllocPool *pool, u32 size) { #if defined(VERSION_EU) || defined(VERSION_SH) u8 *start; - u8 *pos; u32 alignedSize = ALIGN16(size); start = pool->cur; if (start + alignedSize <= pool->start + pool->size) { + bzero(start, alignedSize); pool->cur += alignedSize; - for (pos = start; pos < pool->cur; pos++) { - *pos = 0; - } } else { eu_stubbed_printf_1("Heap OverFlow : Not Allocate %d!\n", size); return NULL; } -#ifdef VERSION_SH pool->numAllocatedEntries++; -#endif return start; #else u8 *start; - s32 last; - s32 i; + u32 alignedSize = ALIGN16(size); - if ((pool->cur + ALIGN16(size) <= pool->size + pool->start)) { - start = pool->cur; - pool->cur += ALIGN16(size); - last = pool->cur - start - 1; - for (i = 0; i <= last; i++) { - start[i] = 0; - } + start = pool->cur; + if ((start + alignedSize <= pool->size + pool->start)) { + bzero(start, alignedSize); + pool->cur += alignedSize; } else { return NULL; } @@ -882,7 +859,7 @@ void *get_bank_or_seq(struct SoundMultiPool *arg0, s32 arg1, s32 id) { struct PersistentPool *persistent = &arg0->persistent; for (i = 0; i < persistent->numEntries; i++) { if (id == persistent->entries[i].id) { - eu_stubbed_printf_2("Cache hit %d at stay %d\n", id, i); + //eu_stubbed_printf_2("Cache hit %d at stay %d\n", id, i); return persistent->entries[i].ptr; } } @@ -998,108 +975,43 @@ void decrease_reverb_gain(void) { #endif } -#if defined(VERSION_SH) -void clear_curr_ai_buffer(void) { - s32 currIndex = gCurrAiBufferIndex; - s32 i; - gAiBufferLengths[currIndex] = gAudioBufferParameters.minAiBufferLength; - for (i = 0; i < (s32) (AIBUFFER_LEN / sizeof(s16)); i++) { - gAiBuffers[currIndex][i] = 0; - } -} -#endif - - #if defined(VERSION_EU) || defined(VERSION_SH) s32 audio_shut_down_and_reset_step(void) { s32 i; s32 j; -#ifdef VERSION_SH - s32 num = gAudioBufferParameters.presetUnk4 == 2 ? 2 : 1; -#endif switch (gAudioResetStatus) { case 5: for (i = 0; i < SEQUENCE_PLAYERS; i++) { sequence_player_disable(&gSequencePlayers[i]); } -#ifdef VERSION_SH - gAudioResetFadeOutFramesLeft = 4 / num; -#else - gAudioResetFadeOutFramesLeft = 4; -#endif gAudioResetStatus--; break; case 4: - if (gAudioResetFadeOutFramesLeft != 0) { - gAudioResetFadeOutFramesLeft--; - decrease_reverb_gain(); - } else { - for (i = 0; i < gMaxSimultaneousNotes; i++) { - if (gNotes[i].noteSubEu.enabled && gNotes[i].adsr.state != ADSR_STATE_DISABLED) { - gNotes[i].adsr.fadeOutVel = gAudioBufferParameters.updatesPerFrameInv; - gNotes[i].adsr.action |= ADSR_ACTION_RELEASE; - } + for (i = 0; i < gMaxSimultaneousNotes; i++) { + if (gNotes[i].noteSubEu.enabled && gNotes[i].adsr.state != ADSR_STATE_DISABLED) { + gNotes[i].adsr.fadeOutVel = gAudioBufferParameters.updatesPerFrameInv; + gNotes[i].adsr.action |= ADSR_ACTION_RELEASE; } -#ifdef VERSION_SH - gAudioResetFadeOutFramesLeft = 16 / num; -#else - gAudioResetFadeOutFramesLeft = 16; -#endif - gAudioResetStatus--; } + gAudioResetFadeOutFramesLeft = 0; + gAudioResetStatus--; break; case 3: - if (gAudioResetFadeOutFramesLeft != 0) { - gAudioResetFadeOutFramesLeft--; -#ifdef VERSION_SH - if (1) { - } -#endif - decrease_reverb_gain(); - } else { - for (i = 0; i < NUMAIBUFFERS; i++) { - for (j = 0; j < (s32) (AIBUFFER_LEN / sizeof(s16)); j++) { - gAiBuffers[i][j] = 0; - } - } -#ifdef VERSION_SH - gAudioResetFadeOutFramesLeft = 4 / num; -#else - gAudioResetFadeOutFramesLeft = 4; -#endif - gAudioResetStatus--; - } + gAudioResetStatus--; break; case 2: + bzero(&gAiBuffers[0][0], (AIBUFFER_LEN * NUMAIBUFFERS)); + gAudioResetStatus--; #ifdef VERSION_SH - clear_curr_ai_buffer(); + func_sh_802f23ec(); #endif - if (gAudioResetFadeOutFramesLeft != 0) { - gAudioResetFadeOutFramesLeft--; - } else { - gAudioResetStatus--; -#ifdef VERSION_SH - func_sh_802f23ec(); -#endif - } break; case 1: audio_reset_session(); + bzero(&gAiBuffers[0][0], (AIBUFFER_LEN * NUMAIBUFFERS)); gAudioResetStatus = 0; -#ifdef VERSION_SH - for (i = 0; i < NUMAIBUFFERS; i++) { - gAiBufferLengths[i] = gAudioBufferParameters.maxAiBufferLength; - for (j = 0; j < (s32) (AIBUFFER_LEN / sizeof(s16)); j++) { - gAiBuffers[i][j] = 0; - } - } -#endif } -#ifdef VERSION_SH - if (gAudioResetFadeOutFramesLeft) { - } -#endif if (gAudioResetStatus < 3) { return 0; } @@ -1112,7 +1024,7 @@ s32 audio_shut_down_and_reset_step(void) { void wait_for_audio_frames(s32 frames) { // VC emulator stubs this function because busy loops are not supported // Technically we can put infinite loop that _looks_ like -O0 for emu but this is cleaner - if (gIsVC) + //if (gIsVC) return; gAudioFrameCount = 0; @@ -1123,37 +1035,281 @@ void wait_for_audio_frames(s32 frames) { } #endif +u8 sAudioFirstBoot = 0; +//Separate the reverb settings into their own func. Bit unstable currently, so still only runs at boot. +#if defined(VERSION_EU) || defined(VERSION_SH) +void init_reverb_eu(void) +{ + s16 *mem; + struct AudioSessionSettingsEU *preset = &gAudioSessionPresets[0]; + struct SynthesisReverb *reverb; + struct ReverbSettingsEU *reverbSettings; + s32 i, j; + + // This is called 4 times for numReverbs to work at higher values. This does eat up some memory though. + for (j = 0; j < 4; j++) + { + gSynthesisReverbs[j].useReverb = 0; + + // Both left and right channels are allocated/cleared together, then separated based on the reverb window size + if (!sAudioFirstBoot) + gSynthesisReverbs[j].ringBuffer.left = soundAlloc(&gNotesAndBuffersPool, REVERB_WINDOW_SIZE_MAX * 4); + } + gNumSynthesisReverbs = preset->numReverbs; + for (j = 0; j < gNumSynthesisReverbs; j++) + { + reverb = &gSynthesisReverbs[j]; + reverbSettings = &sReverbSettings[MIN(gAudioResetPresetIdToLoad+j, (sizeof(sReverbSettings) / sizeof(struct ReverbSettingsEU))-1)]; + reverb->windowSize = reverbSettings->windowSize * 0x40; + reverb->downsampleRate = reverbSettings->downsampleRate; + reverb->reverbGain = reverbSettings->gain; + reverb->useReverb = 8; + if (reverb->windowSize > REVERB_WINDOW_SIZE_MAX) + reverb->windowSize = REVERB_WINDOW_SIZE_MAX; + + if (sAudioFirstBoot) { + bzero(reverb->ringBuffer.left, REVERB_WINDOW_SIZE_MAX * 4); + } + else { + reverb->resampleRate = 0x8000 / reverb->downsampleRate; + reverb->resampleStateLeft = soundAlloc(&gNotesAndBuffersPool, 16 * sizeof(s16)); + reverb->resampleStateRight = soundAlloc(&gNotesAndBuffersPool, 16 * sizeof(s16)); + reverb->unk24 = soundAlloc(&gNotesAndBuffersPool, 16 * sizeof(s16)); + reverb->unk28 = soundAlloc(&gNotesAndBuffersPool, 16 * sizeof(s16)); + for (i = 0; i < gAudioBufferParameters.updatesPerFrame; i++) + { + mem = soundAlloc(&gNotesAndBuffersPool, DEFAULT_LEN_2CH); + reverb->items[0][i].toDownsampleLeft = mem; + reverb->items[0][i].toDownsampleRight = mem + DEFAULT_LEN_1CH / sizeof(s16); + mem = soundAlloc(&gNotesAndBuffersPool, DEFAULT_LEN_2CH); + reverb->items[1][i].toDownsampleLeft = mem; + reverb->items[1][i].toDownsampleRight = mem + DEFAULT_LEN_1CH / sizeof(s16); + } + } + + reverb->ringBuffer.right = &reverb->ringBuffer.left[reverb->windowSize]; + reverb->nextRingBufferPos = 0; + reverb->unkC = 0; + reverb->curFrame = 0; + reverb->bufSizePerChannel = reverb->windowSize; + reverb->framesLeftToIgnore = 2; + if (reverb->downsampleRate != 1) { + reverb->resampleRate = 0x8000 / reverb->downsampleRate; + if (sAudioFirstBoot) { + bzero(reverb->resampleStateLeft, 16 * sizeof(s16)); + bzero(reverb->resampleStateRight, 16 * sizeof(s16)); + bzero(reverb->unk24, 16 * sizeof(s16)); + bzero(reverb->unk28, 16 * sizeof(s16)); + + // All reverb downsample buffers are adjacent in memory, so clear them all in a single call + bzero(reverb->items[0][0].toDownsampleLeft, DEFAULT_LEN_1CH * 4 * gAudioBufferParameters.updatesPerFrame); + } + } + } +} +#else +void init_reverb_us(s32 presetId) +{ + s32 reverbWindowSize; + s16 *mem; + s32 i; +#ifdef BETTER_REVERB + s8 reverbConsole; + s32 bufOffset = 0; +#endif + + reverbWindowSize = gReverbSettings[presetId].windowSize; + gReverbDownsampleRate = gReverbSettings[presetId].downsampleRate; +#ifdef BETTER_REVERB + if (gIsConsole) + reverbConsole = betterReverbDownsampleConsole; // Console! + else + reverbConsole = betterReverbDownsampleEmulator; // Setting this to 1 is REALLY slow, please use sparingly! + + if (reverbConsole <= 0) { + reverbConsole = 1; + toggleBetterReverb = FALSE; + } + else { + toggleBetterReverb = TRUE; + } + + if (toggleBetterReverb && betterReverbWindowsSize >= 0) + reverbWindowSize = betterReverbWindowsSize; + + if (gReverbDownsampleRate < (1 << (reverbConsole - 1))) + gReverbDownsampleRate = (1 << (reverbConsole - 1)); + reverbWindowSize /= gReverbDownsampleRate; + if (reverbWindowSize < DEFAULT_LEN_2CH) // Minimum window size to not overflow + reverbWindowSize = DEFAULT_LEN_2CH; +#endif + + switch (gReverbDownsampleRate) { + case 1: + sReverbDownsampleRateLog = 0; + break; + case 2: + sReverbDownsampleRateLog = 1; + break; + case 4: + sReverbDownsampleRateLog = 2; + break; + case 8: + sReverbDownsampleRateLog = 3; + break; + case 16: + sReverbDownsampleRateLog = 4; + break; + default: + sReverbDownsampleRateLog = 0; + } + + if (reverbWindowSize == 0) { + gSynthesisReverb.useReverb = 0; + } else { + gSynthesisReverb.useReverb = 8; + if (reverbWindowSize > REVERB_WINDOW_SIZE_MAX) + reverbWindowSize = REVERB_WINDOW_SIZE_MAX; + + // Both left and right channels are allocated/cleared together, then separated based on the reverb window size + if (!sAudioFirstBoot) { + gSynthesisReverb.ringBuffer.left = soundAlloc(&gNotesAndBuffersPool, REVERB_WINDOW_SIZE_MAX * 2 * sizeof(s16)); + + gSynthesisReverb.resampleStateLeft = soundAlloc(&gNotesAndBuffersPool, 16 * sizeof(s16)); + gSynthesisReverb.resampleStateRight = soundAlloc(&gNotesAndBuffersPool, 16 * sizeof(s16)); + gSynthesisReverb.unk24 = soundAlloc(&gNotesAndBuffersPool, 16 * sizeof(s16)); + gSynthesisReverb.unk28 = soundAlloc(&gNotesAndBuffersPool, 16 * sizeof(s16)); + for (i = 0; i < gAudioUpdatesPerFrame; i++) { + mem = soundAlloc(&gNotesAndBuffersPool, DEFAULT_LEN_2CH); + gSynthesisReverb.items[0][i].toDownsampleLeft = mem; + gSynthesisReverb.items[0][i].toDownsampleRight = mem + DEFAULT_LEN_1CH / sizeof(s16); + mem = soundAlloc(&gNotesAndBuffersPool, DEFAULT_LEN_2CH); + gSynthesisReverb.items[1][i].toDownsampleLeft = mem; + gSynthesisReverb.items[1][i].toDownsampleRight = mem + DEFAULT_LEN_1CH / sizeof(s16); + } + } + else { + bzero(gSynthesisReverb.ringBuffer.left, REVERB_WINDOW_SIZE_MAX * 2 * sizeof(s16)); + } + + gSynthesisReverb.ringBuffer.right = &gSynthesisReverb.ringBuffer.left[reverbWindowSize]; + gSynthesisReverb.nextRingBufferPos = 0; + gSynthesisReverb.unkC = 0; + gSynthesisReverb.curFrame = 0; + gSynthesisReverb.bufSizePerChannel = reverbWindowSize; + gSynthesisReverb.reverbGain = gReverbSettings[presetId].gain; + gSynthesisReverb.framesLeftToIgnore = 2; + if (gReverbDownsampleRate != 1) { + gSynthesisReverb.resampleFlags = A_INIT; + gSynthesisReverb.resampleRate = 0x8000 / gReverbDownsampleRate; + if (sAudioFirstBoot) { + bzero(gSynthesisReverb.resampleStateLeft, 16 * sizeof(s16)); + bzero(gSynthesisReverb.resampleStateRight, 16 * sizeof(s16)); + bzero(gSynthesisReverb.unk24, 16 * sizeof(s16)); + bzero(gSynthesisReverb.unk28, 16 * sizeof(s16)); + + // All reverb downsample buffers are adjacent in memory, so clear them all in a single call + bzero(gSynthesisReverb.items[0][0].toDownsampleLeft, DEFAULT_LEN_1CH * 4 * gAudioUpdatesPerFrame); + } + } + + // This does not have to be reset after being initialized for the first time, which would speed up load times dramatically. + // However, reseting this allows for proper clearing of the reverb buffers, as well as dynamic customization of the delays array. +#ifdef BETTER_REVERB + if (toggleBetterReverb) { + if (!sAudioFirstBoot) { + delayBufsL = (s32**) soundAlloc(&gAudioSessionPool, NUM_ALLPASS * sizeof(s32*)); + delayBufsR = (s32**) soundAlloc(&gAudioSessionPool, NUM_ALLPASS * sizeof(s32*)); + delayBufsL[0] = (s32*) soundAlloc(&gAudioSessionPool, ALIGN16(BETTER_REVERB_SIZE - 0x80)); + } + else { + bzero(delayBufsL[0], ALIGN16(BETTER_REVERB_SIZE - 0x80)); // Can maybe be simplified to clear only the previous allocation size + } + + for (i = 0; i < NUM_ALLPASS; ++i) { + delaysL[i] = delaysBaselineL[i] / gReverbDownsampleRate; + delaysR[i] = delaysBaselineR[i] / gReverbDownsampleRate; + delayBufsL[i] = (s32*) &delayBufsL[0][bufOffset]; + bufOffset += delaysL[i]; + delayBufsR[i] = (s32*) &delayBufsL[0][bufOffset]; // L and R buffers are interpolated adjacently in memory; not a bug + bufOffset += delaysR[i]; + } + } +#endif + } +} +#endif + + #if defined(VERSION_JP) || defined(VERSION_US) -void audio_reset_session(struct AudioSessionSettings *preset) { +void audio_reset_session(struct AudioSessionSettings *preset, s32 presetId) { + if (sAudioFirstBoot) + { + bzero(&gAiBuffers[0][0], (AIBUFFER_LEN * NUMAIBUFFERS)); + gAudioSessionPool.cur = gAudioSessionPool.start; + gSeqAndBankPool.cur = gSeqAndBankPool.start; + gPersistentCommonPool.cur = gPersistentCommonPool.start; + gTemporaryCommonPool.cur = gTemporaryCommonPool.start; + persistent_pool_clear(&gSeqLoadedPool.persistent); + persistent_pool_clear(&gBankLoadedPool.persistent); + persistent_pool_clear(&gUnusedLoadedPool.persistent); + temporary_pool_clear(&gSeqLoadedPool.temporary); + temporary_pool_clear(&gBankLoadedPool.temporary); + temporary_pool_clear(&gUnusedLoadedPool.temporary); + reset_bank_and_seq_load_status(); + + init_reverb_us(presetId); + bzero(&gAiBuffers[0][0], (AIBUFFER_LEN * NUMAIBUFFERS)); + gAudioFrameCount = 0; + while (gAudioFrameCount < 1) { + // spin + } + bzero(&gAiBuffers[0][0], (AIBUFFER_LEN * NUMAIBUFFERS)); + return; + } #else void audio_reset_session(void) { - struct AudioSessionSettingsEU *preset = &gAudioSessionPresets[gAudioResetPresetIdToLoad]; - struct ReverbSettingsEU *reverbSettings; + if (sAudioFirstBoot) + { + gAudioSessionPool.cur = gAudioSessionPool.start; + gSeqAndBankPool.cur = gSeqAndBankPool.start; + gPersistentCommonPool.cur = gPersistentCommonPool.start; + gTemporaryCommonPool.cur = gTemporaryCommonPool.start; + persistent_pool_clear(&gSeqLoadedPool.persistent); + persistent_pool_clear(&gBankLoadedPool.persistent); + persistent_pool_clear(&gUnusedLoadedPool.persistent); + temporary_pool_clear(&gSeqLoadedPool.temporary); + temporary_pool_clear(&gBankLoadedPool.temporary); + temporary_pool_clear(&gUnusedLoadedPool.temporary); + reset_bank_and_seq_load_status(); + + init_reverb_eu(); + return; + } + struct AudioSessionSettingsEU *preset = &gAudioSessionPresets[0]; #endif - s16 *mem; #if defined(VERSION_JP) || defined(VERSION_US) s8 updatesPerFrame; - s32 reverbWindowSize; - s32 k; #endif - s32 i; +#ifdef PUPPYPRINT + OSTime first = osGetTime(); +#endif s32 j; s32 persistentMem; s32 temporaryMem; s32 totalMem; s32 wantMisc; +/* #if defined(VERSION_JP) || defined(VERSION_US) s32 frames; s32 remainingDmas; -#ifdef BETTER_REVERB - s8 reverbConsole; -#endif -#else - struct SynthesisReverb *reverb; + s32 i; #endif +*/ #ifdef VERSION_EU eu_stubbed_printf_1("Heap Reconstruct Start %x\n", gAudioResetPresetIdToLoad); #endif +/* #if defined(VERSION_JP) || defined(VERSION_US) if (gAudioLoadLock != AUDIO_LOCK_UNINITIALIZED) { decrease_reverb_gain(); @@ -1204,14 +1360,10 @@ void audio_reset_session(void) { } gCurrAudioFrameDmaCount = 0; - for (j = 0; j < NUMAIBUFFERS; j++) { - for (k = 0; k < (s32) (AIBUFFER_LEN / sizeof(s16)); k++) { - gAiBuffers[j][k] = 0; - } - } + bzero(&gAiBuffers[0][0], (AIBUFFER_LEN * NUMAIBUFFERS)); } #endif - +*/ gSampleDmaNumListItems = 0; #if defined(VERSION_EU) || defined(VERSION_SH) gAudioBufferParameters.frequency = preset->frequency; @@ -1255,54 +1407,9 @@ void audio_reset_session(void) { gMaxAudioCmds = gMaxSimultaneousNotes * 0x10 * gAudioBufferParameters.updatesPerFrame + preset->numReverbs * 0x20 + 0x300; #endif #else - reverbWindowSize = preset->reverbWindowSize; gAiFrequency = osAiSetFrequency(preset->frequency); gMaxSimultaneousNotes = preset->maxSimultaneousNotes; gSamplesPerFrameTarget = ALIGN16(gAiFrequency / 60); - gReverbDownsampleRate = preset->reverbDownsampleRate; -#if defined(BETTER_REVERB) && (defined(VERSION_US) || defined(VERSION_JP)) - if (gIsConsole) - reverbConsole = betterReverbDownsampleConsole; // Console! - else - reverbConsole = betterReverbDownsampleEmulator; // Setting this to 1 is REALLY slow, please use sparingly! - - if (reverbConsole <= 0) { - reverbConsole = 1; - toggleBetterReverb = FALSE; - } - else { - toggleBetterReverb = TRUE; - } - - if (toggleBetterReverb && betterReverbWindowsSize >= 0) - reverbWindowSize = betterReverbWindowsSize; - - if (gReverbDownsampleRate < (1 << (reverbConsole - 1))) - gReverbDownsampleRate = (1 << (reverbConsole - 1)); - reverbWindowSize /= gReverbDownsampleRate; - if (reverbWindowSize < DEFAULT_LEN_2CH) // Minimum window size to not overflow - reverbWindowSize = DEFAULT_LEN_2CH; -#endif - - switch (gReverbDownsampleRate) { - case 1: - sReverbDownsampleRateLog = 0; - break; - case 2: - sReverbDownsampleRateLog = 1; - break; - case 4: - sReverbDownsampleRateLog = 2; - break; - case 8: - sReverbDownsampleRateLog = 3; - break; - case 16: - sReverbDownsampleRateLog = 4; - break; - default: - sReverbDownsampleRateLog = 0; - } gVolume = preset->volume; gMinAiBufferLength = gSamplesPerFrameTarget - 0x10; @@ -1376,123 +1483,9 @@ void audio_reset_session(void) { gAudioCmdBuffers[j] = soundAlloc(&gNotesAndBuffersPool, gMaxAudioCmds * sizeof(u64)); } - for (j = 0; j < 4; j++) { - gSynthesisReverbs[j].useReverb = 0; - } - gNumSynthesisReverbs = preset->numReverbs; - for (j = 0; j < gNumSynthesisReverbs; j++) { - reverb = &gSynthesisReverbs[j]; - reverbSettings = &preset->reverbSettings[j]; -#ifdef VERSION_SH - reverb->downsampleRate = reverbSettings->downsampleRate; - reverb->windowSize = reverbSettings->windowSize * 64; - reverb->windowSize /= reverb->downsampleRate; + init_reverb_eu(); #else - reverb->windowSize = reverbSettings->windowSize * 64; - reverb->downsampleRate = reverbSettings->downsampleRate; -#endif - reverb->reverbGain = reverbSettings->gain; -#ifdef VERSION_SH - reverb->panRight = reverbSettings->unk4; - reverb->panLeft = reverbSettings->unk6; - reverb->unk5 = reverbSettings->unk8; - reverb->unk08 = reverbSettings->unkA; -#endif - reverb->useReverb = 8; - reverb->ringBuffer.left = soundAlloc(&gNotesAndBuffersPool, reverb->windowSize * 2); - reverb->ringBuffer.right = soundAlloc(&gNotesAndBuffersPool, reverb->windowSize * 2); - reverb->nextRingBufferPos = 0; - reverb->unkC = 0; - reverb->curFrame = 0; - reverb->bufSizePerChannel = reverb->windowSize; - reverb->framesLeftToIgnore = 2; -#ifdef VERSION_SH - reverb->resampleFlags = A_INIT; -#endif - if (reverb->downsampleRate != 1) { -#ifndef VERSION_SH - reverb->resampleFlags = A_INIT; -#endif - reverb->resampleRate = 0x8000 / reverb->downsampleRate; - reverb->resampleStateLeft = soundAlloc(&gNotesAndBuffersPool, 16 * sizeof(s16)); - reverb->resampleStateRight = soundAlloc(&gNotesAndBuffersPool, 16 * sizeof(s16)); - reverb->unk24 = soundAlloc(&gNotesAndBuffersPool, 16 * sizeof(s16)); - reverb->unk28 = soundAlloc(&gNotesAndBuffersPool, 16 * sizeof(s16)); - for (i = 0; i < gAudioBufferParameters.updatesPerFrame; i++) { - mem = soundAlloc(&gNotesAndBuffersPool, DEFAULT_LEN_2CH); - reverb->items[0][i].toDownsampleLeft = mem; - reverb->items[0][i].toDownsampleRight = mem + DEFAULT_LEN_1CH / sizeof(s16); - mem = soundAlloc(&gNotesAndBuffersPool, DEFAULT_LEN_2CH); - reverb->items[1][i].toDownsampleLeft = mem; - reverb->items[1][i].toDownsampleRight = mem + DEFAULT_LEN_1CH / sizeof(s16); - } - } -#ifdef VERSION_SH - if (reverbSettings->unkC != 0) { - reverb->unk108 = sound_alloc_uninitialized(&gNotesAndBuffersPool, 16 * sizeof(s16)); - reverb->unk100 = sound_alloc_uninitialized(&gNotesAndBuffersPool, 8 * sizeof(s16)); - func_sh_802F0DE8(reverb->unk100, reverbSettings->unkC); - } else { - reverb->unk100 = NULL; - } - if (reverbSettings->unkE != 0) { - reverb->unk10C = sound_alloc_uninitialized(&gNotesAndBuffersPool, 16 * sizeof(s16)); - reverb->unk104 = sound_alloc_uninitialized(&gNotesAndBuffersPool, 8 * sizeof(s16)); - func_sh_802F0DE8(reverb->unk104, reverbSettings->unkE); - } else { - reverb->unk104 = NULL; - } -#endif - } - -#else - if (reverbWindowSize == 0) { - gSynthesisReverb.useReverb = 0; - } else { - gSynthesisReverb.useReverb = 8; - gSynthesisReverb.ringBuffer.left = soundAlloc(&gNotesAndBuffersPool, reverbWindowSize * 2); - gSynthesisReverb.ringBuffer.right = soundAlloc(&gNotesAndBuffersPool, reverbWindowSize * 2); - gSynthesisReverb.nextRingBufferPos = 0; - gSynthesisReverb.unkC = 0; - gSynthesisReverb.curFrame = 0; - gSynthesisReverb.bufSizePerChannel = reverbWindowSize; - gSynthesisReverb.reverbGain = preset->reverbGain; - gSynthesisReverb.framesLeftToIgnore = 2; - if (gReverbDownsampleRate != 1) { - gSynthesisReverb.resampleFlags = A_INIT; - gSynthesisReverb.resampleRate = 0x8000 / gReverbDownsampleRate; - gSynthesisReverb.resampleStateLeft = soundAlloc(&gNotesAndBuffersPool, 16 * sizeof(s16)); - gSynthesisReverb.resampleStateRight = soundAlloc(&gNotesAndBuffersPool, 16 * sizeof(s16)); - gSynthesisReverb.unk24 = soundAlloc(&gNotesAndBuffersPool, 16 * sizeof(s16)); - gSynthesisReverb.unk28 = soundAlloc(&gNotesAndBuffersPool, 16 * sizeof(s16)); - for (i = 0; i < gAudioUpdatesPerFrame; i++) { - mem = soundAlloc(&gNotesAndBuffersPool, DEFAULT_LEN_2CH); - gSynthesisReverb.items[0][i].toDownsampleLeft = mem; - gSynthesisReverb.items[0][i].toDownsampleRight = mem + DEFAULT_LEN_1CH / sizeof(s16); - mem = soundAlloc(&gNotesAndBuffersPool, DEFAULT_LEN_2CH); - gSynthesisReverb.items[1][i].toDownsampleLeft = mem; - gSynthesisReverb.items[1][i].toDownsampleRight = mem + DEFAULT_LEN_1CH / sizeof(s16); - } - } - - // This does not have to be reset after being initialized for the first time, which would speed up load times dramatically. - // However, reseting this allows for proper clearing of the reverb buffers, as well as dynamic customization of the delays array. -#if defined(BETTER_REVERB) && (defined(VERSION_US) || defined(VERSION_JP)) - if (toggleBetterReverb) { - for (i = 0; i < NUM_ALLPASS; ++i) { - delaysL[i] = delaysBaselineL[i] / gReverbDownsampleRate; - delaysR[i] = delaysBaselineR[i] / gReverbDownsampleRate; - } - - delayBufsL = (s32**) soundAlloc(&gAudioSessionPool, NUM_ALLPASS * sizeof(s32*)); - delayBufsR = (s32**) soundAlloc(&gAudioSessionPool, NUM_ALLPASS * sizeof(s32*)); - for (i = 0; i < NUM_ALLPASS; ++i) { - delayBufsL[i] = (s32*) soundAlloc(&gAudioSessionPool, delaysL[i] * sizeof(s32)); - delayBufsR[i] = (s32*) soundAlloc(&gAudioSessionPool, delaysR[i] * sizeof(s32)); - } - } -#endif - } + init_reverb_us(presetId); #endif init_sample_dma_buffers(gMaxSimultaneousNotes); @@ -1513,6 +1506,10 @@ void audio_reset_session(void) { gAudioLoadLock = AUDIO_LOCK_NOT_LOADING; } #endif +#ifdef PUPPYPRINT + append_puppyprint_log("Audio Initialised in %dus.", (s32)OS_CYCLES_TO_USEC(osGetTime() - first)); +#endif + sAudioFirstBoot = 1; } #ifdef VERSION_SH diff --git a/src/audio/heap.h b/src/audio/heap.h index 4bc73bd3..e8c839b7 100644 --- a/src/audio/heap.h +++ b/src/audio/heap.h @@ -129,7 +129,7 @@ void *get_bank_or_seq(struct SoundMultiPool *arg0, s32 arg1, s32 id); s32 audio_shut_down_and_reset_step(void); void audio_reset_session(void); #else -void audio_reset_session(struct AudioSessionSettings *preset); +void audio_reset_session(struct AudioSessionSettings *preset, s32 presetId); #endif void discard_bank(s32 bankId); diff --git a/src/audio/internal.h b/src/audio/internal.h index 68d9cf84..fb38a43e 100644 --- a/src/audio/internal.h +++ b/src/audio/internal.h @@ -84,11 +84,20 @@ #endif #endif +#include "game/puppyprint.h" + #ifdef VERSION_EU +/*#if PUPPYPRINT_DEBUG +#define eu_stubbed_printf_0(msg) append_puppyprint_log(msg) +#define eu_stubbed_printf_1(msg, a) append_puppyprint_log(msg, a) +#define eu_stubbed_printf_2(msg, a, b) append_puppyprint_log(msg, a, b) +#define eu_stubbed_printf_3(msg, a, b, c) append_puppyprint_log(msg, a, b, c) +#else*/ #define eu_stubbed_printf_0(msg) stubbed_printf(msg) #define eu_stubbed_printf_1(msg, a) stubbed_printf(msg, a) #define eu_stubbed_printf_2(msg, a, b) stubbed_printf(msg, a, b) #define eu_stubbed_printf_3(msg, a, b, c) stubbed_printf(msg, a, b, c) +//#endif #else #define eu_stubbed_printf_0(msg) #define eu_stubbed_printf_1(msg, a) @@ -749,6 +758,12 @@ struct ReverbSettingsEU u16 gain; }; #else +struct ReverbSettingsUS +{ + u8 downsampleRate; + u16 windowSize; + u16 gain; +}; struct ReverbSettingsEU { u8 downsampleRate; // always 1 diff --git a/src/audio/load.c b/src/audio/load.c index 9ee4da8d..3210b202 100644 --- a/src/audio/load.c +++ b/src/audio/load.c @@ -847,7 +847,7 @@ void preload_sequence(u32 seqId, u8 preloadMask) { if (preloadMask & PRELOAD_SEQUENCE) { // @bug should be IS_SEQ_LOAD_COMPLETE - if (IS_BANK_LOAD_COMPLETE(seqId) == TRUE) { + if (IS_SEQ_LOAD_COMPLETE(seqId) == TRUE) { eu_stubbed_printf_1("SEQ %d ALREADY CACHED\n", seqId); sequenceData = get_bank_or_seq(&gSeqLoadedPool, 2, seqId); } else { @@ -929,7 +929,7 @@ void load_sequence_internal(u32 player, u32 seqId, s32 loadAsync) { } } - eu_stubbed_printf_1("SEQ %d ALREADY CACHED\n", seqId); + eu_stubbed_printf_1("SEQ %d ALREADY CACHED2\n", seqId); init_sequence_player(player); seqPlayer->scriptState.depth = 0; seqPlayer->delay = 0; @@ -1019,7 +1019,7 @@ void audio_init() { eu_stubbed_printf_1("AudioHeap is %x\n", gAudioHeapSize); for (i = 0; i < NUMAIBUFFERS; i++) { - gAiBufferLengths[i] = 0xa0; + gAiBufferLengths[i] = 10; } gAudioFrameCount = 0; @@ -1037,12 +1037,13 @@ void audio_init() { sound_init_main_pools(gAudioInitPoolSize); + bzero(&gAiBuffers, sizeof(gAiBuffers)); for (i = 0; i < NUMAIBUFFERS; i++) { gAiBuffers[i] = soundAlloc(&gAudioInitPool, AIBUFFER_LEN); - for (j = 0; j < (s32) (AIBUFFER_LEN / sizeof(s16)); j++) { + /*for (j = 0; j < (s32) (AIBUFFER_LEN / sizeof(s16)); j++) { gAiBuffers[i][j] = 0; - } + }*/ } #if defined(VERSION_EU) @@ -1050,7 +1051,7 @@ void audio_init() { gAudioResetStatus = 1; audio_shut_down_and_reset_step(); #else - audio_reset_session(&gAudioSessionPresets[0]); + audio_reset_session(&gAudioSessionPresets[0], 0); #endif // Not sure about these prints diff --git a/src/audio/load.h b/src/audio/load.h index 63379d21..002974d9 100644 --- a/src/audio/load.h +++ b/src/audio/load.h @@ -13,6 +13,7 @@ #define IS_SEQUENCE_CHANNEL_VALID(ptr) ((uintptr_t)(ptr) != (uintptr_t)&gSequenceChannelNone) extern struct Note *gNotes; +extern u8 sAudioFirstBoot; // Music in SM64 is played using 3 players: // gSequencePlayers[0] is level background music diff --git a/src/audio/synthesis.c b/src/audio/synthesis.c index 982a0a77..6393c48e 100644 --- a/src/audio/synthesis.c +++ b/src/audio/synthesis.c @@ -45,13 +45,13 @@ /** * This reverb is a much more natural, ambient implementation over vanilla's, though at the cost of some memory and performance. * These parameters are here to provide maximum control over the usage of the reverb effect, as well as with game performance. - * + * * To take advantage of the reverb effect, you can change the echo parameters set in levels/level_defines.h to tailor the reverb to each specific level area. * To adjust reverb presence with individual sound effects, apply the .set_reverb command within sound/sequences/00_sound_player.s (see examples of other sounds that use it). * To use with M64 sequences, set the Effect parameter for each channel accordingly (CC 91 for MIDI files). - * + * * Most parameter configuration is to be done here, though BETTER_REVERB_SIZE can be adjusted in audio/synthesis.h. - * + * * If after changing the parameters, you hear increasing noise followed by a sudden disappearance of reverb and/or scratchy audio, this indicates an s16 overflow. * If this happens, stop immediately and reduce the parameters at fault. This becomes a ticking time bomb, and may eventually result in very loud noise if it reaches the point of s32 overflow. * Depending on the violating parameters chosen, you probably won't ever experience s32 overflow, but s16 overflow still isn't a pleasant experience. @@ -102,12 +102,13 @@ u8 monoReverbEmulator = FALSE; // Set to -1 to use a default preset instead. Higher values represent more audio delay (usually better for echoey spaces). s32 betterReverbWindowsSize = -1; -// These values are set to s32 instead of u8 to increase performance. Setting these to values larger than 0xFF (255) or less than 0 may cause issues and is not recommended. -s32 gReverbRevIndex = 0x5F; // Affects decay time mostly (large values can cause terrible feedback!); can be messed with at any time -s32 gReverbGainIndex = 0x9F; // Affects signal immediately retransmitted back into buffers (mid-high values yield the strongest effect); can be messed with at any time -s32 gReverbWetSignal = 0xE7; // Amount of reverb specific output in final signal (also affects decay); can be messed with at any time, also very easy to control +// These are set to defines rather than variables to increase performance. Change these to s32 if you want them to be configurable in-game. (Maybe extern them in synthesis.h) +// Setting these to values larger than 0xFF (255) or less than 0 may cause issues and is not recommended. +#define REVERB_REV_INDEX 0x60 // Affects decay time mostly (large values can cause terrible feedback!); can be messed with at any time +#define REVERB_GAIN_INDEX 0xA0 // Affects signal immediately retransmitted back into buffers (mid-high values yield the strongest effect); can be messed with at any time +#define REVERB_WET_SIGNAL 0xE8 // Amount of reverb specific output in final signal (also affects decay); can be messed with at any time, also very easy to control -// s32 gReverbDrySignal = 0x00; // Amount of original input in final signal (large values can cause terrible feedback!); declaration and uses commented out by default to improve compiler optimization +// #define REVERB_DRY_SIGNAL = 0x00; // Amount of original input in final signal (large values can cause terrible feedback!); declaration and uses commented out by default to improve compiler optimization /* ---------------------------------------------------------------------ADVANCED REVERB PARAMETERS-------------------------------------------------------------------- */ @@ -155,8 +156,8 @@ s32 reverbMultsR[NUM_ALLPASS / 3] = {0xCF, 0x73, 0x38, 0x1F}; /* -----------------------------------------------------------------------END REVERB PARAMETERS----------------------------------------------------------------------- */ // Do not touch these values manually, unless you want potential for problems. -u32 reverbFilterCount = NUM_ALLPASS; -u32 reverbFilterCountm1 = NUM_ALLPASS - 1; +s32 reverbFilterCount = NUM_ALLPASS; +s32 reverbFilterCountm1 = NUM_ALLPASS - 1; u8 monoReverb = FALSE; u8 toggleBetterReverb = TRUE; s32 allpassIdxL[NUM_ALLPASS] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; @@ -212,15 +213,15 @@ static inline s16 clamp16(s32 x) { } static inline void reverb_samples(s16 *outSampleL, s16 *outSampleR, s32 inSampleL, s32 inSampleR) { - u32 i = 0; + s32 i = 0; s32 j = 0; - u8 k = 0; + s32 k = 0; s32 outTmpL = 0; s32 outTmpR = 0; - s32 tmpCarryoverL = ((tmpBufL[reverbFilterCountm1] * gReverbRevIndex) / 256) + inSampleL; - s32 tmpCarryoverR = ((tmpBufR[reverbFilterCountm1] * gReverbRevIndex) / 256) + inSampleR; + s32 tmpCarryoverL = ((tmpBufL[reverbFilterCountm1] * REVERB_REV_INDEX) / 256) + inSampleL; + s32 tmpCarryoverR = ((tmpBufR[reverbFilterCountm1] * REVERB_REV_INDEX) / 256) + inSampleR; - for (; i < reverbFilterCount; ++i, ++j) { + for (; i != reverbFilterCount; ++i, ++j) { tmpBufL[i] = delayBufsL[i][allpassIdxL[i]]; tmpBufR[i] = delayBufsR[i][allpassIdxR[i]]; @@ -231,15 +232,15 @@ static inline void reverb_samples(s16 *outSampleL, s16 *outSampleR, s32 inSample delayBufsL[i][allpassIdxL[i]] = tmpCarryoverL; delayBufsR[i][allpassIdxR[i]] = tmpCarryoverR; if (i != reverbFilterCountm1) { - tmpCarryoverL = (tmpBufL[i] * gReverbRevIndex) / 256; - tmpCarryoverR = (tmpBufR[i] * gReverbRevIndex) / 256; + tmpCarryoverL = (tmpBufL[i] * REVERB_REV_INDEX) / 256; + tmpCarryoverR = (tmpBufR[i] * REVERB_REV_INDEX) / 256; } } else { - delayBufsL[i][allpassIdxL[i]] = (tmpBufL[i] * (-gReverbGainIndex)) / 256 + tmpCarryoverL; - delayBufsR[i][allpassIdxR[i]] = (tmpBufR[i] * (-gReverbGainIndex)) / 256 + tmpCarryoverR; - tmpCarryoverL = (delayBufsL[i][allpassIdxL[i]] * gReverbGainIndex) / 256 + tmpBufL[i]; - tmpCarryoverR = (delayBufsR[i][allpassIdxR[i]] * gReverbGainIndex) / 256 + tmpBufR[i]; + delayBufsL[i][allpassIdxL[i]] = (tmpBufL[i] * (-REVERB_GAIN_INDEX)) / 256 + tmpCarryoverL; + delayBufsR[i][allpassIdxR[i]] = (tmpBufR[i] * (-REVERB_GAIN_INDEX)) / 256 + tmpCarryoverR; + tmpCarryoverL = (delayBufsL[i][allpassIdxL[i]] * REVERB_GAIN_INDEX) / 256 + tmpBufL[i]; + tmpCarryoverR = (delayBufsR[i][allpassIdxR[i]] * REVERB_GAIN_INDEX) / 256 + tmpBufR[i]; } if (++allpassIdxL[i] == delaysL[i]) @@ -248,18 +249,18 @@ static inline void reverb_samples(s16 *outSampleL, s16 *outSampleR, s32 inSample allpassIdxR[i] = 0; } - *outSampleL = clamp16((outTmpL * gReverbWetSignal/* + inSampleL * gReverbDrySignal*/) / 256); - *outSampleR = clamp16((outTmpR * gReverbWetSignal/* + inSampleR * gReverbDrySignal*/) / 256); + *outSampleL = clamp16((outTmpL * REVERB_WET_SIGNAL/* + inSampleL * REVERB_DRY_SIGNAL*/) / 256); + *outSampleR = clamp16((outTmpR * REVERB_WET_SIGNAL/* + inSampleR * REVERB_DRY_SIGNAL*/) / 256); } static inline void reverb_mono_sample(s16 *outSample, s32 inSample) { - u32 i = 0; + s32 i = 0; s32 j = 0; - u8 k = 0; + s32 k = 0; s32 outTmp = 0; - s32 tmpCarryover = ((tmpBufL[reverbFilterCountm1] * gReverbRevIndex) / 256) + inSample; + s32 tmpCarryover = ((tmpBufL[reverbFilterCountm1] * REVERB_REV_INDEX) / 256) + inSample; - for (; i < reverbFilterCount; ++i, ++j) { + for (; i != reverbFilterCount; ++i, ++j) { tmpBufL[i] = delayBufsL[i][allpassIdxL[i]]; if (j == 2) { @@ -267,18 +268,18 @@ static inline void reverb_mono_sample(s16 *outSample, s32 inSample) { outTmp += (tmpBufL[i] * reverbMultsL[k++]) / 256; delayBufsL[i][allpassIdxL[i]] = tmpCarryover; if (i != reverbFilterCountm1) - tmpCarryover = (tmpBufL[i] * gReverbRevIndex) / 256; + tmpCarryover = (tmpBufL[i] * REVERB_REV_INDEX) / 256; } else { - delayBufsL[i][allpassIdxL[i]] = (tmpBufL[i] * (-gReverbGainIndex)) / 256 + tmpCarryover; - tmpCarryover = (delayBufsL[i][allpassIdxL[i]] * gReverbGainIndex) / 256 + tmpBufL[i]; + delayBufsL[i][allpassIdxL[i]] = (tmpBufL[i] * (-REVERB_GAIN_INDEX)) / 256 + tmpCarryover; + tmpCarryover = (delayBufsL[i][allpassIdxL[i]] * REVERB_GAIN_INDEX) / 256 + tmpBufL[i]; } if (++allpassIdxL[i] == delaysL[i]) allpassIdxL[i] = 0; } - *outSample = clamp16((outTmp * gReverbWetSignal/* + inSample * gReverbDrySignal*/) / 256); + *outSample = clamp16((outTmp * REVERB_WET_SIGNAL/* + inSample * REVERB_DRY_SIGNAL*/) / 256); } #endif @@ -591,11 +592,11 @@ u64 *synthesis_execute(u64 *cmdBuf, s32 *writtenCmds, s16 *aiBuf, s32 bufLen) { #ifdef BETTER_REVERB if (gIsConsole) { - reverbFilterCount = reverbFilterCountConsole; + reverbFilterCount = (s32) reverbFilterCountConsole; monoReverb = monoReverbConsole; } else { - reverbFilterCount = reverbFilterCountEmulator; + reverbFilterCount = (s32) reverbFilterCountEmulator; monoReverb = monoReverbEmulator; } if (reverbFilterCount > NUM_ALLPASS) diff --git a/src/audio/synthesis.h b/src/audio/synthesis.h index 09eae59f..7ee69ad7 100644 --- a/src/audio/synthesis.h +++ b/src/audio/synthesis.h @@ -18,7 +18,7 @@ #endif #if defined(BETTER_REVERB) && (defined(VERSION_US) || defined(VERSION_JP)) - // Size determined by ((all delaysBaselineL/R values * 8) / (2 ^ Minimum Downsample Factor)) + array pointers. + // Size determined by ((all delaysBaselineL/R values * 8) / (2 ^ Minimum Downsample Factor)) + array pointers (0x80). // The default value can be increased or decreased in conjunction with the values in delaysBaselineL/R #define BETTER_REVERB_SIZE 0xF200 @@ -34,10 +34,6 @@ extern u32 reverbFilterCountEmulator; extern u8 monoReverbConsole; extern u8 monoReverbEmulator; extern s32 betterReverbWindowsSize; -extern s32 gReverbRevIndex; -extern s32 gReverbGainIndex; -extern s32 gReverbWetSigna; -// extern s32 gReverbDrySignal; extern const s32 delaysBaselineL[NUM_ALLPASS]; extern const s32 delaysBaselineR[NUM_ALLPASS]; diff --git a/src/boot/main.c b/src/boot/main.c index 4f646400..7cbabe21 100644 --- a/src/boot/main.c +++ b/src/boot/main.c @@ -51,6 +51,8 @@ OSMesg gUnknownMesgBuf[16]; OSViMode VI; +struct Config gConfig; + struct VblankHandler *gVblankHandler1 = NULL; struct VblankHandler *gVblankHandler2 = NULL; struct VblankHandler *gVblankHandler3 = NULL; @@ -460,6 +462,34 @@ void change_vi(OSViMode *mode, int width, int height){ } } +void get_audio_frequency(void) +{ + switch (gConfig.tvType) + { + #if defined(VERSION_JP) || defined(VERSION_US) + case MODE_NTSC: + gConfig.audioFrequency = 1.0f; + break; + case MODE_MPAL: + gConfig.audioFrequency = 0.9915f; + break; + case MODE_PAL: + gConfig.audioFrequency = 0.9876f; + break; + #else + case MODE_NTSC: + gConfig.audioFrequency = 1.0126f; + break; + case MODE_MPAL: + gConfig.audioFrequency = 1.0086f; + break; + case MODE_PAL: + gConfig.audioFrequency = 1.0f; + break; + #endif + } +} + /** * Initialize hardware, start main thread, then idle. */ @@ -471,18 +501,22 @@ void thread1_idle(UNUSED void *arg) { // NTSC //osViSetMode(&osViModeTable[OS_VI_NTSC_LAN1]); VI = osViModeTable[OS_VI_NTSC_LAN1]; + gConfig.tvType = MODE_NTSC; break; case OS_TV_MPAL: // MPAL //osViSetMode(&osViModeTable[OS_VI_MPAL_LAN1]); - VI = osViModeTable[OS_VI_MPAL_LAN1]; + VI = osViModeTable[OS_VI_NTSC_LAN1]; + gConfig.tvType = MODE_MPAL; break; case OS_TV_PAL: // PAL //osViSetMode(&osViModeTable[OS_VI_PAL_LAN1]); - VI = osViModeTable[OS_VI_PAL_LAN1]; + VI = osViModeTable[OS_VI_NTSC_LAN1]; + gConfig.tvType = MODE_PAL; break; } + get_audio_frequency(); change_vi(&VI, SCREEN_WIDTH, SCREEN_HEIGHT); osViSetMode(&VI); osViBlack(TRUE); diff --git a/src/buffers/buffers.c b/src/buffers/buffers.c index a20b7592..907ccf5c 100644 --- a/src/buffers/buffers.c +++ b/src/buffers/buffers.c @@ -10,7 +10,7 @@ #include "audio/synthesis.h" ALIGNED8 u8 gDecompressionHeap[0xD000]; -ALIGNED16 u8 gAudioHeap[DOUBLE_SIZE_ON_64_BIT(0x31200 + EXT_AUDIO_HEAP_SIZE + EXT_AUDIO_INIT_POOL_SIZE + BETTER_REVERB_SIZE)]; +ALIGNED16 u8 gAudioHeap[(DOUBLE_SIZE_ON_64_BIT(AUDIO_HEAP_SIZE + 0x100))]; ALIGNED8 u8 gIdleThreadStack[0x800]; ALIGNED8 u8 gThread3Stack[0x2000]; diff --git a/src/game/crash_screen.c b/src/game/crash_screen.c index 1d24342f..ac7a284f 100644 --- a/src/game/crash_screen.c +++ b/src/game/crash_screen.c @@ -5,6 +5,7 @@ #include "buffers/framebuffers.h" #include "types.h" #include "puppyprint.h" +#include "audio/external.h" #include "sm64.h" @@ -188,11 +189,16 @@ void draw_crash_screen(OSThread *thread) { } osWritebackDCacheAll(); - crash_screen_sleep(2000); + crash_screen_sleep(500); crash_screen_draw_rect(25, 20, 270, 25); crash_screen_print(30, 25, "THREAD:%d (%s)", thread->id, gCauseDesc[cause]); +#if !PUPPYPRINT_DEBUG crash_screen_print(30, 35, "PC:%08XH SR:%08XH VA:%08XH", tc->pc, tc->sr, tc->badvaddr); +#else + crash_screen_print(30, 35, "PC:%08XH SR:%08XH RA:%08XH", tc->pc, tc->sr, (u32) tc->ra); +#endif crash_screen_draw_rect(25, 45, 270, 185); +#if !PUPPYPRINT_DEBUG crash_screen_print(30, 50, "AT:%08XH V0:%08XH V1:%08XH", (u32) tc->at, (u32) tc->v0, (u32) tc->v1); crash_screen_print(30, 60, "A0:%08XH A1:%08XH A2:%08XH", (u32) tc->a0, (u32) tc->a1, @@ -213,6 +219,7 @@ void draw_crash_screen(OSThread *thread) { (u32) tc->sp); crash_screen_print(30, 140, "S8:%08XH RA:%08XH", (u32) tc->s8, (u32) tc->ra); crash_screen_print_fpcsr(tc->fpcsr); + osWritebackDCacheAll(); crash_screen_print_float_reg(30, 170, 0, &tc->fp0.f.f_even); crash_screen_print_float_reg(120, 170, 2, &tc->fp2.f.f_even); @@ -230,6 +237,15 @@ void draw_crash_screen(OSThread *thread) { crash_screen_print_float_reg(120, 210, 26, &tc->fp26.f.f_even); crash_screen_print_float_reg(210, 210, 28, &tc->fp28.f.f_even); crash_screen_print_float_reg(30, 220, 30, &tc->fp30.f.f_even); +#else + s32 i; +#define LINE_HEIGHT 60 + ((LOG_BUFFER_SIZE-1)*10) + for (i = 0; i < LOG_BUFFER_SIZE; i++) + { + crash_screen_print(30, (LINE_HEIGHT)-(i*10), consoleLogTable[i]); + } +#undef LINE_HEIGHT +#endif osWritebackDCacheAll(); osViBlack(FALSE); osViSwapBuffer(gCrashScreen.framebuffer); @@ -250,6 +266,9 @@ OSThread *get_crashed_thread(void) { } extern u16 sRenderedFramebuffer; +extern void audio_signal_game_loop_tick(void); +extern void stop_sounds_in_continuous_banks(void); +extern struct SequenceQueueItem sBackgroundMusicQueue[6]; void thread2_crash_screen(UNUSED void *arg) { OSMesg mesg; @@ -268,7 +287,13 @@ void thread2_crash_screen(UNUSED void *arg) { profiler_update(faultTime, first); #endif } while (thread == NULL); + gCrashScreen.thread.priority = 15; + stop_sounds_in_continuous_banks(); + stop_background_music(sBackgroundMusicQueue[0].seqId); + audio_signal_game_loop_tick(); draw_crash_screen(thread); + play_sound(SOUND_MARIO_WAAAOOOW, gGlobalSoundSource); + audio_signal_game_loop_tick(); for (;;) { } } diff --git a/src/game/game_init.c b/src/game/game_init.c index 43ba7d4d..e98fc46c 100644 --- a/src/game/game_init.c +++ b/src/game/game_init.c @@ -79,9 +79,6 @@ UNUSED static s32 sUnusedGameInitValue = 0; // General timer that runs as the game starts u32 gGlobalTimer = 0; -#ifdef WIDE -s16 gWidescreen; -#endif u8 *gAreaSkyboxStart[AREA_COUNT]; u8 *gAreaSkyboxEnd[AREA_COUNT]; @@ -736,7 +733,7 @@ void thread5_game_loop(UNUSED void *arg) { play_music(SEQ_PLAYER_SFX, SEQUENCE_ARGS(0, SEQ_SOUND_PLAYER), 0); set_sound_mode(save_file_get_sound_mode()); #ifdef WIDE - gWidescreen = save_file_get_widescreen_mode(); + gConfig.widescreen = save_file_get_widescreen_mode(); #endif render_init(); diff --git a/src/game/game_init.h b/src/game/game_init.h index 3cfbdcad..a61e2d60 100644 --- a/src/game/game_init.h +++ b/src/game/game_init.h @@ -42,9 +42,6 @@ extern u8 *gGfxPoolEnd; extern struct GfxPool *gGfxPool; extern u8 gControllerBits; extern u8 gIsConsole; -#ifdef WIDE -extern s16 gWidescreen; -#endif extern u8 gBorderHeight; #ifdef CUSTOM_DEBUG extern u8 gCustomDebugMode; diff --git a/src/game/ingame_menu.c b/src/game/ingame_menu.c index 46966786..ff23c907 100644 --- a/src/game/ingame_menu.c +++ b/src/game/ingame_menu.c @@ -25,6 +25,7 @@ #include "types.h" #include "config.h" #include "puppycam2.h" +#include "main.h" u16 gDialogColorFadeTimer; s8 gLastDialogLineNum; @@ -1567,7 +1568,7 @@ void render_pause_red_coins(void) { void render_widescreen_setting(void) { gSPDisplayList(gDisplayListHead++, dl_ia_text_begin); gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, gDialogTextAlpha); - if (!gWidescreen) { + if (!gConfig.widescreen) { print_generic_string(10, 20, textCurrRatio43); print_generic_string(10, 7, textPressL); } @@ -1577,8 +1578,8 @@ void render_widescreen_setting(void) { } gSPDisplayList(gDisplayListHead++, dl_ia_text_end); if (gPlayer1Controller->buttonPressed & L_TRIG){ - gWidescreen ^= 1; - save_file_set_widescreen_mode(gWidescreen); + gConfig.widescreen ^= 1; + save_file_set_widescreen_mode(gConfig.widescreen); } } #endif diff --git a/src/game/main.h b/src/game/main.h index 21f196f4..ab3396e3 100644 --- a/src/game/main.h +++ b/src/game/main.h @@ -20,6 +20,7 @@ struct RumbleSettings { s16 unk0C; // vibrate s16 unk0E; // decay }; +extern struct Config gConfig; extern OSThread D_80339210; extern OSThread gIdleThread; diff --git a/src/game/puppycam2.c b/src/game/puppycam2.c index 6cc6ca59..ddb6240f 100644 --- a/src/game/puppycam2.c +++ b/src/game/puppycam2.c @@ -24,6 +24,7 @@ #include "mario.h" #include "puppyprint.h" #include "debug_box.h" +#include "main.h" #ifdef PUPPYCAM @@ -84,7 +85,7 @@ static const struct gPCOptionStruct static const struct gPCOptionStruct gPCOptions[]= { //If the min and max are 0 and 1, then the value text is used, otherwise it's ignored. #ifdef WIDE - {/*Option Name*/ 7, /*Option Variable*/ &gWidescreen, /*Option Value Text Start*/ 0, /*Option Minimum*/ FALSE, /*Option Maximum*/ TRUE}, + {/*Option Name*/ 7, /*Option Variable*/ &gConfig.widescreen, /*Option Value Text Start*/ 0, /*Option Minimum*/ FALSE, /*Option Maximum*/ TRUE}, #endif #if MULTILANG {/*Option Name*/ 8, /*Option Variable*/ &gInGameLanguage, /*Option Value Text Start*/ 4, /*Option Minimum*/ 1, /*Option Maximum*/ 3}, diff --git a/src/game/puppyprint.c b/src/game/puppyprint.c index 9b761a36..d0281491 100644 --- a/src/game/puppyprint.c +++ b/src/game/puppyprint.c @@ -330,6 +330,9 @@ void append_puppyprint_log(const char *str, ...) va_end(arguments); return; } +#ifdef UNF + osSyncPrintf(textBytes); +#endif for (i = 0; i < LOG_BUFFER_SIZE-1; i++) { memcpy(consoleLogTable[i], consoleLogTable[i+1], 255); @@ -373,7 +376,7 @@ void puppyprint_render_profiler(void) if (!ramViewer && !benchViewer && !logViewer) { print_fps(16,40); - sprintf(textBytes, "CPU: %dus (%d_)#RSP: %dus (%d_)#RDP: %dus (%d_)", (s32)cpuCount, (s32)OS_CYCLES_TO_USEC(cpuTime)/333, (s32)OS_CYCLES_TO_USEC(rspTime), (s32)OS_CYCLES_TO_USEC(rspTime)/333, (s32)OS_CYCLES_TO_USEC(rdpTime), (s32)OS_CYCLES_TO_USEC(rdpTime)/333); + sprintf(textBytes, "CPU: %dus (%d_)#RSP: %dus (%d_)#RDP: %dus (%d_)", (s32)cpuCount, (s32)OS_CYCLES_TO_USEC(cpuTime)/248, (s32)OS_CYCLES_TO_USEC(rspTime), (s32)OS_CYCLES_TO_USEC(rspTime)/333, (s32)OS_CYCLES_TO_USEC(rdpTime), (s32)OS_CYCLES_TO_USEC(rdpTime)/333); print_small_text(16, 52, textBytes, PRINT_TEXT_ALIGN_LEFT, PRINT_ALL); sprintf(textBytes, "OBJ: %d/%d", gObjectCounter, OBJECT_POOL_CAPACITY); diff --git a/src/game/rendering_graph_node.c b/src/game/rendering_graph_node.c index 5c349f4a..7d992f1f 100644 --- a/src/game/rendering_graph_node.c +++ b/src/game/rendering_graph_node.c @@ -250,7 +250,7 @@ static void geo_process_perspective(struct GraphNodePerspective *node) { u16 perspNorm; Mtx *mtx = alloc_display_list(sizeof(*mtx)); #ifdef WIDE - if (gWidescreen && (gCurrLevelNum != 0x01)){ + if (gConfig.widescreen && (gCurrLevelNum != 0x01)){ aspect = 1.775f; } else { aspect = 1.33333f; diff --git a/src/game/save_file.c b/src/game/save_file.c index bcdcdbaf..525682de 100644 --- a/src/game/save_file.c +++ b/src/game/save_file.c @@ -408,7 +408,7 @@ void puppycam_get_save(void) gSaveBuffer.menuData[0].firstBoot = gSaveBuffer.menuData[0].firstBoot; #ifdef WIDE - gWidescreen = save_file_get_widescreen_mode(); + gConfig.widescreen = save_file_get_widescreen_mode(); #endif puppycam_check_save(); @@ -421,7 +421,7 @@ void puppycam_set_save(void) gSaveBuffer.menuData[0].firstBoot = 4; #ifdef WIDE - save_file_set_widescreen_mode(gWidescreen); + save_file_set_widescreen_mode(gConfig.widescreen); #endif gMainMenuDataModified = TRUE; diff --git a/src/menu/star_select.c b/src/menu/star_select.c index 8bfacca7..624ff5c8 100644 --- a/src/menu/star_select.c +++ b/src/menu/star_select.c @@ -20,7 +20,7 @@ #include "star_select.h" #include "text_strings.h" #include "prevent_bss_reordering.h" -#include "game/game_init.h" +#include "game/main.h" /** * @file star_select.c @@ -94,7 +94,7 @@ void render_100_coin_star(u8 stars) { if (stars & (1 << 6)) { // If the 100 coin star has been collected, create a new star selector next to the coin score. #ifdef WIDE - if (gWidescreen) { + if (gConfig.widescreen) { sStarSelectorModels[6] = spawn_object_abs_with_rot(gCurrentObject, 0, MODEL_STAR, bhvActSelectorStarType, ((370*4.0f)/3), 24, -300, 0, 0, 0); } else { @@ -160,7 +160,7 @@ void bhv_act_selector_init(void) { // Render star selector objects #ifdef WIDE - if (gWidescreen) { + if (gConfig.widescreen) { for (i = 0; i < sVisibleStars; i++) { sStarSelectorModels[i] = spawn_object_abs_with_rot(gCurrentObject, 0, selectorModelIDs[i], bhvActSelectorStarType,