3
0
mirror of https://github.com/XboxDev/nxdk.git synced 2026-02-05 07:15:40 +00:00
Files
nxdk/hal/input.c
espes acffd306f3 init
(sorry, history contained c t f s e e k r i t s)
2015-12-22 21:40:19 +11:00

269 lines
7.1 KiB
C

#include <xboxkrnl/xboxkrnl.h>
#include <hal/input.h>
#include <hal/io.h>
#include <string.h>
#define XPAD_ANALOG_BUTTON_INTF 0x30
#define USB_IRQ 1
XPAD_INPUT g_Pads[4];
XPAD_INPUT g_DefaultPad;
XMOUSE_INPUT g_Mouse;
/* Has input been inited already? */
static BOOL bInputOK = FALSE;
static BOOL bInputPolling = FALSE;
static KINTERRUPT InterruptObject;
static KDPC DPCObject;
/* Stores time and XPAD state */
extern struct xpad_data XPAD_current[4];
extern struct xpad_data XPAD_last[4];
/* Stores Mouse state */
extern struct xmouse_data XMOUSE_current;
void BootStartUSB(void);
void USBGetEvents(void);
void BootStopUSB(void);
int GetKeyboardStroke(XKEYBOARD_STROKE *pStroke);
static void __stdcall DPC(PKDPC Dpc,
PVOID DeferredContext,
PVOID SystemArgument1,
PVOID SystemArgument2)
{
//DPCs allow to use non reentrant procedures (called sequentially, FOR SURE).
//CAUTION : if you use fpu in DPC you have to save & restore yourself fpu state!!!
//(fpu=floating point unit, i.e the coprocessor executing floating point opcodes)
USBGetEvents();
return;
}
void handle_irqs(int);
static BOOLEAN __stdcall ISR(PKINTERRUPT Interrupt, PVOID ServiceContext)
{
KeInsertQueueDpc(&DPCObject,NULL,NULL); //calls USBGetEvents() very soon
*((DWORD*)0xFED00014)=0x80000000;
return TRUE;
}
void XInput_Init(void)
{
int i;
ULONG tmp;
KIRQL irql;
ULONG vector;
if(bInputOK) {
return;
}
bInputOK = TRUE;
bInputPolling = FALSE;
// Zero our pad structures
for(i=0; i<4; i++)
memset(&g_Pads[i], 0x00, sizeof(XPAD_INPUT));
// Zero the mouse data
memset(&g_Mouse, 0x00, sizeof(XMOUSE_INPUT));
// Startup the cromwell usb code
BootStartUSB();
// Get the current state of our devices
XInput_GetEvents();
vector = HalGetInterruptVector(USB_IRQ, &irql);
KeInitializeDpc(&DPCObject,&DPC,NULL);
KeInitializeInterrupt(&InterruptObject,
&ISR,
NULL,
vector,
irql,
LevelSensitive,
FALSE);
KeConnectInterrupt(&InterruptObject);
}
void XInput_Init_Polling(void)
{
int i;
if(bInputOK) {
return;
}
bInputOK = TRUE;
bInputPolling = TRUE;
// Zero our pad structures
for(i=0; i<4; i++)
memset(&g_Pads[i], 0x00, sizeof(XPAD_INPUT));
// Zero the mouse data
memset(&g_Mouse, 0x00, sizeof(XMOUSE_INPUT));
// Startup the cromwell usb code
BootStartUSB();
// Get the current state of our devices
XInput_GetEvents();
}
void XInput_Quit(void)
{
if(!bInputOK)
return;
int i;
// Stop the cromwell usb code
BootStopUSB();
// Zero our pad structures
for(i=0; i<4; i++)
memset(&g_Pads[i], 0x00, sizeof(XPAD_INPUT));
// Zero the mouse data
memset(&g_Mouse, 0x00, sizeof(XMOUSE_INPUT));
if (!bInputPolling) {
KeDisconnectInterrupt(&InterruptObject);
}
bInputOK = FALSE;
}
void XInput_GetEvents(void)
{
int pad, button;
int iLThumbX, iLThumbY, iRThumbX, iRThumbY;
if (bInputPolling) {
USBGetEvents();
}
for(pad=0; pad<4; pad++)
{
g_Pads[pad].hPresent = XPAD_current[pad].hPresent;
if(!g_Pads[pad].hPresent)
{
memset(&g_Pads[pad], 0x00, sizeof(XPAD_INPUT));
continue;
}
// Digital buttons - dpad (up, down, left, right), start, back, left thumb, right thumb
g_Pads[pad].CurrentButtons.usDigitalButtons = XPAD_current[pad].pad | (XPAD_current[pad].state << 4);
// Analog buttons
g_Pads[pad].CurrentButtons.ucAnalogButtons[0]
= (XPAD_current[pad].keys[0] > XPAD_ANALOG_BUTTON_INTF) ? XPAD_current[pad].keys[0] : 0; // A
g_Pads[pad].CurrentButtons.ucAnalogButtons[1]
= (XPAD_current[pad].keys[1] > XPAD_ANALOG_BUTTON_INTF) ? XPAD_current[pad].keys[1] : 0; // B
g_Pads[pad].CurrentButtons.ucAnalogButtons[2]
= (XPAD_current[pad].keys[2] > XPAD_ANALOG_BUTTON_INTF) ? XPAD_current[pad].keys[2] : 0; // X
g_Pads[pad].CurrentButtons.ucAnalogButtons[3]
= (XPAD_current[pad].keys[3] > XPAD_ANALOG_BUTTON_INTF) ? XPAD_current[pad].keys[3] : 0; // Y
g_Pads[pad].CurrentButtons.ucAnalogButtons[4]
= (XPAD_current[pad].keys[4] > XPAD_ANALOG_BUTTON_INTF) ? XPAD_current[pad].keys[4] : 0; // Black
g_Pads[pad].CurrentButtons.ucAnalogButtons[5]
= (XPAD_current[pad].keys[5] > XPAD_ANALOG_BUTTON_INTF) ? XPAD_current[pad].keys[5] : 0; // White
g_Pads[pad].CurrentButtons.ucAnalogButtons[6]
= (XPAD_current[pad].trig_left > XPAD_ANALOG_BUTTON_INTF) ? XPAD_current[pad].trig_left : 0; // Left trigger
g_Pads[pad].CurrentButtons.ucAnalogButtons[7]
= (XPAD_current[pad].trig_right > XPAD_ANALOG_BUTTON_INTF) ? XPAD_current[pad].trig_right : 0; // Right trigger
// Thumbsticks
g_Pads[pad].sLThumbX = XPAD_current[pad].stick_left_x; // Left stick X
g_Pads[pad].sLThumbY = XPAD_current[pad].stick_left_y; // Left stick Y
g_Pads[pad].sRThumbX = XPAD_current[pad].stick_right_x; // Right stick X
g_Pads[pad].sRThumbY = XPAD_current[pad].stick_right_y; // Right stick Y
// Track changes for buttons
g_Pads[pad].PressedButtons.usDigitalButtons =
g_Pads[pad].CurrentButtons.usDigitalButtons & (g_Pads[pad].LastButtons.usDigitalButtons ^ g_Pads[pad].CurrentButtons.usDigitalButtons);
g_Pads[pad].LastButtons.usDigitalButtons = g_Pads[pad].CurrentButtons.usDigitalButtons;
for(button=0; button<8; button++)
{
g_Pads[pad].PressedButtons.ucAnalogButtons[button] =
(g_Pads[pad].CurrentButtons.ucAnalogButtons[button] > XPAD_ANALOG_BUTTON_INTF) &
(g_Pads[pad].LastButtons.ucAnalogButtons[button] ^
(g_Pads[pad].CurrentButtons.ucAnalogButtons[button] > XPAD_ANALOG_BUTTON_INTF));
g_Pads[pad].LastButtons.ucAnalogButtons[button] = (g_Pads[pad].CurrentButtons.ucAnalogButtons[button] > XPAD_ANALOG_BUTTON_INTF);
}
}
//Fill combination gamepad
memset(&g_DefaultPad, 0x00, sizeof(XPAD_INPUT));
iLThumbX = iLThumbY = iRThumbX = iRThumbY = 0;
for(pad=0; pad<4; pad++)
{
g_DefaultPad.CurrentButtons.usDigitalButtons |= g_Pads[pad].CurrentButtons.usDigitalButtons;
g_DefaultPad.LastButtons.usDigitalButtons |= g_Pads[pad].LastButtons.usDigitalButtons;
g_DefaultPad.PressedButtons.usDigitalButtons |= g_Pads[pad].PressedButtons.usDigitalButtons;
iLThumbX += g_Pads[pad].sLThumbX;
iLThumbY += g_Pads[pad].sLThumbY;
iRThumbX += g_Pads[pad].sRThumbX;
iRThumbY += g_Pads[pad].sRThumbY;
for(button=0; button<8; button++)
{
if(g_Pads[pad].CurrentButtons.ucAnalogButtons[button] >= g_DefaultPad.CurrentButtons.ucAnalogButtons[button])
{
g_DefaultPad.CurrentButtons.ucAnalogButtons[button] = g_Pads[pad].CurrentButtons.ucAnalogButtons[button];
}
g_DefaultPad.LastButtons.ucAnalogButtons[button] |= g_Pads[pad].LastButtons.ucAnalogButtons[button];
g_DefaultPad.PressedButtons.ucAnalogButtons[button] |= g_Pads[pad].PressedButtons.ucAnalogButtons[button];
}
}
g_DefaultPad.sLThumbX = (iLThumbX & 0xffff);
g_DefaultPad.sLThumbY = (iLThumbY & 0xffff);
g_DefaultPad.sRThumbX = (iRThumbX & 0xffff);
g_DefaultPad.sRThumbY = (iRThumbY & 0xffff);
// Mouse status
memcpy(&g_Mouse, &XMOUSE_current, sizeof(XMOUSE_INPUT));
}
int XInputGetPadCount(void)
{
int pad;
int numpads = 0;
for(pad=0; pad<4; pad++)
{
if(XPAD_current[pad].hPresent)
numpads++;
}
return numpads;
}
int XInputGetKeystroke(XKEYBOARD_STROKE *pStroke)
{
return GetKeyboardStroke(pStroke);
}
XMOUSE_INPUT XInputGetMouseData(void)
{
return g_Mouse;
}