#include "stdafx.h" #include "Multitap.h" #include "InternalRegisters.h" #include "SnesController.h" string Multitap::GetKeyNames() { //Repeat key names 4x, once for each controller return "ABXYLRSTUDLR:ABXYLRSTUDLR:ABXYLRSTUDLR:ABXYLRSTUDLR"; } void Multitap::InternalSetStateFromInput() { for (int i = 0; i < 4; i++) { int offset = Multitap::ButtonCount * i; for (KeyMapping keyMapping : _mappings[i]) { SetPressedState(Buttons::A + offset, keyMapping.A); SetPressedState(Buttons::B + offset, keyMapping.B); SetPressedState(Buttons::X + offset, keyMapping.X); SetPressedState(Buttons::Y + offset, keyMapping.Y); SetPressedState(Buttons::L + offset, keyMapping.L); SetPressedState(Buttons::R + offset, keyMapping.R); SetPressedState(Buttons::Start + offset, keyMapping.Start); SetPressedState(Buttons::Select + offset, keyMapping.Select); SetPressedState(Buttons::Up + offset, keyMapping.Up); SetPressedState(Buttons::Down + offset, keyMapping.Down); SetPressedState(Buttons::Left + offset, keyMapping.Left); SetPressedState(Buttons::Right + offset, keyMapping.Right); uint8_t turboFreq = 1 << (4 - _turboSpeed[i]); bool turboOn = (uint8_t)(_console->GetFrameCount() % turboFreq) < turboFreq / 2; if (turboOn) { SetPressedState(Buttons::A + offset, keyMapping.TurboA); SetPressedState(Buttons::B + offset, keyMapping.TurboB); SetPressedState(Buttons::X + offset, keyMapping.TurboX); SetPressedState(Buttons::Y + offset, keyMapping.TurboY); SetPressedState(Buttons::L + offset, keyMapping.TurboL); SetPressedState(Buttons::R + offset, keyMapping.TurboR); } } } } void Multitap::UpdateControllerState(uint8_t controllerNumber, SnesController& controller) { int offset = Multitap::ButtonCount * controllerNumber; SetBitValue(Buttons::A + offset, controller.IsPressed(Buttons::A)); SetBitValue(Buttons::B + offset, controller.IsPressed(Buttons::B)); SetBitValue(Buttons::X + offset, controller.IsPressed(Buttons::X)); SetBitValue(Buttons::Y + offset, controller.IsPressed(Buttons::Y)); SetBitValue(Buttons::L + offset, controller.IsPressed(Buttons::L)); SetBitValue(Buttons::R + offset, controller.IsPressed(Buttons::R)); SetBitValue(Buttons::Start + offset, controller.IsPressed(Buttons::Start)); SetBitValue(Buttons::Select + offset, controller.IsPressed(Buttons::Select)); SetBitValue(Buttons::Up + offset, controller.IsPressed(Buttons::Up)); SetBitValue(Buttons::Down + offset, controller.IsPressed(Buttons::Down)); SetBitValue(Buttons::Left + offset, controller.IsPressed(Buttons::Left)); SetBitValue(Buttons::Right + offset, controller.IsPressed(Buttons::Right)); } uint16_t Multitap::ToByte(uint8_t port) { //"A Super NES controller returns a 16-bit report in a similar order: B, Y, Select, Start, Up, Down, Left, Right, A, X, L, R, then four 0 bits." int offset = port * Multitap::ButtonCount; return (uint8_t)IsPressed(Buttons::B + offset) | ((uint8_t)IsPressed(Buttons::Y + offset) << 1) | ((uint8_t)IsPressed(Buttons::Select + offset) << 2) | ((uint8_t)IsPressed(Buttons::Start + offset) << 3) | ((uint8_t)IsPressed(Buttons::Up + offset) << 4) | ((uint8_t)IsPressed(Buttons::Down + offset) << 5) | ((uint8_t)IsPressed(Buttons::Left + offset) << 6) | ((uint8_t)IsPressed(Buttons::Right + offset) << 7) | ((uint8_t)IsPressed(Buttons::A + offset) << 8) | ((uint8_t)IsPressed(Buttons::X + offset) << 9) | ((uint8_t)IsPressed(Buttons::L + offset) << 10) | ((uint8_t)IsPressed(Buttons::R + offset) << 11); } void Multitap::Serialize(Serializer& s) { BaseControlDevice::Serialize(s); s.Stream(_stateBuffer[0], _stateBuffer[1], _stateBuffer[2], _stateBuffer[3]); } void Multitap::RefreshStateBuffer() { for (int i = 0; i < 4; i++) { _stateBuffer[i] = ToByte(i); } } Multitap::Multitap(Console* console, uint8_t port, KeyMappingSet keyMappings1, KeyMappingSet keyMappings2, KeyMappingSet keyMappings3, KeyMappingSet keyMappings4) : BaseControlDevice( console, port, keyMappings1) { _turboSpeed[0] = keyMappings1.TurboSpeed; _turboSpeed[1] = keyMappings2.TurboSpeed; _turboSpeed[2] = keyMappings3.TurboSpeed; _turboSpeed[3] = keyMappings4.TurboSpeed; _mappings[0] = keyMappings1.GetKeyMappingArray(); _mappings[1] = keyMappings2.GetKeyMappingArray(); _mappings[2] = keyMappings3.GetKeyMappingArray(); _mappings[3] = keyMappings4.GetKeyMappingArray(); _internalRegs = console->GetInternalRegisters().get(); } ControllerType Multitap::GetControllerType() { return ControllerType::Multitap; } void Multitap::SetControllerState(uint8_t controllerNumber, ControlDeviceState state) { SnesController controller(_console, 0, KeyMappingSet()); controller.SetRawState(state); UpdateControllerState(controllerNumber, controller); } uint8_t Multitap::ReadRam(uint16_t addr) { uint8_t selectBit = 0x80 >> ((_port == 0) ? 1 : 0); uint8_t portSelect = (_internalRegs->GetIoPortOutput() & selectBit) ? 0 : 2; uint8_t output = 0; if (IsCurrentPort(addr)) { StrobeProcessRead(); output = _stateBuffer[portSelect] & 0x01; output |= (_stateBuffer[portSelect + 1] & 0x01) << 1; //P3 & P5 are reported in bit 1 if (_strobe) { //Bit 1 is always set when strobe is high output |= 0x02; } _stateBuffer[portSelect] >>= 1; _stateBuffer[portSelect + 1] >>= 1; //"All subsequent reads will return D=1 on an authentic controller but may return D=0 on third party controllers." _stateBuffer[portSelect] |= 0x8000; _stateBuffer[portSelect + 1] |= 0x8000; } return output; } void Multitap::WriteRam(uint16_t addr, uint8_t value) { if (addr == 0x4016) { StrobeProcessWrite(value); } }