/* * Copyright (C) 2017 FIX94 * * This software may be modified and distributed under the terms * of the MIT license. See the LICENSE file for details. */ #include #include #include #include "wiidrc.h" struct WiiDRCStat { s16 xAxisLmid; s16 xAxisRmid; s16 yAxisLmid; s16 yAxisRmid; }; struct WiiDRCButtons { u32 up; u32 down; u32 state; }; static struct WiiDRCStat __WiiDRC_Status; static struct WiiDRCData __WiiDRC_PadData; static struct WiiDRCButtons __WiiDRC_PadButtons; static bool __WiiDRC_ShutdownRequested; static u32 __WiiDRC_Inited = 0; static u8 *__WiiDRC_I2CBuf = NULL; static u8 *__WiiDRC_DRCStateBuf = NULL; static bool __WiiDRC_SetI2CBuf() { DCInvalidateRange((void*)0x938B2964, 4); if(*(vu32*)0x938B2964 == 0x138BB004) //r569 { __WiiDRC_I2CBuf = (u8*)0x938BB004; return true; } DCInvalidateRange((void*)0x938B2564, 4); if(*(vu32*)0x938B2564 == 0x138BB004) //r570 { __WiiDRC_I2CBuf = (u8*)0x938BB004; return true; } else if(*(vu32*)0x938B2564 == 0x138BA004) //r590 { __WiiDRC_I2CBuf = (u8*)0x938BA004; return true; } return false; } static bool __WiiDRC_SetDRCStateBuf() { //TODO r569 DCInvalidateRange((void*)0x938B563C, 4); if(*(vu32*)0x938B563C == 0x138BE770) //r570 { __WiiDRC_DRCStateBuf = (u8*)0x938BE770; return true; } DCInvalidateRange((void*)0x938B5724, 4); if(*(vu32*)0x938B5724 == 0x138BD770) //r590 { __WiiDRC_DRCStateBuf = (u8*)0x938BD770; return true; } return false; } bool WiiDRC_Init() { if(__WiiDRC_Inited == 1) return false; if(!__WiiDRC_SetI2CBuf()) return false; //can fail on r569 for now __WiiDRC_SetDRCStateBuf(); __WiiDRC_Inited = 1; WiiDRC_Recalibrate(); //sets up __WiiDRC_Status memset(&__WiiDRC_PadData,0,sizeof(struct WiiDRCData)); memset(&__WiiDRC_PadButtons,0,sizeof(struct WiiDRCButtons)); __WiiDRC_ShutdownRequested = false; return true; } bool WiiDRC_Inited() { return !!__WiiDRC_Inited; } bool WiiDRC_Recalibrate() { if(__WiiDRC_Inited == 0) return false; DCInvalidateRange(__WiiDRC_I2CBuf,9); __WiiDRC_Status.xAxisLmid = (s8)(__WiiDRC_I2CBuf[4]-0x80); __WiiDRC_Status.yAxisLmid = (s8)(__WiiDRC_I2CBuf[5]-0x80); __WiiDRC_Status.xAxisRmid = (s8)(__WiiDRC_I2CBuf[6]-0x80); __WiiDRC_Status.yAxisRmid = (s8)(__WiiDRC_I2CBuf[7]-0x80); return true; } bool WiiDRC_ScanPads() { if(__WiiDRC_Inited == 0) return false; DCInvalidateRange(__WiiDRC_I2CBuf,9); __WiiDRC_ShutdownRequested = !!(__WiiDRC_I2CBuf[1]&0x80); __WiiDRC_PadData.button = (__WiiDRC_I2CBuf[2]<<8) | (__WiiDRC_I2CBuf[3]); __WiiDRC_PadData.xAxisL = ((s8)(__WiiDRC_I2CBuf[4]-0x80)) - __WiiDRC_Status.xAxisLmid; __WiiDRC_PadData.yAxisL = ((s8)(__WiiDRC_I2CBuf[5]-0x80)) - __WiiDRC_Status.yAxisLmid; __WiiDRC_PadData.xAxisR = ((s8)(__WiiDRC_I2CBuf[6]-0x80)) - __WiiDRC_Status.xAxisRmid; __WiiDRC_PadData.yAxisR = ((s8)(__WiiDRC_I2CBuf[7]-0x80)) - __WiiDRC_Status.yAxisRmid; __WiiDRC_PadData.extra = __WiiDRC_I2CBuf[8]; __WiiDRC_PadData.battery = (__WiiDRC_PadData.extra>>1)&7; u16 newstate, oldstate; newstate = __WiiDRC_PadData.button; oldstate = __WiiDRC_PadButtons.state; __WiiDRC_PadButtons.state = newstate; __WiiDRC_PadButtons.up = oldstate & ~newstate; __WiiDRC_PadButtons.down = newstate & (newstate ^ oldstate); return true; } bool WiiDRC_Connected() { if(__WiiDRC_DRCStateBuf) { DCInvalidateRange(__WiiDRC_DRCStateBuf, 4); return !!(*(vu32*)__WiiDRC_DRCStateBuf); } return true; //default connect } bool WiiDRC_ShutdownRequested() { return __WiiDRC_ShutdownRequested; } const u8 *WiiDRC_GetRawI2CAddr() { return __WiiDRC_I2CBuf; } const struct WiiDRCData *WiiDRC_Data() { return &__WiiDRC_PadData; } u32 WiiDRC_ButtonsUp() { return __WiiDRC_PadButtons.up; } u32 WiiDRC_ButtonsDown() { return __WiiDRC_PadButtons.down; } u32 WiiDRC_ButtonsHeld() { return __WiiDRC_PadButtons.state; } s16 WiiDRC_lStickX() { return __WiiDRC_PadData.xAxisL; } s16 WiiDRC_lStickY() { return __WiiDRC_PadData.yAxisL; } s16 WiiDRC_rStickX() { return __WiiDRC_PadData.xAxisR; } s16 WiiDRC_rStickY() { return __WiiDRC_PadData.yAxisR; }