// called after a poll to execute any shortcuts void CheckShortcuts() { static bool bWasPressed[ sizeof(SHORTCUTSPL)/sizeof(BUTTON) ][4]; static bool bMLWasPressed; // mouselock bool bMatching = false; if ( g_bConfiguring || !g_bRunning ) return; // we don't process shortcuts if we're in a config menu or are not running emulation // just process if key wasnt pressed before for ( int i = 0; i < 4; i++ ) // controllers { for( int j = 0; j < SC_TOTAL; j++ ) { bMatching = IsBtnPressed( g_scShortcuts.Player[i].aButtons[j] ); if( bMatching && !bWasPressed[j][i] ) DoShortcut(i, j); bWasPressed[j][i] = bMatching; } } bMatching = IsBtnPressed( g_scShortcuts.bMouseLock ); if( bMatching && !bMLWasPressed ) DoShortcut(-1, -1); // controller -1 means do mouselock shortcut bMLWasPressed = bMatching; }
// Fill in button states and axis states for controller indexController, into the struct pdwData. // pdwData is a pointer to a 4 byte BUTTONS union, if anyone cares bool GetNControllerInput ( const int indexController, LPDWORD pdwData ) { *pdwData = 0; WORD w_Buttons = 0; // WORD w_Axes = 0; LPCONTROLLER pcController = &g_pcControllers[indexController]; // still needs to be here, but not as important --rabid bool b_Value; long l_Value = 0; long lAxisValueX = ZEROVALUE; long lAxisValueY = ZEROVALUE; // take this info from the N64 controller struct, regardless of input devices float d_ModifierX = (float)pcController->bStickRange / 100.0f; float d_ModifierY = (float)pcController->bStickRange / 100.0f; int i; // do N64-Buttons / modifiers for (i = 0; i < pcController->nModifiers; i++ ) { BUTTON btnButton = pcController->pModifiers[i].btnButton; b_Value = IsBtnPressed( btnButton ); bool fChangeMod = false; if( pcController->pModifiers[i].bModType == MDT_CONFIG ) { // Config-Type if( pcController->pModifiers[i].fToggle ) { if( b_Value && !btnButton.fPrevPressed) { pcController->pModifiers[i].fStatus = !pcController->pModifiers[i].fStatus; fChangeMod = true; } } else { if( b_Value != (bool)(btnButton.fPrevPressed)) fChangeMod = true; } } else { // Move / Macro Type if( pcController->pModifiers[i].fToggle ) { if( b_Value && !btnButton.fPrevPressed ) pcController->pModifiers[i].fStatus = !pcController->pModifiers[i].fStatus; fChangeMod = ( pcController->pModifiers[i].fStatus != 0 ); } else { fChangeMod = b_Value; } } if( fChangeMod ) { switch( pcController->pModifiers[i].bModType ) { case MDT_MOVE: { LPMODSPEC_MOVE args = (LPMODSPEC_MOVE)&pcController->pModifiers[i].dwSpecific; d_ModifierX *= args->XModification / 100.0f; d_ModifierY *= args->YModification / 100.0f; } break; case MDT_MACRO: { LPMODSPEC_MACRO args = (LPMODSPEC_MACRO)&pcController->pModifiers[i].dwSpecific; if (args->fRapidFire) // w00t! Rapid Fire here { if ((unsigned) b_Value != btnButton.fPrevPressed) // New macro pressed { args->fPrevFireState = 0; args->fPrevFireState2 = 0; } if(!args->fPrevFireState) // This round, a firing is needed { w_Buttons |= args->aButtons; if( args->fAnalogRight ) lAxisValueX += MAXAXISVALUE; else if( args->fAnalogLeft ) lAxisValueX -= MAXAXISVALUE; if( args->fAnalogDown ) lAxisValueY -= MAXAXISVALUE; else if( args->fAnalogUp ) // up lAxisValueY += MAXAXISVALUE; } // Ok, update the firing counters here if (args->fRapidFireRate) // Do the rapid fire slowly { // Note that this updates State2 before State... Makes a nice slower square-wave type pulse for the update args->fPrevFireState2 = (args->fPrevFireState2 + 1) & 1; if (!args->fPrevFireState2) { args->fPrevFireState = (args->fPrevFireState + 1) & 1; DebugWriteA("Slow Rapid Fire - Mark 2\n"); } } else // Do a fast rapid fire { args->fPrevFireState = (args->fPrevFireState + 1) & 1; DebugWriteA("Fast Rapid Fire\n"); } } else { w_Buttons |= args->aButtons; // Note this: It lets you push buttons as well as the macro buttons if( args->fAnalogRight ) lAxisValueX += MAXAXISVALUE; else if( args->fAnalogLeft ) lAxisValueX -= MAXAXISVALUE; if( args->fAnalogDown ) lAxisValueY -= MAXAXISVALUE; else if( args->fAnalogUp ) // up lAxisValueY += MAXAXISVALUE; args->fPrevFireState = 0; } } break; case MDT_CONFIG: { LPMODSPEC_CONFIG args = (LPMODSPEC_CONFIG)&pcController->pModifiers[i].dwSpecific; if( args->fChangeAnalogConfig ) { BYTE bConfig = (BYTE)args->fAnalogStickMode; if( bConfig < PF_AXESETS ) pcController->bAxisSet = bConfig; else { if( pcController->bAxisSet == PF_AXESETS-1 ) pcController->bAxisSet = 0; else ++pcController->bAxisSet; } } if( args->fChangeMouseXAxis ) if (pcController->bMouseMoveX == MM_BUFF) pcController->bMouseMoveX = MM_ABS; else if (pcController->bMouseMoveX == MM_ABS) pcController->bMouseMoveX = MM_BUFF; if( args->fChangeMouseYAxis ) if (pcController->bMouseMoveY == MM_BUFF) pcController->bMouseMoveY = MM_ABS; else if (pcController->bMouseMoveY == MM_ABS) pcController->bMouseMoveY = MM_BUFF; if( args->fChangeKeyboardXAxis ) pcController->fKeyAbsoluteX = !pcController->fKeyAbsoluteX; if( args->fChangeKeyboardYAxis ) pcController->fKeyAbsoluteY = !pcController->fKeyAbsoluteY; } break; } } btnButton.fPrevPressed = b_Value; pcController->pModifiers[i].btnButton = btnButton; } // END N64 MODIFIERS for // do N64-Buttons / modifiers for( i = 0; i < PF_APADR; i++ ) { BUTTON btnButton = pcController->aButton[i]; b_Value = IsBtnPressed( btnButton ); w_Buttons |= (((WORD)b_Value) << i); } // END N64 BUTTONS for long lDeadZoneValue = pcController->bPadDeadZone * RANGERELATIVE / 100; float fDeadZoneRelation = (float)RANGERELATIVE / (float)( RANGERELATIVE - lDeadZoneValue ); // do N64 joystick axes for ( i = 0; i < 4; i++ ) { // 0 : right // 1 : left // 2 : down // 3 : up bool fNegInput = (( i == 1 ) || ( i == 2 )); // Input has to be negated BUTTON btnButton = pcController->aButton[PF_APADR + pcController->bAxisSet * 4 + i]; LPLONG plRawState = (LPLONG)&btnButton.parentDevice->stateAs.joyState; switch( btnButton.bBtnType ) { case DT_JOYBUTTON: l_Value = MAXAXISVALUE; b_Value = ( btnButton.parentDevice->stateAs.joyState.rgbButtons[btnButton.bOffset] & 0x80 ) != 0; break; case DT_JOYSLIDER: case DT_JOYAXE: l_Value = plRawState[btnButton.bOffset] - ZEROVALUE; if( btnButton.bAxisID ) // negative Range { fNegInput = !fNegInput; b_Value = ( l_Value <= -lDeadZoneValue ); if( b_Value ) l_Value = (long) ((float)(l_Value + lDeadZoneValue ) * fDeadZoneRelation ); } else { b_Value = ( l_Value >= lDeadZoneValue ); if( b_Value ) l_Value = (long) ((float)(l_Value - lDeadZoneValue ) * fDeadZoneRelation ); } break; case DT_JOYPOV: l_Value = MAXAXISVALUE; b_Value = GetJoyPadPOV( (PDWORD)&plRawState[btnButton.bOffset] , btnButton.bAxisID ); break; case DT_KEYBUTTON: if( btnButton.parentDevice->stateAs.rgbButtons[btnButton.bOffset] & 0x80 ) { b_Value = true; if(( pcController->fKeyAbsoluteX && i < 2 ) || ( pcController->fKeyAbsoluteY && i > 1 )) { if( pcController->wAxeBuffer[i] < MAXAXISVALUE ) { l_Value = pcController->wAxeBuffer[i] = min(( pcController->wAxeBuffer[i] + N64DIVIDER*3), MAXAXISVALUE ); } else l_Value = MAXAXISVALUE; } else { if( pcController->wAxeBuffer[i] < MAXAXISVALUE ) { l_Value = pcController->wAxeBuffer[i] = min(( pcController->wAxeBuffer[i] * 2 + N64DIVIDER*5 ), MAXAXISVALUE ); } else l_Value = MAXAXISVALUE; } } else { if(( pcController->fKeyAbsoluteX && i < 2 ) || ( pcController->fKeyAbsoluteY && i > 1 )) { l_Value = pcController->wAxeBuffer[i]; b_Value = true; } else { if( pcController->wAxeBuffer[i] > N64DIVIDER ) { b_Value = true; l_Value = pcController->wAxeBuffer[i] = pcController->wAxeBuffer[i] / 2 ; } else b_Value = false; } } break; case DT_MOUSEBUTTON: l_Value = MAXAXISVALUE; b_Value = ( btnButton.parentDevice->stateAs.mouseState.rgbButtons[btnButton.bOffset] & 0x80 ) != 0; break; case DT_MOUSEAXE: if( i < 2 ) pcController->wAxeBuffer[i] += plRawState[btnButton.bOffset] * pcController->wMouseSensitivityX * MOUSESCALEVALUE; // l_Value = btnButton.parentDevice->stateAs.mouseState[btnButton.bOffset]; else pcController->wAxeBuffer[i] += plRawState[btnButton.bOffset] * pcController->wMouseSensitivityY * MOUSESCALEVALUE; // l_Value = btnButton.parentDevice->stateAs.mouseState[btnButton.bOffset]; l_Value = pcController->wAxeBuffer[i]; // wAxeBuffer is positive for axes 0 and 3 if buffer remains, else zero // wAxeBuffer is negative for axes 1 and 2 if buffer remains, else zero if(( pcController->bMouseMoveX == MM_ABS && i < 2 ) || ( pcController->bMouseMoveY == MM_ABS && i > 1 )) pcController->wAxeBuffer[i] = min( max( MINAXISVALUE, pcController->wAxeBuffer[i]) , MAXAXISVALUE); else if (( pcController->bMouseMoveX == MM_BUFF && i < 2 ) || ( pcController->bMouseMoveY == MM_BUFF && i > 1 )) pcController->wAxeBuffer[i] = pcController->wAxeBuffer[i] * MOUSEBUFFERDECAY / 100; else // "deadpan" mouse { pcController->wAxeBuffer[i] = 0; } if( btnButton.bAxisID == AI_AXE_N) // the mouse axis has the '-' flag set { fNegInput = !fNegInput; b_Value = ( l_Value < ZEROVALUE ); } else { b_Value = ( l_Value > ZEROVALUE ); } break; case DT_UNASSIGNED: default: b_Value = false; } if ( b_Value ) { if ( fNegInput ) l_Value = -l_Value; if( i < 2 ) lAxisValueX += l_Value; else lAxisValueY += l_Value; } } if( pcController->fKeyboard ) { if( pcController->fKeyAbsoluteX ) { if( pcController->wAxeBuffer[0] > pcController->wAxeBuffer[1] ) { pcController->wAxeBuffer[0] -= pcController->wAxeBuffer[1]; pcController->wAxeBuffer[1] = 0; } else { pcController->wAxeBuffer[1] -= pcController->wAxeBuffer[0]; pcController->wAxeBuffer[0] = 0; } } if( pcController->fKeyAbsoluteY ) { if( pcController->wAxeBuffer[2] > pcController->wAxeBuffer[3] ) { pcController->wAxeBuffer[2] -= pcController->wAxeBuffer[3]; pcController->wAxeBuffer[3] = 0; } else { pcController->wAxeBuffer[3] -= pcController->wAxeBuffer[2]; pcController->wAxeBuffer[2] = 0; } } } if (pcController->bRapidFireEnabled) { if (pcController->bRapidFireCounter >= pcController->bRapidFireRate) { w_Buttons = (w_Buttons & 0xFF1F); pcController->bRapidFireCounter = 0; } else { pcController->bRapidFireCounter = pcController->bRapidFireCounter + 1; } } if( pcController->fRealN64Range && ( lAxisValueX || lAxisValueY )) { long lAbsoluteX = ( lAxisValueX > 0 ) ? lAxisValueX : -lAxisValueX; long lAbsoluteY = ( lAxisValueY > 0 ) ? lAxisValueY : -lAxisValueY; long lRangeX; long lRangeY; if( lAbsoluteX > lAbsoluteY ) { lRangeX = MAXAXISVALUE; lRangeY = lRangeX * lAbsoluteY / lAbsoluteX; } else { lRangeY = MAXAXISVALUE; lRangeX = lRangeY * lAbsoluteX / lAbsoluteY; } // TODO: optimize this --rabid double dRangeDiagonal = sqrt((double)(lRangeX * lRangeX + lRangeY * lRangeY)); // __asm{ // fld fRangeDiagonal // fsqrt // fstp fRangeDiagonal // fwait // } double dRel = MAXAXISVALUE / dRangeDiagonal; *pdwData = MAKELONG(w_Buttons, MAKEWORD( (BYTE)(min( max( MINAXISVALUE, (long)(lAxisValueX * d_ModifierX * dRel )), MAXAXISVALUE) / N64DIVIDER ), (BYTE)(min( max( MINAXISVALUE, (long)(lAxisValueY * d_ModifierY * dRel )), MAXAXISVALUE) / N64DIVIDER ))); } else { *pdwData = MAKELONG(w_Buttons, MAKEWORD( (BYTE)(min( max( MINAXISVALUE, (long)(lAxisValueX * d_ModifierX )), MAXAXISVALUE) / N64DIVIDER ), (BYTE)(min( max( MINAXISVALUE, (long)(lAxisValueY * d_ModifierY )), MAXAXISVALUE) / N64DIVIDER ))); } return true; }