mirror of
https://github.com/SourMesen/Mesen2.git
synced 2025-04-02 10:21:44 -04:00
Integrate NES input devices
This commit is contained in:
parent
8a1ea20e98
commit
add120abdb
47 changed files with 2110 additions and 113 deletions
|
@ -44,6 +44,29 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="Debugger\stdafx.h" />
|
<ClInclude Include="Debugger\stdafx.h" />
|
||||||
|
<ClInclude Include="NES\Input\ArkanoidController.h" />
|
||||||
|
<ClInclude Include="NES\Input\AsciiTurboFile.h" />
|
||||||
|
<ClInclude Include="NES\Input\BandaiHyperShot.h" />
|
||||||
|
<ClInclude Include="NES\Input\BarcodeBattlerReader.h" />
|
||||||
|
<ClInclude Include="NES\Input\BattleBox.h" />
|
||||||
|
<ClInclude Include="NES\Input\ExcitingBoxingController.h" />
|
||||||
|
<ClInclude Include="NES\Input\FamilyBasicDataRecorder.h" />
|
||||||
|
<ClInclude Include="NES\Input\FamilyBasicKeyboard.h" />
|
||||||
|
<ClInclude Include="NES\Input\FamilyMatTrainer.h" />
|
||||||
|
<ClInclude Include="NES\Input\FourScore.h" />
|
||||||
|
<ClInclude Include="NES\Input\HoriTrack.h" />
|
||||||
|
<ClInclude Include="NES\Input\IBarcodeReader.h" />
|
||||||
|
<ClInclude Include="NES\Input\JissenMahjongController.h" />
|
||||||
|
<ClInclude Include="NES\Input\KonamiHyperShot.h" />
|
||||||
|
<ClInclude Include="NES\Input\OekaKidsTablet.h" />
|
||||||
|
<ClInclude Include="NES\Input\PachinkoController.h" />
|
||||||
|
<ClInclude Include="NES\Input\PartyTap.h" />
|
||||||
|
<ClInclude Include="NES\Input\PowerPad.h" />
|
||||||
|
<ClInclude Include="NES\Input\SuborKeyboard.h" />
|
||||||
|
<ClInclude Include="NES\Input\SuborMouse.h" />
|
||||||
|
<ClInclude Include="NES\Input\VirtualBoyController.h" />
|
||||||
|
<ClInclude Include="NES\Input\VsZapper.h" />
|
||||||
|
<ClInclude Include="NES\Input\Zapper.h" />
|
||||||
<ClInclude Include="Netplay\stdafx.h" />
|
<ClInclude Include="Netplay\stdafx.h" />
|
||||||
<ClInclude Include="Shared\Audio\stdafx.h" />
|
<ClInclude Include="Shared\Audio\stdafx.h" />
|
||||||
<ClInclude Include="Shared\BaseControlManager.h" />
|
<ClInclude Include="Shared\BaseControlManager.h" />
|
||||||
|
@ -51,6 +74,7 @@
|
||||||
<ClInclude Include="Gameboy\GbControlManager.h" />
|
<ClInclude Include="Gameboy\GbControlManager.h" />
|
||||||
<ClInclude Include="Gameboy\stdafx.h" />
|
<ClInclude Include="Gameboy\stdafx.h" />
|
||||||
<ClInclude Include="Shared\Interfaces\IAudioProvider.h" />
|
<ClInclude Include="Shared\Interfaces\IAudioProvider.h" />
|
||||||
|
<ClInclude Include="Shared\Interfaces\IBattery.h" />
|
||||||
<ClInclude Include="Shared\Interfaces\IControlManager.h" />
|
<ClInclude Include="Shared\Interfaces\IControlManager.h" />
|
||||||
<ClInclude Include="MemoryOperationType.h" />
|
<ClInclude Include="MemoryOperationType.h" />
|
||||||
<ClInclude Include="Shared\Interfaces\stdafx.h" />
|
<ClInclude Include="Shared\Interfaces\stdafx.h" />
|
||||||
|
|
|
@ -734,6 +734,30 @@
|
||||||
<ClInclude Include="Netplay\stdafx.h" />
|
<ClInclude Include="Netplay\stdafx.h" />
|
||||||
<ClInclude Include="Shared\BaseControlManager.h" />
|
<ClInclude Include="Shared\BaseControlManager.h" />
|
||||||
<ClInclude Include="Shared\RomInfo.h" />
|
<ClInclude Include="Shared\RomInfo.h" />
|
||||||
|
<ClInclude Include="NES\Input\AsciiTurboFile.h" />
|
||||||
|
<ClInclude Include="NES\Input\BandaiHyperShot.h" />
|
||||||
|
<ClInclude Include="NES\Input\BarcodeBattlerReader.h" />
|
||||||
|
<ClInclude Include="NES\Input\BattleBox.h" />
|
||||||
|
<ClInclude Include="NES\Input\ExcitingBoxingController.h" />
|
||||||
|
<ClInclude Include="NES\Input\FamilyBasicDataRecorder.h" />
|
||||||
|
<ClInclude Include="NES\Input\FamilyBasicKeyboard.h" />
|
||||||
|
<ClInclude Include="NES\Input\FamilyMatTrainer.h" />
|
||||||
|
<ClInclude Include="NES\Input\FourScore.h" />
|
||||||
|
<ClInclude Include="NES\Input\HoriTrack.h" />
|
||||||
|
<ClInclude Include="NES\Input\OekaKidsTablet.h" />
|
||||||
|
<ClInclude Include="NES\Input\PachinkoController.h" />
|
||||||
|
<ClInclude Include="NES\Input\PartyTap.h" />
|
||||||
|
<ClInclude Include="NES\Input\PowerPad.h" />
|
||||||
|
<ClInclude Include="NES\Input\VirtualBoyController.h" />
|
||||||
|
<ClInclude Include="NES\Input\VsZapper.h" />
|
||||||
|
<ClInclude Include="NES\Input\Zapper.h" />
|
||||||
|
<ClInclude Include="NES\Input\ArkanoidController.h" />
|
||||||
|
<ClInclude Include="NES\Input\JissenMahjongController.h" />
|
||||||
|
<ClInclude Include="NES\Input\KonamiHyperShot.h" />
|
||||||
|
<ClInclude Include="NES\Input\SuborKeyboard.h" />
|
||||||
|
<ClInclude Include="NES\Input\SuborMouse.h" />
|
||||||
|
<ClInclude Include="NES\Input\IBarcodeReader.h" />
|
||||||
|
<ClInclude Include="Shared\Interfaces\IBattery.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="SNES\Cpu.cpp">
|
<ClCompile Include="SNES\Cpu.cpp">
|
||||||
|
|
|
@ -463,3 +463,8 @@ uint64_t Gameboy::GetMasterClock()
|
||||||
{
|
{
|
||||||
return _memoryManager->GetCycleCount();
|
return _memoryManager->GetCycleCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t Gameboy::GetMasterClockRate()
|
||||||
|
{
|
||||||
|
return 20971520;
|
||||||
|
}
|
||||||
|
|
|
@ -117,5 +117,6 @@ public:
|
||||||
virtual AddressInfo GetRelativeAddress(AddressInfo absAddress, CpuType cpuType) override;
|
virtual AddressInfo GetRelativeAddress(AddressInfo absAddress, CpuType cpuType) override;
|
||||||
|
|
||||||
// Inherited via IConsole
|
// Inherited via IConsole
|
||||||
virtual uint64_t GetMasterClock() override;
|
uint64_t GetMasterClock() override;
|
||||||
|
uint32_t GetMasterClockRate() override;
|
||||||
};
|
};
|
90
Core/NES/Input/ArkanoidController.h
Normal file
90
Core/NES/Input/ArkanoidController.h
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
#pragma once
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "Shared/BaseControlDevice.h"
|
||||||
|
#include "Shared/KeyManager.h"
|
||||||
|
#include "Shared/Emulator.h"
|
||||||
|
#include "Shared/EmuSettings.h"
|
||||||
|
#include "Utilities/Serializer.h"
|
||||||
|
|
||||||
|
class ArkanoidController : public BaseControlDevice
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
uint32_t _currentValue = (0xF4 - 0x54) / 2;
|
||||||
|
uint32_t _stateBuffer = 0;
|
||||||
|
enum Buttons { Fire };
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool HasCoordinates() override { return true; }
|
||||||
|
|
||||||
|
string GetKeyNames() override
|
||||||
|
{
|
||||||
|
return "F";
|
||||||
|
}
|
||||||
|
|
||||||
|
void InternalSetStateFromInput() override
|
||||||
|
{
|
||||||
|
if(_emu->GetSettings()->IsInputEnabled()) {
|
||||||
|
SetPressedState(Buttons::Fire, KeyManager::IsMouseButtonPressed(MouseButton::LeftButton));
|
||||||
|
SetMovement(KeyManager::GetMouseMovement(
|
||||||
|
_emu->GetSettings()->GetVideoConfig().VideoScale,
|
||||||
|
_emu->GetSettings()->GetInputConfig().MouseSensitivity + 1
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Serialize(Serializer& s) override
|
||||||
|
{
|
||||||
|
BaseControlDevice::Serialize(s);
|
||||||
|
s.Stream(_stateBuffer, _currentValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RefreshStateBuffer() override
|
||||||
|
{
|
||||||
|
MouseMovement mov = GetMovement();
|
||||||
|
|
||||||
|
_currentValue += mov.dx;
|
||||||
|
if(_currentValue < 0x54) {
|
||||||
|
_currentValue = 0x54;
|
||||||
|
} else if(_currentValue > 0xF4) {
|
||||||
|
_currentValue = 0xF4;
|
||||||
|
}
|
||||||
|
|
||||||
|
_stateBuffer = _currentValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
ArkanoidController(Emulator* emu, ControllerType type, uint8_t port) : BaseControlDevice(emu, type, port)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t ReadRam(uint16_t addr) override
|
||||||
|
{
|
||||||
|
uint8_t output = 0;
|
||||||
|
if(IsExpansionDevice()) {
|
||||||
|
if(addr == 0x4016) {
|
||||||
|
//Fire button is on port 1
|
||||||
|
if(IsPressed(ArkanoidController::Buttons::Fire)) {
|
||||||
|
output |= 0x02;
|
||||||
|
}
|
||||||
|
} else if(addr == 0x4017) {
|
||||||
|
//Serial data is on port 2
|
||||||
|
output |= ((~_stateBuffer) >> 6) & 0x02;
|
||||||
|
_stateBuffer <<= 1;
|
||||||
|
}
|
||||||
|
} else if(IsCurrentPort(addr)) {
|
||||||
|
output = ((~_stateBuffer) >> 3) & 0x10;
|
||||||
|
_stateBuffer <<= 1;
|
||||||
|
|
||||||
|
if(IsPressed(ArkanoidController::Buttons::Fire)) {
|
||||||
|
output |= 0x08;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteRam(uint16_t addr, uint8_t value) override
|
||||||
|
{
|
||||||
|
StrobeProcessWrite(value);
|
||||||
|
}
|
||||||
|
};
|
66
Core/NES/Input/AsciiTurboFile.h
Normal file
66
Core/NES/Input/AsciiTurboFile.h
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
#pragma once
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "Shared/BaseControlDevice.h"
|
||||||
|
#include "Shared/Emulator.h"
|
||||||
|
#include "Shared/EmuSettings.h"
|
||||||
|
#include "Shared/BatteryManager.h"
|
||||||
|
#include "Shared/Interfaces/IBattery.h"
|
||||||
|
#include "Utilities/Serializer.h"
|
||||||
|
|
||||||
|
class AsciiTurboFile : public BaseControlDevice, public IBattery
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
static constexpr int FileSize = 0x2000;
|
||||||
|
static constexpr int BitCount = FileSize * 8;
|
||||||
|
uint8_t _lastWrite = 0;
|
||||||
|
uint16_t _position = 0;
|
||||||
|
uint8_t _data[AsciiTurboFile::FileSize];
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void Serialize(Serializer& s) override
|
||||||
|
{
|
||||||
|
BaseControlDevice::Serialize(s);
|
||||||
|
ArrayInfo<uint8_t> data { _data, AsciiTurboFile::FileSize };
|
||||||
|
s.Stream(_position, _lastWrite, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
AsciiTurboFile(Emulator* emu) : BaseControlDevice(emu, ControllerType::AsciiTurboFile, BaseControlDevice::ExpDevicePort)
|
||||||
|
{
|
||||||
|
_emu->GetBatteryManager()->LoadBattery(".tf", _data, AsciiTurboFile::FileSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
~AsciiTurboFile()
|
||||||
|
{
|
||||||
|
SaveBattery();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SaveBattery() override
|
||||||
|
{
|
||||||
|
_emu->GetBatteryManager()->SaveBattery(".tf", _data, AsciiTurboFile::FileSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t ReadRam(uint16_t addr) override
|
||||||
|
{
|
||||||
|
if(addr == 0x4017) {
|
||||||
|
return ((_data[_position / 8] >> (_position % 8)) & 0x01) << 2;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteRam(uint16_t addr, uint8_t value) override
|
||||||
|
{
|
||||||
|
if(!(value & 0x02)) {
|
||||||
|
_position = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!(value & 0x04) && (_lastWrite & 0x04)) {
|
||||||
|
//Clock, perform write, increase position
|
||||||
|
_data[_position / 8] &= ~(1 << (_position % 8));
|
||||||
|
_data[_position / 8] |= (value & 0x01) << (_position % 8);
|
||||||
|
_position = (_position + 1) & (AsciiTurboFile::BitCount - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
_lastWrite = value;
|
||||||
|
}
|
||||||
|
};
|
77
Core/NES/Input/BandaiHyperShot.h
Normal file
77
Core/NES/Input/BandaiHyperShot.h
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
#pragma once
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "NES/Input/NesController.h"
|
||||||
|
#include "NES/Input/Zapper.h"
|
||||||
|
#include "NES/NesConsole.h"
|
||||||
|
#include "Shared/KeyManager.h"
|
||||||
|
|
||||||
|
class BandaiHyperShot : public NesController
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
NesConsole* _console;
|
||||||
|
uint32_t _stateBuffer = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
enum ZapperButtons { Fire = 9 };
|
||||||
|
|
||||||
|
bool HasCoordinates() override { return true; }
|
||||||
|
|
||||||
|
string GetKeyNames() override
|
||||||
|
{
|
||||||
|
return NesController::GetKeyNames() + "F";
|
||||||
|
}
|
||||||
|
|
||||||
|
void InternalSetStateFromInput() override
|
||||||
|
{
|
||||||
|
NesController::InternalSetStateFromInput();
|
||||||
|
|
||||||
|
if(_emu->GetSettings()->IsInputEnabled()) {
|
||||||
|
SetPressedState(ZapperButtons::Fire, KeyManager::IsMouseButtonPressed(MouseButton::LeftButton));
|
||||||
|
|
||||||
|
MousePosition pos = KeyManager::GetMousePosition();
|
||||||
|
if(KeyManager::IsMouseButtonPressed(MouseButton::RightButton)) {
|
||||||
|
pos.X = -1;
|
||||||
|
pos.Y = -1;
|
||||||
|
}
|
||||||
|
SetCoordinates(pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsLightFound()
|
||||||
|
{
|
||||||
|
return Zapper::StaticIsLightFound(GetCoordinates(), _console);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Serialize(Serializer& s) override
|
||||||
|
{
|
||||||
|
BaseControlDevice::Serialize(s);
|
||||||
|
s.Stream(_stateBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
BandaiHyperShot(NesConsole* console, KeyMappingSet keyMappings) : NesController(console->GetEmulator(), ControllerType::BandaiHyperShot, BaseControlDevice::ExpDevicePort, keyMappings)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void RefreshStateBuffer() override
|
||||||
|
{
|
||||||
|
_stateBuffer = (uint32_t)ToByte();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t ReadRam(uint16_t addr) override
|
||||||
|
{
|
||||||
|
if(addr == 0x4016) {
|
||||||
|
StrobeProcessRead();
|
||||||
|
uint8_t output = (_stateBuffer & 0x01) << 1;
|
||||||
|
_stateBuffer >>= 1;
|
||||||
|
return output;
|
||||||
|
} else {
|
||||||
|
return (IsLightFound() ? 0 : 0x08) | (IsPressed(ZapperButtons::Fire) ? 0x10 : 0x00);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteRam(uint16_t addr, uint8_t value) override
|
||||||
|
{
|
||||||
|
StrobeProcessWrite(value);
|
||||||
|
}
|
||||||
|
};
|
106
Core/NES/Input/BarcodeBattlerReader.h
Normal file
106
Core/NES/Input/BarcodeBattlerReader.h
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
#pragma once
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "Shared/BaseControlDevice.h"
|
||||||
|
#include "Shared/Emulator.h"
|
||||||
|
#include "Utilities/Serializer.h"
|
||||||
|
#include "NES/Input/IBarcodeReader.h"
|
||||||
|
|
||||||
|
class BarcodeBattlerReader : public BaseControlDevice, public IBarcodeReader
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
static constexpr int StreamSize = 200;
|
||||||
|
uint64_t _newBarcode = 0;
|
||||||
|
uint32_t _newBarcodeDigitCount = 0;
|
||||||
|
|
||||||
|
uint8_t _barcodeStream[BarcodeBattlerReader::StreamSize];
|
||||||
|
uint64_t _insertCycle = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void Serialize(Serializer& s) override
|
||||||
|
{
|
||||||
|
BaseControlDevice::Serialize(s);
|
||||||
|
|
||||||
|
ArrayInfo<uint8_t> bitStream{ _barcodeStream, BarcodeBattlerReader::StreamSize };
|
||||||
|
s.Stream(_newBarcode, _newBarcodeDigitCount, _insertCycle, bitStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsRawString() override
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InitBarcodeStream()
|
||||||
|
{
|
||||||
|
vector<uint8_t> state = GetRawState().State;
|
||||||
|
string barcodeText(state.begin(), state.end());
|
||||||
|
|
||||||
|
//Signature at the end, needed for code to be recognized
|
||||||
|
barcodeText += "EPOCH\xD\xA";
|
||||||
|
//Pad to 20 characters with spaces
|
||||||
|
barcodeText.insert(0, 20 - barcodeText.size(), ' ');
|
||||||
|
|
||||||
|
int pos = 0;
|
||||||
|
vector<uint8_t> bits;
|
||||||
|
for(int i = 0; i < 20; i++) {
|
||||||
|
_barcodeStream[pos++] = 1;
|
||||||
|
for(int j = 0; j < 8; j++) {
|
||||||
|
_barcodeStream[pos++] = ~((barcodeText[i] >> j) & 0x01);
|
||||||
|
}
|
||||||
|
_barcodeStream[pos++] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
BarcodeBattlerReader(Emulator* emu) : BaseControlDevice(emu, ControllerType::BarcodeBattler, BaseControlDevice::ExpDevicePort)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void InternalSetStateFromInput() override
|
||||||
|
{
|
||||||
|
ClearState();
|
||||||
|
|
||||||
|
if(_newBarcodeDigitCount > 0) {
|
||||||
|
string barcodeText = std::to_string(_newBarcode);
|
||||||
|
//Pad 8 or 13 character barcode with 0s at start
|
||||||
|
barcodeText.insert(0, _newBarcodeDigitCount - barcodeText.size(), '0');
|
||||||
|
SetTextState(barcodeText);
|
||||||
|
|
||||||
|
_newBarcode = 0;
|
||||||
|
_newBarcodeDigitCount = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnAfterSetState() override
|
||||||
|
{
|
||||||
|
if(GetRawState().State.size() > 0) {
|
||||||
|
InitBarcodeStream();
|
||||||
|
if(_emu) {
|
||||||
|
_insertCycle = _emu->GetMasterClock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputBarcode(uint64_t barcode, uint32_t digitCount) override
|
||||||
|
{
|
||||||
|
_newBarcode = barcode;
|
||||||
|
_newBarcodeDigitCount = digitCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t ReadRam(uint16_t addr) override
|
||||||
|
{
|
||||||
|
if(addr == 0x4017) {
|
||||||
|
uint64_t elapsedCycles = _emu->GetMasterClock() - _insertCycle;
|
||||||
|
uint32_t cyclesPerBit = _emu->GetMasterClockRate() / 1200;
|
||||||
|
|
||||||
|
uint32_t streamPosition = (uint32_t)(elapsedCycles / cyclesPerBit);
|
||||||
|
if(streamPosition < BarcodeBattlerReader::StreamSize) {
|
||||||
|
return _barcodeStream[streamPosition] << 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteRam(uint16_t addr, uint8_t value) override
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
118
Core/NES/Input/BattleBox.h
Normal file
118
Core/NES/Input/BattleBox.h
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
#pragma once
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "Shared/Emulator.h"
|
||||||
|
#include "Shared/BaseControlDevice.h"
|
||||||
|
#include "Shared/BatteryManager.h"
|
||||||
|
#include "Shared/Interfaces/IBattery.h"
|
||||||
|
#include "Utilities/Serializer.h"
|
||||||
|
|
||||||
|
class BattleBox : public BaseControlDevice, public IBattery
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
static constexpr int FileSize = 0x200;
|
||||||
|
uint8_t _lastWrite = 0;
|
||||||
|
uint8_t _address = 0;
|
||||||
|
uint8_t _chipSelect = 0;
|
||||||
|
uint16_t _data[BattleBox::FileSize/2];
|
||||||
|
uint8_t _output = 0;
|
||||||
|
bool _writeEnabled = false;
|
||||||
|
|
||||||
|
uint8_t _inputBitPosition = 0;
|
||||||
|
uint16_t _inputData = 0;
|
||||||
|
bool _isWrite = false;
|
||||||
|
bool _isRead = false;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void Serialize(Serializer& s) override
|
||||||
|
{
|
||||||
|
BaseControlDevice::Serialize(s);
|
||||||
|
ArrayInfo<uint8_t> data{ (uint8_t*)_data, BattleBox::FileSize };
|
||||||
|
s.Stream(_lastWrite, _address, _chipSelect, _output, _writeEnabled, _inputBitPosition, _isWrite, _isRead, _inputData, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
BattleBox(Emulator* emu) : BaseControlDevice(emu, ControllerType::BattleBox, BaseControlDevice::ExpDevicePort)
|
||||||
|
{
|
||||||
|
_emu->GetBatteryManager()->LoadBattery(".bb", (uint8_t*)_data, BattleBox::FileSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
~BattleBox()
|
||||||
|
{
|
||||||
|
SaveBattery();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SaveBattery() override
|
||||||
|
{
|
||||||
|
_emu->GetBatteryManager()->SaveBattery(".bb", (uint8_t*)_data, BattleBox::FileSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t ReadRam(uint16_t addr) override
|
||||||
|
{
|
||||||
|
if(addr == 0x4017) {
|
||||||
|
if(_lastWrite & 0x01) {
|
||||||
|
_chipSelect ^= 0x01;
|
||||||
|
_inputData = 0;
|
||||||
|
_inputBitPosition = 0;
|
||||||
|
}
|
||||||
|
_output ^= 0x01;
|
||||||
|
|
||||||
|
uint8_t readBit = 0;
|
||||||
|
if(_isRead) {
|
||||||
|
readBit = ((_data[(_chipSelect ? 0x80 : 0) | _address] >> _inputBitPosition) & 0x01) << 3;
|
||||||
|
}
|
||||||
|
uint8_t writeBit = (_output << 4);
|
||||||
|
return readBit | writeBit;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteRam(uint16_t addr, uint8_t value) override
|
||||||
|
{
|
||||||
|
if(value & 0x01 && !(_lastWrite & 0x01)) {
|
||||||
|
//Clock
|
||||||
|
_inputData &= ~(1 << _inputBitPosition);
|
||||||
|
_inputData |= (_output << _inputBitPosition);
|
||||||
|
_inputBitPosition++;
|
||||||
|
|
||||||
|
if(_inputBitPosition > 15) {
|
||||||
|
if(_isWrite) {
|
||||||
|
_data[(_chipSelect ? 0x80 : 0) | _address] = _inputData;
|
||||||
|
_isWrite = false;
|
||||||
|
} else {
|
||||||
|
_isRead = false;
|
||||||
|
|
||||||
|
//done reading addr/command or write data
|
||||||
|
uint8_t address = (_inputData & 0x7F);
|
||||||
|
|
||||||
|
uint8_t cmd = ((_inputData & 0x7F00) >> 8) ^ 0x7F;
|
||||||
|
switch(cmd) {
|
||||||
|
case 0x01:
|
||||||
|
//read
|
||||||
|
_address = address;
|
||||||
|
_isRead = true;
|
||||||
|
break;
|
||||||
|
case 0x06:
|
||||||
|
//program
|
||||||
|
if(_writeEnabled) {
|
||||||
|
_address = address;
|
||||||
|
_isWrite = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x0C:
|
||||||
|
//chip erase
|
||||||
|
if(_writeEnabled) {
|
||||||
|
memset(_data, 0, BattleBox::FileSize);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x0D: break; //busy monitor
|
||||||
|
case 0x09: _writeEnabled = true; break; //erase/write enable
|
||||||
|
case 0x0B: _writeEnabled = false; break; //erase/write disable
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_inputBitPosition = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_lastWrite = value;
|
||||||
|
}
|
||||||
|
};
|
64
Core/NES/Input/ExcitingBoxingController.h
Normal file
64
Core/NES/Input/ExcitingBoxingController.h
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
#pragma once
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "Shared/BaseControlDevice.h"
|
||||||
|
#include "Utilities/Serializer.h"
|
||||||
|
|
||||||
|
class Emulator;
|
||||||
|
|
||||||
|
class ExcitingBoxingController : public BaseControlDevice
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
uint8_t _selectedSensors = 0;
|
||||||
|
enum Buttons { LeftHook = 0, MoveRight, MoveLeft, RightHook, LeftJab, HitBody, RightJab, Straight };
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void Serialize(Serializer& s) override
|
||||||
|
{
|
||||||
|
BaseControlDevice::Serialize(s);
|
||||||
|
s.Stream(_selectedSensors);
|
||||||
|
}
|
||||||
|
|
||||||
|
string GetKeyNames() override
|
||||||
|
{
|
||||||
|
return "HRLhJBjS";
|
||||||
|
}
|
||||||
|
|
||||||
|
void InternalSetStateFromInput() override
|
||||||
|
{
|
||||||
|
for(KeyMapping keyMapping : _keyMappings) {
|
||||||
|
for(int i = 0; i < 8; i++) {
|
||||||
|
SetPressedState(i, keyMapping.CustomKeys[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
ExcitingBoxingController(Emulator* emu, KeyMappingSet keyMappings) : BaseControlDevice(emu, ControllerType::ExcitingBoxing, BaseControlDevice::ExpDevicePort, keyMappings)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t ReadRam(uint16_t addr) override
|
||||||
|
{
|
||||||
|
if(addr == 0x4017) {
|
||||||
|
if(_selectedSensors == 0) {
|
||||||
|
return
|
||||||
|
(IsPressed(ExcitingBoxingController::Buttons::LeftHook) ? 0 : 0x02) |
|
||||||
|
(IsPressed(ExcitingBoxingController::Buttons::MoveRight) ? 0 : 0x04) |
|
||||||
|
(IsPressed(ExcitingBoxingController::Buttons::MoveLeft) ? 0 : 0x08) |
|
||||||
|
(IsPressed(ExcitingBoxingController::Buttons::RightHook) ? 0 : 0x10);
|
||||||
|
} else {
|
||||||
|
return
|
||||||
|
(IsPressed(ExcitingBoxingController::Buttons::LeftJab) ? 0 : 0x02) |
|
||||||
|
(IsPressed(ExcitingBoxingController::Buttons::HitBody) ? 0 : 0x04) |
|
||||||
|
(IsPressed(ExcitingBoxingController::Buttons::RightJab) ? 0 : 0x08) |
|
||||||
|
(IsPressed(ExcitingBoxingController::Buttons::Straight) ? 0 : 0x10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteRam(uint16_t addr, uint8_t value) override
|
||||||
|
{
|
||||||
|
_selectedSensors = (value & 0x02) >> 1;
|
||||||
|
}
|
||||||
|
};
|
141
Core/NES/Input/FamilyBasicDataRecorder.h
Normal file
141
Core/NES/Input/FamilyBasicDataRecorder.h
Normal file
|
@ -0,0 +1,141 @@
|
||||||
|
#pragma once
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "../Utilities/Base64.h"
|
||||||
|
#include "Shared/BaseControlDevice.h"
|
||||||
|
#include "Shared/Emulator.h"
|
||||||
|
#include "Utilities/Serializer.h"
|
||||||
|
|
||||||
|
class FamilyBasicDataRecorder : public BaseControlDevice
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
static constexpr int32_t SamplingRate = 88;
|
||||||
|
vector<uint8_t> _data;
|
||||||
|
vector<uint8_t> _fileData;
|
||||||
|
bool _enabled = false;
|
||||||
|
bool _isPlaying = false;
|
||||||
|
uint64_t _cycle = 0;
|
||||||
|
|
||||||
|
bool _isRecording = false;
|
||||||
|
string _recordFilePath;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void Serialize(Serializer& s) override
|
||||||
|
{
|
||||||
|
BaseControlDevice::Serialize(s);
|
||||||
|
VectorInfo<uint8_t> data { &_data };
|
||||||
|
s.Stream(_enabled, _isPlaying, _cycle, data);
|
||||||
|
|
||||||
|
if(!s.IsSaving() && _isRecording) {
|
||||||
|
StopRecording();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsRawString() override
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InternalSetStateFromInput() override
|
||||||
|
{
|
||||||
|
if(_fileData.size() > 0) {
|
||||||
|
SetTextState(Base64::Encode(_fileData));
|
||||||
|
_fileData.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
FamilyBasicDataRecorder(Emulator* emu) : BaseControlDevice(emu, ControllerType::None, BaseControlDevice::ExpDevicePort2)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
~FamilyBasicDataRecorder()
|
||||||
|
{
|
||||||
|
if(_isRecording) {
|
||||||
|
StopRecording();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnAfterSetState() override
|
||||||
|
{
|
||||||
|
if(GetRawState().State.size() > 0) {
|
||||||
|
_data = Base64::Decode(GetTextState());
|
||||||
|
_cycle = _emu->GetMasterClock();
|
||||||
|
_isPlaying = true;
|
||||||
|
_isRecording = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoadFromFile(VirtualFile file)
|
||||||
|
{
|
||||||
|
if(file.IsValid()) {
|
||||||
|
vector<uint8_t> fileData;
|
||||||
|
file.ReadFile(fileData);
|
||||||
|
_fileData = fileData;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsRecording()
|
||||||
|
{
|
||||||
|
return _isRecording;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StartRecording(string filePath)
|
||||||
|
{
|
||||||
|
_isPlaying = false;
|
||||||
|
_recordFilePath = filePath;
|
||||||
|
_data.clear();
|
||||||
|
_cycle = _emu->GetMasterClock();
|
||||||
|
_isRecording = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StopRecording()
|
||||||
|
{
|
||||||
|
_isRecording = false;
|
||||||
|
|
||||||
|
vector<uint8_t> fileData;
|
||||||
|
|
||||||
|
int bitPos = 0;
|
||||||
|
uint8_t currentByte = 0;
|
||||||
|
for(uint8_t bitValue : _data) {
|
||||||
|
currentByte |= (bitValue & 0x01) << bitPos;
|
||||||
|
bitPos = (bitPos + 1) % 8;
|
||||||
|
if(bitPos == 0) {
|
||||||
|
fileData.push_back(currentByte);
|
||||||
|
currentByte = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ofstream out(_recordFilePath, ios::binary);
|
||||||
|
if(out) {
|
||||||
|
out.write((char*)fileData.data(), fileData.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t ReadRam(uint16_t addr) override
|
||||||
|
{
|
||||||
|
if(addr == 0x4016 && _isPlaying) {
|
||||||
|
uint32_t readPos = (uint32_t)((_emu->GetMasterClock() - _cycle) / FamilyBasicDataRecorder::SamplingRate);
|
||||||
|
|
||||||
|
if((uint32_t)_data.size() > readPos / 8) {
|
||||||
|
uint8_t value = ((_data[readPos / 8] >> (readPos % 8)) & 0x01) << 1;
|
||||||
|
return _enabled ? value : 0;
|
||||||
|
} else {
|
||||||
|
_isPlaying = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteRam(uint16_t addr, uint8_t value) override
|
||||||
|
{
|
||||||
|
_enabled = (value & 0x04) != 0;
|
||||||
|
|
||||||
|
if(_isRecording) {
|
||||||
|
while(_emu->GetMasterClock() - _cycle > FamilyBasicDataRecorder::SamplingRate) {
|
||||||
|
_data.push_back(value & 0x01);
|
||||||
|
_cycle += 88;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
123
Core/NES/Input/FamilyBasicKeyboard.h
Normal file
123
Core/NES/Input/FamilyBasicKeyboard.h
Normal file
|
@ -0,0 +1,123 @@
|
||||||
|
#pragma once
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "Shared/BaseControlDevice.h"
|
||||||
|
#include "Utilities/Serializer.h"
|
||||||
|
|
||||||
|
class FamilyBasicKeyboard : public BaseControlDevice
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
uint8_t _row = 0;
|
||||||
|
uint8_t _column = 0;
|
||||||
|
bool _enabled = false;
|
||||||
|
|
||||||
|
const uint32_t _keyMatrix[72] = {
|
||||||
|
F8, Return, LeftBracket, RightBracket,
|
||||||
|
Kana, RightShift, Yen, Stop,
|
||||||
|
F7, AtSign, Colon, SemiColon,
|
||||||
|
Underscore, Slash, Minus, Caret,
|
||||||
|
F6, O, L, K,
|
||||||
|
Dot, Comma, P, Num0,
|
||||||
|
F5, I, U, J,
|
||||||
|
M, N, Num9, Num8,
|
||||||
|
F4, Y, G, H,
|
||||||
|
B, V, Num7, Num6,
|
||||||
|
F3, T, R, D,
|
||||||
|
F, C, Num5, Num4,
|
||||||
|
F2, W, S, A,
|
||||||
|
X, Z, E, Num3,
|
||||||
|
F1, Esc, Q, Ctrl,
|
||||||
|
LeftShift, Grph, Num1, Num2,
|
||||||
|
ClrHome, Up, Right, Left,
|
||||||
|
Down, Space, Del, Ins
|
||||||
|
};
|
||||||
|
|
||||||
|
enum Buttons
|
||||||
|
{
|
||||||
|
A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z,
|
||||||
|
Num0, Num1, Num2, Num3, Num4, Num5, Num6, Num7, Num8, Num9,
|
||||||
|
Return, Space, Del, Ins, Esc,
|
||||||
|
Ctrl, RightShift, LeftShift,
|
||||||
|
RightBracket, LeftBracket,
|
||||||
|
Up, Down, Left, Right,
|
||||||
|
Dot, Comma, Colon, SemiColon, Underscore, Slash, Minus, Caret,
|
||||||
|
F1, F2, F3, F4, F5, F6, F7, F8,
|
||||||
|
Yen, Stop, AtSign, Grph, ClrHome, Kana
|
||||||
|
};
|
||||||
|
|
||||||
|
string GetKeyNames() override
|
||||||
|
{
|
||||||
|
return "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789rsdiecSs[]udlrd,:;_/-^12345678ysagck";
|
||||||
|
}
|
||||||
|
|
||||||
|
void InternalSetStateFromInput() override
|
||||||
|
{
|
||||||
|
//TODO
|
||||||
|
bool allowInput = false; // _emu->GetSettings()->IsKeyboardMode();
|
||||||
|
|
||||||
|
if(allowInput) {
|
||||||
|
for(KeyMapping keyMapping : _keyMappings) {
|
||||||
|
for(int i = 0; i < 72; i++) {
|
||||||
|
SetPressedState(i, keyMapping.CustomKeys[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t GetActiveKeys(uint8_t row, uint8_t column)
|
||||||
|
{
|
||||||
|
if(row == 9) {
|
||||||
|
//10th row has no keys
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t result = 0;
|
||||||
|
uint32_t baseIndex = row * 8 + (column ? 4 : 0);
|
||||||
|
for(int i = 0; i < 4; i++) {
|
||||||
|
if(IsPressed(_keyMatrix[baseIndex + i])) {
|
||||||
|
result |= 0x10;
|
||||||
|
}
|
||||||
|
result >>= 1;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void Serialize(Serializer& s) override
|
||||||
|
{
|
||||||
|
BaseControlDevice::Serialize(s);
|
||||||
|
s.Stream(_row, _column, _enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
FamilyBasicKeyboard(Emulator* emu, KeyMappingSet keyMappings) : BaseControlDevice(emu, ControllerType::FamilyBasicKeyboard, BaseControlDevice::ExpDevicePort, keyMappings)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t ReadRam(uint16_t addr) override
|
||||||
|
{
|
||||||
|
if(addr == 0x4017) {
|
||||||
|
if(_enabled) {
|
||||||
|
return ((~GetActiveKeys(_row, _column)) << 1) & 0x1E;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteRam(uint16_t addr, uint8_t value) override
|
||||||
|
{
|
||||||
|
uint8_t prevColumn = _column;
|
||||||
|
_column = (value & 0x02) >> 1;
|
||||||
|
if(!_column && prevColumn) {
|
||||||
|
//"Incrementing the row from the (keyless) 10th row will cause it to wrap back to the first row."
|
||||||
|
_row = (_row + 1) % 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(value & 0x01) {
|
||||||
|
_row = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
_enabled = (value & 0x04) != 0;
|
||||||
|
}
|
||||||
|
};
|
46
Core/NES/Input/FamilyMatTrainer.h
Normal file
46
Core/NES/Input/FamilyMatTrainer.h
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
#pragma once
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "NES/Input/PowerPad.h"
|
||||||
|
#include "Utilities/Serializer.h"
|
||||||
|
|
||||||
|
class FamilyMatTrainer : public PowerPad
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
uint8_t _ignoreRows = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void Serialize(Serializer& s) override
|
||||||
|
{
|
||||||
|
BaseControlDevice::Serialize(s);
|
||||||
|
s.Stream(_ignoreRows);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
FamilyMatTrainer(Emulator* emu, KeyMappingSet keyMappings) : PowerPad(emu, ControllerType::FamilyTrainerMat, BaseControlDevice::ExpDevicePort, keyMappings)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t ReadRam(uint16_t addr) override
|
||||||
|
{
|
||||||
|
uint8_t output = 0;
|
||||||
|
if(addr == 0x4017) {
|
||||||
|
uint8_t pressedKeys[4] = {};
|
||||||
|
for(int j = 0; j < 3; j++) {
|
||||||
|
if((_ignoreRows >> (2 - j)) & 0x01) {
|
||||||
|
//Ignore this row
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for(int i = 0; i < 4; i++) {
|
||||||
|
pressedKeys[i] |= IsPressed(j * 4 + i) ? 1 : 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
output = ~((pressedKeys[0] << 4) | (pressedKeys[1] << 3) | (pressedKeys[2] << 2) | (pressedKeys[3] << 1)) & 0x1E;
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteRam(uint16_t addr, uint8_t value) override
|
||||||
|
{
|
||||||
|
_ignoreRows = value & 0x07;
|
||||||
|
}
|
||||||
|
};
|
50
Core/NES/Input/FourScore.h
Normal file
50
Core/NES/Input/FourScore.h
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
#pragma once
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "Shared/BaseControlDevice.h"
|
||||||
|
#include "Utilities/Serializer.h"
|
||||||
|
|
||||||
|
class FourScore : public BaseControlDevice
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
uint32_t _signature4016 = 0;
|
||||||
|
uint32_t _signature4017 = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void Serialize(Serializer &s) override
|
||||||
|
{
|
||||||
|
BaseControlDevice::Serialize(s);
|
||||||
|
s.Stream(_signature4016, _signature4017);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RefreshStateBuffer() override
|
||||||
|
{
|
||||||
|
//Signature for port 0 = 0x10, reversed bit order => 0x08
|
||||||
|
//Signature for port 1 = 0x20, reversed bit order => 0x04
|
||||||
|
_signature4016 = (0x08 << 16);
|
||||||
|
_signature4017 = (0x04 << 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
FourScore(Emulator* emu) : BaseControlDevice(emu, ControllerType::FourScore, BaseControlDevice::ExpDevicePort)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t ReadRam(uint16_t addr) override
|
||||||
|
{
|
||||||
|
StrobeProcessRead();
|
||||||
|
uint8_t output = 0;
|
||||||
|
if(addr == 0x4016) {
|
||||||
|
output = _signature4016 & 0x01;
|
||||||
|
_signature4016 >>= 1;
|
||||||
|
} else if(addr == 0x4017) {
|
||||||
|
output = _signature4017 & 0x01;
|
||||||
|
_signature4017 >>= 1;
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteRam(uint16_t addr, uint8_t value) override
|
||||||
|
{
|
||||||
|
StrobeProcessWrite(value);
|
||||||
|
}
|
||||||
|
};
|
54
Core/NES/Input/HoriTrack.h
Normal file
54
Core/NES/Input/HoriTrack.h
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
#pragma once
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "NES/Input/NesController.h"
|
||||||
|
#include "Shared/KeyManager.h"
|
||||||
|
|
||||||
|
class HoriTrack : public NesController
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
bool HasCoordinates() override { return true; }
|
||||||
|
|
||||||
|
void InternalSetStateFromInput() override
|
||||||
|
{
|
||||||
|
NesController::InternalSetStateFromInput();
|
||||||
|
SetPressedState(NesController::Buttons::A, KeyManager::IsMouseButtonPressed(MouseButton::LeftButton));
|
||||||
|
SetPressedState(NesController::Buttons::B, KeyManager::IsMouseButtonPressed(MouseButton::RightButton));
|
||||||
|
SetMovement(KeyManager::GetMouseMovement(
|
||||||
|
_emu->GetSettings()->GetVideoConfig().VideoScale,
|
||||||
|
_emu->GetSettings()->GetInputConfig().MouseSensitivity + 1
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
HoriTrack(Emulator* emu, KeyMappingSet keyMappings) : NesController(emu, ControllerType::HoriTrack, BaseControlDevice::ExpDevicePort, keyMappings)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t ReadRam(uint16_t addr) override
|
||||||
|
{
|
||||||
|
uint8_t output = 0;
|
||||||
|
if(addr == 0x4016) {
|
||||||
|
StrobeProcessRead();
|
||||||
|
output = (_stateBuffer & 0x01) << 1;
|
||||||
|
_stateBuffer >>= 1;
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RefreshStateBuffer() override
|
||||||
|
{
|
||||||
|
MouseMovement mov = GetMovement();
|
||||||
|
|
||||||
|
mov.dx = std::max(-8, std::min((int)mov.dx, 7));
|
||||||
|
mov.dy = std::max(-8, std::min((int)mov.dy, 7));
|
||||||
|
|
||||||
|
mov.dx = ((mov.dx & 0x08) >> 3) | ((mov.dx & 0x04) >> 1) | ((mov.dx & 0x02) << 1) | ((mov.dx & 0x01) << 3);
|
||||||
|
mov.dy = ((mov.dy & 0x08) >> 3) | ((mov.dy & 0x04) >> 1) | ((mov.dy & 0x02) << 1) | ((mov.dy & 0x01) << 3);
|
||||||
|
|
||||||
|
uint8_t byte1 = (~mov.dy & 0x0F) | ((~mov.dx & 0x0F) << 4);
|
||||||
|
uint8_t byte2 = 0x09;
|
||||||
|
|
||||||
|
NesController::RefreshStateBuffer();
|
||||||
|
_stateBuffer = (_stateBuffer & 0xFF) | (byte1 << 8) | (byte2 << 16);
|
||||||
|
}
|
||||||
|
};
|
8
Core/NES/Input/IBarcodeReader.h
Normal file
8
Core/NES/Input/IBarcodeReader.h
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
#pragma once
|
||||||
|
#include "stdafx.h"
|
||||||
|
|
||||||
|
class IBarcodeReader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void InputBarcode(uint64_t barcode, uint32_t digitCount) = 0;
|
||||||
|
};
|
99
Core/NES/Input/JissenMahjongController.h
Normal file
99
Core/NES/Input/JissenMahjongController.h
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
#pragma once
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "Shared/BaseControlDevice.h"
|
||||||
|
#include "Utilities/Serializer.h"
|
||||||
|
|
||||||
|
class JissenMahjongController : public BaseControlDevice
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
uint8_t _row = 0;
|
||||||
|
uint32_t _stateBuffer = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
enum Buttons { A = 0, B, C, D, E, F, G, H, I, J, K, L, M, N, Select, Start, Kan, Pon, Chii, Riichi, Ron };
|
||||||
|
|
||||||
|
string GetKeyNames() override
|
||||||
|
{
|
||||||
|
return "ABCDEFGHIJKLMNSTkpcir";
|
||||||
|
}
|
||||||
|
|
||||||
|
void InternalSetStateFromInput() override
|
||||||
|
{
|
||||||
|
for(KeyMapping keyMapping : _keyMappings) {
|
||||||
|
for(int i = 0; i < 21; i++) {
|
||||||
|
SetPressedState(i, keyMapping.CustomKeys[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Serialize(Serializer& s) override
|
||||||
|
{
|
||||||
|
BaseControlDevice::Serialize(s);
|
||||||
|
s.Stream(_row, _stateBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
JissenMahjongController(Emulator* emu, KeyMappingSet keyMappings) : BaseControlDevice(emu, ControllerType::JissenMahjong, BaseControlDevice::ExpDevicePort, keyMappings)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t ReadRam(uint16_t addr) override
|
||||||
|
{
|
||||||
|
if(addr == 0x4017) {
|
||||||
|
StrobeProcessRead();
|
||||||
|
uint8_t value = (_stateBuffer & 0x01) << 1;
|
||||||
|
_stateBuffer >>= 1;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RefreshStateBuffer() override
|
||||||
|
{
|
||||||
|
switch(_row) {
|
||||||
|
default:
|
||||||
|
case 0:
|
||||||
|
_stateBuffer = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
_stateBuffer =
|
||||||
|
(IsPressed(JissenMahjongController::Buttons::N) ? 0x04 : 0) |
|
||||||
|
(IsPressed(JissenMahjongController::Buttons::M) ? 0x08 : 0) |
|
||||||
|
(IsPressed(JissenMahjongController::Buttons::L) ? 0x10 : 0) |
|
||||||
|
(IsPressed(JissenMahjongController::Buttons::K) ? 0x20 : 0) |
|
||||||
|
(IsPressed(JissenMahjongController::Buttons::J) ? 0x40 : 0) |
|
||||||
|
(IsPressed(JissenMahjongController::Buttons::I) ? 0x80 : 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
_stateBuffer =
|
||||||
|
(IsPressed(JissenMahjongController::Buttons::H) ? 0x01 : 0) |
|
||||||
|
(IsPressed(JissenMahjongController::Buttons::G) ? 0x02 : 0) |
|
||||||
|
(IsPressed(JissenMahjongController::Buttons::F) ? 0x04 : 0) |
|
||||||
|
(IsPressed(JissenMahjongController::Buttons::E) ? 0x08 : 0) |
|
||||||
|
(IsPressed(JissenMahjongController::Buttons::D) ? 0x10 : 0) |
|
||||||
|
(IsPressed(JissenMahjongController::Buttons::C) ? 0x20 : 0) |
|
||||||
|
(IsPressed(JissenMahjongController::Buttons::B) ? 0x40 : 0) |
|
||||||
|
(IsPressed(JissenMahjongController::Buttons::A) ? 0x80 : 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
_stateBuffer =
|
||||||
|
(IsPressed(JissenMahjongController::Buttons::Ron) ? 0x02 : 0) |
|
||||||
|
(IsPressed(JissenMahjongController::Buttons::Riichi) ? 0x04 : 0) |
|
||||||
|
(IsPressed(JissenMahjongController::Buttons::Chii) ? 0x08 : 0) |
|
||||||
|
(IsPressed(JissenMahjongController::Buttons::Pon) ? 0x10 : 0) |
|
||||||
|
(IsPressed(JissenMahjongController::Buttons::Kan) ? 0x20 : 0) |
|
||||||
|
(IsPressed(JissenMahjongController::Buttons::Start) ? 0x40 : 0) |
|
||||||
|
(IsPressed(JissenMahjongController::Buttons::Select) ? 0x80 : 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteRam(uint16_t addr, uint8_t value) override
|
||||||
|
{
|
||||||
|
_row = (value & 0x6) >> 1;
|
||||||
|
StrobeProcessWrite(value);
|
||||||
|
}
|
||||||
|
};
|
86
Core/NES/Input/KonamiHyperShot.h
Normal file
86
Core/NES/Input/KonamiHyperShot.h
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
#pragma once
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "Shared/BaseControlDevice.h"
|
||||||
|
#include "Shared/Emulator.h"
|
||||||
|
#include "Utilities/Serializer.h"
|
||||||
|
|
||||||
|
class KonamiHyperShot : public BaseControlDevice
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
bool _enableP1 = true;
|
||||||
|
bool _enableP2 = true;
|
||||||
|
uint32_t _p1TurboSpeed;
|
||||||
|
uint32_t _p2TurboSpeed;
|
||||||
|
vector<KeyMapping> _p2KeyMappings;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
enum Buttons { Player1Run = 0, Player1Jump, Player2Run, Player2Jump };
|
||||||
|
|
||||||
|
string GetKeyNames() override
|
||||||
|
{
|
||||||
|
return "RJrj";
|
||||||
|
}
|
||||||
|
|
||||||
|
void InternalSetStateFromInput() override
|
||||||
|
{
|
||||||
|
for(KeyMapping keyMapping : _keyMappings) {
|
||||||
|
SetPressedState(Buttons::Player1Jump, keyMapping.A);
|
||||||
|
SetPressedState(Buttons::Player1Run, keyMapping.B);
|
||||||
|
|
||||||
|
uint8_t turboFreq = 1 << (4 - _p1TurboSpeed);
|
||||||
|
bool turboOn = (uint8_t)(_emu->GetFrameCount() % turboFreq) < turboFreq / 2;
|
||||||
|
if(turboOn) {
|
||||||
|
SetPressedState(Buttons::Player1Jump, keyMapping.TurboA);
|
||||||
|
SetPressedState(Buttons::Player1Run, keyMapping.TurboB);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(KeyMapping keyMapping : _p2KeyMappings) {
|
||||||
|
SetPressedState(Buttons::Player2Jump, keyMapping.A);
|
||||||
|
SetPressedState(Buttons::Player2Run, keyMapping.B);
|
||||||
|
|
||||||
|
uint8_t turboFreq = 1 << (4 - _p2TurboSpeed);
|
||||||
|
bool turboOn = (uint8_t)(_emu->GetFrameCount() % turboFreq) < turboFreq / 2;
|
||||||
|
if(turboOn) {
|
||||||
|
SetPressedState(Buttons::Player2Jump, keyMapping.TurboA);
|
||||||
|
SetPressedState(Buttons::Player2Run, keyMapping.TurboB);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Serialize(Serializer& s) override
|
||||||
|
{
|
||||||
|
BaseControlDevice::Serialize(s);
|
||||||
|
s.Stream(_enableP1, _enableP2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
KonamiHyperShot(Emulator* emu, KeyMappingSet p1, KeyMappingSet p2) : BaseControlDevice(emu, ControllerType::KonamiHyperShot, BaseControlDevice::ExpDevicePort, p1)
|
||||||
|
{
|
||||||
|
_p1TurboSpeed = p1.TurboSpeed;
|
||||||
|
_p2TurboSpeed = p2.TurboSpeed;
|
||||||
|
_p2KeyMappings = p2.GetKeyMappingArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t ReadRam(uint16_t addr) override
|
||||||
|
{
|
||||||
|
uint8_t output = 0;
|
||||||
|
if(addr == 0x4017) {
|
||||||
|
if(_enableP1) {
|
||||||
|
output |= IsPressed(KonamiHyperShot::Buttons::Player1Jump) ? 0x02 : 0;
|
||||||
|
output |= IsPressed(KonamiHyperShot::Buttons::Player1Run) ? 0x04 : 0;
|
||||||
|
}
|
||||||
|
if(_enableP2) {
|
||||||
|
output |= IsPressed(KonamiHyperShot::Buttons::Player2Jump) ? 0x08 : 0;
|
||||||
|
output |= IsPressed(KonamiHyperShot::Buttons::Player2Run) ? 0x10 : 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteRam(uint16_t addr, uint8_t value) override
|
||||||
|
{
|
||||||
|
_enableP2 = (value & 0x02) == 0;
|
||||||
|
_enableP1 = (value & 0x04) == 0;
|
||||||
|
}
|
||||||
|
};
|
|
@ -89,11 +89,10 @@ protected:
|
||||||
public:
|
public:
|
||||||
enum Buttons { Up = 0, Down, Left, Right, Start, Select, B, A, Microphone };
|
enum Buttons { Up = 0, Down, Left, Right, Start, Select, B, A, Microphone };
|
||||||
|
|
||||||
NesController(Emulator* emu, uint8_t port, KeyMappingSet keyMappings) : BaseControlDevice(emu, port, keyMappings)
|
NesController(Emulator* emu, ControllerType type, uint8_t port, KeyMappingSet keyMappings) : BaseControlDevice(emu, type, port, keyMappings)
|
||||||
{
|
{
|
||||||
_turboSpeed = keyMappings.TurboSpeed;
|
_turboSpeed = keyMappings.TurboSpeed;
|
||||||
_microphoneEnabled = false;
|
_microphoneEnabled = port == 1 && type == ControllerType::FamicomController;
|
||||||
//_microphoneEnabled = port == 1 && _console->GetSettings()->GetConsoleType() == ConsoleType::Famicom;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t ToByte()
|
uint8_t ToByte()
|
||||||
|
|
82
Core/NES/Input/OekaKidsTablet.h
Normal file
82
Core/NES/Input/OekaKidsTablet.h
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
#pragma once
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "Shared/BaseControlDevice.h"
|
||||||
|
#include "Shared/Emulator.h"
|
||||||
|
#include "Shared/EmuSettings.h"
|
||||||
|
#include "Shared/KeyManager.h"
|
||||||
|
#include "Utilities/Serializer.h"
|
||||||
|
|
||||||
|
class OekaKidsTablet : public BaseControlDevice
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
bool _strobe = false;
|
||||||
|
bool _shift = false;
|
||||||
|
uint32_t _stateBuffer = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
enum Buttons { Click, Touch };
|
||||||
|
bool HasCoordinates() override { return true; }
|
||||||
|
|
||||||
|
string GetKeyNames() override
|
||||||
|
{
|
||||||
|
return "CT";
|
||||||
|
}
|
||||||
|
|
||||||
|
void InternalSetStateFromInput() override
|
||||||
|
{
|
||||||
|
if(_emu->GetSettings()->IsInputEnabled()) {
|
||||||
|
MousePosition pos = KeyManager::GetMousePosition();
|
||||||
|
SetPressedState(Buttons::Click, KeyManager::IsMouseButtonPressed(MouseButton::LeftButton));
|
||||||
|
SetPressedState(Buttons::Touch, pos.Y >= 48 || KeyManager::IsMouseButtonPressed(MouseButton::LeftButton));
|
||||||
|
SetCoordinates(pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Serialize(Serializer& s) override
|
||||||
|
{
|
||||||
|
BaseControlDevice::Serialize(s);
|
||||||
|
s.Stream(_strobe, _shift, _stateBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
OekaKidsTablet(Emulator* emu) : BaseControlDevice(emu, ControllerType::OekaKidsTablet, BaseControlDevice::ExpDevicePort)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t ReadRam(uint16_t addr) override
|
||||||
|
{
|
||||||
|
if(addr == 0x4017) {
|
||||||
|
if(_strobe) {
|
||||||
|
if(_shift) {
|
||||||
|
return (_stateBuffer & 0x40000) ? 0x00 : 0x08;
|
||||||
|
} else {
|
||||||
|
return 0x04;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return 0x00;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteRam(uint16_t addr, uint8_t value) override
|
||||||
|
{
|
||||||
|
_strobe = (value & 0x01) == 0x01;
|
||||||
|
bool shift = ((value >> 1) & 0x01) == 0x01;
|
||||||
|
|
||||||
|
if(_strobe) {
|
||||||
|
if(!_shift && shift) {
|
||||||
|
_stateBuffer <<= 1;
|
||||||
|
}
|
||||||
|
_shift = shift;
|
||||||
|
} else {
|
||||||
|
MousePosition pos = GetCoordinates();
|
||||||
|
|
||||||
|
uint8_t xPosition = (uint8_t)((double)std::max(0, pos.X + 8) / 256.0 * 240);
|
||||||
|
uint8_t yPosition = (uint8_t)((double)std::max(0, pos.Y - 14) / 240.0 * 256);
|
||||||
|
|
||||||
|
_stateBuffer = (xPosition << 10) | (yPosition << 2) | (IsPressed(OekaKidsTablet::Buttons::Touch) ? 0x02 : 0x00) | (IsPressed(OekaKidsTablet::Buttons::Click) ? 0x01 : 0x00);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
60
Core/NES/Input/PachinkoController.h
Normal file
60
Core/NES/Input/PachinkoController.h
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
#pragma once
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "NES/Input/NesController.h"
|
||||||
|
|
||||||
|
class PachinkoController : public NesController
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
uint8_t _analogData = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
enum PachinkoButtons { Press = 8, Release = 9 };
|
||||||
|
|
||||||
|
void InternalSetStateFromInput() override
|
||||||
|
{
|
||||||
|
NesController::InternalSetStateFromInput();
|
||||||
|
|
||||||
|
for(KeyMapping keyMapping : _keyMappings) {
|
||||||
|
SetPressedState(PachinkoButtons::Press, keyMapping.CustomKeys[0]);
|
||||||
|
SetPressedState(PachinkoButtons::Release, keyMapping.CustomKeys[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
PachinkoController(Emulator* emu, KeyMappingSet keyMappings) : NesController(emu, ControllerType::Pachinko, BaseControlDevice::ExpDevicePort, keyMappings)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t ReadRam(uint16_t addr) override
|
||||||
|
{
|
||||||
|
uint8_t output = 0;
|
||||||
|
if(addr == 0x4016) {
|
||||||
|
StrobeProcessRead();
|
||||||
|
output = (_stateBuffer & 0x01) << 1;
|
||||||
|
_stateBuffer >>= 1;
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RefreshStateBuffer() override
|
||||||
|
{
|
||||||
|
if(_analogData < 63 && IsPressed(PachinkoController::PachinkoButtons::Press)) {
|
||||||
|
_analogData++;
|
||||||
|
} else if(_analogData > 0 && IsPressed(PachinkoController::PachinkoButtons::Release)) {
|
||||||
|
_analogData--;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t analogData =
|
||||||
|
((_analogData & 0x01) << 7) |
|
||||||
|
((_analogData & 0x02) << 5) |
|
||||||
|
((_analogData & 0x04) << 3) |
|
||||||
|
((_analogData & 0x08) << 1) |
|
||||||
|
((_analogData & 0x10) >> 1) |
|
||||||
|
((_analogData & 0x20) >> 3) |
|
||||||
|
((_analogData & 0x40) >> 5) |
|
||||||
|
((_analogData & 0x80) >> 7);
|
||||||
|
|
||||||
|
NesController::RefreshStateBuffer();
|
||||||
|
_stateBuffer = (_stateBuffer & 0xFF) | (~analogData << 8);
|
||||||
|
}
|
||||||
|
};
|
76
Core/NES/Input/PartyTap.h
Normal file
76
Core/NES/Input/PartyTap.h
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
#pragma once
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "Shared/BaseControlDevice.h"
|
||||||
|
#include "Utilities/Serializer.h"
|
||||||
|
|
||||||
|
class Emulator;
|
||||||
|
|
||||||
|
class PartyTap : public BaseControlDevice
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
uint8_t _stateBuffer = 0;
|
||||||
|
uint8_t _readCount = 0;
|
||||||
|
bool _enabled = false;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
enum Buttons { B1 = 0, B2, B3, B4, B5, B6 };
|
||||||
|
|
||||||
|
string GetKeyNames() override
|
||||||
|
{
|
||||||
|
return "123456";
|
||||||
|
}
|
||||||
|
|
||||||
|
void InternalSetStateFromInput() override
|
||||||
|
{
|
||||||
|
for(KeyMapping keyMapping : _keyMappings) {
|
||||||
|
for(int i = 0; i < 6; i++) {
|
||||||
|
SetPressedState(i, keyMapping.CustomKeys[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Serialize(Serializer& s) override
|
||||||
|
{
|
||||||
|
BaseControlDevice::Serialize(s);
|
||||||
|
s.Stream(_stateBuffer, _readCount, _enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
PartyTap(Emulator* emu, KeyMappingSet keyMappings) : BaseControlDevice(emu, ControllerType::PartyTap, BaseControlDevice::ExpDevicePort, keyMappings)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t ReadRam(uint16_t addr) override
|
||||||
|
{
|
||||||
|
if(addr == 0x4017) {
|
||||||
|
StrobeProcessRead();
|
||||||
|
if(_readCount < 2) {
|
||||||
|
uint8_t value = (_stateBuffer & 0x7) << 2;
|
||||||
|
_stateBuffer >>= 3;
|
||||||
|
_readCount++;
|
||||||
|
return value;
|
||||||
|
} else {
|
||||||
|
//"After 1st/2nd reads, a detection value can be read : $4017 & $1C == $14"
|
||||||
|
return 0x14;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RefreshStateBuffer() override
|
||||||
|
{
|
||||||
|
_readCount = 0;
|
||||||
|
_stateBuffer =
|
||||||
|
IsPressed(PartyTap::Buttons::B1) ? 1 : 0 |
|
||||||
|
IsPressed(PartyTap::Buttons::B2) ? 2 : 0 |
|
||||||
|
IsPressed(PartyTap::Buttons::B3) ? 4 : 0 |
|
||||||
|
IsPressed(PartyTap::Buttons::B4) ? 8 : 0 |
|
||||||
|
IsPressed(PartyTap::Buttons::B5) ? 16 : 0 |
|
||||||
|
IsPressed(PartyTap::Buttons::B6) ? 32 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteRam(uint16_t addr, uint8_t value) override
|
||||||
|
{
|
||||||
|
StrobeProcessWrite(value);
|
||||||
|
}
|
||||||
|
};
|
81
Core/NES/Input/PowerPad.h
Normal file
81
Core/NES/Input/PowerPad.h
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
#pragma once
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "Shared/BaseControlDevice.h"
|
||||||
|
#include "Utilities/Serializer.h"
|
||||||
|
|
||||||
|
class Emulator;
|
||||||
|
|
||||||
|
class PowerPad : public BaseControlDevice
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
uint8_t _stateBufferL = 0;
|
||||||
|
uint8_t _stateBufferH = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
string GetKeyNames() override
|
||||||
|
{
|
||||||
|
return "123456789ABC";
|
||||||
|
}
|
||||||
|
|
||||||
|
void InternalSetStateFromInput() override
|
||||||
|
{
|
||||||
|
for(KeyMapping keyMapping : _keyMappings) {
|
||||||
|
for(int i = 0; i < 3; i++) {
|
||||||
|
for(int j = 0; j < 4; j++) {
|
||||||
|
if(false) { //TODO
|
||||||
|
//Invert the order of each row
|
||||||
|
SetPressedState(i*4+j, keyMapping.CustomKeys[i*4+(3-j)]);
|
||||||
|
} else {
|
||||||
|
SetPressedState(i*4+j, keyMapping.CustomKeys[i*4+j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RefreshStateBuffer() override
|
||||||
|
{
|
||||||
|
uint8_t pressedKeys[12] = {};
|
||||||
|
for(int i = 0; i < 12; i++) {
|
||||||
|
pressedKeys[i] |= IsPressed(i) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//"Serial data from buttons 2, 1, 5, 9, 6, 10, 11, 7"
|
||||||
|
_stateBufferL = pressedKeys[1] | (pressedKeys[0] << 1) | (pressedKeys[4] << 2) | (pressedKeys[8] << 3) | (pressedKeys[5] << 4) | (pressedKeys[9] << 5) | (pressedKeys[10] << 6) | (pressedKeys[6] << 7);
|
||||||
|
|
||||||
|
//"Serial data from buttons 4, 3, 12, 8 (following 4 bits read as H=1)"
|
||||||
|
_stateBufferH = pressedKeys[3] | (pressedKeys[2] << 1) | (pressedKeys[11] << 2) | (pressedKeys[7] << 3) | 0xF0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Serialize(Serializer& s) override
|
||||||
|
{
|
||||||
|
BaseControlDevice::Serialize(s);
|
||||||
|
s.Stream(_stateBufferL, _stateBufferH);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
PowerPad(Emulator* emu, ControllerType type, uint8_t port, KeyMappingSet keyMappings) : BaseControlDevice(emu, type, port, keyMappings)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t ReadRam(uint16_t addr) override
|
||||||
|
{
|
||||||
|
uint8_t output = 0;
|
||||||
|
if(IsCurrentPort(addr)) {
|
||||||
|
StrobeProcessRead();
|
||||||
|
|
||||||
|
output = ((_stateBufferH & 0x01) << 4) | ((_stateBufferL & 0x01) << 3);
|
||||||
|
_stateBufferL >>= 1;
|
||||||
|
_stateBufferH >>= 1;
|
||||||
|
|
||||||
|
_stateBufferL |= 0x80;
|
||||||
|
_stateBufferH |= 0x80;
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteRam(uint16_t addr, uint8_t value) override
|
||||||
|
{
|
||||||
|
StrobeProcessWrite(value);
|
||||||
|
}
|
||||||
|
};
|
126
Core/NES/Input/SuborKeyboard.h
Normal file
126
Core/NES/Input/SuborKeyboard.h
Normal file
|
@ -0,0 +1,126 @@
|
||||||
|
#pragma once
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "Shared/BaseControlDevice.h"
|
||||||
|
#include "Utilities/Serializer.h"
|
||||||
|
|
||||||
|
class SuborKeyboard : public BaseControlDevice
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
uint8_t _row = 0;
|
||||||
|
uint8_t _column = 0;
|
||||||
|
bool _enabled = false;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
string GetKeyNames() override
|
||||||
|
{
|
||||||
|
return "ABCDEFGHIJKLMNOPQRSTUVWXYZ01234567891234567890120123456789edpmdmncdsasbemglrcpcsasbteeehidududlr123";
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Buttons
|
||||||
|
{
|
||||||
|
A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z,
|
||||||
|
Num0, Num1, Num2, Num3, Num4, Num5, Num6, Num7, Num8, Num9,
|
||||||
|
F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12,
|
||||||
|
Numpad0, Numpad1, Numpad2, Numpad3, Numpad4, Numpad5, Numpad6, Numpad7, Numpad8, Numpad9,
|
||||||
|
NumpadEnter, NumpadDot, NumpadPlus, NumpadMultiply, NumpadDivide, NumpadMinus, NumLock,
|
||||||
|
Comma, Dot, SemiColon, Apostrophe,
|
||||||
|
Slash, Backslash,
|
||||||
|
Equal, Minus, Grave,
|
||||||
|
LeftBracket, RightBracket,
|
||||||
|
CapsLock, Pause,
|
||||||
|
Ctrl, Shift, Alt,
|
||||||
|
Space, Backspace, Tab, Esc, Enter,
|
||||||
|
End, Home,
|
||||||
|
Ins, Delete,
|
||||||
|
PageUp, PageDown,
|
||||||
|
Up, Down, Left, Right,
|
||||||
|
Unknown1, Unknown2, Unknown3,
|
||||||
|
};
|
||||||
|
|
||||||
|
Buttons _keyboardMatrix[104] = {
|
||||||
|
Num4, G, F, C, F2, E, Num5, V,
|
||||||
|
Num2, D, S, End, F1, W, Num3, X,
|
||||||
|
Ins, Backspace, PageDown, Right, F8, PageUp, Delete, Home,
|
||||||
|
Num9, I, L, Comma, F5, O, Num0, Dot,
|
||||||
|
RightBracket, Enter, Up, Left, F7, LeftBracket, Backslash, Down,
|
||||||
|
Q, CapsLock, Z, Tab, Esc, A, Num1, Ctrl,
|
||||||
|
Num7, Y, K, M, F4, U, Num8, J,
|
||||||
|
Minus, SemiColon, Apostrophe, Slash, F6, P, Equal, Shift,
|
||||||
|
T, H, N, Space, F3, R, Num6, B,
|
||||||
|
Numpad6, NumpadEnter, Numpad4, Numpad8, Numpad2, Unknown1, Unknown2, Unknown3,
|
||||||
|
Alt, Numpad4, Numpad7, F11, F12, Numpad1, Numpad2, Numpad8,
|
||||||
|
NumpadMinus, NumpadPlus, NumpadMultiply, Numpad9, F10, Numpad5, NumpadDivide, NumLock,
|
||||||
|
Grave, Numpad6, Pause, Space, F9, Numpad3, NumpadDot, Numpad0
|
||||||
|
};
|
||||||
|
|
||||||
|
void InternalSetStateFromInput() override
|
||||||
|
{
|
||||||
|
//TODO
|
||||||
|
bool allowInput = false; // _emu->GetSettings()->IsKeyboardMode();
|
||||||
|
if(allowInput) {
|
||||||
|
for(KeyMapping keyMapping : _keyMappings) {
|
||||||
|
for(int i = 0; i < 99; i++) {
|
||||||
|
SetPressedState(i, keyMapping.CustomKeys[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t GetActiveKeys(uint8_t row, uint8_t column)
|
||||||
|
{
|
||||||
|
uint8_t result = 0;
|
||||||
|
uint32_t baseIndex = row * 8 + (column ? 4 : 0);
|
||||||
|
for(int i = 0; i < 4; i++) {
|
||||||
|
if(IsPressed(_keyboardMatrix[baseIndex + i])) {
|
||||||
|
result |= 0x10;
|
||||||
|
}
|
||||||
|
result >>= 1;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Serialize(Serializer& s) override
|
||||||
|
{
|
||||||
|
BaseControlDevice::Serialize(s);
|
||||||
|
s.Stream(_row, _column, _enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RefreshStateBuffer() override
|
||||||
|
{
|
||||||
|
_row = 0;
|
||||||
|
_column = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
SuborKeyboard(Emulator* emu, KeyMappingSet keyMappings) : BaseControlDevice(emu, ControllerType::SuborKeyboard, BaseControlDevice::ExpDevicePort, keyMappings)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t ReadRam(uint16_t addr) override
|
||||||
|
{
|
||||||
|
if(addr == 0x4017) {
|
||||||
|
if(_enabled) {
|
||||||
|
uint8_t value = ((~GetActiveKeys(_row, _column)) << 1) & 0x1E;
|
||||||
|
return value;
|
||||||
|
} else {
|
||||||
|
return 0x1E;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteRam(uint16_t addr, uint8_t value) override
|
||||||
|
{
|
||||||
|
StrobeProcessWrite(value);
|
||||||
|
|
||||||
|
uint8_t prevColumn = _column;
|
||||||
|
_column = (value & 0x02) >> 1;
|
||||||
|
_enabled = (value & 0x04) != 0;
|
||||||
|
|
||||||
|
if(_enabled) {
|
||||||
|
if(!_column && prevColumn) {
|
||||||
|
_row = (_row + 1) % 13;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
110
Core/NES/Input/SuborMouse.h
Normal file
110
Core/NES/Input/SuborMouse.h
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
#pragma once
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "Shared/BaseControlDevice.h"
|
||||||
|
#include "Shared/KeyManager.h"
|
||||||
|
#include "Shared/EmuSettings.h"
|
||||||
|
#include "Shared/Emulator.h"
|
||||||
|
#include "Utilities/Serializer.h"
|
||||||
|
|
||||||
|
class SuborMouse : public BaseControlDevice
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
uint32_t _stateBuffer = 0;
|
||||||
|
uint8_t _packetBytes[3] = {};
|
||||||
|
uint8_t _packetPos = 0;
|
||||||
|
uint8_t _packetSize = 1;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool HasCoordinates() override { return true; }
|
||||||
|
enum Buttons { Left = 0, Right };
|
||||||
|
|
||||||
|
void Serialize(Serializer& s) override
|
||||||
|
{
|
||||||
|
BaseControlDevice::Serialize(s);
|
||||||
|
ArrayInfo<uint8_t> packetBytes { _packetBytes, 3 };
|
||||||
|
s.Stream(_stateBuffer, _packetPos, _packetSize, packetBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InternalSetStateFromInput() override
|
||||||
|
{
|
||||||
|
SetPressedState(Buttons::Left, KeyManager::IsMouseButtonPressed(MouseButton::LeftButton));
|
||||||
|
SetPressedState(Buttons::Right, KeyManager::IsMouseButtonPressed(MouseButton::RightButton));
|
||||||
|
SetMovement(KeyManager::GetMouseMovement(
|
||||||
|
_emu->GetSettings()->GetVideoConfig().VideoScale,
|
||||||
|
_emu->GetSettings()->GetInputConfig().MouseSensitivity + 1
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
SuborMouse(Emulator* emu, uint8_t port) : BaseControlDevice(emu, ControllerType::SuborMouse, port)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteRam(uint16_t addr, uint8_t value) override
|
||||||
|
{
|
||||||
|
StrobeProcessWrite(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t ReadRam(uint16_t addr) override
|
||||||
|
{
|
||||||
|
uint8_t output = 0;
|
||||||
|
if((addr == 0x4016 && (_port & 0x01) == 0) || (addr == 0x4017 && (_port & 0x01) == 1)) {
|
||||||
|
StrobeProcessRead();
|
||||||
|
output = (_stateBuffer & 0x80) >> 7;
|
||||||
|
if(_port >= 2) {
|
||||||
|
output <<= 1;
|
||||||
|
}
|
||||||
|
_stateBuffer <<= 1;
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RefreshStateBuffer() override
|
||||||
|
{
|
||||||
|
if(_packetPos < _packetSize - 1) {
|
||||||
|
//3-byte packet is not done yet, move to next byte
|
||||||
|
_packetPos++;
|
||||||
|
_stateBuffer = _packetBytes[_packetPos];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseMovement mov = GetMovement();
|
||||||
|
|
||||||
|
uint32_t upFlag = mov.dy < 0 ? 0x80 : 0;
|
||||||
|
uint32_t leftFlag = mov.dx < 0 ? 0x80 : 0;
|
||||||
|
|
||||||
|
mov.dx = std::min<int16_t>(std::abs(mov.dx), 31);
|
||||||
|
mov.dy = std::min<int16_t>(std::abs(mov.dy), 31);
|
||||||
|
|
||||||
|
if(mov.dx <= 1 && mov.dy <= 1) {
|
||||||
|
//1-byte packet
|
||||||
|
_packetBytes[0] =
|
||||||
|
(IsPressed(SuborMouse::Buttons::Left) ? 0x80 : 0) |
|
||||||
|
(IsPressed(SuborMouse::Buttons::Right) ? 0x40 : 0) |
|
||||||
|
(leftFlag && mov.dx ? 0x30 : (mov.dx ? 0x10 : 0)) |
|
||||||
|
(upFlag && mov.dy ? 0x0C : (mov.dy ? 0x04 : 0));
|
||||||
|
_packetBytes[1] = 0;
|
||||||
|
_packetBytes[2] = 0;
|
||||||
|
|
||||||
|
_packetSize = 1;
|
||||||
|
} else {
|
||||||
|
//3-byte packet
|
||||||
|
_packetBytes[0] =
|
||||||
|
(IsPressed(SuborMouse::Buttons::Left) ? 0x80 : 0) |
|
||||||
|
(IsPressed(SuborMouse::Buttons::Right) ? 0x40 : 0) |
|
||||||
|
(leftFlag ? 0x20 : 0) |
|
||||||
|
(mov.dx & 0x10) |
|
||||||
|
(upFlag ? 0x08 : 0) |
|
||||||
|
((mov.dy & 0x10) >> 2) |
|
||||||
|
0x01;
|
||||||
|
|
||||||
|
_packetBytes[1] = ((mov.dx & 0x0F) << 2) | 0x02;
|
||||||
|
_packetBytes[2] = ((mov.dy & 0x0F) << 2) | 0x03;
|
||||||
|
|
||||||
|
_packetSize = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
_packetPos = 0;
|
||||||
|
_stateBuffer = _packetBytes[0];
|
||||||
|
}
|
||||||
|
};
|
109
Core/NES/Input/VirtualBoyController.h
Normal file
109
Core/NES/Input/VirtualBoyController.h
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
#pragma once
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "Shared/BaseControlDevice.h"
|
||||||
|
#include "Shared/Emulator.h"
|
||||||
|
#include "Shared/EmuSettings.h"
|
||||||
|
#include "Utilities/Serializer.h"
|
||||||
|
|
||||||
|
class VirtualBoyController : public BaseControlDevice
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
uint32_t _stateBuffer = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
enum Buttons { Down1 = 0, Left1, Select, Start, Up0, Down0, Left0, Right0, Right1, Up1, L, R, B, A };
|
||||||
|
|
||||||
|
string GetKeyNames() override
|
||||||
|
{
|
||||||
|
return "dlSTUDLRruLRBA";
|
||||||
|
}
|
||||||
|
|
||||||
|
void InternalSetStateFromInput() override
|
||||||
|
{
|
||||||
|
for(KeyMapping keyMapping : _keyMappings) {
|
||||||
|
for(int i = 0; i < 14; i++) {
|
||||||
|
SetPressedState(i, keyMapping.CustomKeys[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!_emu->GetSettings()->GetNesConfig().AllowInvalidInput) {
|
||||||
|
//If both U+D or L+R are pressed at the same time, act as if neither is pressed
|
||||||
|
if(IsPressed(Buttons::Up0) && IsPressed(Buttons::Down0)) {
|
||||||
|
ClearBit(Buttons::Down0);
|
||||||
|
ClearBit(Buttons::Up0);
|
||||||
|
}
|
||||||
|
if(IsPressed(Buttons::Left0) && IsPressed(Buttons::Right0)) {
|
||||||
|
ClearBit(Buttons::Left0);
|
||||||
|
ClearBit(Buttons::Right0);
|
||||||
|
}
|
||||||
|
if (IsPressed(Buttons::Up1) && IsPressed(Buttons::Down1)) {
|
||||||
|
ClearBit(Buttons::Down1);
|
||||||
|
ClearBit(Buttons::Up1);
|
||||||
|
}
|
||||||
|
if (IsPressed(Buttons::Left1) && IsPressed(Buttons::Right1)) {
|
||||||
|
ClearBit(Buttons::Left1);
|
||||||
|
ClearBit(Buttons::Right1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t ToByte()
|
||||||
|
{
|
||||||
|
//"A Virtual Boy controller returns a 16-bit report in a similar order as SNES, with two additional buttons."
|
||||||
|
|
||||||
|
return
|
||||||
|
(uint8_t)IsPressed(Buttons::Down1) |
|
||||||
|
((uint8_t)IsPressed(Buttons::Left1) << 1) |
|
||||||
|
((uint8_t)IsPressed(Buttons::Select) << 2) |
|
||||||
|
((uint8_t)IsPressed(Buttons::Start) << 3) |
|
||||||
|
((uint8_t)IsPressed(Buttons::Up0) << 4) |
|
||||||
|
((uint8_t)IsPressed(Buttons::Down0) << 5) |
|
||||||
|
((uint8_t)IsPressed(Buttons::Left0) << 6) |
|
||||||
|
((uint8_t)IsPressed(Buttons::Right0) << 7) |
|
||||||
|
((uint8_t)IsPressed(Buttons::Right1) << 8) |
|
||||||
|
((uint8_t)IsPressed(Buttons::Up1) << 9) |
|
||||||
|
((uint8_t)IsPressed(Buttons::L) << 10) |
|
||||||
|
((uint8_t)IsPressed(Buttons::R) << 11) |
|
||||||
|
((uint8_t)IsPressed(Buttons::B) << 12) |
|
||||||
|
((uint8_t)IsPressed(Buttons::A) << 13) |
|
||||||
|
(1 << 14);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Serialize(Serializer& s) override
|
||||||
|
{
|
||||||
|
BaseControlDevice::Serialize(s);
|
||||||
|
s.Stream(_stateBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RefreshStateBuffer() override
|
||||||
|
{
|
||||||
|
_stateBuffer = (uint32_t)ToByte();
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
VirtualBoyController(Emulator* emu, uint8_t port, KeyMappingSet keyMappings) : BaseControlDevice(emu, ControllerType::VirtualBoyController, port, keyMappings)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t ReadRam(uint16_t addr) override
|
||||||
|
{
|
||||||
|
uint8_t output = 0;
|
||||||
|
|
||||||
|
if(IsCurrentPort(addr)) {
|
||||||
|
StrobeProcessRead();
|
||||||
|
|
||||||
|
output = _stateBuffer & 0x01;
|
||||||
|
_stateBuffer >>= 1;
|
||||||
|
|
||||||
|
//"All subsequent reads will return D=1 on an authentic controller but may return D=0 on third party controllers."
|
||||||
|
_stateBuffer |= 0x8000;
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteRam(uint16_t addr, uint8_t value) override
|
||||||
|
{
|
||||||
|
StrobeProcessWrite(value);
|
||||||
|
}
|
||||||
|
};
|
45
Core/NES/Input/VsZapper.h
Normal file
45
Core/NES/Input/VsZapper.h
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
#pragma once
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "NES/Input/Zapper.h"
|
||||||
|
|
||||||
|
class NesConsole;
|
||||||
|
|
||||||
|
class VsZapper : public Zapper
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
uint32_t _stateBuffer = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void Serialize(Serializer& s) override
|
||||||
|
{
|
||||||
|
BaseControlDevice::Serialize(s);
|
||||||
|
s.Stream(_stateBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RefreshStateBuffer() override
|
||||||
|
{
|
||||||
|
_stateBuffer = 0x10 | (IsLightFound() ? 0x40 : 0x00) | (IsPressed(Zapper::Buttons::Fire) ? 0x80 : 0x00);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
VsZapper(NesConsole* console, uint8_t port) : Zapper(console, ControllerType::VsZapper, port)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t ReadRam(uint16_t addr) override
|
||||||
|
{
|
||||||
|
if(IsCurrentPort(addr)) {
|
||||||
|
StrobeProcessRead();
|
||||||
|
uint8_t returnValue = _stateBuffer & 0x01;
|
||||||
|
_stateBuffer >>= 1;
|
||||||
|
return returnValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteRam(uint16_t addr, uint8_t value) override
|
||||||
|
{
|
||||||
|
StrobeProcessWrite(value);
|
||||||
|
}
|
||||||
|
};
|
98
Core/NES/Input/Zapper.h
Normal file
98
Core/NES/Input/Zapper.h
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
#pragma once
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "Shared/BaseControlDevice.h"
|
||||||
|
#include "NES/NesPpu.h"
|
||||||
|
#include "NES/NesConsole.h"
|
||||||
|
#include "Shared/Emulator.h"
|
||||||
|
#include "Shared/Emulator.h"
|
||||||
|
#include "Shared/EmuSettings.h"
|
||||||
|
#include "Shared/KeyManager.h"
|
||||||
|
#include "Utilities/Serializer.h"
|
||||||
|
|
||||||
|
class Zapper : public BaseControlDevice
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
NesConsole* _console;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool HasCoordinates() override { return true; }
|
||||||
|
|
||||||
|
string GetKeyNames() override
|
||||||
|
{
|
||||||
|
return "F";
|
||||||
|
}
|
||||||
|
|
||||||
|
ControllerType GetControllerType()
|
||||||
|
{
|
||||||
|
return ControllerType::NesController;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Buttons { Fire };
|
||||||
|
|
||||||
|
void InternalSetStateFromInput() override
|
||||||
|
{
|
||||||
|
SetPressedState(Buttons::Fire, KeyManager::IsMouseButtonPressed(MouseButton::LeftButton));
|
||||||
|
|
||||||
|
MousePosition pos = KeyManager::GetMousePosition();
|
||||||
|
if(KeyManager::IsMouseButtonPressed(MouseButton::RightButton)) {
|
||||||
|
pos.X = -1;
|
||||||
|
pos.Y = -1;
|
||||||
|
}
|
||||||
|
SetCoordinates(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsLightFound()
|
||||||
|
{
|
||||||
|
return StaticIsLightFound(GetCoordinates(), _console);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
Zapper(NesConsole* console, ControllerType type, uint8_t port) : BaseControlDevice(console->GetEmulator(), type, port)
|
||||||
|
{
|
||||||
|
_console = console;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t ReadRam(uint16_t addr) override
|
||||||
|
{
|
||||||
|
uint8_t output = 0;
|
||||||
|
if((IsExpansionDevice() && addr == 0x4017) || IsCurrentPort(addr)) {
|
||||||
|
output = (IsLightFound() ? 0 : 0x08) | (IsPressed(Zapper::Buttons::Fire) ? 0x10 : 0x00);
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteRam(uint16_t addr, uint8_t value) override
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool StaticIsLightFound(MousePosition pos, NesConsole* console)
|
||||||
|
{
|
||||||
|
NesPpu* ppu = console ? console->GetPpu() : nullptr;
|
||||||
|
if(!ppu) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t scanline = ppu->GetCurrentScanline();
|
||||||
|
int32_t cycle = ppu->GetCurrentCycle();
|
||||||
|
int radius = (int)console->GetNesConfig().ZapperDetectionRadius;
|
||||||
|
|
||||||
|
if(pos.X >= 0 && pos.Y >= 0) {
|
||||||
|
for(int yOffset = -radius; yOffset <= radius; yOffset++) {
|
||||||
|
int yPos = pos.Y + yOffset;
|
||||||
|
if(yPos >= 0 && yPos < NesPpu::ScreenHeight) {
|
||||||
|
for(int xOffset = -radius; xOffset <= radius; xOffset++) {
|
||||||
|
int xPos = pos.X + xOffset;
|
||||||
|
if(xPos >= 0 && xPos < NesPpu::ScreenWidth) {
|
||||||
|
if(scanline >= yPos && (scanline - yPos <= 20) && (scanline != yPos || cycle > xPos) && ppu->GetPixelBrightness(xPos, yPos) >= 85) {
|
||||||
|
//Light cannot be detected if the Y/X position is further ahead than the PPU, or if the PPU drew a dark color
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
|
@ -249,3 +249,8 @@ uint64_t NesConsole::GetMasterClock()
|
||||||
{
|
{
|
||||||
return _cpu->GetCycleCount();
|
return _cpu->GetCycleCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t NesConsole::GetMasterClockRate()
|
||||||
|
{
|
||||||
|
return NesCpu::ClockRateNtsc;
|
||||||
|
}
|
||||||
|
|
|
@ -77,5 +77,6 @@ public:
|
||||||
virtual AddressInfo GetAbsoluteAddress(AddressInfo relAddress) override;
|
virtual AddressInfo GetAbsoluteAddress(AddressInfo relAddress) override;
|
||||||
virtual AddressInfo GetRelativeAddress(AddressInfo absAddress, CpuType cpuType) override;
|
virtual AddressInfo GetRelativeAddress(AddressInfo absAddress, CpuType cpuType) override;
|
||||||
|
|
||||||
virtual uint64_t GetMasterClock() override;
|
uint64_t GetMasterClock() override;
|
||||||
|
uint32_t GetMasterClockRate() override;
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,8 +3,6 @@
|
||||||
#include "NES/BaseMapper.h"
|
#include "NES/BaseMapper.h"
|
||||||
#include "NES/NesConsole.h"
|
#include "NES/NesConsole.h"
|
||||||
#include "NES/NesMemoryManager.h"
|
#include "NES/NesMemoryManager.h"
|
||||||
#include "NES/Input/NesController.h"
|
|
||||||
#include "SNES/Input/SnesController.h"
|
|
||||||
#include "Shared/EmuSettings.h"
|
#include "Shared/EmuSettings.h"
|
||||||
#include "Shared/Interfaces/IKeyManager.h"
|
#include "Shared/Interfaces/IKeyManager.h"
|
||||||
#include "Shared/Interfaces/IInputProvider.h"
|
#include "Shared/Interfaces/IInputProvider.h"
|
||||||
|
@ -13,30 +11,31 @@
|
||||||
#include "Shared/Emulator.h"
|
#include "Shared/Emulator.h"
|
||||||
#include "Shared/KeyManager.h"
|
#include "Shared/KeyManager.h"
|
||||||
#include "Shared/SystemActionManager.h"
|
#include "Shared/SystemActionManager.h"
|
||||||
/*#include "Zapper.h"
|
#include "NES/Input/NesController.h"
|
||||||
#include "ArkanoidController.h"
|
#include "SNES/Input/SnesController.h"
|
||||||
#include "OekaKidsTablet.h"
|
#include "SNES/Input/SnesMouse.h"
|
||||||
#include "FourScore.h"
|
#include "NES/Input/Zapper.h"
|
||||||
#include "SnesController.h"
|
#include "NES/Input/ArkanoidController.h"
|
||||||
#include "SnesMouse.h"
|
#include "NES/Input/OekaKidsTablet.h"
|
||||||
#include "PowerPad.h"
|
#include "NES/Input/FourScore.h"
|
||||||
#include "FamilyMatTrainer.h"
|
#include "NES/Input/PowerPad.h"
|
||||||
#include "KonamiHyperShot.h"
|
#include "NES/Input/FamilyMatTrainer.h"
|
||||||
#include "FamilyBasicKeyboard.h"
|
#include "NES/Input/KonamiHyperShot.h"
|
||||||
#include "FamilyBasicDataRecorder.h"
|
#include "NES/Input/FamilyBasicKeyboard.h"
|
||||||
#include "PartyTap.h"
|
#include "NES/Input/FamilyBasicDataRecorder.h"
|
||||||
#include "PachinkoController.h"
|
#include "NES/Input/PartyTap.h"
|
||||||
#include "ExcitingBoxingController.h"
|
#include "NES/Input/PachinkoController.h"
|
||||||
#include "SuborKeyboard.h"
|
#include "NES/Input/ExcitingBoxingController.h"
|
||||||
#include "SuborMouse.h"
|
#include "NES/Input/SuborKeyboard.h"
|
||||||
#include "JissenMahjongController.h"
|
#include "NES/Input/SuborMouse.h"
|
||||||
#include "BarcodeBattlerReader.h"
|
#include "NES/Input/JissenMahjongController.h"
|
||||||
#include "HoriTrack.h"
|
#include "NES/Input/BarcodeBattlerReader.h"
|
||||||
#include "BandaiHyperShot.h"
|
#include "NES/Input/HoriTrack.h"
|
||||||
#include "VsZapper.h"
|
#include "NES/Input/BandaiHyperShot.h"
|
||||||
#include "AsciiTurboFile.h"
|
#include "NES/Input/VsZapper.h"
|
||||||
#include "BattleBox.h"
|
#include "NES/Input/AsciiTurboFile.h"
|
||||||
#include "VbController.h"*/
|
#include "NES/Input/BattleBox.h"
|
||||||
|
#include "NES/Input/VirtualBoyController.h"
|
||||||
|
|
||||||
NesControlManager::NesControlManager(shared_ptr<NesConsole> console, shared_ptr<BaseControlDevice> mapperControlDevice) : BaseControlManager(console->GetEmulator())
|
NesControlManager::NesControlManager(shared_ptr<NesConsole> console, shared_ptr<BaseControlDevice> mapperControlDevice) : BaseControlManager(console->GetEmulator())
|
||||||
{
|
{
|
||||||
|
@ -58,48 +57,43 @@ shared_ptr<BaseControlDevice> NesControlManager::CreateControllerDevice(Controll
|
||||||
shared_ptr<BaseControlDevice> device;
|
shared_ptr<BaseControlDevice> device;
|
||||||
|
|
||||||
NesConfig cfg = _emu->GetSettings()->GetNesConfig();
|
NesConfig cfg = _emu->GetSettings()->GetNesConfig();
|
||||||
|
KeyMappingSet keys = cfg.Controllers[port].Keys;
|
||||||
|
|
||||||
switch(type) {
|
switch(type) {
|
||||||
case ControllerType::None: break;
|
case ControllerType::None: break;
|
||||||
case ControllerType::NesController: device.reset(new NesController(_emu, port, cfg.Controllers[port].Keys)); break;
|
case ControllerType::NesController: device.reset(new NesController(_emu, type, port, keys)); break;
|
||||||
//case ControllerType::Zapper: device.reset(new Zapper(console, port)); break;
|
case ControllerType::FamicomController: device.reset(new NesController(_emu, type, port, keys)); break;
|
||||||
//case ControllerType::ArkanoidController: device.reset(new ArkanoidController(console, port)); break;
|
case ControllerType::NesZapper: device.reset(new Zapper(_console.get(), type, port)); break;
|
||||||
case ControllerType::SnesController: device.reset(new SnesController(_emu, port, cfg.Controllers[port].Keys)); break;
|
case ControllerType::NesArkanoidController: device.reset(new ArkanoidController(_emu, type, port)); break;
|
||||||
/*case ControllerType::PowerPad: device.reset(new PowerPad(console, port, console->GetSettings()->GetControllerKeys(port))); break;
|
case ControllerType::SnesController: device.reset(new SnesController(_emu, port, keys)); break;
|
||||||
case ControllerType::SnesMouse: device.reset(new SnesMouse(console, port)); break;
|
case ControllerType::PowerPad: device.reset(new PowerPad(_emu, type, port, keys)); break;
|
||||||
case ControllerType::SuborMouse: device.reset(new SuborMouse(console, port)); break;
|
case ControllerType::SnesMouse: device.reset(new SnesMouse(_emu, port)); break;
|
||||||
case ControllerType::VsZapper: device.reset(new VsZapper(console, port)); break;
|
case ControllerType::SuborMouse: device.reset(new SuborMouse(_emu, port)); break;
|
||||||
case ControllerType::VbController: device.reset(new VbController(console, port, console->GetSettings()->GetControllerKeys(port))); break;*/
|
case ControllerType::VsZapper: device.reset(new VsZapper(_console.get(), port)); break;
|
||||||
}
|
case ControllerType::VirtualBoyController: device.reset(new VirtualBoyController(_emu, port, keys)); break;
|
||||||
|
|
||||||
return device;
|
|
||||||
}
|
|
||||||
|
|
||||||
shared_ptr<BaseControlDevice> NesControlManager::CreateExpansionDevice(ExpansionPortDevice type)
|
//Exp port devices
|
||||||
{
|
case ControllerType::FamicomZapper: device.reset(new Zapper(_console.get(), type, BaseControlDevice::ExpDevicePort)); break;
|
||||||
shared_ptr<BaseControlDevice> device;
|
case ControllerType::FamicomArkanoidController: device.reset(new ArkanoidController(_emu, type, BaseControlDevice::ExpDevicePort)); break;
|
||||||
|
case ControllerType::OekaKidsTablet: device.reset(new OekaKidsTablet(_emu)); break;
|
||||||
|
case ControllerType::FamilyTrainerMat: device.reset(new FamilyMatTrainer(_emu, keys)); break;
|
||||||
|
case ControllerType::KonamiHyperShot: device.reset(new KonamiHyperShot(_emu, keys, cfg.Controllers[1].Keys)); break;
|
||||||
|
case ControllerType::FamilyBasicKeyboard: device.reset(new FamilyBasicKeyboard(_emu, keys)); break;
|
||||||
|
case ControllerType::PartyTap: device.reset(new PartyTap(_emu, keys)); break;
|
||||||
|
case ControllerType::Pachinko: device.reset(new PachinkoController(_emu, keys)); break;
|
||||||
|
case ControllerType::ExcitingBoxing: device.reset(new ExcitingBoxingController(_emu, keys)); break;
|
||||||
|
case ControllerType::JissenMahjong: device.reset(new JissenMahjongController(_emu, keys)); break;
|
||||||
|
case ControllerType::SuborKeyboard: device.reset(new SuborKeyboard(_emu, keys)); break;
|
||||||
|
case ControllerType::BarcodeBattler: device.reset(new BarcodeBattlerReader(_emu)); break;
|
||||||
|
case ControllerType::HoriTrack: device.reset(new HoriTrack(_emu, keys)); break;
|
||||||
|
case ControllerType::BandaiHyperShot: device.reset(new BandaiHyperShot(_console.get(), keys)); break;
|
||||||
|
case ControllerType::AsciiTurboFile: device.reset(new AsciiTurboFile(_emu)); break;
|
||||||
|
case ControllerType::BattleBox: device.reset(new BattleBox(_emu)); break;
|
||||||
|
|
||||||
/*switch(type) {
|
case ControllerType::FourScore: //TODO
|
||||||
case ExpansionPortDevice::Zapper: device.reset(new Zapper(console, BaseControlDevice::ExpDevicePort)); break;
|
case ControllerType::FourPlayerAdapter: //TODO
|
||||||
case ExpansionPortDevice::ArkanoidController: device.reset(new ArkanoidController(console, BaseControlDevice::ExpDevicePort)); break;
|
|
||||||
case ExpansionPortDevice::OekaKidsTablet: device.reset(new OekaKidsTablet(console)); break;
|
|
||||||
case ExpansionPortDevice::FamilyTrainerMat: device.reset(new FamilyMatTrainer(console, console->GetSettings()->GetControllerKeys(0))); break;
|
|
||||||
case ExpansionPortDevice::KonamiHyperShot: device.reset(new KonamiHyperShot(console, console->GetSettings()->GetControllerKeys(0), console->GetSettings()->GetControllerKeys(1))); break;
|
|
||||||
case ExpansionPortDevice::FamilyBasicKeyboard: device.reset(new FamilyBasicKeyboard(console, console->GetSettings()->GetControllerKeys(0))); break;
|
|
||||||
case ExpansionPortDevice::PartyTap: device.reset(new PartyTap(console, console->GetSettings()->GetControllerKeys(0))); break;
|
|
||||||
case ExpansionPortDevice::Pachinko: device.reset(new PachinkoController(console, console->GetSettings()->GetControllerKeys(0))); break;
|
|
||||||
case ExpansionPortDevice::ExcitingBoxing: device.reset(new ExcitingBoxingController(console, console->GetSettings()->GetControllerKeys(0))); break;
|
|
||||||
case ExpansionPortDevice::JissenMahjong: device.reset(new JissenMahjongController(console, console->GetSettings()->GetControllerKeys(0))); break;
|
|
||||||
case ExpansionPortDevice::SuborKeyboard: device.reset(new SuborKeyboard(console, console->GetSettings()->GetControllerKeys(0))); break;
|
|
||||||
case ExpansionPortDevice::BarcodeBattler: device.reset(new BarcodeBattlerReader(console)); break;
|
|
||||||
case ExpansionPortDevice::HoriTrack: device.reset(new HoriTrack(console, console->GetSettings()->GetControllerKeys(0))); break;
|
|
||||||
case ExpansionPortDevice::BandaiHyperShot: device.reset(new BandaiHyperShot(console, console->GetSettings()->GetControllerKeys(0))); break;
|
|
||||||
case ExpansionPortDevice::AsciiTurboFile: device.reset(new AsciiTurboFile(console)); break;
|
|
||||||
case ExpansionPortDevice::BattleBox: device.reset(new BattleBox(console)); break;
|
|
||||||
|
|
||||||
case ExpansionPortDevice::FourPlayerAdapter:
|
|
||||||
default: break;
|
default: break;
|
||||||
}*/
|
}
|
||||||
|
|
||||||
return device;
|
return device;
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,7 @@ shared_ptr<BaseControlDevice> ControlManager::CreateControllerDevice(ControllerT
|
||||||
switch(type) {
|
switch(type) {
|
||||||
case ControllerType::None: break;
|
case ControllerType::None: break;
|
||||||
case ControllerType::SnesController: device.reset(new SnesController(_emu, port, cfg.Controllers[port].Keys)); break;
|
case ControllerType::SnesController: device.reset(new SnesController(_emu, port, cfg.Controllers[port].Keys)); break;
|
||||||
case ControllerType::SnesMouse: device.reset(new SnesMouse(_console, port)); break;
|
case ControllerType::SnesMouse: device.reset(new SnesMouse(_emu, port)); break;
|
||||||
case ControllerType::SuperScope: device.reset(new SuperScope(_console, port, cfg.Controllers[port].Keys)); break;
|
case ControllerType::SuperScope: device.reset(new SuperScope(_console, port, cfg.Controllers[port].Keys)); break;
|
||||||
case ControllerType::Multitap: device.reset(new Multitap(_console, port, cfg.Controllers[port].Keys, cfg.Controllers[2].Keys, cfg.Controllers[3].Keys, cfg.Controllers[4].Keys)); break;
|
case ControllerType::Multitap: device.reset(new Multitap(_console, port, cfg.Controllers[port].Keys, cfg.Controllers[2].Keys, cfg.Controllers[3].Keys, cfg.Controllers[4].Keys)); break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,7 +94,7 @@ void Multitap::RefreshStateBuffer()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Multitap::Multitap(Console* console, uint8_t port, KeyMappingSet keyMappings1, KeyMappingSet keyMappings2, KeyMappingSet keyMappings3, KeyMappingSet keyMappings4) : BaseControlDevice(console->GetEmulator(), port, keyMappings1)
|
Multitap::Multitap(Console* console, uint8_t port, KeyMappingSet keyMappings1, KeyMappingSet keyMappings2, KeyMappingSet keyMappings3, KeyMappingSet keyMappings4) : BaseControlDevice(console->GetEmulator(), ControllerType::Multitap, port, keyMappings1)
|
||||||
{
|
{
|
||||||
_turboSpeed[0] = keyMappings1.TurboSpeed;
|
_turboSpeed[0] = keyMappings1.TurboSpeed;
|
||||||
_turboSpeed[1] = keyMappings2.TurboSpeed;
|
_turboSpeed[1] = keyMappings2.TurboSpeed;
|
||||||
|
@ -108,11 +108,6 @@ Multitap::Multitap(Console* console, uint8_t port, KeyMappingSet keyMappings1, K
|
||||||
_internalRegs = console->GetInternalRegisters().get();
|
_internalRegs = console->GetInternalRegisters().get();
|
||||||
}
|
}
|
||||||
|
|
||||||
ControllerType Multitap::GetControllerType()
|
|
||||||
{
|
|
||||||
return ControllerType::Multitap;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Multitap::SetControllerState(uint8_t controllerNumber, ControlDeviceState state)
|
void Multitap::SetControllerState(uint8_t controllerNumber, ControlDeviceState state)
|
||||||
{
|
{
|
||||||
SnesController controller(_emu, 0, KeyMappingSet());
|
SnesController controller(_emu, 0, KeyMappingSet());
|
||||||
|
|
|
@ -29,8 +29,6 @@ protected:
|
||||||
public:
|
public:
|
||||||
Multitap(Console* console, uint8_t port, KeyMappingSet keyMappings1, KeyMappingSet keyMappings2, KeyMappingSet keyMappings3, KeyMappingSet keyMappings4);
|
Multitap(Console* console, uint8_t port, KeyMappingSet keyMappings1, KeyMappingSet keyMappings2, KeyMappingSet keyMappings3, KeyMappingSet keyMappings4);
|
||||||
|
|
||||||
ControllerType GetControllerType() override;
|
|
||||||
|
|
||||||
void SetControllerState(uint8_t controllerNumber, ControlDeviceState state);
|
void SetControllerState(uint8_t controllerNumber, ControlDeviceState state);
|
||||||
|
|
||||||
uint8_t ReadRam(uint16_t addr) override;
|
uint8_t ReadRam(uint16_t addr) override;
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#include "SNES/Input/SnesController.h"
|
#include "SNES/Input/SnesController.h"
|
||||||
#include "Shared/Emulator.h"
|
#include "Shared/Emulator.h"
|
||||||
|
|
||||||
SnesController::SnesController(Emulator* emu, uint8_t port, KeyMappingSet keyMappings) : BaseControlDevice(emu, port, keyMappings)
|
SnesController::SnesController(Emulator* emu, uint8_t port, KeyMappingSet keyMappings) : BaseControlDevice(emu, ControllerType::SnesController, port, keyMappings)
|
||||||
{
|
{
|
||||||
_turboSpeed = keyMappings.TurboSpeed;
|
_turboSpeed = keyMappings.TurboSpeed;
|
||||||
}
|
}
|
||||||
|
@ -71,11 +71,6 @@ void SnesController::RefreshStateBuffer()
|
||||||
_stateBuffer = (uint32_t)ToByte();
|
_stateBuffer = (uint32_t)ToByte();
|
||||||
}
|
}
|
||||||
|
|
||||||
ControllerType SnesController::GetControllerType()
|
|
||||||
{
|
|
||||||
return ControllerType::SnesController;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t SnesController::ReadRam(uint16_t addr)
|
uint8_t SnesController::ReadRam(uint16_t addr)
|
||||||
{
|
{
|
||||||
uint8_t output = 0;
|
uint8_t output = 0;
|
||||||
|
|
|
@ -21,7 +21,6 @@ public:
|
||||||
|
|
||||||
SnesController(Emulator* emu, uint8_t port, KeyMappingSet keyMappings);
|
SnesController(Emulator* emu, uint8_t port, KeyMappingSet keyMappings);
|
||||||
|
|
||||||
ControllerType GetControllerType() override;
|
|
||||||
uint8_t ReadRam(uint16_t addr) override;
|
uint8_t ReadRam(uint16_t addr) override;
|
||||||
void WriteRam(uint16_t addr, uint8_t value) override;
|
void WriteRam(uint16_t addr, uint8_t value) override;
|
||||||
};
|
};
|
|
@ -1,6 +1,5 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "SNES/Console.h"
|
|
||||||
#include "Shared/BaseControlDevice.h"
|
#include "Shared/BaseControlDevice.h"
|
||||||
#include "Shared/Interfaces/IKeyManager.h"
|
#include "Shared/Interfaces/IKeyManager.h"
|
||||||
#include "Shared/KeyManager.h"
|
#include "Shared/KeyManager.h"
|
||||||
|
@ -42,16 +41,11 @@ protected:
|
||||||
public:
|
public:
|
||||||
enum Buttons { Left = 0, Right };
|
enum Buttons { Left = 0, Right };
|
||||||
|
|
||||||
SnesMouse(Console* console, uint8_t port) : BaseControlDevice(console->GetEmulator(), port)
|
SnesMouse(Emulator* emu, uint8_t port) : BaseControlDevice(emu, ControllerType::SnesMouse, port)
|
||||||
{
|
{
|
||||||
_settings = _emu->GetSettings();
|
_settings = _emu->GetSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
ControllerType GetControllerType() override
|
|
||||||
{
|
|
||||||
return ControllerType::SnesMouse;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WriteRam(uint16_t addr, uint8_t value) override
|
void WriteRam(uint16_t addr, uint8_t value) override
|
||||||
{
|
{
|
||||||
StrobeProcessWrite(value);
|
StrobeProcessWrite(value);
|
||||||
|
|
|
@ -93,16 +93,11 @@ protected:
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SuperScope(Console* console, uint8_t port, KeyMappingSet keyMappings) : BaseControlDevice(console->GetEmulator(), port, keyMappings)
|
SuperScope(Console* console, uint8_t port, KeyMappingSet keyMappings) : BaseControlDevice(console->GetEmulator(), ControllerType::SuperScope, port, keyMappings)
|
||||||
{
|
{
|
||||||
_ppu = console->GetPpu().get();
|
_ppu = console->GetPpu().get();
|
||||||
}
|
}
|
||||||
|
|
||||||
ControllerType GetControllerType() override
|
|
||||||
{
|
|
||||||
return ControllerType::SuperScope;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t ReadRam(uint16_t addr) override
|
uint8_t ReadRam(uint16_t addr) override
|
||||||
{
|
{
|
||||||
uint8_t output = 0;
|
uint8_t output = 0;
|
||||||
|
|
|
@ -5,9 +5,10 @@
|
||||||
#include "Utilities/StringUtilities.h"
|
#include "Utilities/StringUtilities.h"
|
||||||
#include "Utilities/Serializer.h"
|
#include "Utilities/Serializer.h"
|
||||||
|
|
||||||
BaseControlDevice::BaseControlDevice(Emulator* emu, uint8_t port, KeyMappingSet keyMappingSet)
|
BaseControlDevice::BaseControlDevice(Emulator* emu, ControllerType type, uint8_t port, KeyMappingSet keyMappingSet)
|
||||||
{
|
{
|
||||||
_emu = emu;
|
_emu = emu;
|
||||||
|
_type = type;
|
||||||
_port = port;
|
_port = port;
|
||||||
_strobe = false;
|
_strobe = false;
|
||||||
_keyMappings = keyMappingSet.GetKeyMappingArray();
|
_keyMappings = keyMappingSet.GetKeyMappingArray();
|
||||||
|
@ -22,6 +23,11 @@ uint8_t BaseControlDevice::GetPort()
|
||||||
return _port;
|
return _port;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ControllerType BaseControlDevice::GetControllerType()
|
||||||
|
{
|
||||||
|
return _type;
|
||||||
|
}
|
||||||
|
|
||||||
void BaseControlDevice::SetStateFromInput()
|
void BaseControlDevice::SetStateFromInput()
|
||||||
{
|
{
|
||||||
ClearState();
|
ClearState();
|
||||||
|
|
|
@ -17,6 +17,7 @@ protected:
|
||||||
Emulator* _emu;
|
Emulator* _emu;
|
||||||
vector<KeyMapping> _keyMappings;
|
vector<KeyMapping> _keyMappings;
|
||||||
bool _strobe;
|
bool _strobe;
|
||||||
|
ControllerType _type;
|
||||||
uint8_t _port;
|
uint8_t _port;
|
||||||
SimpleLock _stateLock;
|
SimpleLock _stateLock;
|
||||||
|
|
||||||
|
@ -51,10 +52,11 @@ public:
|
||||||
static constexpr uint8_t ExpDevicePort2 = 7;
|
static constexpr uint8_t ExpDevicePort2 = 7;
|
||||||
static constexpr uint8_t PortCount = ExpDevicePort2 + 1;
|
static constexpr uint8_t PortCount = ExpDevicePort2 + 1;
|
||||||
|
|
||||||
BaseControlDevice(Emulator* emu, uint8_t port, KeyMappingSet keyMappingSet = KeyMappingSet());
|
BaseControlDevice(Emulator* emu, ControllerType type, uint8_t port, KeyMappingSet keyMappingSet = KeyMappingSet());
|
||||||
virtual ~BaseControlDevice();
|
virtual ~BaseControlDevice();
|
||||||
|
|
||||||
uint8_t GetPort();
|
uint8_t GetPort();
|
||||||
|
ControllerType GetControllerType();
|
||||||
|
|
||||||
bool IsPressed(uint8_t bit);
|
bool IsPressed(uint8_t bit);
|
||||||
MousePosition GetCoordinates();
|
MousePosition GetCoordinates();
|
||||||
|
@ -74,7 +76,6 @@ public:
|
||||||
void SetRawState(ControlDeviceState state);
|
void SetRawState(ControlDeviceState state);
|
||||||
ControlDeviceState GetRawState();
|
ControlDeviceState GetRawState();
|
||||||
|
|
||||||
virtual ControllerType GetControllerType() = 0;
|
|
||||||
virtual uint8_t ReadRam(uint16_t addr) = 0;
|
virtual uint8_t ReadRam(uint16_t addr) = 0;
|
||||||
virtual void WriteRam(uint16_t addr, uint8_t value) = 0;
|
virtual void WriteRam(uint16_t addr, uint8_t value) = 0;
|
||||||
|
|
||||||
|
|
|
@ -331,8 +331,7 @@ bool Emulator::LoadRom(VirtualFile romFile, VirtualFile patchFile, bool stopRom,
|
||||||
}
|
}
|
||||||
|
|
||||||
if(patchFile.IsValid()) {
|
if(patchFile.IsValid()) {
|
||||||
//TODO
|
_patchFile = patchFile;
|
||||||
//_patchPath = patchFile;
|
|
||||||
if(romFile.ApplyPatch(patchFile)) {
|
if(romFile.ApplyPatch(patchFile)) {
|
||||||
MessageManager::DisplayMessage("Patch", "ApplyingPatch", patchFile.GetFileName());
|
MessageManager::DisplayMessage("Patch", "ApplyingPatch", patchFile.GetFileName());
|
||||||
}
|
}
|
||||||
|
@ -478,6 +477,11 @@ uint64_t Emulator::GetMasterClock()
|
||||||
return _console->GetMasterClock();
|
return _console->GetMasterClock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t Emulator::GetMasterClockRate()
|
||||||
|
{
|
||||||
|
return _console->GetMasterClockRate();
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t Emulator::GetFrameCount()
|
uint32_t Emulator::GetFrameCount()
|
||||||
{
|
{
|
||||||
return _console->GetPpuFrame().FrameCount;
|
return _console->GetPpuFrame().FrameCount;
|
||||||
|
|
|
@ -129,6 +129,7 @@ public:
|
||||||
ConsoleType GetConsoleType();
|
ConsoleType GetConsoleType();
|
||||||
vector<CpuType> GetCpuTypes();
|
vector<CpuType> GetCpuTypes();
|
||||||
uint64_t GetMasterClock();
|
uint64_t GetMasterClock();
|
||||||
|
uint32_t GetMasterClockRate();
|
||||||
|
|
||||||
EmulatorLock AcquireLock();
|
EmulatorLock AcquireLock();
|
||||||
void Lock();
|
void Lock();
|
||||||
|
|
7
Core/Shared/Interfaces/IBattery.h
Normal file
7
Core/Shared/Interfaces/IBattery.h
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
class IBattery
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void SaveBattery() = 0;
|
||||||
|
};
|
|
@ -37,6 +37,7 @@ public:
|
||||||
virtual vector<CpuType> GetCpuTypes() = 0;
|
virtual vector<CpuType> GetCpuTypes() = 0;
|
||||||
|
|
||||||
virtual uint64_t GetMasterClock() = 0;
|
virtual uint64_t GetMasterClock() = 0;
|
||||||
|
virtual uint32_t GetMasterClockRate() = 0;
|
||||||
|
|
||||||
virtual double GetFrameDelay() = 0;
|
virtual double GetFrameDelay() = 0;
|
||||||
virtual double GetFps() = 0;
|
virtual double GetFps() = 0;
|
||||||
|
|
|
@ -144,12 +144,46 @@ struct AudioConfig
|
||||||
//Update ControllerTypeNames when changing this
|
//Update ControllerTypeNames when changing this
|
||||||
enum class ControllerType
|
enum class ControllerType
|
||||||
{
|
{
|
||||||
None = 0,
|
None,
|
||||||
SnesController = 1,
|
|
||||||
SnesMouse = 2,
|
//SNES controllers
|
||||||
SuperScope = 3,
|
SnesController,
|
||||||
Multitap = 4,
|
SnesMouse,
|
||||||
NesController = 5
|
SuperScope,
|
||||||
|
Multitap,
|
||||||
|
|
||||||
|
//NES controllers
|
||||||
|
NesController,
|
||||||
|
FamicomController,
|
||||||
|
NesZapper,
|
||||||
|
NesArkanoidController,
|
||||||
|
PowerPad,
|
||||||
|
SuborMouse,
|
||||||
|
VsZapper,
|
||||||
|
VirtualBoyController,
|
||||||
|
|
||||||
|
//NES/Famicon expansion devices
|
||||||
|
FourScore,
|
||||||
|
FamicomZapper,
|
||||||
|
FourPlayerAdapter,
|
||||||
|
FamicomArkanoidController,
|
||||||
|
OekaKidsTablet,
|
||||||
|
FamilyTrainerMat,
|
||||||
|
KonamiHyperShot,
|
||||||
|
FamilyBasicKeyboard,
|
||||||
|
PartyTap,
|
||||||
|
Pachinko,
|
||||||
|
ExcitingBoxing,
|
||||||
|
JissenMahjong,
|
||||||
|
SuborKeyboard,
|
||||||
|
BarcodeBattler,
|
||||||
|
HoriTrack,
|
||||||
|
BandaiHyperShot,
|
||||||
|
AsciiTurboFile,
|
||||||
|
BattleBox,
|
||||||
|
|
||||||
|
//Game Boy
|
||||||
|
GameboyController,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct KeyMapping
|
struct KeyMapping
|
||||||
|
@ -354,6 +388,7 @@ enum class VsDualOutputOption
|
||||||
struct NesConfig
|
struct NesConfig
|
||||||
{
|
{
|
||||||
ControllerConfig Controllers[5];
|
ControllerConfig Controllers[5];
|
||||||
|
uint32_t ZapperDetectionRadius = 0;
|
||||||
|
|
||||||
bool EnableHdPacks = true;
|
bool EnableHdPacks = true;
|
||||||
bool DisableGameDatabase = false;
|
bool DisableGameDatabase = false;
|
||||||
|
|
|
@ -18,15 +18,10 @@ protected:
|
||||||
public:
|
public:
|
||||||
enum Buttons { ResetButton = 0, PowerButton = 1 };
|
enum Buttons { ResetButton = 0, PowerButton = 1 };
|
||||||
|
|
||||||
SystemActionManager(Emulator* emu) : BaseControlDevice(emu, BaseControlDevice::ConsoleInputPort)
|
SystemActionManager(Emulator* emu) : BaseControlDevice(emu, ControllerType::None, BaseControlDevice::ConsoleInputPort)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
ControllerType GetControllerType() override
|
|
||||||
{
|
|
||||||
return ControllerType::None;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t ReadRam(uint16_t addr) override
|
uint8_t ReadRam(uint16_t addr) override
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -12,6 +12,7 @@ namespace Mesen.GUI.Config
|
||||||
{
|
{
|
||||||
//Input
|
//Input
|
||||||
[Reactive] public List<ControllerConfig> Controllers { get; set; } = new List<ControllerConfig> { new ControllerConfig(), new ControllerConfig(), new ControllerConfig(), new ControllerConfig(), new ControllerConfig() };
|
[Reactive] public List<ControllerConfig> Controllers { get; set; } = new List<ControllerConfig> { new ControllerConfig(), new ControllerConfig(), new ControllerConfig(), new ControllerConfig(), new ControllerConfig() };
|
||||||
|
[Reactive] public UInt32 ZapperDetectionRadius { get; set; } = 0;
|
||||||
|
|
||||||
//Video
|
//Video
|
||||||
[Reactive] public bool EnableHdPacks { get; set; } = true;
|
[Reactive] public bool EnableHdPacks { get; set; } = true;
|
||||||
|
@ -117,6 +118,7 @@ namespace Mesen.GUI.Config
|
||||||
this.Controllers[3].ToInterop(),
|
this.Controllers[3].ToInterop(),
|
||||||
this.Controllers[4].ToInterop()
|
this.Controllers[4].ToInterop()
|
||||||
},
|
},
|
||||||
|
ZapperDetectionRadius = ZapperDetectionRadius,
|
||||||
|
|
||||||
EnableHdPacks = EnableHdPacks,
|
EnableHdPacks = EnableHdPacks,
|
||||||
DisableGameDatabase = DisableGameDatabase,
|
DisableGameDatabase = DisableGameDatabase,
|
||||||
|
@ -246,6 +248,7 @@ namespace Mesen.GUI.Config
|
||||||
{
|
{
|
||||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)]
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)]
|
||||||
public InteropControllerConfig[] Controllers;
|
public InteropControllerConfig[] Controllers;
|
||||||
|
public UInt32 ZapperDetectionRadius;
|
||||||
|
|
||||||
[MarshalAs(UnmanagedType.I1)] public bool EnableHdPacks;
|
[MarshalAs(UnmanagedType.I1)] public bool EnableHdPacks;
|
||||||
[MarshalAs(UnmanagedType.I1)] public bool DisableGameDatabase;
|
[MarshalAs(UnmanagedType.I1)] public bool DisableGameDatabase;
|
||||||
|
|
Loading…
Add table
Reference in a new issue