Files
MesenCE/Core/Shared/BaseControlManager.h
NovaSquirrel 6312748563 SNES: Add Turbo File Twin support (#109)
* SNES: Add Turbo File Twin support

* SNES: Try to make write mode flag more accurate

Hardware tests on Turbo File Twin seem to be showing that if you write data then it stops reporting that the write flag is on, despite letting you write more data

* SNES: Move bit array access to a utility

Also add note about how bit 26 in STF report is not fully verified

* SNES: Add behavior seen when reading without read command

When you turn the strobe on and off outside of a read command, the shift register gets reloaded with the most recently read or written byte

* NES, SNES: Emulator::SaveBattery() for saving console and controller

* Fix range limit in SetBitInArray

* Add notes about unknown aspects of TFII mode

* Add comments to make it clear what's unknown

* STF mode ignores out-of-range addresses

Also allocate _data instead of putting it in the class
2026-05-15 00:05:31 -07:00

91 lines
2.3 KiB
C++

#pragma once
#include "pch.h"
#include "Utilities/SimpleLock.h"
#include "Utilities/ISerializable.h"
class BaseControlDevice;
class IInputRecorder;
class IInputProvider;
class Emulator;
enum class CpuType : uint8_t;
struct ControllerData;
enum class ControllerType;
class BaseControlManager : public ISerializable
{
private:
vector<IInputRecorder*> _inputRecorders;
vector<IInputProvider*> _inputProviders;
protected:
Emulator* _emu = nullptr;
CpuType _cpuType = {};
SimpleLock _deviceLock;
vector<shared_ptr<BaseControlDevice>> _systemDevices;
vector<shared_ptr<BaseControlDevice>> _controlDevices;
uint32_t _pollCounter = 0;
uint32_t _lagCounter = 0;
bool _wasInputRead = false;
void RegisterControlDevice(shared_ptr<BaseControlDevice> controlDevice);
void ClearDevices();
public:
BaseControlManager(Emulator* emu, CpuType cpuType);
virtual ~BaseControlManager();
void Serialize(Serializer& s) override;
void AddSystemControlDevice(shared_ptr<BaseControlDevice> device);
virtual void UpdateControlDevices() {}
virtual void UpdateInputState();
void ProcessEndOfFrame();
void SetInputReadFlag();
uint32_t GetLagCounter();
void ResetLagCounter();
bool HasControlDevice(ControllerType type);
virtual bool IsKeyboardConnected() { return false; }
uint32_t GetPollCounter();
void SetPollCounter(uint32_t value);
void SaveBattery();
virtual void Reset(bool softReset) {}
void RegisterInputProvider(IInputProvider* provider);
void UnregisterInputProvider(IInputProvider* provider);
void RegisterInputRecorder(IInputRecorder* recorder);
void UnregisterInputRecorder(IInputRecorder* recorder);
virtual shared_ptr<BaseControlDevice> CreateControllerDevice(ControllerType type, uint8_t port) = 0;
vector<ControllerData> GetPortStates();
shared_ptr<BaseControlDevice> GetControlDevice(uint8_t port, uint8_t subPort = 0);
shared_ptr<BaseControlDevice> GetControlDeviceByIndex(uint8_t index);
void RefreshHubState();
vector<shared_ptr<BaseControlDevice>> GetControlDevices();
template<typename T>
shared_ptr<T> GetControlDevice()
{
auto lock = _deviceLock.AcquireSafe();
for(shared_ptr<BaseControlDevice>& device : _controlDevices) {
shared_ptr<T> typedDevice = std::dynamic_pointer_cast<T>(device);
if(typedDevice) {
return typedDevice;
}
}
return nullptr;
}
};