diff --git a/README.md b/README.md index 508e4c34e..669c27007 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,25 @@ You must already have a Perfect Dark ROM to run the game, as specified above. 2. Put your Perfect Dark ROM named `pd.ntsc-final.z64` into it. 3. Run `pd.exe`. + +## Bindings + +1964-style and Xbox-style bindings are partially implemented. + +N64 controller literal X and Y refer to the RESERVED buttons which was previously leveraged by 1964. + + +| Action | keyboard | xbox | N64 literal | +|- | - | - | - | +| Use / Cancel Menu | e | n/a | b | +| Use / Accept Menu | n/a | a | a | +| reload | r | x | x `(0x40)` | +| weapon-back | Mousewheel-Forward | b | D-Left | +| weapon-forward | Mousewheel-Back | y | y `(0x80)` | +| radial menu | q | LB | D-Down | +| alt mode | f | RB | L-trigger | +| quick-detonate | e + q | a + b | a + D-Left | + ## Building ### Windows diff --git a/port/src/input.c b/port/src/input.c index a15269e61..0a2e0e164 100644 --- a/port/src/input.c +++ b/port/src/input.c @@ -57,18 +57,16 @@ void inputSetDefaultKeyBinds(void) { // TODO: make VK constants for all these static const u32 kbbinds[][3] = { - { CK_A, SDL_SCANCODE_Q, 0 }, { CK_B, SDL_SCANCODE_E, 0 }, { CK_X, SDL_SCANCODE_R, 0 }, - { CK_Y, SDL_SCANCODE_R, 0 }, { CK_RTRIG, VK_MOUSE_RIGHT, SDL_SCANCODE_Z }, { CK_LTRIG, SDL_SCANCODE_F, SDL_SCANCODE_X }, { CK_ZTRIG, VK_MOUSE_LEFT, SDL_SCANCODE_SPACE }, { CK_START, SDL_SCANCODE_RETURN, SDL_SCANCODE_TAB }, - { CK_DPAD_D, SDL_SCANCODE_G, VK_MOUSE_MIDDLE }, - { CK_DPAD_U, 0, 0 }, - { CK_DPAD_R, 0, 0 }, - { CK_DPAD_L, 0, 0 }, + { CK_DPAD_D, SDL_SCANCODE_Q, VK_MOUSE_MIDDLE }, + { CK_DPAD_U, 0, 0 }, + { CK_Y, VK_MOUSE_WHEEL_DN, 0 }, + { CK_DPAD_L, VK_MOUSE_WHEEL_UP, 0 }, { CK_C_D, SDL_SCANCODE_S, 0 }, { CK_C_U, SDL_SCANCODE_W, 0 }, { CK_C_R, SDL_SCANCODE_D, 0 }, @@ -80,10 +78,10 @@ void inputSetDefaultKeyBinds(void) }; static const u32 joybinds[][2] = { - { CK_A, SDL_CONTROLLER_BUTTON_A }, - { CK_B, SDL_CONTROLLER_BUTTON_B }, + { CK_B, SDL_CONTROLLER_BUTTON_A }, { CK_X, SDL_CONTROLLER_BUTTON_X }, { CK_Y, SDL_CONTROLLER_BUTTON_Y }, + { CK_DPAD_L, SDL_CONTROLLER_BUTTON_B, }, { CK_DPAD_D, SDL_CONTROLLER_BUTTON_LEFTSHOULDER }, { CK_LTRIG, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER }, { CK_RTRIG, VK_JOY1_LTRIG - VK_JOY1_BEGIN }, diff --git a/src/game/bondeyespy.c b/src/game/bondeyespy.c index 900e0ec38..e6f23fd10 100644 --- a/src/game/bondeyespy.c +++ b/src/game/bondeyespy.c @@ -741,8 +741,13 @@ void eyespyProcessInput(bool allowbuttons) } else if (controlmode <= CONTROLMODE_14) { aimpressed = c1buttons & (R_TRIG); shootpressed = c1buttons & Z_TRIG; - exitpressed = c1buttons & A_BUTTON; - activatepressed = c1buttons & B_BUTTON; + #ifdef PLATFORM_N64 + exitpressed = (c1buttons | c2buttons) & A_BUTTON; + activatepressed = (c1buttons | c2buttons) & B_BUTTON; + #else + exitpressed = (c1buttons | c2buttons) & (BUTTON_WPNBACK | BUTTON_RADIAL); + activatepressed = (c1buttons | c2buttons) & (BUTTON_CANCEL_USE | BUTTON_ACCEPT_USE); + #endif } else { if (controlmode >= CONTROLMODE_23) { aimpressed = c1buttons & Z_TRIG; diff --git a/src/game/bondmove.c b/src/game/bondmove.c index 1c425466b..ce7d29e58 100644 --- a/src/game/bondmove.c +++ b/src/game/bondmove.c @@ -903,6 +903,15 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i } } else { for (i = 0; i < numsamples; i++) { + #ifndef PLATFORM_N64 + if (joyGetButtonsPressedOnSample(i, contpad1, c1allowedbuttons & BUTTON_WPNFORWARD)) { + movedata.weaponforwardoffset++; + g_Vars.currentplayer->invdowntime = -1; + } else if (joyGetButtonsPressedOnSample(i, contpad1, c1allowedbuttons & BUTTON_WPNBACK)) { + movedata.weaponbackoffset++; + g_Vars.currentplayer->invdowntime = -1; + } + #else if (joyGetButtonsOnSample(i, contpad1, c1allowedbuttons & A_BUTTON) || joyGetButtonsOnSample(i, contpad2, c2allowedbuttons & A_BUTTON)) { if (g_Vars.currentplayer->invdowntime > -2) { @@ -929,10 +938,12 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i g_Vars.currentplayer->invdowntime = 0; } + #endif } } } + #ifdef PLATFORM_N64 // Handle B button activation if (allowc1buttons) { for (i = 0; i < numsamples; i++) { @@ -974,6 +985,7 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i } } } + #endif // Handle manual zoom in and out (sniper, farsight and horizon scanner) if (canmanualzoom && g_Vars.currentplayer->insightaimmode) { @@ -1275,6 +1287,15 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i } } else { for (i = 0; i < numsamples; i++) { + #ifndef PLATFORM_N64 + if (joyGetButtonsPressedOnSample(i, contpad1, c1allowedbuttons & BUTTON_WPNFORWARD)) { + movedata.weaponforwardoffset++; + g_Vars.currentplayer->invdowntime = -1; + } else if (joyGetButtonsPressedOnSample(i, contpad1, c1allowedbuttons & BUTTON_WPNBACK)) { + movedata.weaponbackoffset++; + g_Vars.currentplayer->invdowntime = -1; + } + #else if (joyGetButtonsOnSample(i, contpad1, invbuttons & c1allowedbuttons)) { if (g_Vars.currentplayer->invdowntime > -2) { if (joyGetButtonsPressedOnSample(i, contpad1, shootbuttons & c1allowedbuttons)) { @@ -1302,24 +1323,31 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i g_Vars.currentplayer->invdowntime = 0; } + #endif } } } - // Handle B button + // Handle B and use-like button if (allowc1buttons) { for (i = 0; i < numsamples; i++) { - if (joyGetButtonsOnSample(i, contpad1, c1allowedbuttons & B_BUTTON)) { + if (joyGetButtonsOnSample(i, contpad1, c1allowedbuttons & (B_BUTTON | BUTTON_CANCEL_USE | BUTTON_ACCEPT_USE))) { if (g_Vars.currentplayer->usedowntime >= -1) { + #ifdef PLATFORM_N64 if (joyGetButtonsPressedOnSample(i, contpad1, shootbuttons & c1allowedbuttons) && g_Vars.currentplayer->usedowntime >= 0 && bgunConsiderToggleGunFunction(g_Vars.currentplayer->usedowntime, true, false, 0) != USETIMER_CONTINUE) { g_Vars.currentplayer->usedowntime = -3; } + #endif if (g_Vars.currentplayer->usedowntime >= 0) { if (g_Vars.currentplayer->usedowntime > TICKS(25)) { + #ifdef PLATFORM_N64 s32 result = bgunConsiderToggleGunFunction(g_Vars.currentplayer->usedowntime, false, false, 0); + #else + s32 result = USETIMER_CONTINUE; + #endif if (result == USETIMER_STOP) { g_Vars.currentplayer->usedowntime = -1; @@ -1333,9 +1361,11 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i } } } else { + #ifdef PLATFORM_N64 if (g_Vars.currentplayer->usedowntime >= -2) { bgunConsiderToggleGunFunction(g_Vars.currentplayer->usedowntime, false, false, 0); } + #endif } } else { // Released B @@ -1350,73 +1380,78 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i } - // handle L button - for (i = 0; i< numsamples; i++) { - if (joyGetButtonsOnSample(i, contpad1, c1allowedbuttons & L_TRIG)) { - if (g_Vars.currentplayer->altdowntime >= -1) { - if (joyGetButtonsPressedOnSample(i, contpad1, shootbuttons & c1allowedbuttons) - && g_Vars.currentplayer->altdowntime >= 0 - && bgunConsiderToggleGunFunction(g_Vars.currentplayer->altdowntime, true, false, true) != USETIMER_CONTINUE) { - g_Vars.currentplayer->altdowntime = -3; - } - - if (g_Vars.currentplayer->altdowntime != -4) { - if (g_Vars.currentplayer->altdowntime <= 0) { - g_Vars.currentplayer->altdowntime++; + #ifndef PLATFORM_N64 + if (allowc1buttons) { + // handle L button : alt switching + for (i = 0; i< numsamples; i++) { + if (joyGetButtonsOnSample(i, contpad1, c1allowedbuttons & BUTTON_ALTMODE)) { + if (g_Vars.currentplayer->altdowntime >= -1) { + if (joyGetButtonsPressedOnSample(i, contpad1, shootbuttons & c1allowedbuttons) + && g_Vars.currentplayer->altdowntime >= 0 + && bgunConsiderToggleGunFunction(g_Vars.currentplayer->altdowntime, true, false, true) != USETIMER_CONTINUE) { + g_Vars.currentplayer->altdowntime = -3; } - } - } else { - if (g_Vars.currentplayer->altdowntime == -2) { - bgunConsiderToggleGunFunction(g_Vars.currentplayer->altdowntime, false, false, true); - g_Vars.currentplayer->altdowntime = -4; - } - } - } else { - // Released L - if (g_Vars.currentplayer->altdowntime != 0) { - s32 result = bgunConsiderToggleGunFunction(g_Vars.currentplayer->altdowntime, (g_Vars.currentplayer->altdowntime == -3 ? true: false), false, true); - if (result == USETIMER_STOP) { - g_Vars.currentplayer->altdowntime = -1; - } else if (result == USETIMER_REPEAT) { - g_Vars.currentplayer->altdowntime = -2; - } - } - g_Vars.currentplayer->altdowntime = 0; - } - } - - // Handle ALT1 / MI Reload Hack - for (i = 0; i < numsamples; i++) { - if (joyGetButtonsOnSample(i, contpad1, c1allowedbuttons & X_BUTTON)) { - movedata.alt1tapcount++; - } - } - - - // Handle radial menu (D-Down) - for (i = 0; i < numsamples; i++) { - if (joyGetButtonsOnSample(i, contpad1, c1allowedbuttons & D_JPAD)) { - if (g_Vars.currentplayer->amdowntime < -2) { - g_Vars.currentplayer->amdowntime += numsamples; - - if (g_Vars.currentplayer->amdowntime > -3) { - g_Vars.currentplayer->amdowntime = 0; + if (g_Vars.currentplayer->altdowntime != -4) { + if (g_Vars.currentplayer->altdowntime <= 0) { + g_Vars.currentplayer->altdowntime++; + } + } + } else { + if (g_Vars.currentplayer->altdowntime == -2) { + bgunConsiderToggleGunFunction(g_Vars.currentplayer->altdowntime, false, false, true); + g_Vars.currentplayer->altdowntime = -4; + } } } else { - if (g_Vars.currentplayer->amdowntime >= 0) { - if (joyGetButtonsPressedOnSample(i, contpad1, c1allowedbuttons & D_JPAD)) { - amOpen(); - g_Vars.currentplayer->amdowntime = -1; - } else { - g_Vars.currentplayer->amdowntime++; + // Released L + if (g_Vars.currentplayer->altdowntime != 0) { + s32 result = bgunConsiderToggleGunFunction(g_Vars.currentplayer->altdowntime, (g_Vars.currentplayer->altdowntime == -3 ? true: false), false, true); + + if (result == USETIMER_STOP) { + g_Vars.currentplayer->altdowntime = -1; + } else if (result == USETIMER_REPEAT) { + g_Vars.currentplayer->altdowntime = -2; } } + g_Vars.currentplayer->altdowntime = 0; + bgun0f0a8c50(); + } + } + + // Handle ALT1 / MI Reload Hack + for (i = 0; i < numsamples; i++) { + if (joyGetButtonsOnSample(i, contpad1, c1allowedbuttons & BUTTON_RELOAD)) { + movedata.alt1tapcount++; + } + } + + + // Handle radial menu (D-Down) + for (i = 0; i < numsamples; i++) { + if (joyGetButtonsOnSample(i, contpad1, c1allowedbuttons & BUTTON_RADIAL)) { + if (g_Vars.currentplayer->amdowntime < -2) { + g_Vars.currentplayer->amdowntime += numsamples; + + if (g_Vars.currentplayer->amdowntime > -3) { + g_Vars.currentplayer->amdowntime = 0; + } + } else { + if (g_Vars.currentplayer->amdowntime >= 0) { + if (joyGetButtonsPressedOnSample(i, contpad1, c1allowedbuttons & BUTTON_RADIAL)) { + amOpen(); + g_Vars.currentplayer->amdowntime = -1; + } else { + g_Vars.currentplayer->amdowntime++; + } + } + } + } else { + g_Vars.currentplayer->amdowntime = 0; } - } else { - g_Vars.currentplayer->amdowntime = 0; } } + #endif // Handle manual zoom in and out (sniper, farsight and horizon scanner) if (canmanualzoom && g_Vars.currentplayer->insightaimmode) { @@ -1503,6 +1538,7 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i } // Handle mine detonation + #ifdef PLATFORM_N64 if ((((c1buttons & invbuttons) && (c1buttonsthisframe & B_BUTTON)) || ((c1buttons & B_BUTTON) && (c1buttonsthisframe & invbuttons))) && weaponnum == WEAPON_REMOTEMINE) { @@ -1513,6 +1549,30 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i g_Vars.currentplayer->invdowntime = -2; g_Vars.currentplayer->usedowntime = -2; } + #else + if ((((c1buttons & BUTTON_RADIAL) && (c1buttonsthisframe & BUTTON_CANCEL_USE)) + || ((c1buttons & BUTTON_CANCEL_USE) && (c1buttonsthisframe & BUTTON_RADIAL))) + && weaponnum == WEAPON_REMOTEMINE) { + movedata.detonating = true; + movedata.weaponbackoffset = 0; + movedata.weaponforwardoffset = 0; + movedata.btapcount = 0; + amClose(); + g_Vars.currentplayer->invdowntime = -2; + g_Vars.currentplayer->usedowntime = -2; + g_Vars.currentplayer->amdowntime = 0; + } + if ((((c1buttons & BUTTON_WPNBACK) && (c1buttonsthisframe & BUTTON_CANCEL_USE)) + || ((c1buttons & BUTTON_CANCEL_USE) && (c1buttonsthisframe & BUTTON_WPNBACK))) + && weaponnum == WEAPON_REMOTEMINE) { + movedata.detonating = true; + movedata.weaponbackoffset = 0; + movedata.weaponforwardoffset = 0; + movedata.btapcount = 0; + g_Vars.currentplayer->invdowntime = -2; + g_Vars.currentplayer->usedowntime = -2; + } + #endif } movedata.aiming = g_Vars.currentplayer->insightaimmode; diff --git a/src/game/menu.c b/src/game/menu.c index cc88cc78d..e95c69c68 100644 --- a/src/game/menu.c +++ b/src/game/menu.c @@ -4607,6 +4607,17 @@ void menuProcessInput(void) inputs.select = 1; } + #ifndef PLATFORM_N64 + // this seems sensible to achieve 1964 parity + if (buttonsnow & BUTTON_RADIAL) { + inputs.select = 1; + } + // this will naturally feel nice w/ a switch layout + // with the default mapping for weapon-back + if (buttonsnow & BUTTON_WPNBACK) { + inputs.select = 1; + } + #endif if (buttonsnow & B_BUTTON) { inputs.back = 1; } diff --git a/src/include/constants.h b/src/include/constants.h index e5fc90f8c..7e96a2f68 100644 --- a/src/include/constants.h +++ b/src/include/constants.h @@ -4626,7 +4626,35 @@ enum weaponnum { #define BODY_DARK_LEATHER 0x95 #define BODY_DARK_NEGOTIATOR 0x96 -#endif - #define JO_ACTION_ACTIVATE 0x0001 #define JO_ACTION_RELOAD 0x0002 + + +#ifdef PLATFORM_N64 + +#define BUTTON_ACCEPT_WPNFORWARD CONT_A +#define BUTTON_CANCEL_USE CONT_B + +#define BUTTON_USE BUTTON_CANCEL_USE +#define BUTTON_CANCEL BUTTON_CANCEL_USE +#define BUTTON_RELOAD BUTTON_USE +#define BUTTON_ACCEPT BUTTON_ACCEPT_WPNFORWARD +#define BUTTON_WPNFORWARD BUTTON_ACCEPT_WPNFORWARD + +#else + +// xbla behavior +#define BUTTON_ACCEPT_USE A_BUTTON +// 1964 behavior +#define BUTTON_CANCEL_USE B_BUTTON + +#define BUTTON_RELOAD X_BUTTON +// dedicated button for mousewheel / xbla parity +#define BUTTON_WPNBACK L_JPAD +// dedicated button for mousewheel / xbla parity +#define BUTTON_WPNFORWARD Y_BUTTON +#define BUTTON_RADIAL D_JPAD +#define BUTTON_ALTMODE L_TRIG +#endif + +#endif