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>
|
||||
<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="Shared\Audio\stdafx.h" />
|
||||
<ClInclude Include="Shared\BaseControlManager.h" />
|
||||
|
@ -51,6 +74,7 @@
|
|||
<ClInclude Include="Gameboy\GbControlManager.h" />
|
||||
<ClInclude Include="Gameboy\stdafx.h" />
|
||||
<ClInclude Include="Shared\Interfaces\IAudioProvider.h" />
|
||||
<ClInclude Include="Shared\Interfaces\IBattery.h" />
|
||||
<ClInclude Include="Shared\Interfaces\IControlManager.h" />
|
||||
<ClInclude Include="MemoryOperationType.h" />
|
||||
<ClInclude Include="Shared\Interfaces\stdafx.h" />
|
||||
|
|
|
@ -734,6 +734,30 @@
|
|||
<ClInclude Include="Netplay\stdafx.h" />
|
||||
<ClInclude Include="Shared\BaseControlManager.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>
|
||||
<ClCompile Include="SNES\Cpu.cpp">
|
||||
|
|
|
@ -463,3 +463,8 @@ uint64_t Gameboy::GetMasterClock()
|
|||
{
|
||||
return _memoryManager->GetCycleCount();
|
||||
}
|
||||
|
||||
uint32_t Gameboy::GetMasterClockRate()
|
||||
{
|
||||
return 20971520;
|
||||
}
|
||||
|
|
|
@ -117,5 +117,6 @@ public:
|
|||
virtual AddressInfo GetRelativeAddress(AddressInfo absAddress, CpuType cpuType) override;
|
||||
|
||||
// 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:
|
||||
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;
|
||||
_microphoneEnabled = false;
|
||||
//_microphoneEnabled = port == 1 && _console->GetSettings()->GetConsoleType() == ConsoleType::Famicom;
|
||||
_microphoneEnabled = port == 1 && type == ControllerType::FamicomController;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
uint32_t NesConsole::GetMasterClockRate()
|
||||
{
|
||||
return NesCpu::ClockRateNtsc;
|
||||
}
|
||||
|
|
|
@ -77,5 +77,6 @@ public:
|
|||
virtual AddressInfo GetAbsoluteAddress(AddressInfo relAddress) 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/NesConsole.h"
|
||||
#include "NES/NesMemoryManager.h"
|
||||
#include "NES/Input/NesController.h"
|
||||
#include "SNES/Input/SnesController.h"
|
||||
#include "Shared/EmuSettings.h"
|
||||
#include "Shared/Interfaces/IKeyManager.h"
|
||||
#include "Shared/Interfaces/IInputProvider.h"
|
||||
|
@ -13,30 +11,31 @@
|
|||
#include "Shared/Emulator.h"
|
||||
#include "Shared/KeyManager.h"
|
||||
#include "Shared/SystemActionManager.h"
|
||||
/*#include "Zapper.h"
|
||||
#include "ArkanoidController.h"
|
||||
#include "OekaKidsTablet.h"
|
||||
#include "FourScore.h"
|
||||
#include "SnesController.h"
|
||||
#include "SnesMouse.h"
|
||||
#include "PowerPad.h"
|
||||
#include "FamilyMatTrainer.h"
|
||||
#include "KonamiHyperShot.h"
|
||||
#include "FamilyBasicKeyboard.h"
|
||||
#include "FamilyBasicDataRecorder.h"
|
||||
#include "PartyTap.h"
|
||||
#include "PachinkoController.h"
|
||||
#include "ExcitingBoxingController.h"
|
||||
#include "SuborKeyboard.h"
|
||||
#include "SuborMouse.h"
|
||||
#include "JissenMahjongController.h"
|
||||
#include "BarcodeBattlerReader.h"
|
||||
#include "HoriTrack.h"
|
||||
#include "BandaiHyperShot.h"
|
||||
#include "VsZapper.h"
|
||||
#include "AsciiTurboFile.h"
|
||||
#include "BattleBox.h"
|
||||
#include "VbController.h"*/
|
||||
#include "NES/Input/NesController.h"
|
||||
#include "SNES/Input/SnesController.h"
|
||||
#include "SNES/Input/SnesMouse.h"
|
||||
#include "NES/Input/Zapper.h"
|
||||
#include "NES/Input/ArkanoidController.h"
|
||||
#include "NES/Input/OekaKidsTablet.h"
|
||||
#include "NES/Input/FourScore.h"
|
||||
#include "NES/Input/PowerPad.h"
|
||||
#include "NES/Input/FamilyMatTrainer.h"
|
||||
#include "NES/Input/KonamiHyperShot.h"
|
||||
#include "NES/Input/FamilyBasicKeyboard.h"
|
||||
#include "NES/Input/FamilyBasicDataRecorder.h"
|
||||
#include "NES/Input/PartyTap.h"
|
||||
#include "NES/Input/PachinkoController.h"
|
||||
#include "NES/Input/ExcitingBoxingController.h"
|
||||
#include "NES/Input/SuborKeyboard.h"
|
||||
#include "NES/Input/SuborMouse.h"
|
||||
#include "NES/Input/JissenMahjongController.h"
|
||||
#include "NES/Input/BarcodeBattlerReader.h"
|
||||
#include "NES/Input/HoriTrack.h"
|
||||
#include "NES/Input/BandaiHyperShot.h"
|
||||
#include "NES/Input/VsZapper.h"
|
||||
#include "NES/Input/AsciiTurboFile.h"
|
||||
#include "NES/Input/BattleBox.h"
|
||||
#include "NES/Input/VirtualBoyController.h"
|
||||
|
||||
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;
|
||||
|
||||
NesConfig cfg = _emu->GetSettings()->GetNesConfig();
|
||||
KeyMappingSet keys = cfg.Controllers[port].Keys;
|
||||
|
||||
switch(type) {
|
||||
case ControllerType::None: break;
|
||||
case ControllerType::NesController: device.reset(new NesController(_emu, port, cfg.Controllers[port].Keys)); break;
|
||||
//case ControllerType::Zapper: device.reset(new Zapper(console, port)); break;
|
||||
//case ControllerType::ArkanoidController: device.reset(new ArkanoidController(console, port)); break;
|
||||
case ControllerType::SnesController: device.reset(new SnesController(_emu, port, cfg.Controllers[port].Keys)); break;
|
||||
/*case ControllerType::PowerPad: device.reset(new PowerPad(console, port, console->GetSettings()->GetControllerKeys(port))); break;
|
||||
case ControllerType::SnesMouse: device.reset(new SnesMouse(console, port)); break;
|
||||
case ControllerType::SuborMouse: device.reset(new SuborMouse(console, port)); break;
|
||||
case ControllerType::VsZapper: device.reset(new VsZapper(console, port)); break;
|
||||
case ControllerType::VbController: device.reset(new VbController(console, port, console->GetSettings()->GetControllerKeys(port))); break;*/
|
||||
}
|
||||
|
||||
return device;
|
||||
}
|
||||
case ControllerType::NesController: device.reset(new NesController(_emu, type, port, keys)); break;
|
||||
case ControllerType::FamicomController: device.reset(new NesController(_emu, type, port, keys)); break;
|
||||
case ControllerType::NesZapper: device.reset(new Zapper(_console.get(), type, port)); break;
|
||||
case ControllerType::NesArkanoidController: device.reset(new ArkanoidController(_emu, type, port)); break;
|
||||
case ControllerType::SnesController: device.reset(new SnesController(_emu, port, keys)); break;
|
||||
case ControllerType::PowerPad: device.reset(new PowerPad(_emu, type, port, keys)); break;
|
||||
case ControllerType::SnesMouse: device.reset(new SnesMouse(_emu, port)); break;
|
||||
case ControllerType::SuborMouse: device.reset(new SuborMouse(_emu, port)); break;
|
||||
case ControllerType::VsZapper: device.reset(new VsZapper(_console.get(), port)); break;
|
||||
case ControllerType::VirtualBoyController: device.reset(new VirtualBoyController(_emu, port, keys)); break;
|
||||
|
||||
shared_ptr<BaseControlDevice> NesControlManager::CreateExpansionDevice(ExpansionPortDevice type)
|
||||
{
|
||||
shared_ptr<BaseControlDevice> device;
|
||||
//Exp port devices
|
||||
case ControllerType::FamicomZapper: device.reset(new Zapper(_console.get(), type, BaseControlDevice::ExpDevicePort)); break;
|
||||
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 ExpansionPortDevice::Zapper: device.reset(new Zapper(console, BaseControlDevice::ExpDevicePort)); break;
|
||||
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:
|
||||
case ControllerType::FourScore: //TODO
|
||||
case ControllerType::FourPlayerAdapter: //TODO
|
||||
default: break;
|
||||
}*/
|
||||
}
|
||||
|
||||
return device;
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ shared_ptr<BaseControlDevice> ControlManager::CreateControllerDevice(ControllerT
|
|||
switch(type) {
|
||||
case ControllerType::None: 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::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[1] = keyMappings2.TurboSpeed;
|
||||
|
@ -108,11 +108,6 @@ Multitap::Multitap(Console* console, uint8_t port, KeyMappingSet keyMappings1, K
|
|||
_internalRegs = console->GetInternalRegisters().get();
|
||||
}
|
||||
|
||||
ControllerType Multitap::GetControllerType()
|
||||
{
|
||||
return ControllerType::Multitap;
|
||||
}
|
||||
|
||||
void Multitap::SetControllerState(uint8_t controllerNumber, ControlDeviceState state)
|
||||
{
|
||||
SnesController controller(_emu, 0, KeyMappingSet());
|
||||
|
|
|
@ -29,8 +29,6 @@ protected:
|
|||
public:
|
||||
Multitap(Console* console, uint8_t port, KeyMappingSet keyMappings1, KeyMappingSet keyMappings2, KeyMappingSet keyMappings3, KeyMappingSet keyMappings4);
|
||||
|
||||
ControllerType GetControllerType() override;
|
||||
|
||||
void SetControllerState(uint8_t controllerNumber, ControlDeviceState state);
|
||||
|
||||
uint8_t ReadRam(uint16_t addr) override;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#include "SNES/Input/SnesController.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;
|
||||
}
|
||||
|
@ -71,11 +71,6 @@ void SnesController::RefreshStateBuffer()
|
|||
_stateBuffer = (uint32_t)ToByte();
|
||||
}
|
||||
|
||||
ControllerType SnesController::GetControllerType()
|
||||
{
|
||||
return ControllerType::SnesController;
|
||||
}
|
||||
|
||||
uint8_t SnesController::ReadRam(uint16_t addr)
|
||||
{
|
||||
uint8_t output = 0;
|
||||
|
|
|
@ -21,7 +21,6 @@ public:
|
|||
|
||||
SnesController(Emulator* emu, uint8_t port, KeyMappingSet keyMappings);
|
||||
|
||||
ControllerType GetControllerType() override;
|
||||
uint8_t ReadRam(uint16_t addr) override;
|
||||
void WriteRam(uint16_t addr, uint8_t value) override;
|
||||
};
|
|
@ -1,6 +1,5 @@
|
|||
#pragma once
|
||||
#include "stdafx.h"
|
||||
#include "SNES/Console.h"
|
||||
#include "Shared/BaseControlDevice.h"
|
||||
#include "Shared/Interfaces/IKeyManager.h"
|
||||
#include "Shared/KeyManager.h"
|
||||
|
@ -42,16 +41,11 @@ protected:
|
|||
public:
|
||||
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();
|
||||
}
|
||||
|
||||
ControllerType GetControllerType() override
|
||||
{
|
||||
return ControllerType::SnesMouse;
|
||||
}
|
||||
|
||||
void WriteRam(uint16_t addr, uint8_t value) override
|
||||
{
|
||||
StrobeProcessWrite(value);
|
||||
|
|
|
@ -93,16 +93,11 @@ protected:
|
|||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
ControllerType GetControllerType() override
|
||||
{
|
||||
return ControllerType::SuperScope;
|
||||
}
|
||||
|
||||
uint8_t ReadRam(uint16_t addr) override
|
||||
{
|
||||
uint8_t output = 0;
|
||||
|
|
|
@ -5,9 +5,10 @@
|
|||
#include "Utilities/StringUtilities.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;
|
||||
_type = type;
|
||||
_port = port;
|
||||
_strobe = false;
|
||||
_keyMappings = keyMappingSet.GetKeyMappingArray();
|
||||
|
@ -22,6 +23,11 @@ uint8_t BaseControlDevice::GetPort()
|
|||
return _port;
|
||||
}
|
||||
|
||||
ControllerType BaseControlDevice::GetControllerType()
|
||||
{
|
||||
return _type;
|
||||
}
|
||||
|
||||
void BaseControlDevice::SetStateFromInput()
|
||||
{
|
||||
ClearState();
|
||||
|
|
|
@ -17,6 +17,7 @@ protected:
|
|||
Emulator* _emu;
|
||||
vector<KeyMapping> _keyMappings;
|
||||
bool _strobe;
|
||||
ControllerType _type;
|
||||
uint8_t _port;
|
||||
SimpleLock _stateLock;
|
||||
|
||||
|
@ -51,10 +52,11 @@ public:
|
|||
static constexpr uint8_t ExpDevicePort2 = 7;
|
||||
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();
|
||||
|
||||
uint8_t GetPort();
|
||||
ControllerType GetControllerType();
|
||||
|
||||
bool IsPressed(uint8_t bit);
|
||||
MousePosition GetCoordinates();
|
||||
|
@ -74,7 +76,6 @@ public:
|
|||
void SetRawState(ControlDeviceState state);
|
||||
ControlDeviceState GetRawState();
|
||||
|
||||
virtual ControllerType GetControllerType() = 0;
|
||||
virtual uint8_t ReadRam(uint16_t addr) = 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()) {
|
||||
//TODO
|
||||
//_patchPath = patchFile;
|
||||
_patchFile = patchFile;
|
||||
if(romFile.ApplyPatch(patchFile)) {
|
||||
MessageManager::DisplayMessage("Patch", "ApplyingPatch", patchFile.GetFileName());
|
||||
}
|
||||
|
@ -478,6 +477,11 @@ uint64_t Emulator::GetMasterClock()
|
|||
return _console->GetMasterClock();
|
||||
}
|
||||
|
||||
uint32_t Emulator::GetMasterClockRate()
|
||||
{
|
||||
return _console->GetMasterClockRate();
|
||||
}
|
||||
|
||||
uint32_t Emulator::GetFrameCount()
|
||||
{
|
||||
return _console->GetPpuFrame().FrameCount;
|
||||
|
|
|
@ -129,6 +129,7 @@ public:
|
|||
ConsoleType GetConsoleType();
|
||||
vector<CpuType> GetCpuTypes();
|
||||
uint64_t GetMasterClock();
|
||||
uint32_t GetMasterClockRate();
|
||||
|
||||
EmulatorLock AcquireLock();
|
||||
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 uint64_t GetMasterClock() = 0;
|
||||
virtual uint32_t GetMasterClockRate() = 0;
|
||||
|
||||
virtual double GetFrameDelay() = 0;
|
||||
virtual double GetFps() = 0;
|
||||
|
|
|
@ -144,12 +144,46 @@ struct AudioConfig
|
|||
//Update ControllerTypeNames when changing this
|
||||
enum class ControllerType
|
||||
{
|
||||
None = 0,
|
||||
SnesController = 1,
|
||||
SnesMouse = 2,
|
||||
SuperScope = 3,
|
||||
Multitap = 4,
|
||||
NesController = 5
|
||||
None,
|
||||
|
||||
//SNES controllers
|
||||
SnesController,
|
||||
SnesMouse,
|
||||
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
|
||||
|
@ -354,6 +388,7 @@ enum class VsDualOutputOption
|
|||
struct NesConfig
|
||||
{
|
||||
ControllerConfig Controllers[5];
|
||||
uint32_t ZapperDetectionRadius = 0;
|
||||
|
||||
bool EnableHdPacks = true;
|
||||
bool DisableGameDatabase = false;
|
||||
|
|
|
@ -18,15 +18,10 @@ protected:
|
|||
public:
|
||||
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
|
||||
{
|
||||
return 0;
|
||||
|
|
|
@ -12,6 +12,7 @@ namespace Mesen.GUI.Config
|
|||
{
|
||||
//Input
|
||||
[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
|
||||
[Reactive] public bool EnableHdPacks { get; set; } = true;
|
||||
|
@ -117,6 +118,7 @@ namespace Mesen.GUI.Config
|
|||
this.Controllers[3].ToInterop(),
|
||||
this.Controllers[4].ToInterop()
|
||||
},
|
||||
ZapperDetectionRadius = ZapperDetectionRadius,
|
||||
|
||||
EnableHdPacks = EnableHdPacks,
|
||||
DisableGameDatabase = DisableGameDatabase,
|
||||
|
@ -246,6 +248,7 @@ namespace Mesen.GUI.Config
|
|||
{
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)]
|
||||
public InteropControllerConfig[] Controllers;
|
||||
public UInt32 ZapperDetectionRadius;
|
||||
|
||||
[MarshalAs(UnmanagedType.I1)] public bool EnableHdPacks;
|
||||
[MarshalAs(UnmanagedType.I1)] public bool DisableGameDatabase;
|
||||
|
|
Loading…
Add table
Reference in a new issue