diff --git a/include/config/config_audio.h b/include/config/config_audio.h index 268cccf5e..7e7923291 100644 --- a/include/config/config_audio.h +++ b/include/config/config_audio.h @@ -22,8 +22,9 @@ // #define DISABLE_MARIO_PITCH_SHIFTING /** - * Enables the funky sound processing that takes place with sound effects, that can sometimes cause sounds like the waterfall in castle grounds to sound more unpleasant than necessary. - * This is not the same thing as enabling stereo audio, but it does completely represent the sole differences between the Stereo and Headset sound options. + * Enables the additional spacial processing that takes place with sound effects in vanilla. + * SM64's implementation of this isn't the best, which causes some sounds like the waterfall in castle grounds to sound more unpleasant than necessary. + * This is not the same thing as enabling stereo audio, but it does represent the sole differences between the Stereo and Headset sound options. * Because of this, the Headset sound option will also not appear in the file select menu with this disabled. * Leaving this disabled may also be slightly beneficial for CPU performance. */ diff --git a/include/level_commands.h b/include/level_commands.h index d85a1cebe..323312863 100644 --- a/include/level_commands.h +++ b/include/level_commands.h @@ -73,6 +73,7 @@ enum LevelCommands { /*0x3E*/ LEVEL_CMD_CHANGE_AREA_SKYBOX, /*0x3F*/ LEVEL_CMD_PUPPYLIGHT_ENVIRONMENT, /*0x40*/ LEVEL_CMD_PUPPYLIGHT_NODE, + /*0x41*/ LEVEL_CMD_SET_ECHO, }; enum LevelActs { @@ -448,6 +449,9 @@ enum GoddardScene { #define STOP_MUSIC(fadeOutTime) \ CMD_BBH(LEVEL_CMD_FADEOUT_MUSIC, 0x04, fadeOutTime) +#define SET_ECHO(console, emulator) \ + CMD_BBBB(LEVEL_CMD_SET_ECHO, 0x04, console, emulator) + #define MACRO_OBJECTS(objList) \ CMD_BBH(LEVEL_CMD_SET_MACRO_OBJECTS, 0x08, 0x0000), \ CMD_PTR(objList) diff --git a/src/audio/data.c b/src/audio/data.c index 9515c25e0..e84df0384 100644 --- a/src/audio/data.c +++ b/src/audio/data.c @@ -43,7 +43,7 @@ struct AudioSessionSettingsEU gAudioSessionPresets[] = { #ifdef BETTER_REVERB // Each entry represents an array of variable audio buffer sizes / delays for each respective filter. -u32 delaysArr[][NUM_ALLPASS] = { +u32 sReverbDelaysArr[][NUM_ALLPASS] = { { /* 0 */ 4, 4, 4, 4, 4, 4, @@ -65,7 +65,7 @@ u32 delaysArr[][NUM_ALLPASS] = { }; // Each entry represents an array of multipliers applied to the final output of each group of 3 filters. -u8 reverbMultsArr[][NUM_ALLPASS / 3] = { +u8 sReverbMultsArr[][NUM_ALLPASS / 3] = { /* 0 */ {0x00, 0x00, 0x00, 0x00}, /* 1 */ {0xD7, 0x6F, 0x36, 0x22}, /* 2 */ {0xCF, 0x73, 0x38, 0x1F}, @@ -74,11 +74,11 @@ u8 reverbMultsArr[][NUM_ALLPASS / 3] = { /** * Format: * - useLightweightSettings (Reduce some runtime configurability options in favor of a slight speed boost during processing; Light configurability settings are found in synthesis.h) - * - downsampleRate (Higher values exponentially reduce the number of input samples to process, improving perfomance at cost of quality) + * - downsampleRate (Higher values exponentially reduce the number of input samples to process, improving perfomance at cost of quality; number <= 0 signifies use of vanilla reverb) * - isMono (Only process reverb on the left channel and share it with the right channel, improving performance at cost of quality) * - filterCount (Number of filters to process data with; in general, more filters means higher quality at the cost of performance demand; always 3 with light settings) * - * - windowSize (Size of circular reverb buffer; higher values work better for a more open soundscape, lower is better for a more compact sound) + * - windowSize (Size of circular reverb buffer; higher values work better for a more open soundscape, lower is better for a more compact sound; value of 0 disables all reverb) * - gain (Amount of audio retransmitted into the circular reverb buffer, emulating decay; higher values represent a lengthier decay period) * - gainIndex (Advanced parameter; used to tune the outputs of every first two of three filters; overridden when using light settings) * - reverbIndex (Advanced parameter; used to tune the incoming output of every third filter; overridden when using light settings) @@ -93,36 +93,36 @@ u8 reverbMultsArr[][NUM_ALLPASS / 3] = { */ struct BetterReverbSettings gBetterReverbSettings[] = { { /* Preset 0 - Vanilla Reverb [Default Preset] */ - .useLightweightSettings = FALSE, // Ignored with vanilla reverb - .downsampleRate = -1, // Signifies use of vanilla reverb - .isMono = FALSE, // Ignored with vanilla reverb - .filterCount = NUM_ALLPASS, // Ignored with vanilla reverb + .useLightweightSettings = FALSE, // Ignored with vanilla reverb + .downsampleRate = -1, // Signifies use of vanilla reverb + .isMono = FALSE, // Ignored with vanilla reverb + .filterCount = NUM_ALLPASS, // Ignored with vanilla reverb - .windowSize = -1, // Use vanilla preset window size - .gain = -1, // Use vanilla preset gain value - .gainIndex = 0x00, // Ignored with vanilla reverb - .reverbIndex = 0x00, // Ignored with vanilla reverb + .windowSize = -1, // Use vanilla preset window size + .gain = -1, // Use vanilla preset gain value + .gainIndex = 0x00, // Ignored with vanilla reverb + .reverbIndex = 0x00, // Ignored with vanilla reverb - .delaysL = delaysArr[0], // Ignored with vanilla reverb - .delaysR = delaysArr[0], // Ignored with vanilla reverb - .reverbMultsL = reverbMultsArr[0], // Ignored with vanilla reverb - .reverbMultsR = reverbMultsArr[0], // Ignored with vanilla reverb + .delaysL = sReverbDelaysArr[0], // Ignored with vanilla reverb + .delaysR = sReverbDelaysArr[0], // Ignored with vanilla reverb + .reverbMultsL = sReverbMultsArr[0], // Ignored with vanilla reverb + .reverbMultsR = sReverbMultsArr[0], // Ignored with vanilla reverb }, { /* Preset 1 - Sample Console Configuration */ .useLightweightSettings = TRUE, .downsampleRate = 2, .isMono = FALSE, - .filterCount = (NUM_ALLPASS - 9), // Ignored with lightweight settings + .filterCount = (NUM_ALLPASS - 9), // Ignored with lightweight settings .windowSize = 0x0E00, - .gain = 0x43FF, - .gainIndex = 0xA0, // Ignored with lightweight settings - .reverbIndex = 0x30, // Ignored with lightweight settings + .gain = 0x2FFF, + .gainIndex = 0xA0, // Ignored with lightweight settings + .reverbIndex = 0x30, // Ignored with lightweight settings - .delaysL = delaysArr[1], - .delaysR = delaysArr[2], - .reverbMultsL = reverbMultsArr[1], // Ignored with lightweight settings - .reverbMultsR = reverbMultsArr[2], // Ignored with lightweight settings + .delaysL = sReverbDelaysArr[1], + .delaysR = sReverbDelaysArr[2], + .reverbMultsL = sReverbMultsArr[1], // Ignored with lightweight settings + .reverbMultsR = sReverbMultsArr[2], // Ignored with lightweight settings }, { /* Preset 2 - Sample Emulator Configuration (RCVI Hack or Emulator CPU Overclocking Required!) */ .useLightweightSettings = FALSE, @@ -131,17 +131,60 @@ struct BetterReverbSettings gBetterReverbSettings[] = { .filterCount = NUM_ALLPASS, .windowSize = 0x0E00, - .gain = 0x28FF, + .gain = 0x2AFF, .gainIndex = 0xA0, - .reverbIndex = 0x60, + .reverbIndex = 0x40, - .delaysL = delaysArr[1], - .delaysR = delaysArr[2], - .reverbMultsL = reverbMultsArr[1], - .reverbMultsR = reverbMultsArr[2], + .delaysL = sReverbDelaysArr[1], + .delaysR = sReverbDelaysArr[2], + .reverbMultsL = sReverbMultsArr[1], + .reverbMultsR = sReverbMultsArr[2], }, }; -#endif + +#ifdef PUPPYPRINT_DEBUG +// Used for A/B comparisons and preset configuration debugging alongside Puppyprint Debug +struct BetterReverbSettings gDebugBetterReverbSettings[2] = { + { /* Preset A */ + .useLightweightSettings = FALSE, + .downsampleRate = 2, + .isMono = FALSE, + .filterCount = (NUM_ALLPASS - 9), + + .windowSize = 0x0E00, + .gain = 0x2FFF, + .gainIndex = 0xA0, + .reverbIndex = 0x30, + + .delaysL = sReverbDelaysArr[1], + .delaysR = sReverbDelaysArr[2], + .reverbMultsL = sReverbMultsArr[1], + .reverbMultsR = sReverbMultsArr[2], + }, + { /* Preset B */ + .useLightweightSettings = FALSE, + .downsampleRate = 2, + .isMono = FALSE, + .filterCount = (NUM_ALLPASS - 9), + + .windowSize = 0x0E00, + .gain = 0x2FFF, + .gainIndex = 0xA0, + .reverbIndex = 0x30, + + .delaysL = sReverbDelaysArr[1], + .delaysR = sReverbDelaysArr[2], + .reverbMultsL = sReverbMultsArr[1], + .reverbMultsR = sReverbMultsArr[2], + }, +}; +#endif // PUPPYPRINT_DEBUG + +STATIC_ASSERT(ARRAY_COUNT(gBetterReverbSettings) > 0, "gBetterReverbSettings must contain presets!"); +STATIC_ASSERT(ARRAY_COUNT(sReverbDelaysArr) > 0, "sReverbDelaysArr must not be empty!"); +STATIC_ASSERT(ARRAY_COUNT(sReverbMultsArr) > 0, "sReverbMultsArr must not be empty!"); + +#endif // BETTER_REVERB // Format: // - frequency @@ -913,6 +956,14 @@ s16 gAiBufferLengths[NUMAIBUFFERS]; u32 gAudioRandom; +#ifdef BETTER_REVERB +u8 gBetterReverbPresetCount = ARRAY_COUNT(gBetterReverbSettings); +#ifdef PUPPYPRINT_DEBUG +u8 gReverbDelaysArrCount = ARRAY_COUNT(sReverbDelaysArr); +u8 gReverbMultsArrCount = ARRAY_COUNT(sReverbMultsArr); +#endif // PUPPYPRINT_DEBUG +#endif // BETTER_REVERB + #if defined(VERSION_EU) || defined(VERSION_SH) s32 gAudioErrorFlags; #endif diff --git a/src/audio/data.h b/src/audio/data.h index e614eaa29..acca13717 100644 --- a/src/audio/data.h +++ b/src/audio/data.h @@ -54,8 +54,16 @@ extern struct AudioSessionSettings gAudioSessionSettings; extern struct ReverbSettingsUS gReverbSettings[18]; #endif #ifdef BETTER_REVERB +extern u8 gBetterReverbPresetCount; extern struct BetterReverbSettings gBetterReverbSettings[]; -#endif +#ifdef PUPPYPRINT_DEBUG +extern struct BetterReverbSettings gDebugBetterReverbSettings[2]; +extern u32 sReverbDelaysArr[][NUM_ALLPASS]; +extern u8 sReverbMultsArr[][NUM_ALLPASS / 3]; +extern u8 gReverbDelaysArrCount; +extern u8 gReverbMultsArrCount; +#endif // PUPPYPRINT_DEBUG +#endif // BETTER_REVERB #if defined(VERSION_EU) || defined(VERSION_SH) extern f32 gPitchBendFrequencyScale[256]; diff --git a/src/audio/external.c b/src/audio/external.c index a0fadc2f9..cf33cd378 100644 --- a/src/audio/external.c +++ b/src/audio/external.c @@ -232,7 +232,7 @@ struct MusicDynamic sMusicDynamics[8] = { #define STUB_LEVEL(_0, _1, _2, _3, echo1, echo2, echo3, _7, _8) { echo1, echo2, echo3 }, #define DEFINE_LEVEL(_0, _1, _2, _3, _4, _5, echo1, echo2, echo3, _9, _10) { echo1, echo2, echo3 }, -u8 sLevelAreaReverbs[LEVEL_COUNT][3] = { +s8 sLevelAreaReverbs[LEVEL_COUNT][3] = { { 0x00, 0x00, 0x00 }, // LEVEL_NONE #include "levels/level_defines.h" }; @@ -1138,7 +1138,8 @@ static f32 get_sound_freq_scale(u8 bank, u8 item) { static u32 get_sound_reverb(UNUSED u8 bank, UNUSED u8 soundIndex, u8 channelIndex) { u8 area; u8 level; - u8 reverb; + s8 areaEcho; + s16 reverb; // Disable level reverb if NO_ECHO is set if (sSoundBanks[bank][soundIndex].soundBits & SOUND_NO_ECHO) { @@ -1152,18 +1153,27 @@ static u32 get_sound_reverb(UNUSED u8 bank, UNUSED u8 soundIndex, u8 channelInde } } - // reverb = reverb adjustment + level reverb + a volume-dependent value + areaEcho = sLevelAreaReverbs[level][area]; + + if (gAreaData[gCurrAreaIndex].useEchoOverride && !(sSoundBanks[bank][soundIndex].soundBits & SOUND_NO_ECHO)) { + areaEcho = gAreaData[gCurrAreaIndex].echoOverride; + } + + // reverb = reverb adjustment + level reverb (or level script override value) + a volume-dependent value // The volume-dependent value is 0 when volume is at maximum, and raises to // LOW_VOLUME_REVERB when the volume is 0 - reverb = (u8)(u8) gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->soundScriptIO[5] - + sLevelAreaReverbs[level][area] - + ((1.0f - gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->volume) - * LOW_VOLUME_REVERB); + reverb = (s16) ((u8) gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->soundScriptIO[5]) + areaEcho; - if (reverb > 0x7f) { + // NOTE: In some cases, it may be better to apply this after ensuring reverb is non-negative so the result doesn't end up sounding way too dry. + // This has been left as-is however because in most cases where negative reverb is even used, this is probably desirable anyway. + reverb += (s16) ((1.0f - gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->volume) * LOW_VOLUME_REVERB); + + if (reverb < 0 || areaEcho <= -0x80) { + reverb = 0; + } else if (reverb > 0x7f) { reverb = 0x7f; } - return reverb; + return (u8) reverb; } /** diff --git a/src/audio/external.h b/src/audio/external.h index 706d073cc..8265cde40 100644 --- a/src/audio/external.h +++ b/src/audio/external.h @@ -4,6 +4,7 @@ #include #include "types.h" +#include "level_table.h" // Sequence arguments, passed to seq_player_play_sequence. seqId may be bit-OR'ed with // SEQ_VARIATION; this will load the same sequence, but set a variation @@ -34,6 +35,8 @@ extern f32 gGlobalSoundSource[3]; // defined in data.c, used by the game extern u32 gAudioRandom; +extern s8 sLevelAreaReverbs[LEVEL_COUNT][3]; + struct SPTask *create_next_audio_frame_task(void); void play_sound(s32 soundBits, f32 *pos); void audio_signal_game_loop_tick(void); diff --git a/src/audio/heap.c b/src/audio/heap.c index 205817501..eab71dbcd 100644 --- a/src/audio/heap.c +++ b/src/audio/heap.c @@ -1048,8 +1048,20 @@ void init_reverb_us(s32 presetId) { s32 reverbWindowSize = gReverbSettings[presetId].windowSize; gReverbDownsampleRate = gReverbSettings[presetId].downsampleRate; #ifdef BETTER_REVERB - // This will likely crash if given an invalid preset value. Adding a safety check here isn't worth the usability interference. - struct BetterReverbSettings *betterReverbPreset = &gBetterReverbSettings[gBetterReverbPreset]; + struct BetterReverbSettings *betterReverbPreset = &gBetterReverbSettings[gBetterReverbPresetValue]; + +#ifdef PUPPYPRINT_DEBUG + if ((s8) gBetterReverbPresetValue < 0 && (s8) gBetterReverbPresetValue >= -ARRAY_COUNT(gDebugBetterReverbSettings)) { + betterReverbPreset = &gDebugBetterReverbSettings[ARRAY_COUNT(gDebugBetterReverbSettings) + (s8) gBetterReverbPresetValue]; + } else if (gBetterReverbPresetValue >= gBetterReverbPresetCount) { +#else + if (gBetterReverbPresetValue >= gBetterReverbPresetCount) { +#endif + aggress(gBetterReverbPresetCount > 0, "No BETTER_REVERB presets exist!"); + + assert(gBetterReverbPresetValue < gBetterReverbPresetCount, "BETTER_REVERB preset value exceeds total number of available presets!"); + betterReverbPreset = &gBetterReverbSettings[0]; + } betterReverbLightweight = betterReverbPreset->useLightweightSettings; betterReverbDownsampleRate = betterReverbPreset->downsampleRate; @@ -1071,9 +1083,10 @@ void init_reverb_us(s32 presetId) { if (betterReverbWindowsSize >= 0) { reverbWindowSize = betterReverbWindowsSize; + if (reverbWindowSize < (DEFAULT_LEN_2CH * 2) && betterReverbWindowsSize != 0) // Minimum window size to not overflow + reverbWindowSize = (DEFAULT_LEN_2CH * 2); reverbWindowSize /= gReverbDownsampleRate; - if (reverbWindowSize < DEFAULT_LEN_2CH && betterReverbWindowsSize != 0) // Minimum window size to not overflow - reverbWindowSize = DEFAULT_LEN_2CH; + reverbWindowSize = ALIGN16(reverbWindowSize); } } @@ -1138,7 +1151,7 @@ void init_reverb_us(s32 presetId) { if (!gSynthesisReverb.useReverb) toggleBetterReverb = FALSE; - if (betterReverbPreset->gain > 0) + if (betterReverbPreset->gain >= 0) gSynthesisReverb.reverbGain = (u16) betterReverbPreset->gain; if (!sAudioIsInitialized) diff --git a/src/audio/heap.h b/src/audio/heap.h index 26a3e2ddd..f34a5a673 100644 --- a/src/audio/heap.h +++ b/src/audio/heap.h @@ -140,9 +140,11 @@ void *alloc_bank_or_seq(struct SoundMultiPool *arg0, s32 arg1, s32 size, s32 arg void *get_bank_or_seq(struct SoundMultiPool *arg0, s32 arg1, s32 id); #endif #if defined(VERSION_EU) || defined(VERSION_SH) +void init_reverb_eu(void); s32 audio_shut_down_and_reset_step(void); void audio_reset_session(void); #else +void init_reverb_us(s32 presetId); void audio_reset_session(s32 reverbPresetId); #endif void discard_bank(s32 bankId); diff --git a/src/audio/synthesis.c b/src/audio/synthesis.c index de5bf8985..e32dd616b 100644 --- a/src/audio/synthesis.c +++ b/src/audio/synthesis.c @@ -43,7 +43,7 @@ #ifdef BETTER_REVERB // Do not touch these values manually, unless you want potential for problems. -u8 gBetterReverbPreset = 0; +u8 gBetterReverbPresetValue = 0; u8 toggleBetterReverb = FALSE; u8 betterReverbLightweight = FALSE; u8 monoReverb; @@ -768,9 +768,9 @@ u64 *synthesis_do_one_audio_update(s16 *aiBuf, s32 bufLen, u64 *cmd, s32 updateI aResample(cmd++, gSynthesisReverb.resampleFlags, (u16) gSynthesisReverb.resampleRate, VIRTUAL_TO_PHYSICAL2(gSynthesisReverb.resampleStateLeft)); aSetBuffer(cmd++, 0, t4 + DMEM_ADDR_WET_RIGHT_CH, DMEM_ADDR_RIGHT_CH, bufLen << 1); aResample(cmd++, gSynthesisReverb.resampleFlags, (u16) gSynthesisReverb.resampleRate, VIRTUAL_TO_PHYSICAL2(gSynthesisReverb.resampleStateRight)); - aSetBuffer(cmd++, 0, 0, 0, DEFAULT_LEN_2CH); - aMix(cmd++, 0, /*gain*/ 0x8000 + gSynthesisReverb.reverbGain, /*in*/ DMEM_ADDR_LEFT_CH, /*out*/ DMEM_ADDR_LEFT_CH); aDMEMMove(cmd++, DMEM_ADDR_LEFT_CH, DMEM_ADDR_WET_LEFT_CH, DEFAULT_LEN_2CH); + aSetBuffer(cmd++, 0, 0, 0, DEFAULT_LEN_2CH); + aMix(cmd++, 0, /*gain*/ 0x8000 + gSynthesisReverb.reverbGain, /*in*/ DMEM_ADDR_WET_LEFT_CH, /*out*/ DMEM_ADDR_WET_LEFT_CH); } AUDIO_PROFILER_SWITCH(PROFILER_TIME_SUB_AUDIO_SYNTHESIS_ENVELOPE_REVERB, PROFILER_TIME_SUB_AUDIO_SYNTHESIS_PROCESSING); diff --git a/src/audio/synthesis.h b/src/audio/synthesis.h index 075914d59..dc585d5d5 100644 --- a/src/audio/synthesis.h +++ b/src/audio/synthesis.h @@ -54,7 +54,7 @@ enum ChannelIndexes { /* ------------ BETTER REVERB EXTERNED VARIABLES ------------ */ extern u8 toggleBetterReverb; -extern u8 gBetterReverbPreset; +extern u8 gBetterReverbPresetValue; extern u8 betterReverbLightweight; extern s8 betterReverbDownsampleRate; extern u8 monoReverb; diff --git a/src/engine/level_script.c b/src/engine/level_script.c index fc6280c6f..2caa0eff7 100644 --- a/src/engine/level_script.c +++ b/src/engine/level_script.c @@ -754,9 +754,9 @@ static void level_cmd_set_menu_music(void) { #ifdef BETTER_REVERB // Must come before set_background_music() if (gIsConsole) - gBetterReverbPreset = CMD_GET(u8, 4); + gBetterReverbPresetValue = CMD_GET(u8, 4); else - gBetterReverbPreset = CMD_GET(u8, 5); + gBetterReverbPresetValue = CMD_GET(u8, 5); #endif set_background_music(0, CMD_GET(s16, 2), 0); sCurrentCmd = CMD_NEXT; @@ -904,6 +904,17 @@ static void level_cmd_puppylight_node(void) { sCurrentCmd = CMD_NEXT; } +static void level_cmd_set_echo(void) { + if (sCurrAreaIndex >= 0 && sCurrAreaIndex < AREA_COUNT) { + gAreaData[sCurrAreaIndex].useEchoOverride = TRUE; + if (gIsConsole) + gAreaData[sCurrAreaIndex].echoOverride = CMD_GET(s8, 2); + else + gAreaData[sCurrAreaIndex].echoOverride = CMD_GET(s8, 3); + } + sCurrentCmd = CMD_NEXT; +} + static void (*LevelScriptJumpTable[])(void) = { /*LEVEL_CMD_LOAD_AND_EXECUTE */ level_cmd_load_and_execute, /*LEVEL_CMD_EXIT_AND_EXECUTE */ level_cmd_exit_and_execute, @@ -970,6 +981,7 @@ static void (*LevelScriptJumpTable[])(void) = { /*LEVEL_CMD_CHANGE_AREA_SKYBOX */ level_cmd_change_area_skybox, /*LEVEL_CMD_PUPPYLIGHT_ENVIRONMENT */ level_cmd_puppylight_environment, /*LEVEL_CMD_PUPPYLIGHT_NODE */ level_cmd_puppylight_node, + /*LEVEL_CMD_SET_ECHO */ level_cmd_set_echo, }; struct LevelCommand *level_script_execute(struct LevelCommand *cmd) { diff --git a/src/game/area.c b/src/game/area.c index b9fe4484f..53b0ea2d3 100644 --- a/src/game/area.c +++ b/src/game/area.c @@ -208,6 +208,8 @@ void clear_areas(void) { gAreaData[i].dialog[1] = DIALOG_NONE; gAreaData[i].musicParam = 0; gAreaData[i].musicParam2 = 0; + gAreaData[i].useEchoOverride = FALSE; + gAreaData[i].echoOverride = 0; #ifdef BETTER_REVERB gAreaData[i].betterReverbPreset = 0; #endif diff --git a/src/game/area.h b/src/game/area.h index ff544e9bb..36cfdc3f3 100644 --- a/src/game/area.h +++ b/src/game/area.h @@ -73,8 +73,10 @@ struct Area { /*0x34*/ u8 dialog[2]; // Level start dialog number (set by level script cmd 0x30) /*0x36*/ u16 musicParam; /*0x38*/ u16 musicParam2; + /*0x3A*/ u8 useEchoOverride; // Should area echo be overridden using echoOverride? + /*0x3B*/ s8 echoOverride; // Value used to override the area echo values defined in level_defines.h #ifdef BETTER_REVERB - /*0x3A*/ u8 betterReverbPreset; + /*0x3C*/ u8 betterReverbPreset; #endif }; diff --git a/src/game/level_update.c b/src/game/level_update.c index 77f1de81d..c4d4e7b34 100644 --- a/src/game/level_update.c +++ b/src/game/level_update.c @@ -178,6 +178,16 @@ u32 pressed_pause(void) { u32 dialogActive = get_dialog_id() >= 0; u32 intangible = (gMarioState->action & ACT_FLAG_INTANGIBLE) != 0; +#ifdef PUPPYPRINT_DEBUG +#ifdef BETTER_REVERB + if (sPPDebugPage == PUPPYPRINT_PAGE_RAM || sPPDebugPage == PUPPYPRINT_PAGE_LEVEL_SELECT || sPPDebugPage == PUPPYPRINT_PAGE_BETTER_REVERB) { +#else + if (sPPDebugPage == PUPPYPRINT_PAGE_RAM || sPPDebugPage == PUPPYPRINT_PAGE_LEVEL_SELECT) { +#endif + return FALSE; + } +#endif + if (!intangible && !dialogActive && !gWarpTransition.isActive && sDelayedWarpOp == WARP_OP_NONE && (gPlayer1Controller->buttonPressed & START_BUTTON)) { return TRUE; @@ -397,7 +407,7 @@ void init_mario_after_warp(void) { if (gCurrDemoInput == NULL) { #ifdef BETTER_REVERB - gBetterReverbPreset = gCurrentArea->betterReverbPreset; + gBetterReverbPresetValue = gCurrentArea->betterReverbPreset; #endif set_background_music(gCurrentArea->musicParam, gCurrentArea->musicParam2, 0); @@ -509,7 +519,7 @@ void warp_credits(void) { if (gCurrCreditsEntry == NULL || gCurrCreditsEntry == sCreditsSequence) { #ifdef BETTER_REVERB - gBetterReverbPreset = gCurrentArea->betterReverbPreset; + gBetterReverbPresetValue = gCurrentArea->betterReverbPreset; #endif set_background_music(gCurrentArea->musicParam, gCurrentArea->musicParam2, 0); } @@ -1008,7 +1018,11 @@ s32 play_mode_normal(void) { check_instant_warp(); #ifdef PUPPYPRINT_DEBUG +#ifdef BETTER_REVERB + if (sPPDebugPage != PUPPYPRINT_PAGE_RAM && sPPDebugPage != PUPPYPRINT_PAGE_LEVEL_SELECT && sPPDebugPage != PUPPYPRINT_PAGE_BETTER_REVERB) { +#else if (sPPDebugPage != PUPPYPRINT_PAGE_RAM && sPPDebugPage != PUPPYPRINT_PAGE_LEVEL_SELECT) { +#endif if (sTimerRunning && gHudDisplay.timer < 17999) { gHudDisplay.timer++; } @@ -1026,7 +1040,11 @@ s32 play_mode_normal(void) { #endif if (gCurrentArea != NULL) { #ifdef PUPPYPRINT_DEBUG - if (sPPDebugPage != PUPPYPRINT_PAGE_RAM && sPPDebugPage != PUPPYPRINT_PAGE_LEVEL_SELECT) { +#ifdef BETTER_REVERB + if (sPPDebugPage != PUPPYPRINT_PAGE_RAM && sPPDebugPage != PUPPYPRINT_PAGE_LEVEL_SELECT && sPPDebugPage != PUPPYPRINT_PAGE_BETTER_REVERB) { +#else + if (sPPDebugPage != PUPPYPRINT_PAGE_RAM && sPPDebugPage != PUPPYPRINT_PAGE_LEVEL_SELECT) { +#endif update_camera(gCurrentArea->camera); } #else @@ -1275,7 +1293,7 @@ s32 init_level(void) { if (gCurrDemoInput == NULL) { #ifdef BETTER_REVERB - gBetterReverbPreset = gCurrentArea->betterReverbPreset; + gBetterReverbPresetValue = gCurrentArea->betterReverbPreset; #endif set_background_music(gCurrentArea->musicParam, gCurrentArea->musicParam2, 0); } diff --git a/src/game/puppyprint.c b/src/game/puppyprint.c index 30651dcb5..41e69fa30 100644 --- a/src/game/puppyprint.c +++ b/src/game/puppyprint.c @@ -26,7 +26,9 @@ a modern game engine's developer's console. #include #include "config.h" +#include "seq_ids.h" #include "game_init.h" +#include "sound_init.h" #include "memory.h" #include "print.h" #include "string.h" @@ -40,7 +42,9 @@ a modern game engine's developer's console. #include "object_list_processor.h" #include "engine/surface_load.h" #include "audio/data.h" +#include "audio/external.h" #include "audio/heap.h" +#include "audio/load.h" #include "hud.h" #include "debug_box.h" #include "color_presets.h" @@ -599,6 +603,378 @@ void puppyprint_level_select_menu(void) { } } +#ifdef BETTER_REVERB + +#define DEBUG_REVERB_PRESET_COUNT ARRAY_COUNT(gDebugBetterReverbSettings) + +enum BetterReverbDebugFields { + PPREVERB_USE_LIGHTWEIGHT, + PPREVERB_DOWNSAMPLE_RATE, + PPREVERB_IS_MONO, + PPREVERB_FILTER_COUNT, + PPREVERB_WINDOW_SIZE, + PPREVERB_GAIN, + PPREVERB_GAIN_INDEX, + PPREVERB_REVERB_INDEX, + PPREVERB_DELAYS_L, + PPREVERB_DELAYS_R, + PPREVERB_REVERB_MULTS_L, + PPREVERB_REVERB_MULTS_R, + PPREVERB_AREA_ECHO, + PPREVERB_TOTAL, +}; + +struct BetterReverbDebugSizes { + u8 treatAsEntryCount; + u8 bytes; + s32 entryMinimum; + s32 entryMaximum; +}; + +static struct BetterReverbDebugSizes maxReverbEntrySizes[PPREVERB_TOTAL] = { + {.treatAsEntryCount = TRUE, .bytes = 1, .entryMinimum = 0, .entryMaximum = 1}, // useLightweightSettings + {.treatAsEntryCount = TRUE, .bytes = 1, .entryMinimum = -1, .entryMaximum = 5}, // downsampleRate (seems to work up to 7 before things are audibly dangerous, but I suspect it's still unsafe) + {.treatAsEntryCount = TRUE, .bytes = 1, .entryMinimum = 0, .entryMaximum = 1}, // isMono + {.treatAsEntryCount = TRUE, .bytes = 1, .entryMinimum = 3, .entryMaximum = NUM_ALLPASS}, // filterCount + {.treatAsEntryCount = FALSE, .bytes = 2, .entryMinimum = -1, .entryMaximum = 0x7FFF}, // windowSize + {.treatAsEntryCount = FALSE, .bytes = 2, .entryMinimum = -1, .entryMaximum = 0x7FFF}, // gain + {.treatAsEntryCount = FALSE, .bytes = 1, .entryMinimum = 0, .entryMaximum = 0xFF}, // gainIndex + {.treatAsEntryCount = FALSE, .bytes = 1, .entryMinimum = 0, .entryMaximum = 0xFF}, // reverbIndex + {.treatAsEntryCount = TRUE, .bytes = 1, .entryMinimum = 0, .entryMaximum = 1}, // delaysL + {.treatAsEntryCount = TRUE, .bytes = 1, .entryMinimum = 0, .entryMaximum = 1}, // delaysR + {.treatAsEntryCount = TRUE, .bytes = 1, .entryMinimum = 0, .entryMaximum = 1}, // reverbMultsL + {.treatAsEntryCount = TRUE, .bytes = 1, .entryMinimum = 0, .entryMaximum = 1}, // reverbMultsR + {.treatAsEntryCount = FALSE, .bytes = 1, .entryMinimum = -0x80, .entryMaximum = 0x7F}, // area echo (not part of struct) +}; + +#define REVERB_TOP_PRIO(x) (((x) | (0xFF << SOUNDARGS_SHIFT_PRIORITY)) & ~SOUND_NO_ECHO) +static u32 betterReverbSfx[] = { + REVERB_TOP_PRIO(SOUND_MARIO_YAH_WAH_HOO), + REVERB_TOP_PRIO(SOUND_MARIO_YAH_WAH_HOO + (1 << 16)), + REVERB_TOP_PRIO(SOUND_MARIO_YAH_WAH_HOO + (2 << 16)), + REVERB_TOP_PRIO(SOUND_MARIO_HOOHOO), + REVERB_TOP_PRIO(SOUND_MARIO_YAHOO), + REVERB_TOP_PRIO(SOUND_MARIO_UH), + REVERB_TOP_PRIO(SOUND_MARIO_HRMM), + REVERB_TOP_PRIO(SOUND_MARIO_WAH2), + REVERB_TOP_PRIO(SOUND_MARIO_WHOA), + REVERB_TOP_PRIO(SOUND_MARIO_EEUH), + REVERB_TOP_PRIO(SOUND_MARIO_ATTACKED), + REVERB_TOP_PRIO(SOUND_MARIO_OOOF), + REVERB_TOP_PRIO(SOUND_MARIO_HERE_WE_GO), + REVERB_TOP_PRIO(SOUND_MARIO_YAWNING), + REVERB_TOP_PRIO(SOUND_MARIO_WAAAOOOW), + REVERB_TOP_PRIO(SOUND_MARIO_HAHA), + REVERB_TOP_PRIO(SOUND_MARIO_UH_LEDGE_CLIMB_FAST), + REVERB_TOP_PRIO(SOUND_MARIO_ON_FIRE), + REVERB_TOP_PRIO(SOUND_MARIO_DYING), + REVERB_TOP_PRIO(SOUND_MARIO_PANTING_COLD), + REVERB_TOP_PRIO(SOUND_MARIO_PANTING), + REVERB_TOP_PRIO(SOUND_MARIO_MAMA_MIA), + REVERB_TOP_PRIO(SOUND_MARIO_DROWNING), + REVERB_TOP_PRIO(SOUND_MARIO_YAHOO_WAHA_YIPPEE), + REVERB_TOP_PRIO(SOUND_MARIO_YAHOO_WAHA_YIPPEE + (3 << 16)), + REVERB_TOP_PRIO(SOUND_MARIO_YAHOO_WAHA_YIPPEE + (4 << 16)), + REVERB_TOP_PRIO(SOUND_MARIO_DOH), + REVERB_TOP_PRIO(SOUND_MARIO_GAME_OVER), + REVERB_TOP_PRIO(SOUND_MARIO_HELLO), + REVERB_TOP_PRIO(SOUND_MARIO_PRESS_START_TO_PLAY), + REVERB_TOP_PRIO(SOUND_MARIO_TWIRL_BOUNCE), + REVERB_TOP_PRIO(SOUND_MARIO_SO_LONGA_BOWSER), + REVERB_TOP_PRIO(SOUND_MARIO_IMA_TIRED), +}; +#undef REVERB_TOP_PRIO + +static s8 ppAreaEchos[DEBUG_REVERB_PRESET_COUNT] = {0}; + +static s32 ppReverbSide = 0; +static s32 ppReverbSelectY = 0; + +s32 better_reverb_get_or_set_field(u8 shouldSet, s32 xIndex, s32 yIndex, s32 valueToSet) { + s32 ret = 0; + + if (shouldSet) { + if (valueToSet < maxReverbEntrySizes[yIndex].entryMinimum) { + valueToSet = maxReverbEntrySizes[yIndex].entryMinimum; + } else if (valueToSet > maxReverbEntrySizes[yIndex].entryMaximum) { + valueToSet = maxReverbEntrySizes[yIndex].entryMaximum; + } + + switch(yIndex) { + case PPREVERB_USE_LIGHTWEIGHT: + gDebugBetterReverbSettings[xIndex].useLightweightSettings = valueToSet; + break; + case PPREVERB_DOWNSAMPLE_RATE: + gDebugBetterReverbSettings[xIndex].downsampleRate = valueToSet; + break; + case PPREVERB_IS_MONO: + gDebugBetterReverbSettings[xIndex].isMono = valueToSet; + break; + case PPREVERB_FILTER_COUNT: + gDebugBetterReverbSettings[xIndex].filterCount = valueToSet; + break; + case PPREVERB_WINDOW_SIZE: + gDebugBetterReverbSettings[xIndex].windowSize = valueToSet; + break; + case PPREVERB_GAIN: + gDebugBetterReverbSettings[xIndex].gain = valueToSet; + break; + case PPREVERB_GAIN_INDEX: + gDebugBetterReverbSettings[xIndex].gainIndex = valueToSet; + break; + case PPREVERB_REVERB_INDEX: + gDebugBetterReverbSettings[xIndex].reverbIndex = valueToSet; + break; + case PPREVERB_DELAYS_L: + gDebugBetterReverbSettings[xIndex].delaysL = sReverbDelaysArr[valueToSet]; + break; + case PPREVERB_DELAYS_R: + gDebugBetterReverbSettings[xIndex].delaysR = sReverbDelaysArr[valueToSet]; + break; + case PPREVERB_REVERB_MULTS_L: + gDebugBetterReverbSettings[xIndex].reverbMultsL = sReverbMultsArr[valueToSet]; + break; + case PPREVERB_REVERB_MULTS_R: + gDebugBetterReverbSettings[xIndex].reverbMultsR = sReverbMultsArr[valueToSet]; + break; + case PPREVERB_AREA_ECHO: + if (gCurrentArea != NULL && !gCurrentArea->useEchoOverride) { + u8 level = gCurrLevelNum; + u8 area = gCurrAreaIndex - 1; + if (level > LEVEL_MAX) { + level = LEVEL_MAX; + } + if (area > 2) { + area = 2; + } + + gCurrentArea->echoOverride = sLevelAreaReverbs[level][area]; + gCurrentArea->useEchoOverride = TRUE; + + for (u32 i = 0; i < DEBUG_REVERB_PRESET_COUNT; i++) { + ppAreaEchos[i] = gCurrentArea->echoOverride; + } + } + ppAreaEchos[xIndex] = valueToSet; + break; + + ret = valueToSet; + } + } else { + switch(yIndex) { + case PPREVERB_USE_LIGHTWEIGHT: + ret = gDebugBetterReverbSettings[xIndex].useLightweightSettings; + break; + case PPREVERB_DOWNSAMPLE_RATE: + ret = gDebugBetterReverbSettings[xIndex].downsampleRate; + break; + case PPREVERB_IS_MONO: + ret = gDebugBetterReverbSettings[xIndex].isMono; + break; + case PPREVERB_FILTER_COUNT: + ret = gDebugBetterReverbSettings[xIndex].filterCount; + break; + case PPREVERB_WINDOW_SIZE: + ret = gDebugBetterReverbSettings[xIndex].windowSize; + break; + case PPREVERB_GAIN: + ret = gDebugBetterReverbSettings[xIndex].gain; + break; + case PPREVERB_GAIN_INDEX: + ret = gDebugBetterReverbSettings[xIndex].gainIndex; + break; + case PPREVERB_REVERB_INDEX: + ret = gDebugBetterReverbSettings[xIndex].reverbIndex; + break; + case PPREVERB_DELAYS_L: + ret = (u32) ((u8*) gDebugBetterReverbSettings[xIndex].delaysL - (u8*) &sReverbDelaysArr[0][0]) / sizeof(sReverbDelaysArr[0]); + break; + case PPREVERB_DELAYS_R: + ret = (u32) ((u8*) gDebugBetterReverbSettings[xIndex].delaysR - (u8*) &sReverbDelaysArr[0][0]) / sizeof(sReverbDelaysArr[0]); + break; + case PPREVERB_REVERB_MULTS_L: + ret = (u32) ((u8*) gDebugBetterReverbSettings[xIndex].reverbMultsL - (u8*) &sReverbMultsArr[0][0]) / sizeof(sReverbMultsArr[0]); + break; + case PPREVERB_REVERB_MULTS_R: + ret = (u32) ((u8*) gDebugBetterReverbSettings[xIndex].reverbMultsR - (u8*) &sReverbMultsArr[0][0]) / sizeof(sReverbMultsArr[0]); + break; + case PPREVERB_AREA_ECHO: + if (gCurrentArea != NULL && !gCurrentArea->useEchoOverride) { + u8 level = gCurrLevelNum; + u8 area = gCurrAreaIndex - 1; + if (level > LEVEL_MAX) { + level = LEVEL_MAX; + } + if (area > 2) { + area = 2; + } + + gCurrentArea->echoOverride = sLevelAreaReverbs[level][area]; + gCurrentArea->useEchoOverride = TRUE; + + for (u32 i = 0; i < DEBUG_REVERB_PRESET_COUNT; i++) { + ppAreaEchos[i] = gCurrentArea->echoOverride; + } + } + ret = ppAreaEchos[xIndex]; + break; + } + + if (ret < maxReverbEntrySizes[yIndex].entryMinimum) { + ret = maxReverbEntrySizes[yIndex].entryMinimum; + } else if (ret > maxReverbEntrySizes[yIndex].entryMaximum) { + ret = maxReverbEntrySizes[yIndex].entryMaximum; + } + } + + return ret; +} + +void better_reverb_preset_menu(void) { + char textBytes[16]; + s32 printValue; + s32 x; + s32 y; + + prepare_blank_box(); + render_blank_box_rounded(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0, 0, 127); + finish_blank_box(); + + print_set_envcolour(63, 159, 127, 255), + print_small_text(SCREEN_WIDTH/2, SCREEN_HEIGHT - 48, "D-Pad Up/Down: Scroll, Start: Switch Preset A/B", PRINT_TEXT_ALIGN_CENTRE, PRINT_ALL, FONT_OUTLINE); + print_set_envcolour(63, 159, 127, 255), + print_small_text(SCREEN_WIDTH/2, SCREEN_HEIGHT - 36, "D-Pad L/R: Fine Adjustment, Z/R: Coarse Adjustment", PRINT_TEXT_ALIGN_CENTRE, PRINT_ALL, FONT_OUTLINE); + print_set_envcolour(63, 159, 127, 255), + print_small_text(SCREEN_WIDTH/2, SCREEN_HEIGHT - 24, "A: Apply Selected Preset, B: Preview SFX", PRINT_TEXT_ALIGN_CENTRE, PRINT_ALL, FONT_OUTLINE); + + x = 32; + y = 16; + for (s32 j = 0; j < PPREVERB_TOTAL; j++) { + y += 12; + if (j == ppReverbSelectY) { + print_set_envcolour(255, 255, 159, 255); + } else { + print_set_envcolour(191, 159, 191, 255); + } + switch(j) { + case PPREVERB_USE_LIGHTWEIGHT: + print_small_text_light(x, y, "Lightweight:", PRINT_TEXT_ALIGN_LEFT, PRINT_ALL, FONT_OUTLINE); + break; + case PPREVERB_DOWNSAMPLE_RATE: + print_small_text_light(x, y, "Downsample Rate:", PRINT_TEXT_ALIGN_LEFT, PRINT_ALL, FONT_OUTLINE); + break; + case PPREVERB_IS_MONO: + print_small_text_light(x, y, "Mono:", PRINT_TEXT_ALIGN_LEFT, PRINT_ALL, FONT_OUTLINE); + break; + case PPREVERB_FILTER_COUNT: + print_small_text_light(x, y, "Filter Count:", PRINT_TEXT_ALIGN_LEFT, PRINT_ALL, FONT_OUTLINE); + break; + case PPREVERB_WINDOW_SIZE: + print_small_text_light(x, y, "Window Size:", PRINT_TEXT_ALIGN_LEFT, PRINT_ALL, FONT_OUTLINE); + break; + case PPREVERB_GAIN: + print_small_text_light(x, y, "Gain:", PRINT_TEXT_ALIGN_LEFT, PRINT_ALL, FONT_OUTLINE); + break; + case PPREVERB_GAIN_INDEX: + print_small_text_light(x, y, "Gain Index:", PRINT_TEXT_ALIGN_LEFT, PRINT_ALL, FONT_OUTLINE); + break; + case PPREVERB_REVERB_INDEX: + print_small_text_light(x, y, "Reverb Index:", PRINT_TEXT_ALIGN_LEFT, PRINT_ALL, FONT_OUTLINE); + break; + case PPREVERB_DELAYS_L: + print_small_text_light(x, y, "Delays L:", PRINT_TEXT_ALIGN_LEFT, PRINT_ALL, FONT_OUTLINE); + break; + case PPREVERB_DELAYS_R: + print_small_text_light(x, y, "Delays R:", PRINT_TEXT_ALIGN_LEFT, PRINT_ALL, FONT_OUTLINE); + break; + case PPREVERB_REVERB_MULTS_L: + print_small_text_light(x, y, "Reverb Mults L:", PRINT_TEXT_ALIGN_LEFT, PRINT_ALL, FONT_OUTLINE); + break; + case PPREVERB_REVERB_MULTS_R: + print_small_text_light(x, y, "Reverb Mults R:", PRINT_TEXT_ALIGN_LEFT, PRINT_ALL, FONT_OUTLINE); + break; + case PPREVERB_AREA_ECHO: + print_small_text_light(x, y, "Area Echo:", PRINT_TEXT_ALIGN_LEFT, PRINT_ALL, FONT_OUTLINE); + break; + } + } + + for (s32 i = 0; i < DEBUG_REVERB_PRESET_COUNT; i++) { + s32 windowSize = better_reverb_get_or_set_field(FALSE, i, PPREVERB_WINDOW_SIZE, 0); + s32 downsampleRate = better_reverb_get_or_set_field(FALSE, i, PPREVERB_DOWNSAMPLE_RATE, 0); + s32 isLightweight = better_reverb_get_or_set_field(FALSE, i, PPREVERB_USE_LIGHTWEIGHT, 0); + x = (SCREEN_WIDTH/2) + (i * 84); + y = 12; + if (i == ppReverbSide) { + print_set_envcolour(255, 255, 159, 255); + } else { + print_set_envcolour(191, 159, 191, 255); + } + sprintf(textBytes, "PRESET %c", 'A' + i); + print_small_text_light(x, y, textBytes, PRINT_TEXT_ALIGN_LEFT, PRINT_ALL, FONT_OUTLINE); + y += 4; + for (s32 j = 0; j < PPREVERB_TOTAL; j++) { + y += 12; + printValue = better_reverb_get_or_set_field(FALSE, i, j, 0); + if (i == ppReverbSide && j == ppReverbSelectY) { + print_set_envcolour(255, 159, 0, 255); + } else if (windowSize == 0) { // All reverb disabled + if (j == PPREVERB_WINDOW_SIZE) { + print_set_envcolour(255, 255, 255, 255); + } else { + print_set_envcolour(95, 95, 95, 255); + } + } else if (downsampleRate <= 0) { // Vanilla reverb + switch(j) { + case PPREVERB_DOWNSAMPLE_RATE: + case PPREVERB_WINDOW_SIZE: + case PPREVERB_GAIN: + case PPREVERB_AREA_ECHO: + print_set_envcolour(255, 255, 255, 255); + break; + default: + print_set_envcolour(95, 95, 95, 255); + break; + } + } + else if (isLightweight) { // Lightweight reverb + switch(j) { + case PPREVERB_FILTER_COUNT: + case PPREVERB_GAIN_INDEX: + case PPREVERB_REVERB_INDEX: + case PPREVERB_REVERB_MULTS_L: + case PPREVERB_REVERB_MULTS_R: + print_set_envcolour(95, 95, 95, 255); + break; + default: + print_set_envcolour(255, 255, 255, 255); + break; + + } + } else { // Standard reverb + print_set_envcolour(255, 255, 255, 255); + } + + if (maxReverbEntrySizes[j].bytes == 2) { + sprintf(textBytes, "0x%04X", (u16) printValue); + } else if (!maxReverbEntrySizes[j].treatAsEntryCount) { + sprintf(textBytes, "0x%02X", (u8) printValue); + } else if (j == PPREVERB_USE_LIGHTWEIGHT || j == PPREVERB_IS_MONO) { + if (printValue == 0) { + sprintf(textBytes, "FALSE"); + } else { + sprintf(textBytes, "TRUE"); + } + } else { + sprintf(textBytes, "%d", printValue); + } + + print_small_text_light(x, y, textBytes, PRINT_TEXT_ALIGN_LEFT, PRINT_ALL, FONT_OUTLINE); + } + } +} +#endif + u8 gLastWarpID = 0; void puppyprint_render_general_vars(void) { @@ -650,18 +1026,21 @@ void puppyprint_render_general_vars(void) { struct PuppyPrintPage ppPages[] = { #ifdef USE_PROFILER - {&puppyprint_render_standard, "Profiler"}, - {&puppyprint_render_minimal, "Minimal"}, + [PUPPYPRINT_PAGE_PROFILER] = {&puppyprint_render_standard, "Profiler"}, + [PUPPYPRINT_PAGE_MINIMAL] = {&puppyprint_render_minimal, "Minimal"}, #endif - {&puppyprint_render_general_vars, "General"}, - {&print_audio_overview, "Audio"}, - {&print_ram_overview, "Segments"}, - {&puppyprint_render_collision, "Collision"}, - {&print_console_log, "Log"}, - {&puppyprint_level_select_menu, "Level Select"}, - {&render_coverage_map, "Coverage"}, + [PUPPYPRINT_PAGE_GENERAL] = {&puppyprint_render_general_vars, "General"}, + [PUPPYPRINT_PAGE_AUDIO] = {&print_audio_overview, "Audio"}, + [PUPPYPRINT_PAGE_RAM] = {&print_ram_overview, "Segments"}, + [PUPPYPRINT_PAGE_COLLISION] = {&puppyprint_render_collision, "Collision"}, + [PUPPYPRINT_PAGE_LOG] = {&print_console_log, "Log"}, + [PUPPYPRINT_PAGE_LEVEL_SELECT] = {&puppyprint_level_select_menu, "Level Select"}, + [PUPPYPRINT_PAGE_COVERAGE] = {&render_coverage_map, "Coverage"}, #ifdef PUPPYCAM - {&puppycamera_debug_view, "Unlock Camera"}, + [PUPPYPRINT_PAGE_CAMERA] = {&puppycamera_debug_view, "Unlock Camera"}, +#endif +#ifdef BETTER_REVERB + [PUPPYPRINT_PAGE_BETTER_REVERB] = {&better_reverb_preset_menu, "Reverb Config"}, #endif }; @@ -810,6 +1189,115 @@ void puppyprint_profiler_process(void) { gPPSegScroll += 4; } } +#ifdef BETTER_REVERB + if (sPPDebugPage == PUPPYPRINT_PAGE_BETTER_REVERB) + { + s32 grabbedValue = better_reverb_get_or_set_field(FALSE, ppReverbSide, ppReverbSelectY, 0); + + // These only need to be done once, but not really worth optimizing tbh + maxReverbEntrySizes[PPREVERB_DELAYS_L].entryMaximum = gReverbDelaysArrCount - 1; + maxReverbEntrySizes[PPREVERB_DELAYS_R].entryMaximum = gReverbDelaysArrCount - 1; + maxReverbEntrySizes[PPREVERB_REVERB_MULTS_L].entryMaximum = gReverbMultsArrCount - 1; + maxReverbEntrySizes[PPREVERB_REVERB_MULTS_R].entryMaximum = gReverbMultsArrCount - 1; + + if (gPlayer1Controller->buttonPressed & (A_BUTTON | B_BUTTON)) { + u8 betterReverbLastPreset = gBetterReverbPresetValue; + + if (gCurrentArea != NULL) { + gCurrentArea->useEchoOverride = TRUE; + gBetterReverbPresetValue = (u8)(s8) (ppReverbSide - DEBUG_REVERB_PRESET_COUNT); + gCurrentArea->echoOverride = ppAreaEchos[ppReverbSide]; + } + + if (sAudioIsInitialized) { + if (gAudioLoadLock != AUDIO_LOCK_UNINITIALIZED) { + gAudioLoadLock = AUDIO_LOCK_LOADING; + + init_reverb_us(0); + + if (gAudioLoadLock != AUDIO_LOCK_UNINITIALIZED) { + gAudioLoadLock = AUDIO_LOCK_NOT_LOADING; + } + } + } + + gBetterReverbPresetValue = betterReverbLastPreset; + + if (gPlayer1Controller->buttonPressed & B_BUTTON) { + u32 sound = random_u16() % ARRAY_COUNT(betterReverbSfx); + play_sound(betterReverbSfx[sound], gGlobalSoundSource); + } else { // A_BUTTON + sPPDebugPage = 0; + } + } else if (gPlayer1Controller->buttonPressed & L_JPAD) { + if (ppReverbSelectY == PPREVERB_FILTER_COUNT) { + grabbedValue -= 3; + } else if ((ppReverbSelectY == PPREVERB_WINDOW_SIZE || ppReverbSelectY == PPREVERB_GAIN) && grabbedValue > 0 && grabbedValue <= 0x80) { + grabbedValue = 0; + } else { + if (maxReverbEntrySizes[ppReverbSelectY].bytes == 2) { + grabbedValue -= 0x80; + } else { + grabbedValue -= 0x1; + } + } + + better_reverb_get_or_set_field(TRUE, ppReverbSide, ppReverbSelectY, grabbedValue); + } else if (gPlayer1Controller->buttonPressed & R_JPAD) { + if (ppReverbSelectY == PPREVERB_FILTER_COUNT) { + grabbedValue += 3; + } else if ((ppReverbSelectY == PPREVERB_WINDOW_SIZE || ppReverbSelectY == PPREVERB_GAIN) && grabbedValue < 0) { + grabbedValue = 0; + } else { + if (maxReverbEntrySizes[ppReverbSelectY].bytes == 2) { + grabbedValue += 0x80; + } else { + grabbedValue += 0x1; + } + } + + better_reverb_get_or_set_field(TRUE, ppReverbSide, ppReverbSelectY, grabbedValue); + } else if (gPlayer1Controller->buttonPressed & Z_TRIG) { + if (ppReverbSelectY == PPREVERB_FILTER_COUNT) { + grabbedValue -= 3; + } else if ((ppReverbSelectY == PPREVERB_WINDOW_SIZE || ppReverbSelectY == PPREVERB_GAIN) && grabbedValue > 0 && grabbedValue <= 0x800) { + grabbedValue = 0; + } else { + if (maxReverbEntrySizes[ppReverbSelectY].bytes == 2) { + grabbedValue -= 0x800; + } else if (!maxReverbEntrySizes[ppReverbSelectY].treatAsEntryCount) { + grabbedValue -= 0x10; + } else { + grabbedValue -= 0x1; + } + } + + better_reverb_get_or_set_field(TRUE, ppReverbSide, ppReverbSelectY, grabbedValue); + } else if (gPlayer1Controller->buttonPressed & R_TRIG) { + if (ppReverbSelectY == PPREVERB_FILTER_COUNT) { + grabbedValue += 3; + } else if ((ppReverbSelectY == PPREVERB_WINDOW_SIZE || ppReverbSelectY == PPREVERB_GAIN) && grabbedValue < 0) { + grabbedValue = 0; + } else { + if (maxReverbEntrySizes[ppReverbSelectY].bytes == 2) { + grabbedValue += 0x800; + } else if (!maxReverbEntrySizes[ppReverbSelectY].treatAsEntryCount) { + grabbedValue += 0x10; + } else { + grabbedValue += 0x1; + } + } + + better_reverb_get_or_set_field(TRUE, ppReverbSide, ppReverbSelectY, grabbedValue); + } else if (gPlayer1Controller->buttonPressed & D_JPAD) { + ppReverbSelectY = (ppReverbSelectY + 1) % PPREVERB_TOTAL; + } else if (gPlayer1Controller->buttonPressed & U_JPAD) { + ppReverbSelectY = (ppReverbSelectY + PPREVERB_TOTAL - 1) % PPREVERB_TOTAL; + } else if (gPlayer1Controller->buttonPressed & START_BUTTON) { + ppReverbSide = (ppReverbSide + 1) % DEBUG_REVERB_PRESET_COUNT; + } + } +#endif } profiler_update(PROFILER_TIME_PUPPYPRINT2, osGetCount() - first); } diff --git a/src/game/puppyprint.h b/src/game/puppyprint.h index cbfa7b992..0411694a0 100644 --- a/src/game/puppyprint.h +++ b/src/game/puppyprint.h @@ -94,8 +94,12 @@ enum PPPages { PUPPYPRINT_PAGE_COLLISION, PUPPYPRINT_PAGE_LOG, PUPPYPRINT_PAGE_LEVEL_SELECT, + PUPPYPRINT_PAGE_COVERAGE, #ifdef PUPPYCAM - PUPPYPRINT_PAGE_CAMERA + PUPPYPRINT_PAGE_CAMERA, +#endif +#ifdef BETTER_REVERB + PUPPYPRINT_PAGE_BETTER_REVERB, #endif };