diff --git a/gc/ogc/pad.h b/gc/ogc/pad.h index 5fd590422..b41b1dd72 100644 --- a/gc/ogc/pad.h +++ b/gc/ogc/pad.h @@ -3,6 +3,12 @@ #include +#define PAD_TYPE_NONE -1 +#define PAD_TYPE_STANDARD 0 +#define PAD_TYPE_WAVEBIRD 1 +#define PAD_TYPE_KEYBOARD 2 +#define PAD_TYPE_STEERING 3 + #define PAD_CHAN0 0 #define PAD_CHAN1 1 #define PAD_CHAN2 2 @@ -53,6 +59,7 @@ typedef struct _padstatus { u8 triggerR; u8 analogA; u8 analogB; + u8 keyboard[3]; s8 err; } PADStatus; @@ -69,6 +76,7 @@ u32 PAD_Recalibrate(u32 mask); void PAD_Clamp(PADStatus *status); void PAD_ControlMotor(s32 chan,u32 cmd); void PAD_SetSpec(u32 spec); +s32 PAD_GetType(s32 chan); u32 PAD_ScanPads(void); @@ -76,6 +84,10 @@ u16 PAD_ButtonsUp(int pad); u16 PAD_ButtonsDown(int pad); u16 PAD_ButtonsHeld(int pad); +s32 PAD_KeyboardUp(int pad, u8 *keys); +s32 PAD_KeyboardDown(int pad, u8 *keys); +s32 PAD_KeyboardHeld(int pad, u8 *keys); + s8 PAD_SubStickX(int pad); s8 PAD_SubStickY(int pad); diff --git a/gc/ogc/si.h b/gc/ogc/si.h index c57f2fd12..742652deb 100644 --- a/gc/ogc/si.h +++ b/gc/ogc/si.h @@ -33,9 +33,10 @@ #define SI_TYPE_GC SI_TYPE_DOLPHIN // GameCube specific -#define SI_GC_WIRELESS 0x80000000u -#define SI_GC_NOMOTOR 0x20000000u // no rumble motor -#define SI_GC_STANDARD 0x01000000u // dolphin standard controller +#define SI_GC_FEATURE_WIRELESS 0x80000000u +#define SI_GC_FEATURE_NOMOTOR 0x20000000u // no rumble motor +#define SI_GC_FEATURE_STANDARD 0x01000000u // dolphin standard controller +#define SI_GC_FEATURE_KEYBOARD 0x00200000u // ASCII keyboard controller // WaveBird specific #define SI_WIRELESS_RECEIVED 0x40000000u // 0: no wireless unit @@ -56,10 +57,10 @@ #define SI_N64_KEYBOARD (SI_TYPE_N64 | 0x00020000) #define SI_N64_MOUSE (SI_TYPE_N64 | 0x02000000) #define SI_GBA (SI_TYPE_N64 | 0x00040000) -#define SI_GC_CONTROLLER (SI_TYPE_GC | SI_GC_STANDARD) -#define SI_GC_RECEIVER (SI_TYPE_GC | SI_GC_WIRELESS) -#define SI_GC_WAVEBIRD (SI_TYPE_GC | SI_GC_WIRELESS | SI_GC_STANDARD | SI_WIRELESS_STATE | SI_WIRELESS_FIX_ID) -#define SI_GC_KEYBOARD (SI_TYPE_GC | 0x00200000) +#define SI_GC_CONTROLLER (SI_TYPE_GC | SI_GC_FEATURE_STANDARD) +#define SI_GC_RECEIVER (SI_TYPE_GC | SI_GC_FEATURE_WIRELESS) +#define SI_GC_WAVEBIRD (SI_TYPE_GC | SI_GC_FEATURE_WIRELESS | SI_GC_FEATURE_STANDARD | SI_WIRELESS_STATE | SI_WIRELESS_FIX_ID) +#define SI_GC_KEYBOARD (SI_TYPE_GC | SI_GC_FEATURE_KEYBOARD) #define SI_GC_STEERING (SI_TYPE_GC | 0x00000000) #ifdef __cplusplus diff --git a/gc/wiiuse/wiiuse.h b/gc/wiiuse/wiiuse.h index a5c515015..69a8bb39e 100644 --- a/gc/wiiuse/wiiuse.h +++ b/gc/wiiuse/wiiuse.h @@ -534,6 +534,9 @@ typedef struct wii_board_t { short cbr[3]; /* /Calibration */ float x; float y; + ubyte tmp; + ubyte ref_tmp; + ubyte bat; } wii_board_t; typedef struct motion_plus_t diff --git a/libogc/pad.c b/libogc/pad.c index 58b6368d7..d4a1772a1 100644 --- a/libogc/pad.c +++ b/libogc/pad.c @@ -26,6 +26,9 @@ typedef struct _keyinput { u16 up; u16 down; u16 state; + u8 keyboard_up[3]; + u8 keyboard_down[3]; + u8 keyboard_state[3]; u32 chan; } keyinput; @@ -43,6 +46,7 @@ static u32 __pad_checkingbits = 0; static u32 __pad_resettingchan = 32; static u32 __pad_spec = 5; +static u32 __pad_cmdinitkeyboard = 0x00540000; static u32 __pad_analogmode = 0x00000300; static u32 __pad_cmdreadorigin = 0x41000000; static u32 __pad_cmdcalibrate = 0x42000000; @@ -63,6 +67,7 @@ static u8 __pad_clampregion[8] = {30, 180, 15, 72, 40, 15, 59, 31}; extern u32 __PADFixBits; static void __pad_enable(u32 chan); +static void __pad_enablekeyboard(u32 chan); static void __pad_disable(u32 chan); static void __pad_doreset(void); static s32 __pad_onreset(s32 final); @@ -369,18 +374,24 @@ static void __pad_typeandstatuscallback(s32 chan,u32 type) __pad_type[__pad_resettingchan] = (type&~0xff); if(((type&SI_TYPE_MASK)-SI_TYPE_GC) - || !(type&SI_GC_STANDARD)) { + || !(type&SI_TYPE_GC)) { __pad_doreset(); return; } - + if(__pad_spec<2) { __pad_enable(__pad_resettingchan); __pad_doreset(); return; } - if(!(type&SI_GC_WIRELESS) || type&SI_WIRELESS_IR) { + if (type == SI_GC_KEYBOARD) { + __pad_enablekeyboard(__pad_resettingchan); + __pad_doreset(); + return; + } + + if(!(type&SI_GC_FEATURE_WIRELESS) || type&SI_WIRELESS_IR) { if(recal_bits) ret = SI_Transfer(__pad_resettingchan,&__pad_cmdcalibrate,3,__pad_origin[__pad_resettingchan],10,__pad_origincallback,0); else ret = SI_Transfer(__pad_resettingchan,&__pad_cmdreadorigin,1,__pad_origin[__pad_resettingchan],10,__pad_origincallback,0); } else if(type&SI_WIRELESS_FIX_ID && !(type&SI_WIRELESS_CONT_MASK) && !(type&SI_WIRELESS_LITE)) { @@ -406,7 +417,7 @@ static void __pad_receivecheckcallback(s32 chan,u32 type) __pad_waitingbits &= ~mask; __pad_checkingbits &= ~mask; if(!(tmp&0x0f) - && (type&SI_GC_WIRELESS) && (type&SI_WIRELESS_RECEIVED) && (type&SI_WIRELESS_FIX_ID) + && (type&SI_GC_FEATURE_WIRELESS) && (type&SI_WIRELESS_RECEIVED) && (type&SI_WIRELESS_FIX_ID) && !(type&SI_WIRELESS_IR) && !(type&SI_WIRELESS_CONT_MASK) && !(type&SI_WIRELESS_LITE)) SI_Transfer(chan,&__pad_cmdreadorigin,1,__pad_origin[chan],10,__pad_originupdatecallback,0); else __pad_disable(chan); } @@ -424,6 +435,18 @@ static void __pad_enable(u32 chan) SI_EnablePolling(__pad_enabledbits); } +static void __pad_enablekeyboard(u32 chan) +{ + u32 buf[2]; +#ifdef _PAD_DEBUG + printf("__pad_enablekeyboard(%d)\n",chan); +#endif + __pad_enabledbits |= PAD_ENABLEDMASK(chan); + SI_GetResponse(chan,(void*)buf); + SI_SetCommand(chan,__pad_cmdinitkeyboard); + SI_EnablePolling(__pad_enabledbits); +} + static void __pad_disable(u32 chan) { u32 level,mask; @@ -664,7 +687,7 @@ void PAD_ControlMotor(s32 chan,u32 cmd) mask = PAD_ENABLEDMASK(chan); if(__pad_enabledbits&mask) { type = SI_GetType(chan); - if(!(type&SI_GC_NOMOTOR)) { + if(!(type&SI_GC_FEATURE_NOMOTOR)) { if(__pad_spec<2 && cmd==PAD_MOTOR_STOP_HARD) cmd = 0; cmd = 0x00400000|__pad_analogmode|(cmd&0x03); @@ -675,6 +698,44 @@ void PAD_ControlMotor(s32 chan,u32 cmd) _CPU_ISR_Restore(level); } +s32 PAD_GetType(s32 chan) +{ + u32 level; + u32 mask, sitype; + s32 type = PAD_TYPE_NONE; + + _CPU_ISR_Disable(level); + + mask = PAD_ENABLEDMASK(chan); + if(__pad_enabledbits&mask) { + sitype = SI_GetType(chan); + sitype = SI_DecodeType(sitype); + switch (sitype) + { + case SI_GC_CONTROLLER: + type = PAD_TYPE_STANDARD; + break; + case SI_GC_WAVEBIRD: + type = PAD_TYPE_WAVEBIRD; + break; + case SI_GC_KEYBOARD: + type = PAD_TYPE_KEYBOARD; + break; + case SI_GC_STEERING: + type = PAD_TYPE_STEERING; + break; + default: +#ifdef _PAD_DEBUG + printf("Unknown pad type %08x\n", sitype); +#endif + break; + } + } + _CPU_ISR_Restore(level); + + return type; +} + sampling_callback PAD_SetSamplingCallback(sampling_callback cb) { sampling_callback ret; @@ -710,6 +771,9 @@ u32 PAD_ScanPads(void) u32 resetBits; u32 padBit,connected; u16 state,oldstate; + u32 type; + u8 oldkeys[3]; + u8 keys[3]; PADStatus padstatus[PAD_CHANMAX]; resetBits = 0; @@ -719,22 +783,81 @@ u32 PAD_ScanPads(void) //PAD_Clamp(padstatus); for(i=0;i>i); + type = PAD_GetType(i); switch(padstatus[i].err) { case PAD_ERR_NONE: - oldstate = __pad_keys[i].state; - state = padstatus[i].button; - __pad_keys[i].stickX = padstatus[i].stickX; - __pad_keys[i].stickY = padstatus[i].stickY; - __pad_keys[i].substickX = padstatus[i].substickX; - __pad_keys[i].substickY = padstatus[i].substickY; - __pad_keys[i].triggerL = padstatus[i].triggerL; - __pad_keys[i].triggerR = padstatus[i].triggerR; - __pad_keys[i].up = oldstate & ~state; - __pad_keys[i].down = state & (state ^ oldstate); - __pad_keys[i].state = state; - __pad_keys[i].chan = i; + if (type == PAD_TYPE_KEYBOARD) { + keys[0] = (u8)(padstatus[i].substickX - 128); + keys[1] = (u8)(padstatus[i].substickY - 128); + keys[2] = (u8)(padstatus[i].triggerL); + + // Only update if keys did not roll over + if (keys[0] != 1 && keys[1] != 1 && keys[2] != 1 && + keys[0] != 2 && keys[1] != 2 && keys[2] != 2) { + oldkeys[0] = __pad_keys[i].keyboard_state[0]; + oldkeys[1] = __pad_keys[i].keyboard_state[1]; + oldkeys[2] = __pad_keys[i].keyboard_state[2]; + + memset(&__pad_keys[i],0,sizeof(keyinput)); + + // Check if any keyboard keys are being newly pressed + if (keys[0] && ((keys[0] != oldkeys[0]) && (keys[0] != oldkeys[1]) && (keys[0] != oldkeys[2]))) + __pad_keys[i].keyboard_down[0] = keys[0]; + if (keys[1] && ((keys[1] != oldkeys[0]) && (keys[1] != oldkeys[1]) && (keys[1] != oldkeys[2]))) + __pad_keys[i].keyboard_down[1] = keys[1]; + if (keys[2] && ((keys[2] != oldkeys[0]) && (keys[2] != oldkeys[1]) && (keys[2] != oldkeys[2]))) + __pad_keys[i].keyboard_down[2] = keys[2]; + + if (!__pad_keys[i].keyboard_down[0]) { + __pad_keys[i].keyboard_down[0] = __pad_keys[i].keyboard_down[1]; + __pad_keys[i].keyboard_down[1] = __pad_keys[i].keyboard_down[2]; + __pad_keys[i].keyboard_down[2] = 0; + } + + if (!__pad_keys[i].keyboard_down[1]) { + __pad_keys[i].keyboard_down[1] = __pad_keys[i].keyboard_down[2]; + __pad_keys[i].keyboard_down[2] = 0; + } + + // Check if any keyboard keys have been released + if (oldkeys[0] && ((oldkeys[0] != keys[0]) && (oldkeys[0] != keys[1]) && (oldkeys[0] != keys[2]))) + __pad_keys[i].keyboard_up[0] = oldkeys[0]; + if (oldkeys[1] && ((oldkeys[1] != keys[0]) && (oldkeys[1] != keys[1]) && (oldkeys[1] != keys[2]))) + __pad_keys[i].keyboard_up[1] = oldkeys[1]; + if (oldkeys[2] && ((oldkeys[2] != keys[0]) && (oldkeys[2] != keys[1]) && (oldkeys[2] != keys[2]))) + __pad_keys[i].keyboard_up[2] = oldkeys[2]; + + if (!__pad_keys[i].keyboard_up[0]) { + __pad_keys[i].keyboard_up[0] = __pad_keys[i].keyboard_up[1]; + __pad_keys[i].keyboard_up[1] = __pad_keys[i].keyboard_up[2]; + __pad_keys[i].keyboard_up[2] = 0; + } + + if (!__pad_keys[i].keyboard_up[1]) { + __pad_keys[i].keyboard_up[1] = __pad_keys[i].keyboard_up[2]; + __pad_keys[i].keyboard_up[2] = 0; + } + __pad_keys[i].keyboard_state[0] = keys[0]; + __pad_keys[i].keyboard_state[1] = keys[1]; + __pad_keys[i].keyboard_state[2] = keys[2]; + } + } else { + oldstate = __pad_keys[i].state; + memset(&__pad_keys[i],0,sizeof(keyinput)); + state = padstatus[i].button; + __pad_keys[i].stickX = padstatus[i].stickX; + __pad_keys[i].stickY = padstatus[i].stickY; + __pad_keys[i].substickX = padstatus[i].substickX; + __pad_keys[i].substickY = padstatus[i].substickY; + __pad_keys[i].triggerL = padstatus[i].triggerL; + __pad_keys[i].triggerR = padstatus[i].triggerR; + __pad_keys[i].up = oldstate & ~state; + __pad_keys[i].down = state & (state ^ oldstate); + __pad_keys[i].state = state; + } + __pad_keys[i].chan = i; connected |= (1<PAD_CHAN3 || __pad_keys[pad].chan==-1 || PAD_GetType(pad) != PAD_TYPE_KEYBOARD) return 0; + for (i = 0; i < 3; i++) { + if (__pad_keys[pad].keyboard_up[i]) { + keys[i] = __pad_keys[pad].keyboard_up[i]; + count++; + } + } + // Clear after checking so new buttons are only seen once + memset(__pad_keys[pad].keyboard_up, 0, sizeof(__pad_keys[pad].keyboard_up)); + return count; +} + +s32 PAD_KeyboardDown(int pad, u8 *keys) +{ + s32 i, count = 0; + if (keys == NULL) return 0; + memset(keys, 0, 3); + if(padPAD_CHAN3 || __pad_keys[pad].chan==-1 || PAD_GetType(pad) != PAD_TYPE_KEYBOARD) return 0; + for (i = 0; i < 3; i++) { + if (__pad_keys[pad].keyboard_down[i]) { + keys[i] = __pad_keys[pad].keyboard_down[i]; + count++; + } + } + // Clear after checking so new buttons are only seen once + memset(__pad_keys[pad].keyboard_down, 0, sizeof(__pad_keys[pad].keyboard_down)); + return count; +} + +s32 PAD_KeyboardHeld(int pad, u8 *keys) +{ + s32 i, count = 0; + if (keys == NULL) return 0; + memset(keys, 0, 3); + if(padPAD_CHAN3 || __pad_keys[pad].chan==-1 || PAD_GetType(pad) != PAD_TYPE_KEYBOARD) return 0; + for (i = 0; i < 3; i++) { + keys[i] = 0; + if (__pad_keys[pad].keyboard_state[i]) { + keys[i] = __pad_keys[pad].keyboard_state[i]; + count++; + } + } + return count; +} + s8 PAD_SubStickX(int pad) { if(padPAD_CHAN3 || __pad_keys[pad].chan==-1) return 0; diff --git a/libogc/si.c b/libogc/si.c index 48c557d70..3603755fd 100644 --- a/libogc/si.c +++ b/libogc/si.c @@ -275,7 +275,7 @@ static void __si_gettypecallback(s32 chan,u32 type) __PADFixBits &= ~SI_CHAN_BIT(chan); if(type&0x0f || ((si_type[chan]&SI_TYPE_MASK)-SI_TYPE_GC) - || !(si_type[chan]&SI_GC_WIRELESS) || si_type[chan]&SI_WIRELESS_IR) { + || !(si_type[chan]&SI_GC_FEATURE_WIRELESS) || si_type[chan]&SI_WIRELESS_IR) { SYS_SetWirelessID(chan,0); __si_calltypandstatuscallback(chan,si_type[chan]); return; @@ -675,7 +675,7 @@ u32 SI_DecodeType(u32 type) case SI_TYPE_GC: if(type==SI_GC_STEERING) return SI_GC_STEERING; if(type==SI_GC_KEYBOARD) return SI_GC_KEYBOARD; - if((type&SI_GC_WIRELESS) && !(type&SI_WIRELESS_IR)) { + if((type&SI_GC_FEATURE_WIRELESS) && !(type&SI_WIRELESS_IR)) { if((type&SI_GC_WAVEBIRD)==SI_GC_WAVEBIRD) return SI_GC_WAVEBIRD; else if(!(type&SI_WIRELESS_STATE)) return SI_GC_RECEIVER; } diff --git a/wiiuse/io_wii.c b/wiiuse/io_wii.c index 75b43a2d3..fd25f9700 100644 --- a/wiiuse/io_wii.c +++ b/wiiuse/io_wii.c @@ -265,17 +265,18 @@ void wiiuse_sensorbar_enable(int enable) __wiiuse_sensorbar_enable(enable); } -void wiiuse_init_cmd_queue(struct wiimote_t *wm) +int wiiuse_init_cmd_queue(struct wiimote_t *wm) { u32 size; if (!__queue_buffer[wm->unid]) { size = (MAX_COMMANDS*sizeof(struct cmd_blk_t)); __queue_buffer[wm->unid] = __lwp_wkspace_allocate(size); - if(!__queue_buffer[wm->unid]) return; + if(!__queue_buffer[wm->unid]) return ERR_MEM; } __lwp_queue_initialize(&wm->cmdq,__queue_buffer[wm->unid],MAX_COMMANDS,sizeof(struct cmd_blk_t)); + return ERR_OK; } int wiiuse_io_write(struct wiimote_t *wm,ubyte *buf,int len) diff --git a/wiiuse/wiiboard.c b/wiiuse/wiiboard.c index cca1a1567..3f1e78da3 100644 --- a/wiiuse/wiiboard.c +++ b/wiiuse/wiiboard.c @@ -84,6 +84,8 @@ int wii_board_handshake(struct wiimote_t* wm, struct wii_board_t* wb, ubyte* dat wb->ctl[2] = (data[offset+24]<<8)|data[offset+25]; wb->cbl[2] = (data[offset+26]<<8)|data[offset+27]; + wb->ref_tmp = data[offset+64]; + /* handshake done */ wm->event = WIIUSE_WII_BOARD_INSERTED; wm->exp.type = EXP_WII_BOARD; @@ -114,5 +116,7 @@ void wii_board_event(struct wii_board_t* wb, ubyte* msg) wb->rtr = (msg[0]<<8)|msg[1]; wb->rbr = (msg[2]<<8)|msg[3]; wb->rtl = (msg[4]<<8)|msg[5]; - wb->rbl = (msg[6]<<8)|msg[7]; + wb->rbl = (msg[6]<<8)|msg[7]; + wb->tmp = msg[8]; + wb->bat = msg[10]; } diff --git a/wiiuse/wiiuse.c b/wiiuse/wiiuse.c index 5f9b50377..7d22b15b7 100644 --- a/wiiuse/wiiuse.c +++ b/wiiuse/wiiuse.c @@ -88,7 +88,10 @@ struct wiimote_t** wiiuse_init(int wiimotes, wii_event_cb event_cb) { __wm[i]->sock = NULL; __wm[i]->bdaddr = *BD_ADDR_ANY; __wm[i]->event_cb = event_cb; - wiiuse_init_cmd_queue(__wm[i]); + if (wiiuse_init_cmd_queue(__wm[i])) { + WIIUSE_ERROR("Could not allocate command queue"); + return NULL; + } #elif defined(unix) __wm[i]->bdaddr = *BDADDR_ANY; __wm[i]->out_sock = -1; diff --git a/wiiuse/wiiuse_internal.h b/wiiuse/wiiuse_internal.h index 9c0013b1b..87d2bd1a8 100644 --- a/wiiuse/wiiuse_internal.h +++ b/wiiuse/wiiuse_internal.h @@ -267,7 +267,7 @@ struct op_t } __attribute__((packed)); /* not part of the api */ -void wiiuse_init_cmd_queue(struct wiimote_t *wm); +int wiiuse_init_cmd_queue(struct wiimote_t *wm); void wiiuse_send_next_command(struct wiimote_t *wm); int wiiuse_set_report_type(struct wiimote_t* wm,cmd_blk_cb cb); int wiiuse_sendcmd(struct wiimote_t *wm,ubyte report_type,ubyte *msg,int len,cmd_blk_cb cb);