From 212f17215c5c0ca12d462146ad8bacd45a2abb54 Mon Sep 17 00:00:00 2001 From: Persune <54422576+Gumball2415@users.noreply.github.com> Date: Sat, 14 Aug 2021 20:36:24 +0800 Subject: [PATCH 1/5] Reduce /A13 aliasing PPU /A13 changes at the PPU's clock rate, which is 3x that of the CPU clock rate. --- Core/Console.cpp | 3 ++- Core/PPU.cpp | 2 +- Core/PPU.h | 2 +- Core/SoundMixer.cpp | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Core/Console.cpp b/Core/Console.cpp index fb6a1c4e..68b54b7d 100644 --- a/Core/Console.cpp +++ b/Core/Console.cpp @@ -473,7 +473,8 @@ void Console::ProcessCpuClock() void Console::ProcessInterferenceAudio() { - _InvA13 = (_ppu->_A13pinLow == 1) ? 0 : 1; // invert relative to 2A03 + _InvA13 = _ppu->_A13pinLowSum; + _ppu->_A13pinLowSum = 0; _controlManager->GetInvOE1(_controlManager->_address); _InvOE1 = (_controlManager->_OE1pinLow == 1) ? 0 : 1; // invert relative to 2A03 diff --git a/Core/PPU.cpp b/Core/PPU.cpp index 81b6edda..5edbdd9c 100644 --- a/Core/PPU.cpp +++ b/Core/PPU.cpp @@ -466,7 +466,7 @@ void PPU::WriteRAM(uint16_t addr, uint8_t value) void PPU::GetInvA13() { // pull level high when PPU/VRAM addr bit 13 is low - _A13pinLow = (_ppuBusAddress & 0x2000) ? 0 : 1; + _A13pinLowSum += (_ppuBusAddress & 0x2000) ? 1 : 0; // invert relative to 2A03 } uint8_t PPU::ReadPaletteRAM(uint16_t addr) diff --git a/Core/PPU.h b/Core/PPU.h index 7d097003..f68f9454 100644 --- a/Core/PPU.h +++ b/Core/PPU.h @@ -180,7 +180,7 @@ class PPU : public IMemoryHandler, public Snapshotable static constexpr int32_t OutputBufferSize = 256*240*2; static constexpr int32_t OamDecayCycleCount = 3000; - uint8_t _A13pinLow; + uint8_t _A13pinLowSum; PPU(shared_ptr console); virtual ~PPU(); diff --git a/Core/SoundMixer.cpp b/Core/SoundMixer.cpp index 7446f193..186e62da 100644 --- a/Core/SoundMixer.cpp +++ b/Core/SoundMixer.cpp @@ -277,7 +277,7 @@ int16_t SoundMixer::GetOutputVolume(bool forRightChannel) #endif GetChannelOutput(AudioChannel::EPSM_L, forRightChannel) * 4 + GetChannelOutput(AudioChannel::EPSM_R, forRightChannel) * 4 + - GetChannelOutput(AudioChannel::InvA13, forRightChannel) * 20 + + (GetChannelOutput(AudioChannel::InvA13, forRightChannel) * 20) / 3.0 + // 3 PPU samples per CPU clock GetChannelOutput(AudioChannel::InvOE1, forRightChannel) * 1000 ); } From 5b58c011be68d239ed69daaa29e5a1d01a3bcc1c Mon Sep 17 00:00:00 2001 From: Persune <54422576+Gumball2415@users.noreply.github.com> Date: Sun, 15 Aug 2021 00:22:20 +0800 Subject: [PATCH 2/5] Refactor code --- Core/Console.cpp | 3 +-- Core/ControlManager.cpp | 5 +++-- Core/ControlManager.h | 4 ++-- Core/PPU.cpp | 2 +- Core/SoundMixer.cpp | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Core/Console.cpp b/Core/Console.cpp index 68b54b7d..ee61be78 100644 --- a/Core/Console.cpp +++ b/Core/Console.cpp @@ -476,8 +476,7 @@ void Console::ProcessInterferenceAudio() _InvA13 = _ppu->_A13pinLowSum; _ppu->_A13pinLowSum = 0; - _controlManager->GetInvOE1(_controlManager->_address); - _InvOE1 = (_controlManager->_OE1pinLow == 1) ? 0 : 1; // invert relative to 2A03 + _InvOE1 = !_controlManager->GetInvOE1(_controlManager->_address); // invert relative to 2A03 if (_controlManager->_strobed == true) _controlManager->_strobed = false; diff --git a/Core/ControlManager.cpp b/Core/ControlManager.cpp index 9e80e937..bc5045ef 100644 --- a/Core/ControlManager.cpp +++ b/Core/ControlManager.cpp @@ -351,11 +351,12 @@ void ControlManager::WriteRAM(uint16_t addr, uint8_t value) } } -void ControlManager::GetInvOE1(uint16_t addr) +bool ControlManager::GetInvOE1(uint16_t addr) { // pull low for only one clock if (addr == 0x4016) - _OE1pinLow = (_strobed) ? 0 : 1; + _OE1pinLow = !_strobed; + return _OE1pinLow; } void ControlManager::Reset(bool softReset) diff --git a/Core/ControlManager.h b/Core/ControlManager.h index 976ecb9e..1b590734 100644 --- a/Core/ControlManager.h +++ b/Core/ControlManager.h @@ -43,7 +43,7 @@ protected: virtual uint8_t GetOpenBusMask(uint8_t port); public: - uint8_t _OE1pinLow; + bool _OE1pinLow; uint16_t _address; bool _strobed; @@ -85,5 +85,5 @@ public: virtual uint8_t ReadRAM(uint16_t addr) override; virtual void WriteRAM(uint16_t addr, uint8_t value) override; - void GetInvOE1(uint16_t addr); + bool GetInvOE1(uint16_t addr); }; diff --git a/Core/PPU.cpp b/Core/PPU.cpp index 5edbdd9c..1ee1d1bb 100644 --- a/Core/PPU.cpp +++ b/Core/PPU.cpp @@ -466,7 +466,7 @@ void PPU::WriteRAM(uint16_t addr, uint8_t value) void PPU::GetInvA13() { // pull level high when PPU/VRAM addr bit 13 is low - _A13pinLowSum += (_ppuBusAddress & 0x2000) ? 1 : 0; // invert relative to 2A03 + _A13pinLowSum += (bool)(_ppuBusAddress & 0x2000); // invert relative to 2A03 } uint8_t PPU::ReadPaletteRAM(uint16_t addr) diff --git a/Core/SoundMixer.cpp b/Core/SoundMixer.cpp index 186e62da..854e2cda 100644 --- a/Core/SoundMixer.cpp +++ b/Core/SoundMixer.cpp @@ -278,7 +278,7 @@ int16_t SoundMixer::GetOutputVolume(bool forRightChannel) GetChannelOutput(AudioChannel::EPSM_L, forRightChannel) * 4 + GetChannelOutput(AudioChannel::EPSM_R, forRightChannel) * 4 + (GetChannelOutput(AudioChannel::InvA13, forRightChannel) * 20) / 3.0 + // 3 PPU samples per CPU clock - GetChannelOutput(AudioChannel::InvOE1, forRightChannel) * 1000 + GetChannelOutput(AudioChannel::InvOE1, forRightChannel) * 100 ); } From 649a62e7e13737fad45d9f46be732f352f7f3a66 Mon Sep 17 00:00:00 2001 From: Perkka2 <36314461+Perkka2@users.noreply.github.com> Date: Thu, 26 Aug 2021 15:03:02 +0200 Subject: [PATCH 3/5] Added basic EPSM IRQ behaviour Added IRQ's for EPSM still WIP but should work Some cleanup of build warnings --- Core/BaseMapper.cpp | 4 +- Core/EPSMAudio.h | 115 ++++++++++++++++++++++++++++++++++++++--- Core/MemoryManager.cpp | 2 +- Core/Types.h | 1 + Core/Vrc7Audio.h | 1 - 5 files changed, 113 insertions(+), 10 deletions(-) diff --git a/Core/BaseMapper.cpp b/Core/BaseMapper.cpp index d7785537..ff19cf62 100644 --- a/Core/BaseMapper.cpp +++ b/Core/BaseMapper.cpp @@ -14,7 +14,7 @@ #include "CPU.h" void BaseMapper::WriteRegister(uint16_t addr, uint8_t value) { } -void BaseMapper::WriteEPSM(uint16_t addr, uint8_t value) { _epsmaudio->WriteRegister(addr, value); } +void BaseMapper::WriteEPSM(uint16_t addr, uint8_t value) {_epsmaudio->WriteRegister(addr, value); } uint8_t BaseMapper::ReadRegister(uint16_t addr) { return 0; } void BaseMapper::InitMapper(RomData &romData) { } void BaseMapper::Reset(bool softReset) { } @@ -787,7 +787,7 @@ uint8_t BaseMapper::DebugReadRAM(uint16_t addr) void BaseMapper::WriteRAM(uint16_t addr, uint8_t value) { if((addr == 0x4016) & (_console->GetCpu()->GetCycleCount() % 2 == 1)){ WriteEPSM(addr, value); } - if ((addr >= 0x401c && addr <= 0x401f)) { WriteEPSM(addr, value); } + if ((addr >= 0x401c && addr <= 0x401f)) {WriteEPSM(addr, value); } if(_isWriteRegisterAddr[addr]) { if(_hasBusConflicts) { uint8_t prgValue = _prgPages[addr >> 8][(uint8_t)addr]; diff --git a/Core/EPSMAudio.h b/Core/EPSMAudio.h index 9aff336e..9a6ed86a 100644 --- a/Core/EPSMAudio.h +++ b/Core/EPSMAudio.h @@ -5,6 +5,7 @@ #include "BaseExpansionAudio.h" #include "SSGAudio.h" #include "Console.h" +#include "Cpu.h" #include #include "ym3438.h" @@ -19,9 +20,22 @@ private: int16_t _lastOutputs[2]; int16_t _currentOutputs[2]; uint8_t writeValue; - int16_t writeAddr; + uint16_t writeAddr; + uint16_t irqATimer; + uint16_t irqBTimer; + uint16_t irqACurrentTimer; + uint16_t irqBCurrentTimer; + uint8_t irqATimerEnable; + uint8_t irqBTimerEnable; + uint8_t irqAHighValue; + uint8_t irqALowValue; + uint8_t irqBValue; + uint16_t currentRegister; + double _clock; + double _clockIRQ; + double _cycleCountIRQ = 0; static constexpr uint8_t cycleCount = 24; @@ -39,7 +53,6 @@ private: void UpdateOutputLevel() { - int16_t summedOutput = 0; for (size_t x = 0; x < 2; x++) { _console->GetApu()->AddExpansionAudioDelta(x == 0 ? AudioChannel::EPSM_L : AudioChannel::EPSM_R, _currentOutputs[x] - _lastOutputs[x]); @@ -69,6 +82,71 @@ private: }; } + + void WriteToChipIRQ(uint16_t addr, uint8_t value) + { + switch (addr) { + case 0xC000: + case 0xC002: + currentRegister = value; + break; + + case 0xE000: + if (currentRegister == 0x24) { + //Timer A High 8 bits + //std::cout << "Timer A High 8 bits" << std::endl; + irqAHighValue = value; + } + if (currentRegister == 0x25) { + //Timer A Low 2 bits + //std::cout << "Timer A Low 2 bits" << std::endl; + irqALowValue = (value & 0x3); + } + if (currentRegister == 0x26) { + //Timer B 8 bits + //std::cout << "Timer B 8 bits" << std::endl; + irqBValue = value; + } + if ((currentRegister == 0x27) && ((value & 0x5)|(value & 0xA))) { + //Load+Enable IRQ (0xA = TimerB, 0x5 = TimerA) + //std::cout << "Load+Enable IRQ" << std::endl; + if ((currentRegister == 0x27) && (value & 0x5)) { + irqATimer = (uint16_t(irqAHighValue) << 2) | irqALowValue; + irqACurrentTimer = 72 * (1024 - irqATimer) * 2; + irqATimerEnable = 1; + //std::cout << "Load+Enable IRQ A" << std::endl; + } + if ((currentRegister == 0x27) && (value & 0xA)) { + irqBTimer = 1152 * (256 - irqBValue) * 2; + irqBCurrentTimer = irqBTimer; + irqBTimerEnable = 1; + //std::cout << "Load+Enable IRQ B " << irqBCurrentTimer << std::endl; + } + } + if ((currentRegister == 0x27) && (value & 0x30)) { + //Enable/Reset IRQ + //std::cout << std::hex << uint16_t(value) << "Reset IRQ" << std::endl; + _console->GetCpu()->ClearIrqSource(IRQSource::EPSM); + irqATimerEnable = 0; + irqBTimerEnable = 0; + } + if ((currentRegister == 0x29) && (value & 0x3)) { + //enable IRQ's + //std::cout << "enable IRQ's" << std::endl; + } + break; + case 0xE002: + /*if (currentRegister == 0x10) { + std::cout << "0x10" << std::endl; + }*/ + break; + } + + //irqBValue = value; + //std::cout << std::hex << irqBValue << std::endl; + + } + uint32_t getClockFrequency() { return _console->GetSettings()->GetEPSMClockFrequency() / 6; @@ -92,6 +170,29 @@ protected: EPSMSSGAudio::ClockAudio(); _clock += getClockFrequency() / (double)_console->GetCpu()->GetClockRate(_console->GetModel()); + _clockIRQ += (getClockFrequency()*6) / (double)_console->GetCpu()->GetClockRate(_console->GetModel()); + while (_clockIRQ >= _cycleCountIRQ) { + _cycleCountIRQ++; + //std::cout << _cycleCountIRQ << std::endl; + if (irqATimerEnable) { + irqACurrentTimer--; + if (!irqACurrentTimer) { + //std::cout << "***IRQ***" << std::endl; + irqATimerEnable = 0; + _console->GetCpu()->SetIrqSource(IRQSource::EPSM); + } + + } + if (irqBTimerEnable) { + irqBCurrentTimer--; + if (!irqBCurrentTimer) { + //std::cout << "***IRQ***" << std::endl; + irqBTimerEnable = 0; + _console->GetCpu()->SetIrqSource(IRQSource::EPSM); + } + + } + } while (_clock >= cycleCount) { @@ -117,7 +218,6 @@ protected: if(input.wrote) { input.wrote = false; - OPN2_Write(&_chip, input.addr, input.data); } } @@ -131,9 +231,9 @@ protected: } } - virtual uint32_t GetSSGClockFrequency() + virtual uint32_t GetSSGClockFrequency() override { - return EPSMSSGAudio::GetSSGClockFrequency() * (_console->GetSettings()->GetEPSMClockFrequency() / 3579545.0 ); + return EPSMSSGAudio::GetSSGClockFrequency() * (_console->GetSettings()->GetEPSMClockFrequency() / 3579545 ); } public: @@ -144,7 +244,10 @@ public: _inputBuffer = {}; _clock = 0; + _clockIRQ = 0; + irqATimerEnable = 0; + irqBTimerEnable = 0; OPN2_Reset(&_chip); OPN2_SetChipType(0); } @@ -182,13 +285,13 @@ public: if (addr == 0x401d) { addr = 0xE000; } if (addr == 0x401e) { addr = 0xC002; } if (addr == 0x401f) { addr = 0xE002; } - switch(addr) { case 0xC000: case 0xE000: case 0xC002: case 0xE002: + WriteToChipIRQ(addr, value); const uint8_t a0 = (addr & 0xF000) == 0xE000; const uint8_t a1 = !!(addr & 0xF); EPSMSSGAudio::WriteRegister(addr, value); diff --git a/Core/MemoryManager.cpp b/Core/MemoryManager.cpp index ce330890..1d642392 100644 --- a/Core/MemoryManager.cpp +++ b/Core/MemoryManager.cpp @@ -133,7 +133,7 @@ void MemoryManager::Write(uint16_t addr, uint8_t value, MemoryOperationType oper { if(_console->DebugProcessRamOperation(operationType, addr, value)) { _ramWriteHandlers[addr]->WriteRAM(addr, value); - if ((addr == 0x4016) | (addr >= 0x401c && addr <= 0x401f)) { + if ((addr == 0x4016) /*| (addr >= 0x401c && addr <= 0x401f)*/) { _ramWriteHandlers[0xE000]->WriteRAM(addr, value); } } diff --git a/Core/Types.h b/Core/Types.h index 0d3d0c9a..6da8021a 100644 --- a/Core/Types.h +++ b/Core/Types.h @@ -30,6 +30,7 @@ enum class IRQSource FrameCounter = 2, DMC = 4, FdsDisk = 8, + EPSM = 16, }; enum class MemoryOperation diff --git a/Core/Vrc7Audio.h b/Core/Vrc7Audio.h index 0c5c6b78..97564086 100644 --- a/Core/Vrc7Audio.h +++ b/Core/Vrc7Audio.h @@ -41,7 +41,6 @@ private: void UpdateOutputLevel() { - int16_t summedOutput = 0; _console->GetApu()->AddExpansionAudioDelta(AudioChannel::VRC7, _currentOutput - _lastOutput); _lastOutput = _currentOutput; } From b344199fc303ab7b7324c571d8bc59e3c69a3c69 Mon Sep 17 00:00:00 2001 From: Perkka2 <36314461+Perkka2@users.noreply.github.com> Date: Thu, 26 Aug 2021 15:55:35 +0200 Subject: [PATCH 4/5] Fix Linux build Error --- Core/EPSMAudio.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/EPSMAudio.h b/Core/EPSMAudio.h index 9a6ed86a..b7e355d1 100644 --- a/Core/EPSMAudio.h +++ b/Core/EPSMAudio.h @@ -5,7 +5,7 @@ #include "BaseExpansionAudio.h" #include "SSGAudio.h" #include "Console.h" -#include "Cpu.h" +#include "CPU.h" #include #include "ym3438.h" From b746ef932ee795689d1fb098f89358d14d9ab582 Mon Sep 17 00:00:00 2001 From: Perkka2 <36314461+Perkka2@users.noreply.github.com> Date: Sat, 4 Sep 2021 21:42:47 +0200 Subject: [PATCH 5/5] Code cleanup for EPSM addressing Added cleaner custom mapper support for EPSM --- Core/EPSMAudio.h | 92 +++++++++++++++++++++++------------------------- 1 file changed, 44 insertions(+), 48 deletions(-) diff --git a/Core/EPSMAudio.h b/Core/EPSMAudio.h index b7e355d1..50789aa1 100644 --- a/Core/EPSMAudio.h +++ b/Core/EPSMAudio.h @@ -86,12 +86,12 @@ private: void WriteToChipIRQ(uint16_t addr, uint8_t value) { switch (addr) { - case 0xC000: - case 0xC002: + case 0x0: + case 0x2: currentRegister = value; break; - case 0xE000: + case 0x1: if (currentRegister == 0x24) { //Timer A High 8 bits //std::cout << "Timer A High 8 bits" << std::endl; @@ -135,7 +135,7 @@ private: //std::cout << "enable IRQ's" << std::endl; } break; - case 0xE002: + case 0x3: /*if (currentRegister == 0x10) { std::cout << "0x10" << std::endl; }*/ @@ -173,11 +173,9 @@ protected: _clockIRQ += (getClockFrequency()*6) / (double)_console->GetCpu()->GetClockRate(_console->GetModel()); while (_clockIRQ >= _cycleCountIRQ) { _cycleCountIRQ++; - //std::cout << _cycleCountIRQ << std::endl; if (irqATimerEnable) { irqACurrentTimer--; if (!irqACurrentTimer) { - //std::cout << "***IRQ***" << std::endl; irqATimerEnable = 0; _console->GetCpu()->SetIrqSource(IRQSource::EPSM); } @@ -186,7 +184,6 @@ protected: if (irqBTimerEnable) { irqBCurrentTimer--; if (!irqBCurrentTimer) { - //std::cout << "***IRQ***" << std::endl; irqBTimerEnable = 0; _console->GetCpu()->SetIrqSource(IRQSource::EPSM); } @@ -252,52 +249,51 @@ public: OPN2_SetChipType(0); } - void WriteRegister(uint16_t addr, uint8_t value) + void WriteRegister(uint16_t addr, uint8_t value, uint8_t custom = 0, uint8_t epsmA0 = 0, uint8_t epsmA1 = 0) { + if (!custom) { + switch (addr) { + case 0x4016: + if ((value & 0x0F) == 0x02) {writeAddr = 0x0;} //A0 = 0, A1 = 0 + if ((value & 0x0F) == 0x0A) {writeAddr = 0x1;} //A0 = 1, A1 = 0 + if ((value & 0x0F) == 0x06) {writeAddr = 0x2;} //A0 = 0, A1 = 1 + if ((value & 0x0F) == 0x0E) {writeAddr = 0x3;} //A0 = 1, A1 = 1 + if (value & 0x0E) {writeValue = value;} + if ((value & 0x0F) == 0x00) { + writeValue = (writeValue & 0xF0) | (value >> 4); - if (addr == 0x4016) { - if ((value & 0x0F) == 0x02) { - writeValue = value; - writeAddr = 0xC000; - } - if ((value & 0x0F) == 0x0A) { - writeValue = value; - writeAddr = 0xE000; - } - if ((value & 0x0F) == 0x06) { - writeValue = value; - writeAddr = 0xC002; - } - if ((value & 0x0F) == 0x0E) { - writeValue = value; - writeAddr = 0xE002; - } - if ((value & 0x0F) == 0x00) { - writeValue = (writeValue & 0xF0) | (value >> 4); - - const uint8_t a04016 = (writeAddr & 0xF000) == 0xE000; - const uint8_t a14016 = !!(writeAddr & 0xF); - EPSMSSGAudio::WriteRegister(writeAddr, writeValue); - WriteToChip(a04016 | (a14016 << 1), writeValue); - } - } - if (addr == 0x401c) { addr = 0xC000; } - if (addr == 0x401d) { addr = 0xE000; } - if (addr == 0x401e) { addr = 0xC002; } - if (addr == 0x401f) { addr = 0xE002; } - switch(addr) { - case 0xC000: - case 0xE000: - case 0xC002: - case 0xE002: - - WriteToChipIRQ(addr, value); - const uint8_t a0 = (addr & 0xF000) == 0xE000; - const uint8_t a1 = !!(addr & 0xF); - EPSMSSGAudio::WriteRegister(addr, value); + const uint8_t a0 = !!(writeAddr & 0x1); + const uint8_t a1 = !!(writeAddr & 0x2); + if (a0 == 0x0) { writeAddr = 0xC000; } + if (a0 == 0x1) { writeAddr = 0xE000; } + if (a1 == 0x0) { EPSMSSGAudio::WriteRegister(writeAddr, value); } + WriteToChip(a0 | (a1 << 1), writeValue); + WriteToChipIRQ(a0 | (a1 << 1), value); + } + break; + case 0x401c: //0xC000 A0 = 0, A1 = 0 + case 0x401d: //0xE000 A0 = 1, A1 = 0 + case 0x401e: //0xC002 A0 = 0, A1 = 1 + case 0x401f: //0xE002 A0 = 1, A1 = 1 + + const uint8_t a0 = !!(addr & 0x1); //const uint8_t a0 = (addr & 0xF000) == 0xE000; + const uint8_t a1 = !!(addr & 0x2); //const uint8_t a1 = !!(addr & 0xF); + if (a0 == 0x0) { addr = 0xC000; } + if (a0 == 0x1) { addr = 0xE000; } + if (a1 == 0x0) { EPSMSSGAudio::WriteRegister(addr, value); } WriteToChip(a0 | (a1 << 1), value); + WriteToChipIRQ(a0 | (a1 << 1), value); break; + } } + else{ + if (epsmA0 == 0x0) { addr = 0xC000; } + if (epsmA0 == 0x1) { addr = 0xE000; } + if (epsmA1 == 0x0) { EPSMSSGAudio::WriteRegister(addr, value); } + WriteToChip(epsmA0 | (epsmA1 << 1), value); + WriteToChipIRQ(epsmA0 | (epsmA1 << 1), value); + } + } }; \ No newline at end of file