#include "../psx.h" #include "../frontio.h" #include "gamepad.h" class InputDevice_Gamepad : public InputDevice { public: InputDevice_Gamepad(); virtual ~InputDevice_Gamepad(); virtual void Power(void); virtual int StateAction(StateMem* sm, int load, int data_only, const char* section_name); virtual void UpdateInput(const void *data); // // // virtual void SetDTR(bool new_dtr); virtual bool GetDSR(void); virtual bool Clock(bool TxD, int32 &dsr_pulse_delay); private: bool dtr; uint8 buttons[2]; int32 command_phase; uint32 bitpos; uint8 receive_buffer; uint8 command; uint8 transmit_buffer[3]; uint32 transmit_pos; uint32 transmit_count; }; InputDevice_Gamepad::InputDevice_Gamepad() { Power(); } InputDevice_Gamepad::~InputDevice_Gamepad() { } void InputDevice_Gamepad::Power(void) { dtr = 0; buttons[0] = buttons[1] = 0; command_phase = 0; bitpos = 0; receive_buffer = 0; command = 0; memset(transmit_buffer, 0, sizeof(transmit_buffer)); transmit_pos = 0; transmit_count = 0; } int InputDevice_Gamepad::StateAction(StateMem* sm, int load, int data_only, const char* section_name) { SFORMAT StateRegs[] = { SFVAR(dtr), SFARRAY(buttons, sizeof(buttons)), SFVAR(command_phase), SFVAR(bitpos), SFVAR(receive_buffer), SFVAR(command), SFARRAY(transmit_buffer, sizeof(transmit_buffer)), SFVAR(transmit_pos), SFVAR(transmit_count), SFEND }; int ret = MDFNSS_StateAction(sm, load, data_only, StateRegs, section_name); if(load) { if(((uint64_t)transmit_pos + transmit_count) > sizeof(transmit_buffer)) { transmit_pos = 0; transmit_count = 0; } } return(ret); } void InputDevice_Gamepad::UpdateInput(const void *data) { uint8 *d8 = (uint8 *)data; buttons[0] = d8[0]; buttons[1] = d8[1]; } void InputDevice_Gamepad::SetDTR(bool new_dtr) { if(!dtr && new_dtr) { command_phase = 0; bitpos = 0; transmit_pos = 0; transmit_count = 0; } else if(dtr && !new_dtr) { //if(bitpos || transmit_count) // printf("[PAD] Abort communication!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); } dtr = new_dtr; } bool InputDevice_Gamepad::GetDSR(void) { if(!dtr) return(0); if(!bitpos && transmit_count) return(1); return(0); } bool InputDevice_Gamepad::Clock(bool TxD, int32 &dsr_pulse_delay) { bool ret = 1; dsr_pulse_delay = 0; if(!dtr) return(1); if(transmit_count) ret = (transmit_buffer[transmit_pos] >> bitpos) & 1; receive_buffer &= ~(1 << bitpos); receive_buffer |= TxD << bitpos; bitpos = (bitpos + 1) & 0x7; if(!bitpos) { //printf("[PAD] Receive: %02x -- command_phase=%d\n", receive_buffer, command_phase); if(transmit_count) { transmit_pos++; transmit_count--; } switch(command_phase) { case 0: if(receive_buffer != 0x01) command_phase = -1; else { transmit_buffer[0] = 0x41; transmit_pos = 0; transmit_count = 1; command_phase++; } break; case 1: command = receive_buffer; command_phase++; transmit_buffer[0] = 0x5A; //if(command != 0x42) // fprintf(stderr, "Gamepad unhandled command: 0x%02x\n", command); //assert(command == 0x42); if(command == 0x42) { //printf("PAD COmmand 0x42, sl=%u\n", GPU->GetScanlineNum()); transmit_buffer[1] = 0xFF ^ buttons[0]; transmit_buffer[2] = 0xFF ^ buttons[1]; transmit_pos = 0; transmit_count = 3; } else { command_phase = -1; transmit_buffer[1] = 0; transmit_buffer[2] = 0; transmit_pos = 0; transmit_count = 0; } break; } } if(!bitpos && transmit_count) dsr_pulse_delay = 0x40; //0x100; return(ret); } InputDevice *Device_Gamepad_Create(void) { return new InputDevice_Gamepad(); } InputDeviceInputInfoStruct Device_Gamepad_IDII[16] = { { "select", "SELECT", 4, IDIT_BUTTON, NULL }, { NULL, "empty", 0, IDIT_BUTTON }, { NULL, "empty", 0, IDIT_BUTTON }, { "start", "START", 5, IDIT_BUTTON, NULL }, { "up", "UP ↑", 0, IDIT_BUTTON, "down" }, { "right", "RIGHT →", 3, IDIT_BUTTON, "left" }, { "down", "DOWN ↓", 1, IDIT_BUTTON, "up" }, { "left", "LEFT ←", 2, IDIT_BUTTON, "right" }, { "l2", "L2 (rear left shoulder)", 11, IDIT_BUTTON, NULL }, { "r2", "R2 (rear right shoulder)", 13, IDIT_BUTTON, NULL }, { "l1", "L1 (front left shoulder)", 10, IDIT_BUTTON, NULL }, { "r1", "R1 (front right shoulder)", 12, IDIT_BUTTON, NULL }, { "triangle", "△ (upper)", 6, IDIT_BUTTON_CAN_RAPID, NULL }, { "circle", "○ (right)", 9, IDIT_BUTTON_CAN_RAPID, NULL }, { "cross", "x (lower)", 7, IDIT_BUTTON_CAN_RAPID, NULL }, { "square", "□ (left)", 8, IDIT_BUTTON_CAN_RAPID, NULL }, }; InputDeviceInputInfoStruct Device_Dancepad_IDII[16] = { { "select", "SELECT", 0, IDIT_BUTTON, NULL }, { NULL, "empty", 0, IDIT_BUTTON }, { NULL, "empty", 0, IDIT_BUTTON }, { "start", "START", 1, IDIT_BUTTON, NULL }, { "up", "UP ↑", 3, IDIT_BUTTON, NULL }, { "right", "RIGHT →", 6, IDIT_BUTTON, NULL }, { "down", "DOWN ↓", 8, IDIT_BUTTON, NULL }, { "left", "LEFT ←", 5, IDIT_BUTTON, NULL }, { NULL, "empty", 0, IDIT_BUTTON, NULL }, { NULL, "empty", 0, IDIT_BUTTON, NULL }, { NULL, "empty", 0, IDIT_BUTTON, NULL }, { NULL, "empty", 0, IDIT_BUTTON, NULL }, { "triangle", "△ (lower left)", 7, IDIT_BUTTON, NULL }, { "circle", "○ (upper right)", 4, IDIT_BUTTON, NULL }, { "cross", "x (upper left)", 2, IDIT_BUTTON, NULL }, { "square", "□ (lower right)", 9, IDIT_BUTTON, NULL }, };