diff --git a/Makefile b/Makefile index ef738ab1..cbfc3966 100644 --- a/Makefile +++ b/Makefile @@ -43,8 +43,9 @@ endif # COMPILER - selects the C compiler to use # gcc - uses the GNU C Compiler +# clang - uses clang C/C++ frontend for LLVM COMPILER ?= gcc -$(eval $(call validate-option,COMPILER,gcc)) +$(eval $(call validate-option,COMPILER,gcc clang)) # LIBGCCDIR - selects the libgcc configuration for checking for dividing by zero @@ -158,7 +159,12 @@ LINK_LIBRARIES = $(foreach i,$(LIBRARIES),-l$(i)) ifeq ($(COMPILER),gcc) NON_MATCHING := 1 MIPSISET := -mips3 - OPT_FLAGS := -O2 -g + OPT_FLAGS := -O2 +else ifeq ($(COMPILER),clang) + NON_MATCHING := 1 + # clang doesn't support ABI 'o32' for 'mips3' + MIPSISET := -mips2 + OPT_FLAGS := -O2 endif @@ -390,6 +396,8 @@ export LD_LIBRARY_PATH=./tools AS := $(CROSS)as ifeq ($(COMPILER),gcc) CC := $(CROSS)gcc +else ifeq ($(COMPILER),clang) + CC := clang endif # Prefer gcc's cpp if installed on the system ifneq (,$(call find-command,cpp-10)) @@ -423,9 +431,12 @@ DEF_INC_CFLAGS := $(foreach i,$(INCLUDE_DIRS),-I$(i)) $(C_DEFINES) CFLAGS = -G 0 $(OPT_FLAGS) $(TARGET_CFLAGS) $(MIPSISET) $(DEF_INC_CFLAGS) ifeq ($(COMPILER),gcc) CFLAGS += -mno-shared -march=vr4300 -mfix4300 -mabi=32 -mhard-float -mdivide-breaks -fno-stack-protector -fno-common -fno-zero-initialized-in-bss -fno-PIC -mno-abicalls -fno-strict-aliasing -fno-inline-functions -ffreestanding -fwrapv -Wall -Wextra -Wno-missing-braces -fno-jump-tables +else ifeq ($(COMPILER),clang) + CFLAGS += -target mips -mabi=32 -G 0 -mhard-float -fomit-frame-pointer -fno-stack-protector -fno-common -I include -I src/ -I $(BUILD_DIR)/include -fno-PIC -mno-abicalls -fno-strict-aliasing -fno-inline-functions -ffreestanding -fwrapv -Wall -Wextra -Wno-missing-braces -fno-jump-tables else CFLAGS += -non_shared -Wab,-r4300_mul -Xcpluscomm -Xfullwarn -signed -32 endif +ASMFLAGS = -G 0 $(OPT_FLAGS) $(TARGET_CFLAGS) -mips3 $(DEF_INC_CFLAGS) -mno-shared -march=vr4300 -mfix4300 -mabi=32 -mhard-float -mdivide-breaks -fno-stack-protector -fno-common -fno-zero-initialized-in-bss -fno-PIC -mno-abicalls -fno-strict-aliasing -fno-inline-functions -ffreestanding -fwrapv -Wall -Wextra ASFLAGS := -march=vr4300 -mabi=32 $(foreach i,$(INCLUDE_DIRS),-I$(i)) $(foreach d,$(DEFINES),--defsym $(d)) RSPASMFLAGS := $(foreach d,$(DEFINES),-definelabel $(subst =, ,$(d))) @@ -479,8 +490,8 @@ YELLOW := \033[0;33m BLINK := \033[33;5m endif -# Use Objcopy instead of extract_data_for_mio -ifeq ($(COMPILER),gcc) +# For non-IDO, use objcopy instead of extract_data_for_mio +ifneq ($(COMPILER),ido) EXTRACT_DATA_FOR_MIO := $(OBJCOPY) -O binary --only-section=.data endif @@ -746,7 +757,7 @@ $(BUILD_DIR)/%.o: $(BUILD_DIR)/%.c # Assemble assembly code $(BUILD_DIR)/%.o: %.s $(call print,Assembling:,$<,$@) - $(V)$(CC) -c $(CFLAGS) $(foreach i,$(INCLUDE_DIRS),-Wa,-I$(i)) -x assembler-with-cpp -MMD -MF $(BUILD_DIR)/$*.d -o $@ $< + $(V)$(CROSS)gcc -c $(ASMFLAGS) $(foreach i,$(INCLUDE_DIRS),-Wa,-I$(i)) -x assembler-with-cpp -MMD -MF $(BUILD_DIR)/$*.d -o $@ $< # Assemble RSP assembly code $(BUILD_DIR)/rsp/%.bin $(BUILD_DIR)/rsp/%_data.bin: rsp/%.s diff --git a/README.md b/README.md index 3c835b5c..cb7856c4 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ This is a fork of the ultrasm64 repo by CrashOveride which includes the followin **Hacker QOL:** - Global, non-level based, star IDs (off by default) * -- FPS counter (use the function `print_fps(x,y)` anywhere that runs code every frame) +- Debug mode: prints mario's coordinates, angle and speed, and a FPS counter. - Automatic console/emulator detection. If emulator is detected, LODs are disabled. * - Ability to configure whether there's a 100 coin star at all and how many coins are required to spawn it * - Ability to easily change the warp that EXIT COURSE takes you to via config.h, or disable it entirely. * @@ -53,6 +53,7 @@ This is a fork of the ultrasm64 repo by CrashOveride which includes the followin - Expanded audio heap allows for a larger concurrent note count and the importing of more m64 sequences and sound banks (By ArcticJaguar725) * - You can set a test level in config.h in order to boot straight into it, so you can quickly test the level you're working on. * - Allows all surfaces in the game to have a `force` parameter. Activating this doesn't REQUIRE you to set `force` for every surface: If you don't set, it will default to 0x0000 rather than crashing. Increases RAM usage of collision. * +- The clown font includes the entire English alphabet. - Colored ia4 text support. Format: `"@XXXXXXXX[YOUR TEXT]@--------"` (By ArcticJaguar725) - Example Text: `"@FF0000FFRED @00FF00FFGREEN @0000FFFFBLUE @FFFFFF00INVISIBLE @--------NORMAL"` - NOTE: It is not mandatory to reset the text color with `"@--------"`, but text will need to be recolored each time it scrolls in a dialog box, or the custom color will reset. diff --git a/bin/segment2.c b/bin/segment2.c index 20ffa240..0e0fdbd9 100644 --- a/bin/segment2.c +++ b/bin/segment2.c @@ -86,11 +86,9 @@ ALIGNED8 static const Texture texture_hud_char_I[] = { #include "textures/segment2/segment2.02400.rgba16.inc.c" }; -#if defined(VERSION_JP) || defined(VERSION_SH) ALIGNED8 static const Texture texture_hud_char_J[] = { #include "textures/segment2/segment2.02600.rgba16.inc.c" }; -#endif ALIGNED8 static const Texture texture_hud_char_K[] = { #include "textures/segment2/segment2.02800.rgba16.inc.c" @@ -116,11 +114,9 @@ ALIGNED8 static const Texture texture_hud_char_P[] = { #include "textures/segment2/segment2.03200.rgba16.inc.c" }; -#if defined(VERSION_JP) || defined(VERSION_SH) ALIGNED8 static const Texture texture_hud_char_Q[] = { #include "textures/segment2/segment2.03400.rgba16.inc.c" }; -#endif ALIGNED8 static const Texture texture_hud_char_R[] = { #include "textures/segment2/segment2.03600.rgba16.inc.c" @@ -138,31 +134,25 @@ ALIGNED8 static const Texture texture_hud_char_U[] = { #include "textures/segment2/segment2.03C00.rgba16.inc.c" }; -#if defined(VERSION_JP) || defined(VERSION_EU) || defined(VERSION_SH) ALIGNED8 static const Texture texture_hud_char_V[] = { #include "textures/segment2/segment2.03E00.rgba16.inc.c" }; -#endif ALIGNED8 static const Texture texture_hud_char_W[] = { #include "textures/segment2/segment2.04000.rgba16.inc.c" }; -#if defined(VERSION_JP) || defined(VERSION_SH) ALIGNED8 static const Texture texture_hud_char_X[] = { #include "textures/segment2/segment2.04200.rgba16.inc.c" }; -#endif ALIGNED8 static const Texture texture_hud_char_Y[] = { #include "textures/segment2/segment2.04400.rgba16.inc.c" }; -#if defined(VERSION_JP) || defined(VERSION_EU) || defined(VERSION_SH) ALIGNED8 static const Texture texture_hud_char_Z[] = { #include "textures/segment2/segment2.04600.rgba16.inc.c" }; -#endif ALIGNED8 static const Texture texture_hud_char_apostrophe[] = { #include "textures/segment2/segment2.04800.rgba16.inc.c" @@ -178,7 +168,6 @@ ALIGNED8 static const Texture texture_hud_char_umlaut[] = { }; #endif -#if defined(VERSION_JP) || defined(VERSION_SH) ALIGNED8 static const Texture texture_hud_char_exclamation[] = { #include "textures/segment2/segment2.04C00.rgba16.inc.c"// JP ! }; @@ -198,7 +187,6 @@ ALIGNED8 static const Texture texture_hud_char_ampersand[] = { ALIGNED8 static const Texture texture_hud_char_percent[] = { #include "textures/segment2/segment2.05400.rgba16.inc.c"// JP % }; -#endif ALIGNED8 static const Texture texture_hud_char_multiply[] = { #include "textures/segment2/segment2.05600.rgba16.inc.c" @@ -216,11 +204,9 @@ ALIGNED8 static const Texture texture_hud_char_star[] = { #include "textures/segment2/segment2.05C00.rgba16.inc.c" }; -#if defined(VERSION_JP) || defined(VERSION_SH) ALIGNED8 static const Texture texture_hud_char_decimal_point[] = { #include "textures/segment2/segment2.05E00.rgba16.inc.c" }; -#endif #if defined(VERSION_JP) || defined(VERSION_SH) ALIGNED8 static const Texture texture_hud_char_beta_key[] = { @@ -1827,16 +1813,16 @@ const Texture *const main_hud_lut[] = { texture_hud_char_4, texture_hud_char_5, texture_hud_char_6, texture_hud_char_7, texture_hud_char_8, texture_hud_char_9, texture_hud_char_A, texture_hud_char_B, texture_hud_char_C, texture_hud_char_D, texture_hud_char_E, texture_hud_char_F, - texture_hud_char_G, texture_hud_char_H, texture_hud_char_I, 0x0, + texture_hud_char_G, texture_hud_char_H, texture_hud_char_I, texture_hud_char_J, texture_hud_char_K, texture_hud_char_L, texture_hud_char_M, texture_hud_char_N, - texture_hud_char_O, texture_hud_char_P, 0x0, texture_hud_char_R, - texture_hud_char_S, texture_hud_char_T, texture_hud_char_U, 0x0, - texture_hud_char_W, 0x0, texture_hud_char_Y, 0x0, - 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, + texture_hud_char_O, texture_hud_char_P, texture_hud_char_Q, texture_hud_char_R, + texture_hud_char_S, texture_hud_char_T, texture_hud_char_U, texture_hud_char_V, + texture_hud_char_W, texture_hud_char_X, texture_hud_char_Y, texture_hud_char_Z, + texture_hud_char_exclamation, texture_hud_char_double_exclamation, texture_hud_char_question, texture_hud_char_ampersand, + texture_hud_char_percent, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, texture_hud_char_multiply, texture_hud_char_coin, - texture_hud_char_mario_head, texture_hud_char_star, 0x0, 0x0, + texture_hud_char_mario_head, texture_hud_char_star, texture_hud_char_decimal_point, 0x0, texture_hud_char_apostrophe, texture_hud_char_double_quote, #else texture_hud_char_0, texture_hud_char_1, texture_hud_char_2, texture_hud_char_3, diff --git a/gziprules.mk b/gziprules.mk index d7c2fb7d..8f0be75c 100644 --- a/gziprules.mk +++ b/gziprules.mk @@ -10,7 +10,7 @@ endif # Strip gzip header $(BUILD_DIR)/%.szp: $(BUILD_DIR)/%.gz $(call print,Converting:,$<,$@) - $(V)dd bs=10 skip=1 if=$< of=$(<:.gz=.gz.strip) + $(V)dd bs=10 skip=1 if=$< of=$(<:.gz=.gz.strip) status=none $(V)$(FILESIZER) $(<:.gz=.gz.strip) $@ `stat --format="%s" $(<:.gz=.bin)` # convert binary szp to object file diff --git a/include/config.h b/include/config.h index c9002a94..2ca41605 100644 --- a/include/config.h +++ b/include/config.h @@ -84,8 +84,8 @@ //#define NO_FALL_DAMAGE_SOUND // Number of coins to spawn the "100 coin" star. If you remove the define altogether, then there won't be a 100 coin star at all. #define X_COIN_STAR 100 -// Platform displacement 2 also known as momentum patch. Makes Mario keep the momemtum from moving platforms. Breaks treadmills. -//#define PLATFORM_DISPLACEMENT_2 +// Platform displacement 2 also known as momentum patch. Makes Mario keep the momemtum from moving platforms. Doesn't break treadmills anymore! +#define PLATFORM_DISPLACEMENT_2 // Stars don't kick you out of the level // #define NON_STOP_STARS // Uncomment this if you want global star IDs (useful for creating an open world hack ala MVC) @@ -109,6 +109,8 @@ #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 +// Custom debug mode. Press DPAD left to show the debug UI. Press DPAD right to enter the noclip mode. +//#define CUSTOM_DEBUG // BUG/GAME QOL FIXES // Fix instant warp offset not working when warping across different areas diff --git a/src/audio/heap.c b/src/audio/heap.c index 27423a10..d7580eed 100644 --- a/src/audio/heap.c +++ b/src/audio/heap.c @@ -1240,9 +1240,9 @@ void audio_reset_session(void) { gReverbDownsampleRate = preset->reverbDownsampleRate; #ifdef BETTER_REVERB if (gIsConsole) - reverbConsole = betterReverbConsoleDownsample; // Console! + reverbConsole = betterReverbDownsampleConsole; // Console! else - reverbConsole = betterReverbEmulatorDownsample; // Setting this to 1 is REALLY slow, please use sparingly! + reverbConsole = betterReverbDownsampleEmulator; // Setting this to 1 is REALLY slow, please use sparingly! if (reverbConsole <= 0) { reverbConsole = 1; @@ -1457,15 +1457,16 @@ void audio_reset_session(void) { // 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) { - for (i = 0; i < NUM_ALLPASS; ++i) - delays[i] = delaysBaseline[i] / gReverbDownsampleRate; - - delayBufs = (s32***) soundAlloc(&gAudioSessionPool, 2 * sizeof(s32**)); - delayBufs[0] = (s32**) soundAlloc(&gAudioSessionPool, NUM_ALLPASS * sizeof(s32*)); - delayBufs[1] = (s32**) soundAlloc(&gAudioSessionPool, NUM_ALLPASS * sizeof(s32*)); for (i = 0; i < NUM_ALLPASS; ++i) { - delayBufs[0][i] = (s32*) soundAlloc(&gAudioSessionPool, delays[i] * sizeof(s32)); - delayBufs[1][i] = (s32*) soundAlloc(&gAudioSessionPool, delays[i] * sizeof(s32)); + 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 diff --git a/src/audio/synthesis.c b/src/audio/synthesis.c index 96ddd0a7..38f242f1 100644 --- a/src/audio/synthesis.c +++ b/src/audio/synthesis.c @@ -8,6 +8,7 @@ #include "seqplayer.h" #include "internal.h" #include "external.h" +#include "game/game_init.h" #define DMEM_ADDR_TEMP 0x0 @@ -37,7 +38,9 @@ #define AUDIO_ALIGN(val, amnt) (((val) + (1 << amnt) - 1) & ~((1 << amnt) - 1)) -/* -------------------------------------------------------BEGIN REVERB PARAMETERS-------------------------------------------------------------- */ +#ifdef BETTER_REVERB +/* ----------------------------------------------------------------------BEGIN REVERB PARAMETERS---------------------------------------------------------------------- */ + /** * This reverb is a much more natural, ambient implementation over vanilla's, though at the cost of some memory and performance. @@ -46,72 +49,121 @@ * 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. + * Checks to prevent this have not been implemented to maximize performance potential, so choose your parameters wisely. + * Generally speaking, a sound that doesn't seem to be fading is a parameter red flag (also known as feedback). */ -s32 gReverbRevIndex = 0x7F; // Affects decay time mostly; can be messed with at any time (and also probably the most useful parameter here) -s32 gReverbGainIndex = 0xA3; // Affects signal immediately retransmitted back into buffers; can be messed with at any time -s32 gReverbWetSignal = 0xEF; // Amount of reverb specific output in final signal; can be messed with at any time -s32 gReverbDrySignal = 0x00; // Amount of original input in final signal (large values can cause terrible feedback!); can be messed with at any time - -// This value controls the size of the reverb buffer. It affects the global reverb delay time. This is probably the easiest parameter to control usefully. -// It is not recommended setting this to values greater than 0x1000 * 2^(downsample factor - 1), as you run the risk of running into a memory issue (though this is far from a guarantee). -// Setting the value lower than the downsample buffer size will destroy the game audio, so this is taken into account automatically but may limit the lower possibilities. -// If this value is changed, it will go into effect the next time audio_reset_session is called. -// 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 affect filter delays. Bigger values will result in fatter echo (and more memory); must be cumulatively smaller than BETTER_REVERB_SIZE/4. -// If setting a reverb downsample value to 1, this must be smaller than BETTER_REVERB_SIZE/8. -// These values should never be changed unless in this declaration or during a call to audio_reset_session, as it could otherwise lead to a major memory leak or garbage audio. -// None of the delay values should ever be smaller than 1 either; these are s32s purely to avoid typecasts. -// These values are currently set by using delaysBaseline in the audio_reset_session function, so its behavior must be overridden to use dynamically (or at all). -s32 delays[NUM_ALLPASS] = { - 1080, 1352, 1200, - 1384, 1048, 1352, - 1200, 1232, 1432, - 928, 1504, 1512 -}; - -// Like the delays array, but represents default max values that don't change (also probably somewhat redundant) -// Change this array rather than the delays array to customize reverb delay times globally. -// Similarly to delays, these should be kept within the memory constraints defined by BETTER_REVERB_SIZE. -const s32 delaysBaseline[NUM_ALLPASS] = { - 1080, 1352, 1200, - 1384, 1048, 1352, - 1200, 1232, 1432, - 928, 1504, 1512 -}; - -// These values affect reverb decay depending on the filter index; can be messed with at any time -const s32 reverbMults[2][NUM_ALLPASS / 3] = { - {0xD2, 0x6E, 0x36, 0x1F}, // Left Channel - {0x38, 0x26, 0xCF, 0x71} // Right Channel -}; // Setting this to 4 corrupts the game, so set this value to -1 to use vanilla reverb if this is too slow, or if it just doesn't fit the desired aesthetic of a level. // You can change this value before audio_reset_session gets called if different levels can tolerate the demand better than others or just have different reverb goals. // A higher downsample value hits the game's frequency limit sooner, which can cause the reverb sometimes to be off pitch. This is a vanilla level issue (and also counter intuitive). // Higher downsample values also result in slightly shorter reverb decay times. -s8 betterReverbConsoleDownsample = 3; +s8 betterReverbDownsampleConsole = 3; // Most emulators can handle a default value of 2, but 3 may be advisable in some cases if targeting older emulators (e.g. PJ64 1.6). Setting this to -1 also uses vanilla reverb. // Using a value of 1 is not recommended except in very specific situations. If you do decide to use 1 here, you must adjust BETTER_REVERB_SIZE appropriately. // You can change this value before audio_reset_session gets called if different levels can tolerate the demand better than others or just have different reverb goals. // A higher downsample value hits the game's frequency limit sooner, which can cause the reverb sometimes to be off pitch. This is a vanilla level issue (and also counter intuitive). // Higher downsample values also result in slightly shorter reverb decay times. -s8 betterReverbEmulatorDownsample = 2; +s8 betterReverbDownsampleEmulator = 2; -/* --------------------------------------------------------END REVERB PARAMETERS--------------------------------------------------------------- */ +// This value represents the number of filters to use with the reverb. This can be decreased to improve performance, but at the cost of a lesser presence of reverb in the final audio. +// Filter count should always be a multiple of 3. Never ever set this value to be greater than NUM_ALLPASS. +// Setting it to anything less 3 will disable reverb outright. +// This can be changed at any time, but is best set when calling audio_reset_session. +u32 reverbFilterCountConsole = NUM_ALLPASS - 3; -// Do not touch these values. -u8 toggleBetterReverb = TRUE; -s32 allpassIdx[2][NUM_ALLPASS] = { - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +// This value represents the number of filters to use with the reverb. This can be decreased to improve performance, but at the cost of a lesser presence of reverb in the final audio. +// Filter count should always be a multiple of 3. Never ever set this value to be greater than NUM_ALLPASS. +// Setting it to anything less 3 will disable reverb outright. +// This can be changed at any time, but is best set when calling audio_reset_session. +u32 reverbFilterCountEmulator = NUM_ALLPASS; + +// Set this to TRUE to use mono over stereo for reverb. This should increase performance, but at the cost of a less fullfilling reverb experience. +// If performance is desirable, it is recommended to change reverbFilterCountConsole or betterReverbDownsampleConsole first. +// This can be changed at any time, but is best set when calling audio_reset_session. +u8 monoReverbConsole = FALSE; + +// Set this to TRUE to use mono over stereo for reverb. This should increase performance, but at the cost of a less fullfilling reverb experience. +// If performance is desirable, it is recommended to change reverbFilterCountEmulator or betterReverbDownsampleEmulator first. +// This can be changed at any time, but is best set when calling audio_reset_session. +u8 monoReverbEmulator = FALSE; + +// This value controls the size of the reverb buffer. It affects the global reverb delay time. This variable is one of the easiest to control. +// It is not recommended setting this to values greater than 0x1000 * 2^(downsample factor - 1), as you run the risk of running into a memory issue (though this is far from a guarantee). +// Setting the value lower than the downsample buffer size will destroy the game audio. This is taken into account automatically, but also means the value set here isn't what always gets used. +// If this value is changed, it will go into effect the next time audio_reset_session is called. +// Set to -1 to use a default preset instead. Higher values represent more audio delay (usually better for echoey spaces). +s32 betterReverbWindowsSize = -1; + +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 + +// 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 + + +/* ---------------------------------------------------------------------ADVANCED REVERB PARAMETERS-------------------------------------------------------------------- */ + + +// These values affect filter delays. Bigger values will result in fatter echo (and more memory); must be cumulatively smaller than BETTER_REVERB_SIZE/2. +// If setting a reverb downsample value to 1, these must be cumulatively smaller than BETTER_REVERB_SIZE/4. +// These values should never be changed unless in this declaration or during a call to audio_reset_session, as it could otherwise lead to a major memory leak or garbage audio. +// None of the delay values should ever be smaller than 1 either; these are s32s purely to avoid typecasts. +// These values are currently set by using delaysBaseline in the audio_reset_session function, so its behavior must be overridden to use dynamically (or at all). +s32 delaysL[NUM_ALLPASS] = { + 1080, 1352, 1200, + 1200, 1232, 1432, + 1384, 1048, 1352, + 928, 1504, 1512 }; +s32 delaysR[NUM_ALLPASS] = { + 1384, 1352, 1048, + 928, 1512, 1504, + 1080, 1200, 1352, + 1200, 1432, 1232 +}; + +// Like the delays array, but represents default max values that don't change (also probably somewhat redundant) +// Change this array rather than the delays array to customize reverb delay times globally. +// Similarly to delaysL/R, these should be kept within the memory constraints defined by BETTER_REVERB_SIZE. +const s32 delaysBaselineL[NUM_ALLPASS] = { + 1080, 1352, 1200, + 1200, 1232, 1432, + 1384, 1048, 1352, + 928, 1504, 1512 +}; +const s32 delaysBaselineR[NUM_ALLPASS] = { + 1384, 1352, 1048, + 928, 1512, 1504, + 1080, 1200, 1352, + 1200, 1432, 1232 +}; + +// These values affect reverb decay depending on the filter index; can be messed with at any time +s32 reverbMultsL[NUM_ALLPASS / 3] = {0xD7, 0x6F, 0x36, 0x22}; +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; +u8 monoReverb = FALSE; +u8 toggleBetterReverb = TRUE; +s32 allpassIdxL[NUM_ALLPASS] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +s32 allpassIdxR[NUM_ALLPASS] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; s32 tmpBufL[NUM_ALLPASS] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; s32 tmpBufR[NUM_ALLPASS] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; -s32 ***delayBufs; +s32 **delayBufsL; +s32 **delayBufsR; +#endif struct VolumeChange { @@ -147,7 +199,8 @@ struct SynthesisReverb gSynthesisReverb; u8 sAudioSynthesisPad[0x20]; #endif -inline s16 clamp16(s32 x) { +#ifdef BETTER_REVERB +static inline s16 clamp16(s32 x) { if (x >= 32767) return 32767; if (x <= -32768) @@ -156,113 +209,76 @@ inline s16 clamp16(s32 x) { return (s16) x; } -inline void reverb_samples(s16 *outSampleL, s16 *outSampleR, s32 inSampleL, s32 inSampleR) { +static inline void reverb_samples(s16 *outSampleL, s16 *outSampleR, s32 inSampleL, s32 inSampleR) { u32 i = 0; s32 j = 0; u8 k = 0; s32 outTmpL = 0; s32 outTmpR = 0; - s32 tmpCarryoverL = ((tmpBufL[NUM_ALLPASS-1] * gReverbRevIndex) / 256) + inSampleL; // Unique to left channel - s32 tmpCarryoverR = ((tmpBufR[NUM_ALLPASS-1] * gReverbRevIndex) / 256); + s32 tmpCarryoverL = ((tmpBufL[reverbFilterCountm1] * gReverbRevIndex) / 256) + inSampleL; + s32 tmpCarryoverR = ((tmpBufR[reverbFilterCountm1] * gReverbRevIndex) / 256) + inSampleR; - for (; i < NUM_ALLPASS; ++i, ++j) { - tmpBufL[i] = delayBufs[0][i][allpassIdx[0][i]]; - tmpBufR[i] = delayBufs[1][i][allpassIdx[1][i]]; + for (; i < reverbFilterCount; ++i, ++j) { + tmpBufL[i] = delayBufsL[i][allpassIdxL[i]]; + tmpBufR[i] = delayBufsR[i][allpassIdxR[i]]; if (j == 2) { j = -1; - outTmpL += (tmpBufL[i] * reverbMults[0][k]) / 256; - outTmpR += (tmpBufR[i] * reverbMults[1][k++]) / 256; - delayBufs[0][i][allpassIdx[0][i]] = tmpCarryoverL; - delayBufs[1][i][allpassIdx[1][i]] = tmpCarryoverR; - if (i != NUM_ALLPASS - 1) { + outTmpL += (tmpBufL[i] * reverbMultsL[k]) / 256; + outTmpR += (tmpBufR[i] * reverbMultsR[k++]) / 256; + delayBufsL[i][allpassIdxL[i]] = tmpCarryoverL; + delayBufsR[i][allpassIdxR[i]] = tmpCarryoverR; + if (i != reverbFilterCountm1) { tmpCarryoverL = (tmpBufL[i] * gReverbRevIndex) / 256; tmpCarryoverR = (tmpBufR[i] * gReverbRevIndex) / 256; } } else { - delayBufs[0][i][allpassIdx[0][i]] = (tmpBufL[i] * (-gReverbGainIndex)) / 256 + tmpCarryoverL; - delayBufs[1][i][allpassIdx[1][i]] = (tmpBufR[i] * (-gReverbGainIndex)) / 256 + tmpCarryoverR; - - if (i == 6) - delayBufs[1][i][allpassIdx[1][i]] += inSampleR; // Unique to right channel - - tmpCarryoverL = (delayBufs[0][i][allpassIdx[0][i]] * gReverbGainIndex) / 256 + tmpBufL[i]; - tmpCarryoverR = (delayBufs[1][i][allpassIdx[1][i]] * gReverbGainIndex) / 256 + tmpBufR[i]; + 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]; } - if (++allpassIdx[0][i] == delays[i]) { - allpassIdx[0][i] = 0; - allpassIdx[1][i] = -1; // To avoid an else branch - } - ++allpassIdx[1][i]; + if (++allpassIdxL[i] == delaysL[i]) + allpassIdxL[i] = 0; + if (++allpassIdxR[i] == delaysR[i]) + allpassIdxR[i] = 0; } - *outSampleL = clamp16((outTmpL * gReverbWetSignal + inSampleL * gReverbDrySignal) / 256); - *outSampleR = clamp16((outTmpR * gReverbWetSignal + inSampleR * gReverbDrySignal) / 256); + *outSampleL = clamp16((outTmpL * gReverbWetSignal/* + inSampleL * gReverbDrySignal*/) / 256); + *outSampleR = clamp16((outTmpR * gReverbWetSignal/* + inSampleR * gReverbDrySignal*/) / 256); } -inline s16 reverb_sample_left(s32 inSample) { +static inline void reverb_mono_sample(s16 *outSample, s32 inSample) { u32 i = 0; s32 j = 0; u8 k = 0; s32 outTmp = 0; - s32 tmpCarryover = ((tmpBufL[NUM_ALLPASS-1] * gReverbRevIndex) / 256) + inSample; + s32 tmpCarryover = ((tmpBufL[reverbFilterCountm1] * gReverbRevIndex) / 256) + inSample; - for (; i < NUM_ALLPASS; ++i, ++j) { - tmpBufL[i] = delayBufs[0][i][allpassIdx[0][i]]; + for (; i < reverbFilterCount; ++i, ++j) { + tmpBufL[i] = delayBufsL[i][allpassIdxL[i]]; if (j == 2) { j = -1; - outTmp += (tmpBufL[i] * reverbMults[0][k++]) / 256; - delayBufs[0][i][allpassIdx[0][i]] = tmpCarryover; - if (i != NUM_ALLPASS - 1) + outTmp += (tmpBufL[i] * reverbMultsL[k++]) / 256; + delayBufsL[i][allpassIdxL[i]] = tmpCarryover; + if (i != reverbFilterCountm1) tmpCarryover = (tmpBufL[i] * gReverbRevIndex) / 256; } else { - delayBufs[0][i][allpassIdx[0][i]] = (tmpBufL[i] * (-gReverbGainIndex)) / 256 + tmpCarryover; - tmpCarryover = (delayBufs[0][i][allpassIdx[0][i]] * gReverbGainIndex) / 256 + tmpBufL[i]; + delayBufsL[i][allpassIdxL[i]] = (tmpBufL[i] * (-gReverbGainIndex)) / 256 + tmpCarryover; + tmpCarryover = (delayBufsL[i][allpassIdxL[i]] * gReverbGainIndex) / 256 + tmpBufL[i]; } - if (++allpassIdx[0][i] == delays[i]) - allpassIdx[0][i] = 0; + if (++allpassIdxL[i] == delaysL[i]) + allpassIdxL[i] = 0; } - return clamp16((outTmp * gReverbWetSignal + inSample * gReverbDrySignal) / 256); -} - -inline s16 reverb_sample_right(s32 inSample) { - u32 i = 0; - s32 j = 0; - u8 k = 0; - s32 outTmp = 0; - s32 tmpCarryover = ((tmpBufR[NUM_ALLPASS-1] * gReverbRevIndex) / 256); - - for (; i < NUM_ALLPASS; ++i, ++j) { - tmpBufR[i] = delayBufs[1][i][allpassIdx[1][i]]; - - if (j == 2) { - j = -1; - outTmp += (tmpBufR[i] * reverbMults[1][k++]) / 256; - delayBufs[1][i][allpassIdx[1][i]] = tmpCarryover; - if (i != NUM_ALLPASS - 1) - tmpCarryover = (tmpBufR[i] * gReverbRevIndex) / 256; - } - else { - delayBufs[1][i][allpassIdx[1][i]] = (tmpBufR[i] * (-gReverbGainIndex)) / 256 + tmpCarryover; - - if (i == 6) - delayBufs[1][i][allpassIdx[1][i]] += inSample; - - tmpCarryover = (delayBufs[1][i][allpassIdx[1][i]] * gReverbGainIndex) / 256 + tmpBufR[i]; - } - - if (++allpassIdx[1][i] == delays[i]) - allpassIdx[1][i] = 0; - } - - return clamp16((outTmp * gReverbWetSignal + inSample * gReverbDrySignal) / 256); + *outSample = clamp16((outTmp * gReverbWetSignal/* + inSample * gReverbDrySignal*/) / 256); } +#endif #ifdef VERSION_EU s16 gVolume; @@ -373,25 +389,25 @@ void prepare_reverb_ring_buffer(s32 chunkLen, u32 updateIndex) { #ifdef BETTER_REVERB else if (toggleBetterReverb) { item = &gSynthesisReverb.items[gSynthesisReverb.curFrame][updateIndex]; - if (gSoundMode == SOUND_MODE_MONO) { + if (gSoundMode == SOUND_MODE_MONO || monoReverb) { if (gReverbDownsampleRate != 1) { osInvalDCache(item->toDownsampleLeft, DEFAULT_LEN_2CH); for (srcPos = 0, dstPos = item->startPos; dstPos < item->lengthA / 2 + item->startPos; srcPos += gReverbDownsampleRate, dstPos++) { - gSynthesisReverb.ringBuffer.left[dstPos] = reverb_sample_left(((s32) item->toDownsampleLeft[srcPos] + (s32) item->toDownsampleRight[srcPos]) / 2); + reverb_mono_sample(&gSynthesisReverb.ringBuffer.left[dstPos], ((s32) item->toDownsampleLeft[srcPos] + (s32) item->toDownsampleRight[srcPos]) / 2); gSynthesisReverb.ringBuffer.right[dstPos] = gSynthesisReverb.ringBuffer.left[dstPos]; } for (dstPos = 0; dstPos < item->lengthB / 2; srcPos += gReverbDownsampleRate, dstPos++) { - gSynthesisReverb.ringBuffer.left[dstPos] = reverb_sample_left(((s32) item->toDownsampleLeft[srcPos] + (s32) item->toDownsampleRight[srcPos]) / 2); + reverb_mono_sample(&gSynthesisReverb.ringBuffer.left[dstPos], ((s32) item->toDownsampleLeft[srcPos] + (s32) item->toDownsampleRight[srcPos]) / 2); gSynthesisReverb.ringBuffer.right[dstPos] = gSynthesisReverb.ringBuffer.left[dstPos]; } } else { // Too slow for practical use, not recommended most of the time. for (dstPos = item->startPos; dstPos < item->lengthA / 2 + item->startPos; dstPos++) { - gSynthesisReverb.ringBuffer.left[dstPos] = reverb_sample_left(((s32) gSynthesisReverb.ringBuffer.left[dstPos] + (s32) gSynthesisReverb.ringBuffer.right[dstPos]) / 2); + reverb_mono_sample(&gSynthesisReverb.ringBuffer.left[dstPos], ((s32) gSynthesisReverb.ringBuffer.left[dstPos] + (s32) gSynthesisReverb.ringBuffer.right[dstPos]) / 2); gSynthesisReverb.ringBuffer.right[dstPos] = gSynthesisReverb.ringBuffer.left[dstPos]; } for (dstPos = 0; dstPos < item->lengthB / 2; dstPos++) { - gSynthesisReverb.ringBuffer.left[dstPos] = reverb_sample_left(((s32) gSynthesisReverb.ringBuffer.left[dstPos] + (s32) gSynthesisReverb.ringBuffer.right[dstPos]) / 2); + reverb_mono_sample(&gSynthesisReverb.ringBuffer.left[dstPos], ((s32) gSynthesisReverb.ringBuffer.left[dstPos] + (s32) gSynthesisReverb.ringBuffer.right[dstPos]) / 2); gSynthesisReverb.ringBuffer.right[dstPos] = gSynthesisReverb.ringBuffer.left[dstPos]; } } @@ -403,31 +419,12 @@ void prepare_reverb_ring_buffer(s32 chunkLen, u32 updateIndex) { reverb_samples(&gSynthesisReverb.ringBuffer.left[dstPos], &gSynthesisReverb.ringBuffer.right[dstPos], item->toDownsampleLeft[srcPos], item->toDownsampleRight[srcPos]); for (dstPos = 0; dstPos < item->lengthB / 2; srcPos += gReverbDownsampleRate, dstPos++) reverb_samples(&gSynthesisReverb.ringBuffer.left[dstPos], &gSynthesisReverb.ringBuffer.right[dstPos], item->toDownsampleLeft[srcPos], item->toDownsampleRight[srcPos]); - - // for (srcPos = 0, dstPos = item->startPos; dstPos < item->lengthA / 2 + item->startPos; - // srcPos += gReverbDownsampleRate, dstPos++) { - // gSynthesisReverb.ringBuffer.left[dstPos] = reverb_sample_left(item->toDownsampleLeft[srcPos]); - // gSynthesisReverb.ringBuffer.right[dstPos] = reverb_sample_right(item->toDownsampleRight[srcPos]); - // } - // for (dstPos = 0; dstPos < item->lengthB / 2; srcPos += gReverbDownsampleRate, dstPos++) { - // gSynthesisReverb.ringBuffer.left[dstPos] = reverb_sample_left(item->toDownsampleLeft[srcPos]); - // gSynthesisReverb.ringBuffer.right[dstPos] = reverb_sample_right(item->toDownsampleRight[srcPos]); - // } } else { // Too slow for practical use, not recommended most of the time. for (dstPos = item->startPos; dstPos < item->lengthA / 2 + item->startPos; dstPos++) reverb_samples(&gSynthesisReverb.ringBuffer.left[dstPos], &gSynthesisReverb.ringBuffer.right[dstPos], gSynthesisReverb.ringBuffer.left[dstPos], gSynthesisReverb.ringBuffer.right[dstPos]); for (dstPos = 0; dstPos < item->lengthB / 2; dstPos++) reverb_samples(&gSynthesisReverb.ringBuffer.left[dstPos], &gSynthesisReverb.ringBuffer.right[dstPos], gSynthesisReverb.ringBuffer.left[dstPos], gSynthesisReverb.ringBuffer.right[dstPos]); - - // for (dstPos = item->startPos; dstPos < item->lengthA / 2 + item->startPos; dstPos++) { - // gSynthesisReverb.ringBuffer.left[dstPos] = reverb_sample_left(gSynthesisReverb.ringBuffer.left[dstPos]); - // gSynthesisReverb.ringBuffer.right[dstPos] = reverb_sample_right(gSynthesisReverb.ringBuffer.right[dstPos]); - // } - // for (dstPos = 0; dstPos < item->lengthB / 2; srcPos += gReverbDownsampleRate, dstPos++) { - // gSynthesisReverb.ringBuffer.left[dstPos] = reverb_sample_left(gSynthesisReverb.ringBuffer.left[dstPos]); - // gSynthesisReverb.ringBuffer.right[dstPos] = reverb_sample_right(gSynthesisReverb.ringBuffer.right[dstPos]); - // } } } } @@ -590,6 +587,22 @@ u64 *synthesis_execute(u64 *cmdBuf, s32 *writtenCmds, s16 *aiBuf, s32 bufLen) { aSegment(cmdBuf, 0, 0); +#ifdef BETTER_REVERB + if (gIsConsole) { + reverbFilterCount = reverbFilterCountConsole; + monoReverb = monoReverbConsole; + } + else { + reverbFilterCount = reverbFilterCountEmulator; + monoReverb = monoReverbEmulator; + } + if (reverbFilterCount > NUM_ALLPASS) + reverbFilterCount = NUM_ALLPASS; + reverbFilterCountm1 = reverbFilterCount - 1; + if (reverbFilterCount < 3) + reverbFilterCountm1 = 0; +#endif + for (i = gAudioUpdatesPerFrame; i > 0; i--) { if (i == 1) { // 'bufLen' will automatically be divisible by 8, no need to round diff --git a/src/audio/synthesis.h b/src/audio/synthesis.h index 19f341ab..ee1d96ce 100644 --- a/src/audio/synthesis.h +++ b/src/audio/synthesis.h @@ -18,22 +18,40 @@ #endif #ifdef BETTER_REVERB -#define BETTER_REVERB_SIZE 0xF200 // Size determined by ((all delaysBaseline values * 16) / (2 ^ Minimum Downsample Factor)) + array pointers; can be increased if needed -// #define BETTER_REVERB_SIZE 0x1E200 // For use with a downsampling value of 1 (i.e. no downsampling at all) -#else -#define BETTER_REVERB_SIZE 0 -#endif + // Size determined by ((all delaysBaselineL/R values * 8) / (2 ^ Minimum Downsample Factor)) + array pointers. + // The default value can be increased or decreased in conjunction with the values in delaysBaselineL/R +#define BETTER_REVERB_SIZE 0xF200 + +// #define BETTER_REVERB_SIZE 0x7A00 // Default for use only with a downsampling value of 3 (i.e. double the emulator default) +// #define BETTER_REVERB_SIZE 0x1E200 // Default for use with a downsampling value of 1 (i.e. no downsampling at all) #define NUM_ALLPASS 12 // Number of delay filters to use with better reverb; do not change this value if you don't know what you're doing. +extern s8 betterReverbDownsampleConsole; +extern s8 betterReverbDownsampleEmulator; +extern u32 reverbFilterCountConsole; +extern u32 reverbFilterCountEmulator; +extern u8 monoReverbConsole; +extern u8 monoReverbEmulator; extern s32 betterReverbWindowsSize; -extern const s32 delaysBaseline[NUM_ALLPASS]; -extern s32 delays[NUM_ALLPASS]; -extern s32 ***delayBufs; +extern s32 gReverbRevIndex; +extern s32 gReverbGainIndex; +extern s32 gReverbWetSigna; +// extern s32 gReverbDrySignal; + +extern const s32 delaysBaselineL[NUM_ALLPASS]; +extern const s32 delaysBaselineR[NUM_ALLPASS]; +extern s32 delaysL[NUM_ALLPASS]; +extern s32 delaysR[NUM_ALLPASS]; +extern s32 reverbMultsL[NUM_ALLPASS / 3]; +extern s32 reverbMultsR[NUM_ALLPASS / 3]; +extern s32 **delayBufsL; +extern s32 **delayBufsR; extern u8 toggleBetterReverb; -extern s8 betterReverbConsoleDownsample; -extern s8 betterReverbEmulatorDownsample; +#else +#define BETTER_REVERB_SIZE 0 +#endif struct ReverbRingBufferItem { diff --git a/src/game/behaviors/snow_mound.inc.c b/src/game/behaviors/snow_mound.inc.c index f8fcc539..b9bfb978 100644 --- a/src/game/behaviors/snow_mound.inc.c +++ b/src/game/behaviors/snow_mound.inc.c @@ -33,7 +33,7 @@ void bhv_snow_mound_spawn_loop(void) { if (o->oTimer == 64 || o->oTimer == 128 || o->oTimer == 192 || o->oTimer == 224 || o->oTimer == 256) sp1C = spawn_object(o, MODEL_SL_SNOW_TRIANGLE, bhvSlidingSnowMound); - if (o->oTimer == 256) { + if (sp1C && o->oTimer == 256) { sp1C->header.gfx.scale[0] = 2.0f; sp1C->header.gfx.scale[1] = 2.0f; } diff --git a/src/game/game_init.c b/src/game/game_init.c index 98639acd..b82d89d9 100644 --- a/src/game/game_init.c +++ b/src/game/game_init.c @@ -47,6 +47,9 @@ OSContPad gControllerPads[4]; u8 gControllerBits; u8 gIsConsole = TRUE; // Needs to be initialized before audio_reset_session is called u8 gBorderHeight; +#ifdef CUSTOM_DEBUG +u8 gCustomDebugMode; +#endif #ifdef EEP s8 gEepromProbe; #endif diff --git a/src/game/game_init.h b/src/game/game_init.h index 87386cea..f3f650c3 100644 --- a/src/game/game_init.h +++ b/src/game/game_init.h @@ -46,6 +46,9 @@ extern u8 gIsConsole; extern u8 gWidescreen; #endif extern u8 gBorderHeight; +#ifdef CUSTOM_DEBUG +extern u8 gCustomDebugMode; +#endif #ifdef EEP extern s8 gEepromProbe; #endif diff --git a/src/game/hud.c b/src/game/hud.c index ee927a00..126072bd 100644 --- a/src/game/hud.c +++ b/src/game/hud.c @@ -16,6 +16,8 @@ #include "engine/surface_load.h" #include "puppycam2.h" +#include "config.h" + /* @file hud.c * This file implements HUD rendering and power meter animations. * That includes stars, lives, coins, camera status, power meter, timer @@ -49,9 +51,9 @@ f32 calculate_and_update_fps() void print_fps(s32 x, s32 y) { f32 fps = calculate_and_update_fps(); - char text[10]; + char text[14]; - sprintf(text, "%2.2f", fps); + sprintf(text, "FPS %2.2f", fps); print_text(x, y, text); } @@ -309,6 +311,18 @@ void render_hud_mario_lives(void) { print_text_fmt_int(GFX_DIMENSIONS_RECT_FROM_LEFT_EDGE(54), HUD_TOP_Y, "%d", gHudDisplay.lives); } +#ifdef CUSTOM_DEBUG +void render_debug_mode(void) { + print_text(180, 40, "DEBUG MODE"); + print_text_fmt_int(5, 20, "Z %d", gMarioState->pos[2]); + print_text_fmt_int(5, 40, "Y %d", gMarioState->pos[1]); + print_text_fmt_int(5, 60, "X %d", gMarioState->pos[0]); + print_text_fmt_int(10, 100, "SPD %d", (s32) gMarioState->forwardVel); + print_text_fmt_int(10, 120, "ANG 0*%04x", (u16) gMarioState->faceAngle[1]); + print_fps(10,80); +} +#endif + /** * Renders the amount of coins collected. */ @@ -523,5 +537,10 @@ void render_hud(void) { { print_text(10, 60, "SURFACE NODE POOL FULL"); } + #ifdef CUSTOM_DEBUG + if (gCustomDebugMode) { + render_debug_mode(); + } + #endif } } diff --git a/src/game/mario.c b/src/game/mario.c index 15d6c78e..1ea37156 100644 --- a/src/game/mario.c +++ b/src/game/mario.c @@ -1283,6 +1283,23 @@ void update_mario_button_inputs(struct MarioState *m) { m->input |= INPUT_A_DOWN; } +#ifdef CUSTOM_DEBUG + if (m->controller->buttonPressed & L_JPAD) { + gCustomDebugMode ^= 1; + } + if (gCustomDebugMode) { + if (m->controller->buttonPressed & R_JPAD) { + if (gMarioState->action == ACT_DEBUG_FREE_MOVE) { + set_mario_action(gMarioState, ACT_IDLE, 0); + } else { + set_mario_action(gMarioState, ACT_DEBUG_FREE_MOVE, 0); + } + } + } else if (gMarioState->action == ACT_DEBUG_FREE_MOVE) { + set_mario_action(gMarioState, ACT_IDLE, 0); + } +#endif + // Don't update for these buttons if squished. if (m->squishTimer == 0) { if (m->controller->buttonPressed & B_BUTTON) { diff --git a/src/game/mario_actions_moving.c b/src/game/mario_actions_moving.c index b72b6cff..b6248cbb 100644 --- a/src/game/mario_actions_moving.c +++ b/src/game/mario_actions_moving.c @@ -386,12 +386,8 @@ void update_shell_speed(struct MarioState *m) { m->forwardVel = 64.0f; } -#ifdef SUPER_RESPONSIVE_CONTROLS - m->faceAngle[1] = m->intendedYaw; -#else m->faceAngle[1] = m->intendedYaw - approach_s32((s16)(m->intendedYaw - m->faceAngle[1]), 0, 0x800, 0x800); -#endif apply_slope_accel(m); @@ -465,9 +461,13 @@ void update_walking_speed(struct MarioState *m) { if (m->forwardVel > 48.0f) { m->forwardVel = 48.0f; } - + +#ifdef SUPER_RESPONSIVE_CONTROLS + m->faceAngle[1] = m->intendedYaw; +#else m->faceAngle[1] = m->intendedYaw - approach_s32((s16)(m->intendedYaw - m->faceAngle[1]), 0, 0x800, 0x800); +#endif apply_slope_accel(m); } diff --git a/src/game/platform_displacement.c b/src/game/platform_displacement.c index e42f4829..392f4fe0 100644 --- a/src/game/platform_displacement.c +++ b/src/game/platform_displacement.c @@ -144,6 +144,14 @@ void apply_platform_displacement(struct PlatformDisplacementInfo *displaceInfo, vec3f_sub(pos, platformPos); } + if (platformPos[0] == platform->oPosX + && platformPos[1] == platform->oPosY + && platformPos[2] == platform->oPosZ) { + pos[0] += platform->oVelX; + pos[1] += platform->oVelY; + pos[2] += platform->oVelZ; + } + // Transform from world positions to relative positions for use next frame linear_mtxf_transpose_mul_vec3f(*platform->header.gfx.throwMatrix, scaledPos, pos); scale_vec3f(displaceInfo->prevTransformedPos, scaledPos, platform->header.gfx.scale, TRUE); diff --git a/tools/rncpack.c b/tools/rncpack.c index 2eaaff4f..31cd6c64 100644 --- a/tools/rncpack.c +++ b/tools/rncpack.c @@ -1641,10 +1641,10 @@ int parse_args(int argc, char **argv, vars_t *vars) int main(int argc, char *argv[]) { - printf("-= RNC ProPackED v1.5 [by Lab 313] (12/02/2020) =-\n"); - printf("-----------------------------\n"); if (argc <= 2) { + printf("-= RNC ProPackED v1.5 [by Lab 313] (12/02/2020) =-\n"); + printf("-----------------------------\n"); printf("Compression type: Huffman + LZ77\n"); printf("De/Compressor: Dr.MefistO\n"); printf("Coding: Dr. MefistO\n"); @@ -1725,8 +1725,8 @@ int main(int argc, char *argv[]) fwrite(v->output, v->output_offset, 1, out); fclose(out); - printf("File successfully %s!\n", ((v->puse_mode == 'p') ? "packed" : "unpacked")); - printf("Original/new size: %d/%zd bytes\n", (v->puse_mode == 'u') ? (v->packed_size + RNC_HEADER_SIZE) : v->file_size, v->output_offset); +// printf("File successfully %s!\n", ((v->puse_mode == 'p') ? "packed" : "unpacked")); +// printf("Original/new size: %d/%zd bytes\n", (v->puse_mode == 'u') ? (v->packed_size + RNC_HEADER_SIZE) : v->file_size, v->output_offset); } else { switch (error_code) { diff --git a/tools/slienc.c b/tools/slienc.c index 30e3911f..ec44e519 100644 --- a/tools/slienc.c +++ b/tools/slienc.c @@ -199,7 +199,7 @@ void encode() } if ( v1 != 0x80000000 ) ++cp; - fprintf(stderr, "IN=%d OUT=%d\n", insize, dp + 2 * pp + 4 * cp + 16); + //fprintf(stderr, "IN=%d OUT=%d\n", insize, dp + 2 * pp + 4 * cp + 16); } void search(unsigned int a1, int a2, int *a3, unsigned int *a4)