Files
MesenCE/Core/SNES/Input/SnesRumbleController.cpp
SourMesen 37de357b75 NES: FDS - Performance improvements (#143)
-ProcessCpuClock was used to check for events that don't need to be checked that often (auto-switch disk + auto fast-forward options). This has been moved to an EndFrame callback.
-This was even slower than intended because of the call to _emu->GetFrameCount() which was, relatively speaking, fairly slow. To improve its performance (since it's used rarely for some things like turbo button processing), a separate GetFrameCount function was added on all console classes, and Emulator::GetFrameCount was also optimized to be faster when called from the emulation thread.

When the auto-switch disk option is enabled, this can improve performance by about 25-30%. When the option is not enabled, this still improves performance by 4-5%.
2026-05-27 04:02:54 -07:00

71 lines
1.9 KiB
C++

#include "pch.h"
#include "SNES/Input/SnesRumbleController.h"
#include "SNES/SnesConsole.h"
#include "SNES/InternalRegisters.h"
#include "Shared/Emulator.h"
#include "Shared/KeyManager.h"
SnesRumbleController::SnesRumbleController(Emulator* emu, SnesConsole* console, uint8_t port, KeyMappingSet keyMappings) : SnesController(emu, port, keyMappings)
{
_console = console;
_type = ControllerType::SnesRumbleController;
}
SnesRumbleController::~SnesRumbleController()
{
KeyManager::SetForceFeedback(0, 0);
}
void SnesRumbleController::Serialize(Serializer& s)
{
SnesController::Serialize(s);
SV(_rumbleData);
SV(_rumbleActive);
SV(_lastRumbleFrame);
}
void SnesRumbleController::RefreshStateBuffer()
{
_rumbleData = 0;
//The LRG rumble controller stops rumbling shortly after the last rumble command.
//Not accurate, assumes the game regularly latches the controller.
if(_rumbleActive) {
if(_console->GetFrameCount() - _lastRumbleFrame > 2) {
KeyManager::SetForceFeedback(0, 0);
_rumbleActive = false;
}
}
SnesController::RefreshStateBuffer();
}
uint8_t SnesRumbleController::ReadRam(uint16_t addr)
{
if(IsCurrentPort(addr)) {
uint8_t ioPort = _console->GetInternalRegisters()->GetIoPortOutput();
//Technically, when plugged into port 2, this uses bit 7, but activating the rumble
//in both ports at the same time could potentially draw too much current, so the
//UI current prevents picking a rumble controller for P2
uint8_t ioBit = (GetPort() == 0 ? (ioPort >> 6) : (ioPort >> 7)) & 0x01;
_rumbleData = (_rumbleData << 1) | ioBit;
if((_rumbleData & 0xFF00) == 0x7200) {
uint8_t rumble = _rumbleData & 0xFF;
//Multiply by 4369 to use all values from 0 to 65535
uint16_t rightRumble = (rumble >> 4) * 4369;
uint16_t leftRumble = (rumble & 0x0F) * 4369;
KeyManager::SetForceFeedback(rightRumble, leftRumble);
_rumbleActive = true;
_lastRumbleFrame = _console->GetFrameCount();
}
}
return SnesController::ReadRam(addr);
}