From 024e9cdaf37cd9d13ad2fbef09ab9fbc38141590 Mon Sep 17 00:00:00 2001 From: Sour Date: Fri, 18 Oct 2019 17:14:47 -0400 Subject: [PATCH] Input: Fixed turbo for multitap --- Core/Core.vcxproj | 1 + Core/Core.vcxproj.filters | 3 + Core/Multitap.cpp | 131 ++++++++++++++++++++++++++++++++++++++ Core/Multitap.h | 121 ++++------------------------------- Libretro/Makefile.common | 1 + 5 files changed, 150 insertions(+), 107 deletions(-) create mode 100644 Core/Multitap.cpp diff --git a/Core/Core.vcxproj b/Core/Core.vcxproj index 341cbae..8f6b88b 100644 --- a/Core/Core.vcxproj +++ b/Core/Core.vcxproj @@ -235,6 +235,7 @@ + diff --git a/Core/Core.vcxproj.filters b/Core/Core.vcxproj.filters index 2bf1d9c..9e7c3da 100644 --- a/Core/Core.vcxproj.filters +++ b/Core/Core.vcxproj.filters @@ -677,6 +677,9 @@ SNES\Input + + SNES\Input + diff --git a/Core/Multitap.cpp b/Core/Multitap.cpp new file mode 100644 index 0000000..9f16b67 --- /dev/null +++ b/Core/Multitap.cpp @@ -0,0 +1,131 @@ +#include "stdafx.h" +#include "Multitap.h" +#include "InternalRegisters.h" +#include "Ppu.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)(_ppu->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); + } + } + } +} + +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) +{ + _ppu = console->GetPpu().get(); + _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; +} + +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); + } +} diff --git a/Core/Multitap.h b/Core/Multitap.h index fc76f50..46a4f49 100644 --- a/Core/Multitap.h +++ b/Core/Multitap.h @@ -1,128 +1,35 @@ #pragma once #include "stdafx.h" #include "BaseControlDevice.h" -#include "InternalRegisters.h" #include "../Utilities/Serializer.h" +class Ppu; +class InternalRegisters; + class Multitap : public BaseControlDevice { private: enum Buttons { A = 0, B, X, Y, L, R, Select, Start, Up, Down, Left, Right }; static constexpr int ButtonCount = 12; + Ppu *_ppu; vector _mappings[4]; + uint8_t _turboSpeed[4] = {}; uint16_t _stateBuffer[4] = {}; InternalRegisters *_internalRegs = nullptr; protected: - string GetKeyNames() override - { - //Repeat key names 4x, once for each controller - return "ABXYLRSTUDLR:ABXYLRSTUDLR:ABXYLRSTUDLR:ABXYLRSTUDLR"; - } - - void InternalSetStateFromInput() override - { - 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); - } - } - } - - uint16_t 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 Serialize(Serializer &s) override - { - BaseControlDevice::Serialize(s); - s.Stream(_stateBuffer[0], _stateBuffer[1], _stateBuffer[2], _stateBuffer[3]); - } - - void RefreshStateBuffer() override - { - for(int i = 0; i < 4; i++) { - _stateBuffer[i] = ToByte(i); - } - } + string GetKeyNames() override; + void InternalSetStateFromInput() override; + uint16_t ToByte(uint8_t port); + void Serialize(Serializer &s) override; + void RefreshStateBuffer() override; public: - Multitap(Console* console, uint8_t port, KeyMappingSet keyMappings1, KeyMappingSet keyMappings2, KeyMappingSet keyMappings3, KeyMappingSet keyMappings4) : BaseControlDevice(console, port, keyMappings1) - { - _mappings[0] = keyMappings1.GetKeyMappingArray(); - _mappings[1] = keyMappings2.GetKeyMappingArray(); - _mappings[2] = keyMappings3.GetKeyMappingArray(); - _mappings[3] = keyMappings4.GetKeyMappingArray(); - _internalRegs = console->GetInternalRegisters().get(); - } + Multitap(Console* console, uint8_t port, KeyMappingSet keyMappings1, KeyMappingSet keyMappings2, KeyMappingSet keyMappings3, KeyMappingSet keyMappings4); - ControllerType GetControllerType() override - { - return ControllerType::Multitap; - } + ControllerType GetControllerType() override; - uint8_t ReadRam(uint16_t addr) override - { - 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 WriteRam(uint16_t addr, uint8_t value) override - { - if(addr == 0x4016) { - StrobeProcessWrite(value); - } - } + uint8_t ReadRam(uint16_t addr) override; + void WriteRam(uint16_t addr, uint8_t value) override; }; \ No newline at end of file diff --git a/Libretro/Makefile.common b/Libretro/Makefile.common index 992caa3..b06fb97 100644 --- a/Libretro/Makefile.common +++ b/Libretro/Makefile.common @@ -68,6 +68,7 @@ SOURCES_CXX := $(LIBRETRO_DIR)/libretro.cpp \ $(CORE_DIR)/MessageManager.cpp \ $(CORE_DIR)/MovieManager.cpp \ $(CORE_DIR)/MovieRecorder.cpp \ + $(CORE_DIR)/Multitap.cpp \ $(CORE_DIR)/NecDsp.cpp \ $(CORE_DIR)/NecDspDisUtils.cpp \ $(CORE_DIR)/NotificationManager.cpp \