Compare commits

..

8 Commits

Author SHA1 Message Date
Reonu
bc3a4186c5 fixed wrong check 2022-06-28 23:26:09 +01:00
Reonu
0028b33597 Added gGamecubeControllerPort 2022-06-28 23:20:39 +01:00
Reonu
df0c4d11a3 Changed threshold for L trig to around 33%
Changed threshold based on feedback
2022-06-24 19:20:33 +01:00
Reonu
77a3e81fc4 L to Z logic for GC controller uses a threshold 2022-06-24 01:08:37 +01:00
Reonu
b3ca34cfa2 read GC controllers from port 2 2022-06-23 23:16:48 +01:00
Mr-Wiseguy
8be89acaf8 Added workaround in controller type detection for mupen bug 2022-06-15 20:18:25 -04:00
Mr-Wiseguy
7de132ca34 Added X and Y buttons to VALID_BUTTONS in sm64.h 2022-06-06 21:13:25 -04:00
Mr-Wiseguy
dd9f0eeec1 Implemented native Gamecube controller support and corresponding emulator hint in ROM header 2022-05-24 02:28:00 -04:00
28 changed files with 740 additions and 194 deletions

View File

@@ -25,7 +25,7 @@
"TARGET_N64=1",
"VERSION_US=1",
"F3DEX_GBI_2=1",
"F3DZEX_NON_GBI_2=1",
"F3DZEX_GBI_2=1",
"F3DEX_GBI_SHARED=1",
"NON_MATCHING=1",
"AVOID_UB=1"

View File

@@ -108,7 +108,7 @@ else ifeq ($(GRUCODE),l3dex2) # Line3DEX2
else ifeq ($(GRUCODE),f3dex2pl) # Fast3DEX2_PosLight
DEFINES += F3DEX2PL_GBI=1 F3DEX_GBI_2=1 F3DEX_GBI_SHARED=1
else ifeq ($(GRUCODE),f3dzex) # Fast3DZEX (2.08J / Animal Forest - DĹŤbutsu no Mori)
DEFINES += F3DZEX_NON_GBI_2=1 F3DEX_GBI_2=1 F3DEX_GBI_SHARED=1
DEFINES += F3DZEX_GBI_2=1 F3DEX_GBI_2=1 F3DEX_GBI_SHARED=1
else ifeq ($(GRUCODE),super3d) # Super3D
$(warning Super3D is experimental. Try at your own risk.)
DEFINES += SUPER3D_GBI=1 F3D_NEW=1

View File

@@ -33,7 +33,7 @@ This is a fork of the ultrasm64 repo by CrashOveride which includes the followin
Thanks to Frame#5375 and AloXado320 for also helping with silhouette stuff
**Lighting Engine by Wiseguy**
- Lighting Engine is available on a separate branch ([base/lighting-engine](https://github.com/Reonu/HackerSM64/tree/base/lighting-engine)). Instructions on how to use it are in the readme of that branch.
- Lighting Engine is available on a separate branch ([base/lighting-engine-wip](https://github.com/Reonu/HackerSM64/tree/base/lighting-engine-wip)). Instructions on how to use it are in the readme of that branch.
- Alternatively, the main repo has `Puppylights` available, which is a more lightweight, but limited lighting library intended to be used to modify existing light properties. You can look at `puppylights.c` to find out how to use it.
**Puppycam**

View File

@@ -15,9 +15,14 @@
.word 0x00000000 /* Unknown */
.word 0x00000000 /* Unknown */
.ascii INTERNAL_ROM_NAME /* Internal ROM name */
#if defined(USE_GAMECUBE_CONTROLLER)
/* Advanced homebrew ROM header bytes: https://n64brew.dev/wiki/ROM_Header#Advanced_Homebrew_ROM_Header */
.word 0x82000000
#else
.word 0x00000000 /* Unknown */
#endif
.word 0x0000004E /* Cartridge */
#if defined(EEP4K)
#if defined(EEP4K) && !defined(USE_GAMECUBE_CONTROLLER)
.ascii "SM" /* Cartridge ID */
#else
.ascii "ED" /* Cartridge ID */

View File

@@ -9,11 +9,6 @@
*/
#define CASTLE_MUSIC_FIX
/**
* Do not restart the music on cap grabs
*/
#define PERSISTENT_CAP_MUSIC
/**
* Increase audio heap size to allow for larger/more custom sequences/banks/sfx to be imported without causing issues (not supported for SH).
*/
@@ -33,3 +28,8 @@
* Reverb parameters can be configured in audio/synthesis.c to meet desired aesthetic/performance needs. Currently US/JP only. Hurts emulator and console performance.
*/
// #define BETTER_REVERB
/**
* Do not restart the music on cap grabs
*/
#define PERSISTENT_CAP_MUSIC

View File

@@ -17,9 +17,6 @@
// Number of walls that can push Mario at once. Vanilla is 4.
#define MAX_REFERENCED_WALLS 4
// Allow vertical rooms to be a thing by using the SURFACE_INTANGIBLE floor type to separate the rooms. Note that this will add an extra floor check every frame.
// #define VERTICAL_ROOMS
// Collision data is the type that the collision system uses. All data by default is stored as an s16, but you may change it to s32.
// Naturally, that would double the size of all collision data, but would allow you to use 32 bit values instead of 16.
// Rooms are s8 in vanilla, but if you somehow have more than 255 rooms, you may raise this number.

View File

@@ -39,7 +39,7 @@
// Similar to the above, but 30 FPS (Textures by InTheBeef, cleaned up by Arceveti)
#define IA8_30FPS_COINS
// Use .rej microcode for certain objects (experimental - only should be used when F3DEX_GBI_2 is defined).
// Use .rej microcode for certain objects (experimental - only should be used when F3DZEX_GBI_2 is defined).
// For advanced users only. Does not work perfectly out the box, best used when exported actor models are
// using 64 vertex sizes, offered by Fast64 in the microcode menu.
// #define OBJECTS_REJ

View File

@@ -23,3 +23,6 @@
// There is generally no reason to have a value other than 0 for emulator. As for console, it provides a (small) performance boost.
#define BORDER_HEIGHT_CONSOLE 0
#define BORDER_HEIGHT_EMULATOR 0
// Informs supported emulators to default to gamecube controller inputs
// #define USE_GAMECUBE_CONTROLLER

View File

@@ -54,9 +54,9 @@
* config_graphics
*/
#ifndef F3DEX_GBI_2
#undef OBJECTS_REJ // OBJECTS_REJ requires f3dex2.
#endif // !F3DEX_GBI_2
#ifndef F3DZEX_GBI_2
#undef OBJECTS_REJ // OBJECTS_REJ requires f3dzex.
#endif // !F3DZEX_GBI_2
#ifndef F3DEX_GBI_SHARED
#undef OBJECTS_REJ // Non F3DEX-based ucodes do NOT support ucode switching.

View File

@@ -63,6 +63,18 @@ typedef struct {
u8 error;
} OSContPad;
// Custom extended controller pad struct that contains fields for gamecube controllers
typedef struct {
u16 button;
s8 stick_x; /* -80 <= stick_x <= 80 */
s8 stick_y; /* -80 <= stick_y <= 80 */
s8 c_stick_x;
s8 c_stick_y;
u8 l_trig;
u8 r_trig;
u8 errno;
} OSContPadEx;
typedef struct {
void *address; /* Ram pad Address: 11 bits */
u8 databuffer[32]; /* address of the data buffer */
@@ -103,6 +115,7 @@ typedef struct {
#define CONT_ABSOLUTE 0x0001
#define CONT_RELATIVE 0x0002
#define CONT_JOYPORT 0x0004
#define CONT_GCN 0x0008
#define CONT_EEPROM 0x8000
#define CONT_EEP16K 0x4000
#define CONT_TYPE_MASK 0x1f07
@@ -150,6 +163,25 @@ typedef struct {
#define L_CBUTTONS CONT_C
#define R_CBUTTONS CONT_F
#define D_CBUTTONS CONT_D
#define GCN_X_BUTTON 0x0040
#define GCN_Y_BUTTON 0x0080
/* Gamecube controller buttons */
#define CONT_GCN_GET_ORIGIN 0x2000
#define CONT_GCN_START 0x1000
#define CONT_GCN_Y 0x0800
#define CONT_GCN_X 0x0400
#define CONT_GCN_B 0x0200
#define CONT_GCN_A 0x0100
#define CONT_GCN_USE_ORIGIN 0x0080
#define CONT_GCN_L 0x0040
#define CONT_GCN_R 0x0020
#define CONT_GCN_Z 0x0010
#define CONT_GCN_UP 0x0008
#define CONT_GCN_DOWN 0x0004
#define CONT_GCN_RIGHT 0x0002
#define CONT_GCN_LEFT 0x0001
/* Controller error number */
@@ -162,6 +194,9 @@ typedef struct {
#define CONT_ERR_VOICE_WORD 14
#define CONT_ERR_VOICE_NO_RESPONSE 15
#define CONT_TYPE_N64 0
#define CONT_TYPE_GCN 1
#if defined(_LANGUAGE_C) || defined(_LANGUAGE_C_PLUS_PLUS)
@@ -178,6 +213,7 @@ typedef struct {
*
*/
extern u8 __osControllerTypes[MAXCONTROLLERS];
/**************************************************************************
*
@@ -191,11 +227,13 @@ extern s32 osContInit( OSMesgQueue *mq, u8 *bitpattern, OSContStatus *s
extern s32 osContReset( OSMesgQueue *mq, OSContStatus *status);
extern s32 osContStartQuery( OSMesgQueue *mq);
extern s32 osContStartReadData(OSMesgQueue *mq);
extern s32 osContStartReadDataEx(OSMesgQueue *mq);
#ifndef _HW_VERSION_1
extern s32 osContSetCh(u8 ch);
#endif
extern void osContGetQuery(OSContStatus *status);
extern void osContGetReadData(OSContPad *pad);
extern void osContGetReadDataEx(OSContPadEx *pad);
#endif /* defined(_LANGUAGE_C) || defined(_LANGUAGE_C_PLUS_PLUS) */

View File

@@ -62,12 +62,14 @@ extern "C" {
/* Rumble PAK interface */
extern s32 osMotorInit(OSMesgQueue *mq, OSPfs *pfs, int controller_no);
extern s32 osMotorInitEx(OSMesgQueue *mq, OSPfs *pfs, int controller_no);
#if 1
#define MOTOR_START 1
#define MOTOR_STOP 0
#define osMotorStart(x) __osMotorAccess((x), MOTOR_START)
#define osMotorStop(x) __osMotorAccess((x), MOTOR_STOP)
#define osMotorStart(x) __osMotorAccessEx((x), MOTOR_START)
#define osMotorStop(x) __osMotorAccessEx((x), MOTOR_STOP)
extern s32 __osMotorAccess(OSPfs *pfs, s32 flag);
extern s32 __osMotorAccessEx(OSPfs *pfs, s32 flag);
#else
extern s32 osMotorStop( OSPfs *pfs);
extern s32 osMotorStart(OSPfs *pfs);

View File

@@ -715,7 +715,8 @@ enum MarioActionFlags {
#define VALID_BUTTONS (A_BUTTON | B_BUTTON | Z_TRIG | START_BUTTON | \
U_JPAD | D_JPAD | L_JPAD | R_JPAD | \
L_TRIG | R_TRIG | \
U_CBUTTONS | D_CBUTTONS | L_CBUTTONS | R_CBUTTONS )
U_CBUTTONS | D_CBUTTONS | L_CBUTTONS | R_CBUTTONS | \
GCN_X_BUTTON | GCN_Y_BUTTON)
#define C_BUTTONS (U_CBUTTONS | D_CBUTTONS | L_CBUTTONS | R_CBUTTONS )

View File

@@ -40,11 +40,10 @@ struct Controller {
/*0x0C*/ f32 stickMag; // distance from center [0, 64]
/*0x10*/ u16 buttonDown;
/*0x12*/ u16 buttonPressed;
/*0x14*/ u16 buttonReleased;
/*0x18*/ OSContStatus *statusData;
/*0x1C*/ OSContPad *controllerData;
/*0x14*/ OSContStatus *statusData;
/*0x18*/ OSContPadEx *controllerData;
#if ENABLE_RUMBLE
/*0x20*/ s32 port;
/*0x1C*/ s32 port;
#endif
};

View File

@@ -186,6 +186,8 @@ SECTIONS
lib/PR/audio/n_aspMain.o(.text*);
lib/PR/hvqm/hvqm2sp1.o(.text*);
_mainSegmentTextEnd = .;
/* Overwrite a libultra function with its modified counterpart for GCN controller support */
__osContGetInitData = __osContGetInitDataEx;
/* data */
BUILD_DIR/asm/n64_assert.o(.*data*);

View File

@@ -1059,6 +1059,7 @@ void init_reverb_us(s32 presetId) {
s32 i;
#ifdef BETTER_REVERB
s8 reverbConsole;
s32 bufOffset = 0;
#endif
s32 reverbWindowSize = gReverbSettings[presetId].windowSize;
@@ -1111,7 +1112,9 @@ void init_reverb_us(s32 presetId) {
gSynthesisReverb.items[1][i].toDownsampleRight = (mem + (DEFAULT_LEN_1CH / sizeof(s16)));
}
#ifdef BETTER_REVERB
initialize_better_reverb_buffers();
delayBufsL = (s32**) soundAlloc(&gBetterReverbPool, BETTER_REVERB_PTR_SIZE);
delayBufsR = &delayBufsL[NUM_ALLPASS];
delayBufsL[0] = (s32*) soundAlloc(&gBetterReverbPool, BETTER_REVERB_SIZE - BETTER_REVERB_PTR_SIZE);
#endif
} else {
bzero(gSynthesisReverb.ringBuffer.left, (REVERB_WINDOW_SIZE_MAX * 2 * sizeof(s16)));
@@ -1143,10 +1146,17 @@ void init_reverb_us(s32 presetId) {
#ifdef BETTER_REVERB
if (toggleBetterReverb) {
if (sAudioIsInitialized) {
clear_better_reverb_buffers();
}
bzero(delayBufsL[0], (BETTER_REVERB_SIZE - BETTER_REVERB_PTR_SIZE));
}
set_better_reverb_buffers();
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
}

View File

@@ -93,9 +93,6 @@ extern struct SoundAllocPool gAudioInitPool;
extern struct SoundAllocPool gNotesAndBuffersPool;
extern struct SoundAllocPool gPersistentCommonPool;
extern struct SoundAllocPool gTemporaryCommonPool;
#ifdef BETTER_REVERB
extern struct SoundAllocPool gBetterReverbPool;
#endif
extern struct SoundMultiPool gSeqLoadedPool;
extern struct SoundMultiPool gBankLoadedPool;
#ifdef VERSION_SH

View File

@@ -69,7 +69,7 @@
// 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 betterReverbDownsampleConsole = 2;
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 on emulator unless reducing other parameters to compensate. If you do decide to use 1 here, you must adjust BETTER_REVERB_SIZE appropriately.
@@ -80,22 +80,22 @@ s8 betterReverbDownsampleEmulator = 2;
// 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.
// This value cannot be less than 3. Setting it to anything lower will act as if it was set to 3.
// Setting it to anything less than 3 will disable reverb outright.
// This can be changed at any time, but is best set immediately before calling audio_reset_session.
s32 reverbFilterCountConsole = (NUM_ALLPASS - 9);
u32 reverbFilterCountConsole = (NUM_ALLPASS - 6);
// 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.
// This value cannot be less than 3. Setting it to anything lower will act as if it was set to 3.
// Setting it to anything less than 3 will disable reverb outright.
// This can be changed at any time, but is best set immediately before calling audio_reset_session.
s32 reverbFilterCountEmulator = NUM_ALLPASS;
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 fulfilling reverb experience.
// 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 immediately before 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 fulfilling reverb experience.
// 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 immediately before calling audio_reset_session.
u8 monoReverbEmulator = FALSE;
@@ -111,7 +111,7 @@ s32 betterReverbWindowsSize = -1;
// 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 0xE0 // Amount of reverb specific output in final signal (also affects decay); can be messed with at any time, also very easy to control
#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
// #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
@@ -136,25 +136,26 @@ s32 delaysBaselineR[NUM_ALLPASS] = {
1200, 1432, 1232
};
// These values affect reverb decay depending on the filter index; can be messed with at any time, and will have effects updated in real time
s32 gReverbMultsL[NUM_ALLPASS / 3] = {0xD7, 0x6F, 0x36, 0x22};
s32 gReverbMultsR[NUM_ALLPASS / 3] = {0xCF, 0x73, 0x38, 0x1F};
// 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.
s32 reverbFilterCount = NUM_ALLPASS;
s32 reverbFilterCountm1 = (NUM_ALLPASS - 1);
u8 monoReverb = FALSE;
u8 toggleBetterReverb = TRUE;
static u8 monoReverb = FALSE;
static s32 reverbFilterCount = NUM_ALLPASS;
static s32 allpassIdxL[NUM_ALLPASS] = {0};
static s32 allpassIdxR[NUM_ALLPASS] = {0};
static s32 delaysL[NUM_ALLPASS] = {0};
static s32 delaysR[NUM_ALLPASS] = {0};
static u8 reverbMultsL[NUM_ALLPASS / 3] = {0};
static u8 reverbMultsR[NUM_ALLPASS / 3] = {0};
static s32 **delayBufsL;
static s32 **delayBufsR;
s32 allpassIdxL[NUM_ALLPASS] = {0};
s32 allpassIdxR[NUM_ALLPASS] = {0};
s32 tmpBufL[NUM_ALLPASS] = {0};
s32 tmpBufR[NUM_ALLPASS] = {0};
s32 delaysL[NUM_ALLPASS] = {0};
s32 delaysR[NUM_ALLPASS] = {0};
s32 **delayBufsL;
s32 **delayBufsR;
#endif
@@ -192,109 +193,72 @@ u8 sAudioSynthesisPad[0x20];
#endif
#ifdef BETTER_REVERB
static void reverb_samples(s16 *outSampleL, s16 *outSampleR, s32 inSampleL, s32 inSampleR) {
s32 *curDelaySampleL;
s32 *curDelaySampleR;
s32 historySampleL;
s32 historySampleR;
static inline void reverb_samples(s16 *outSampleL, s16 *outSampleR, s32 inSampleL, s32 inSampleR) {
s32 i = 0;
s32 j = 0;
s32 k = 0;
s32 outTmpL = 0;
s32 outTmpR = 0;
s32 tmpCarryoverL = (((delayBufsL[reverbFilterCount][allpassIdxL[reverbFilterCount]] * REVERB_REV_INDEX) >> 8) + inSampleL);
s32 tmpCarryoverR = (((delayBufsR[reverbFilterCount][allpassIdxR[reverbFilterCount]] * REVERB_REV_INDEX) >> 8) + inSampleR);
s32 tmpCarryoverL = (((tmpBufL[reverbFilterCountm1] * REVERB_REV_INDEX) / 256) + inSampleL);
s32 tmpCarryoverR = (((tmpBufR[reverbFilterCountm1] * REVERB_REV_INDEX) / 256) + inSampleR);
for (; i <= reverbFilterCount; ++i, ++j) {
curDelaySampleL = &delayBufsL[i][allpassIdxL[i]];
curDelaySampleR = &delayBufsR[i][allpassIdxR[i]];
historySampleL = *curDelaySampleL;
historySampleR = *curDelaySampleR;
for (; i != reverbFilterCount; ++i, ++j) {
tmpBufL[i] = delayBufsL[i][allpassIdxL[i]];
tmpBufR[i] = delayBufsR[i][allpassIdxR[i]];
if (j == 2) {
j = -1;
outTmpL += ((historySampleL * reverbMultsL[k ]) >> 8);
outTmpR += ((historySampleR * reverbMultsR[k++]) >> 8);
*curDelaySampleL = tmpCarryoverL;
*curDelaySampleR = tmpCarryoverR;
if (i != reverbFilterCount) {
tmpCarryoverL = ((historySampleL * REVERB_REV_INDEX) >> 8);
tmpCarryoverR = ((historySampleR * REVERB_REV_INDEX) >> 8);
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] * REVERB_REV_INDEX) / 256);
tmpCarryoverR = ((tmpBufR[i] * REVERB_REV_INDEX) / 256);
}
} else {
*curDelaySampleL = (((historySampleL * (-REVERB_GAIN_INDEX)) >> 8) + tmpCarryoverL);
*curDelaySampleR = (((historySampleR * (-REVERB_GAIN_INDEX)) >> 8) + tmpCarryoverR);
tmpCarryoverL = (((*curDelaySampleL * REVERB_GAIN_INDEX) >> 8) + historySampleL);
tmpCarryoverR = (((*curDelaySampleR * REVERB_GAIN_INDEX) >> 8) + historySampleR);
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]) allpassIdxL[i] = 0;
if (++allpassIdxR[i] == delaysR[i]) allpassIdxR[i] = 0;
}
s32 outUnclamped = ((outTmpL * REVERB_WET_SIGNAL/* + inSampleL * REVERB_DRY_SIGNAL*/) >> 8);
s32 outUnclamped = ((outTmpL * REVERB_WET_SIGNAL/* + inSampleL * REVERB_DRY_SIGNAL*/) / 256);
*outSampleL = CLAMP_S16(outUnclamped);
outUnclamped = ((outTmpR * REVERB_WET_SIGNAL/* + inSampleL * REVERB_DRY_SIGNAL*/) >> 8);
outUnclamped = ((outTmpR * REVERB_WET_SIGNAL/* + inSampleL * REVERB_DRY_SIGNAL*/) / 256);
*outSampleR = CLAMP_S16(outUnclamped);
}
static void reverb_mono_sample(s16 *outSample, s32 inSample) {
s32 *curDelaySample;
s32 historySample;
static inline void reverb_mono_sample(s16 *outSample, s32 inSample) {
s32 i = 0;
s32 j = 0;
s32 k = 0;
s32 outTmp = 0;
s32 tmpCarryover = (((delayBufsL[reverbFilterCount][allpassIdxL[reverbFilterCount]] * REVERB_REV_INDEX) >> 8) + inSample);
s32 tmpCarryover = (((tmpBufL[reverbFilterCountm1] * REVERB_REV_INDEX) / 256) + inSample);
for (; i <= reverbFilterCount; ++i, ++j) {
curDelaySample = &delayBufsL[i][allpassIdxL[i]];
historySample = *curDelaySample;
for (; i != reverbFilterCount; ++i, ++j) {
tmpBufL[i] = delayBufsL[i][allpassIdxL[i]];
if (j == 2) {
j = -1;
outTmp += ((historySample * reverbMultsL[k++]) >> 8);
*curDelaySample = tmpCarryover;
if (i != reverbFilterCount)
tmpCarryover = ((historySample * REVERB_REV_INDEX) >> 8);
outTmp += ((tmpBufL[i] * reverbMultsL[k++]) / 256);
delayBufsL[i][allpassIdxL[i]] = tmpCarryover;
if (i != reverbFilterCountm1)
tmpCarryover = ((tmpBufL[i] * REVERB_REV_INDEX) / 256);
} else {
*curDelaySample = (((historySample * (-REVERB_GAIN_INDEX)) >> 8) + tmpCarryover);
tmpCarryover = (((*curDelaySample * REVERB_GAIN_INDEX) >> 8) + historySample);
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;
if (++allpassIdxL[i] == delaysL[i])
allpassIdxL[i] = 0;
}
s32 outUnclamped = ((outTmp * REVERB_WET_SIGNAL/* + inSample * REVERB_DRY_SIGNAL*/) >> 8);
s32 outUnclamped = ((outTmp * REVERB_WET_SIGNAL/* + inSample * REVERB_DRY_SIGNAL*/) / 256);
*outSample = CLAMP_S16(outUnclamped);
}
void initialize_better_reverb_buffers(void) {
delayBufsL = (s32**) soundAlloc(&gBetterReverbPool, BETTER_REVERB_PTR_SIZE);
delayBufsR = &delayBufsL[NUM_ALLPASS];
delayBufsL[0] = (s32*) soundAlloc(&gBetterReverbPool, BETTER_REVERB_SIZE - BETTER_REVERB_PTR_SIZE);
}
void clear_better_reverb_buffers(void) {
bzero(delayBufsL[0], (BETTER_REVERB_SIZE - BETTER_REVERB_PTR_SIZE));
bzero(allpassIdxL, sizeof(allpassIdxL));
bzero(allpassIdxR, sizeof(allpassIdxR));
}
void set_better_reverb_buffers(void) {
s32 bufOffset = 0;
s32 i;
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
#ifdef VERSION_EU
@@ -397,7 +361,6 @@ void prepare_reverb_ring_buffer(s32 chunkLen, u32 updateIndex) {
}
#ifdef BETTER_REVERB
else if (toggleBetterReverb) {
reverbFilterCount--; // Temporarily lower filter count for optimized bulk processing
item = &gSynthesisReverb.items[gSynthesisReverb.curFrame][updateIndex];
if (gSoundMode == SOUND_MODE_MONO || monoReverb) {
if (gReverbDownsampleRate != 1) {
@@ -434,7 +397,6 @@ void prepare_reverb_ring_buffer(s32 chunkLen, u32 updateIndex) {
reverb_samples(&gSynthesisReverb.ringBuffer.left[dstPos], &gSynthesisReverb.ringBuffer.right[dstPos], gSynthesisReverb.ringBuffer.left[dstPos], gSynthesisReverb.ringBuffer.right[dstPos]);
}
}
reverbFilterCount++; // Reset filter count to accurate numbers
}
#endif
item = &gSynthesisReverb.items[gSynthesisReverb.curFrame][updateIndex];
@@ -594,31 +556,18 @@ 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) {
reverbFilterCount = NUM_ALLPASS;
} else if (reverbFilterCount < 3) {
reverbFilterCount = 3;
}
s32 filterCountDiv3 = reverbFilterCount / 3;
reverbFilterCount = filterCountDiv3 * 3; // reverbFilterCount should always be a multiple of 3.
// Update reverbMultsL every audio frame just in case gReverbMults is ever to change.
for (i = 0; i < filterCountDiv3; ++i) {
reverbMultsL[i] = gReverbMultsL[i];
reverbMultsR[i] = gReverbMultsR[i];
}
// If there's only one reverb multiplier set, adjust these to match so one channel doesn't end up potentially overpowering the other.
if (filterCountDiv3 == 1) {
reverbMultsL[0] = (reverbMultsR[0] + reverbMultsL[0]) / 2;
reverbMultsR[0] = reverbMultsL[0];
reverbFilterCountm1 = (reverbFilterCount - 1);
if (reverbFilterCount < 3) {
reverbFilterCountm1 = 0;
}
#endif

View File

@@ -33,16 +33,20 @@
extern s8 betterReverbDownsampleConsole;
extern s8 betterReverbDownsampleEmulator;
extern u32 reverbFilterCountConsole;
extern u32 reverbFilterCountEmulator;
extern u8 monoReverbConsole;
extern u8 monoReverbEmulator;
extern s32 reverbFilterCountConsole;
extern s32 reverbFilterCountEmulator;
extern s32 betterReverbWindowsSize;
extern s32 delaysBaselineL[NUM_ALLPASS];
extern s32 delaysBaselineR[NUM_ALLPASS];
extern s32 gReverbMultsL[NUM_ALLPASS / 3];
extern s32 gReverbMultsR[NUM_ALLPASS / 3];
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;
#define REVERB_WINDOW_SIZE_MAX 0x2000
@@ -145,12 +149,6 @@ extern struct SynthesisReverb gSynthesisReverb;
extern s16 D_SH_803479B4;
#endif
#ifdef BETTER_REVERB
void initialize_better_reverb_buffers(void);
void clear_better_reverb_buffers(void);
void set_better_reverb_buffers(void);
#endif
u64 *synthesis_execute(u64 *cmdBuf, s32 *writtenCmds, s16 *aiBuf, s32 bufLen);
#if defined(VERSION_JP) || defined(VERSION_US)
void note_init_volume(struct Note *note);

View File

@@ -428,7 +428,7 @@ void thread2_crash_screen(UNUSED void *arg) {
#if ENABLE_RUMBLE
block_until_rumble_pak_free();
#endif
osContStartReadData(&gSIEventMesgQueue);
osContStartReadDataEx(&gSIEventMesgQueue);
}
read_controller_inputs(THREAD_2_CRASH_SCREEN);
draw_crash_screen(thread);

View File

@@ -42,8 +42,9 @@ struct GfxPool *gGfxPool;
// OS Controllers
OSContStatus gControllerStatuses[4];
OSContPad gControllerPads[4];
OSContPadEx gControllerPads[4];
u8 gControllerBits;
s8 gGamecubeControllerPort = -1; // HackerSM64: This is set to -1 if there's no GC controller, 0 if there's one in the first port and 1 if there's one in the second port.
u8 gIsConsole = TRUE; // Needs to be initialized before audio_reset_session is called
u8 gBorderHeight;
#ifdef VANILLA_STYLE_CUSTOM_DEBUG
@@ -294,11 +295,6 @@ void create_gfx_task_structure(void) {
gGfxSPTask->task.t.ucode_data = gspF3DZEX2_PosLight_fifoDataStart;
gGfxSPTask->task.t.ucode_size = ((u8 *) gspF3DZEX2_PosLight_fifoTextEnd - (u8 *) gspF3DZEX2_PosLight_fifoTextStart);
gGfxSPTask->task.t.ucode_data_size = ((u8 *) gspF3DZEX2_PosLight_fifoDataEnd - (u8 *) gspF3DZEX2_PosLight_fifoDataStart);
#elif F3DZEX_NON_GBI_2
gGfxSPTask->task.t.ucode = gspF3DZEX2_NoN_PosLight_fifoTextStart;
gGfxSPTask->task.t.ucode_data = gspF3DZEX2_NoN_PosLight_fifoDataStart;
gGfxSPTask->task.t.ucode_size = ((u8 *) gspF3DZEX2_NoN_PosLight_fifoTextEnd - (u8 *) gspF3DZEX2_NoN_PosLight_fifoTextStart);
gGfxSPTask->task.t.ucode_data_size = ((u8 *) gspF3DZEX2_NoN_PosLight_fifoDataEnd - (u8 *) gspF3DZEX2_NoN_PosLight_fifoDataStart);
#elif F3DEX2PL_GBI
gGfxSPTask->task.t.ucode = gspF3DEX2_PosLight_fifoTextStart;
gGfxSPTask->task.t.ucode_data = gspF3DEX2_PosLight_fifoDataStart;
@@ -600,7 +596,7 @@ void read_controller_inputs(s32 threadID) {
if (threadID == THREAD_5_GAME_LOOP) {
osRecvMesg(&gSIEventMesgQueue, &gMainReceivedMesg, OS_MESG_BLOCK);
}
osContGetReadData(&gControllerPads[0]);
osContGetReadDataEx(&gControllerPads[0]);
#if ENABLE_RUMBLE
release_rumble_pak_control();
#endif
@@ -611,13 +607,24 @@ void read_controller_inputs(s32 threadID) {
for (i = 0; i < 2; i++) {
struct Controller *controller = &gControllers[i];
// HackerSM64: Swaps Z and L, only on console, and only when playing with a GameCube controller.
u32 oldButton = controller->controllerData->button;
if (gIsConsole && (gGamecubeControllerPort >= 0)) {
u32 newButton = oldButton & ~(Z_TRIG | L_TRIG);
if (oldButton & Z_TRIG) {
newButton |= L_TRIG;
}
if (controller->controllerData->l_trig > 85) { // How far the player has to press the L trigger for it to be considered a Z press. 64 is about 25%. 127 would be about 50%.
newButton |= Z_TRIG;
}
controller->controllerData->button = newButton;
}
// if we're receiving inputs, update the controller struct with the new button info.
if (controller->controllerData != NULL) {
controller->rawStickX = controller->controllerData->stick_x;
controller->rawStickY = controller->controllerData->stick_y;
controller->buttonPressed = ~controller->buttonDown & controller->controllerData->button;
controller->buttonReleased = ~controller->controllerData->button & controller->buttonDown;
controller->buttonPressed = controller->controllerData->button
& (controller->controllerData->button ^ controller->buttonDown);
// 0.5x A presses are a good meme
controller->buttonDown = controller->controllerData->button;
adjust_analog_stick(controller);
@@ -625,7 +632,6 @@ void read_controller_inputs(s32 threadID) {
controller->rawStickX = 0;
controller->rawStickY = 0;
controller->buttonPressed = 0;
controller->buttonReleased = 0;
controller->buttonDown = 0;
controller->stickX = 0;
controller->stickY = 0;
@@ -642,7 +648,6 @@ void read_controller_inputs(s32 threadID) {
gPlayer3Controller->stickY = gPlayer1Controller->stickY;
gPlayer3Controller->stickMag = gPlayer1Controller->stickMag;
gPlayer3Controller->buttonPressed = gPlayer1Controller->buttonPressed;
gPlayer3Controller->buttonReleased = gPlayer1Controller->buttonReleased;
gPlayer3Controller->buttonDown = gPlayer1Controller->buttonDown;
}
@@ -688,6 +693,15 @@ void init_controllers(void) {
gControllers[cont++].controllerData = &gControllerPads[port];
}
}
if (__osControllerTypes[1] == CONT_TYPE_GCN) {
gGamecubeControllerPort = 1;
gPlayer1Controller = &gControllers[1];
} else {
if (__osControllerTypes[0] == CONT_TYPE_GCN) {
gGamecubeControllerPort = 0;
}
gPlayer1Controller = &gControllers[0];
}
}
// Game thread core
@@ -778,7 +792,7 @@ void thread5_game_loop(UNUSED void *arg) {
#if ENABLE_RUMBLE
block_until_rumble_pak_free();
#endif
osContStartReadData(&gSIEventMesgQueue);
osContStartReadDataEx(&gSIEventMesgQueue);
}
audio_game_loop_tick();

Some files were not shown because too many files have changed in this diff Show More