Merge pull request #16 from NovaSquirrel/master

Pull from NovaSquirrel
This commit is contained in:
mkwong98 2021-09-20 17:25:41 +08:00 committed by GitHub
commit 94f6597e86
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 161 additions and 61 deletions

View file

@ -14,7 +14,7 @@
#include "CPU.h" #include "CPU.h"
void BaseMapper::WriteRegister(uint16_t addr, uint8_t value) { } 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; } uint8_t BaseMapper::ReadRegister(uint16_t addr) { return 0; }
void BaseMapper::InitMapper(RomData &romData) { } void BaseMapper::InitMapper(RomData &romData) { }
void BaseMapper::Reset(bool softReset) { } 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) void BaseMapper::WriteRAM(uint16_t addr, uint8_t value)
{ {
if((addr == 0x4016) & (_console->GetCpu()->GetCycleCount() % 2 == 1)){ WriteEPSM(addr, 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(_isWriteRegisterAddr[addr]) {
if(_hasBusConflicts) { if(_hasBusConflicts) {
uint8_t prgValue = _prgPages[addr >> 8][(uint8_t)addr]; uint8_t prgValue = _prgPages[addr >> 8][(uint8_t)addr];

View file

@ -473,10 +473,10 @@ void Console::ProcessCpuClock()
void Console::ProcessInterferenceAudio() 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->GetInvOE1(_controlManager->_address); // invert relative to 2A03
_InvOE1 = (_controlManager->_OE1pinLow == 1) ? 0 : 1; // invert relative to 2A03
if (_controlManager->_strobed == true) if (_controlManager->_strobed == true)
_controlManager->_strobed = false; _controlManager->_strobed = false;

View file

@ -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 // pull low for only one clock
if (addr == 0x4016) if (addr == 0x4016)
_OE1pinLow = (_strobed) ? 0 : 1; _OE1pinLow = !_strobed;
return _OE1pinLow;
} }
void ControlManager::Reset(bool softReset) void ControlManager::Reset(bool softReset)

View file

@ -43,7 +43,7 @@ protected:
virtual uint8_t GetOpenBusMask(uint8_t port); virtual uint8_t GetOpenBusMask(uint8_t port);
public: public:
uint8_t _OE1pinLow; bool _OE1pinLow;
uint16_t _address; uint16_t _address;
bool _strobed; bool _strobed;
@ -85,5 +85,5 @@ public:
virtual uint8_t ReadRAM(uint16_t addr) override; virtual uint8_t ReadRAM(uint16_t addr) override;
virtual void WriteRAM(uint16_t addr, uint8_t value) override; virtual void WriteRAM(uint16_t addr, uint8_t value) override;
void GetInvOE1(uint16_t addr); bool GetInvOE1(uint16_t addr);
}; };

View file

@ -5,6 +5,7 @@
#include "BaseExpansionAudio.h" #include "BaseExpansionAudio.h"
#include "SSGAudio.h" #include "SSGAudio.h"
#include "Console.h" #include "Console.h"
#include "CPU.h"
#include <array> #include <array>
#include "ym3438.h" #include "ym3438.h"
@ -19,9 +20,22 @@ private:
int16_t _lastOutputs[2]; int16_t _lastOutputs[2];
int16_t _currentOutputs[2]; int16_t _currentOutputs[2];
uint8_t writeValue; 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 _clock;
double _clockIRQ;
double _cycleCountIRQ = 0;
static constexpr uint8_t cycleCount = 24; static constexpr uint8_t cycleCount = 24;
@ -39,7 +53,6 @@ private:
void UpdateOutputLevel() void UpdateOutputLevel()
{ {
int16_t summedOutput = 0;
for (size_t x = 0; x < 2; x++) for (size_t x = 0; x < 2; x++)
{ {
_console->GetApu()->AddExpansionAudioDelta(x == 0 ? AudioChannel::EPSM_L : AudioChannel::EPSM_R, _currentOutputs[x] - _lastOutputs[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 0x0:
case 0x2:
currentRegister = value;
break;
case 0x1:
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 0x3:
/*if (currentRegister == 0x10) {
std::cout << "0x10" << std::endl;
}*/
break;
}
//irqBValue = value;
//std::cout << std::hex << irqBValue << std::endl;
}
uint32_t getClockFrequency() uint32_t getClockFrequency()
{ {
return _console->GetSettings()->GetEPSMClockFrequency() / 6; return _console->GetSettings()->GetEPSMClockFrequency() / 6;
@ -92,6 +170,26 @@ protected:
EPSMSSGAudio::ClockAudio(); EPSMSSGAudio::ClockAudio();
_clock += getClockFrequency() / (double)_console->GetCpu()->GetClockRate(_console->GetModel()); _clock += getClockFrequency() / (double)_console->GetCpu()->GetClockRate(_console->GetModel());
_clockIRQ += (getClockFrequency()*6) / (double)_console->GetCpu()->GetClockRate(_console->GetModel());
while (_clockIRQ >= _cycleCountIRQ) {
_cycleCountIRQ++;
if (irqATimerEnable) {
irqACurrentTimer--;
if (!irqACurrentTimer) {
irqATimerEnable = 0;
_console->GetCpu()->SetIrqSource(IRQSource::EPSM);
}
}
if (irqBTimerEnable) {
irqBCurrentTimer--;
if (!irqBCurrentTimer) {
irqBTimerEnable = 0;
_console->GetCpu()->SetIrqSource(IRQSource::EPSM);
}
}
}
while (_clock >= cycleCount) while (_clock >= cycleCount)
{ {
@ -117,7 +215,6 @@ protected:
if(input.wrote) if(input.wrote)
{ {
input.wrote = false; input.wrote = false;
OPN2_Write(&_chip, input.addr, input.data); OPN2_Write(&_chip, input.addr, input.data);
} }
} }
@ -131,9 +228,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: public:
@ -144,57 +241,59 @@ public:
_inputBuffer = {}; _inputBuffer = {};
_clock = 0; _clock = 0;
_clockIRQ = 0;
irqATimerEnable = 0;
irqBTimerEnable = 0;
OPN2_Reset(&_chip); OPN2_Reset(&_chip);
OPN2_SetChipType(0); 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) { const uint8_t a0 = !!(writeAddr & 0x1);
if ((value & 0x0F) == 0x02) { const uint8_t a1 = !!(writeAddr & 0x2);
writeValue = value; if (a0 == 0x0) { writeAddr = 0xC000; }
writeAddr = 0xC000; if (a0 == 0x1) { writeAddr = 0xE000; }
} if (a1 == 0x0) { EPSMSSGAudio::WriteRegister(writeAddr, value); }
if ((value & 0x0F) == 0x0A) { WriteToChip(a0 | (a1 << 1), writeValue);
writeValue = value; WriteToChipIRQ(a0 | (a1 << 1), value);
writeAddr = 0xE000; }
} break;
if ((value & 0x0F) == 0x06) { case 0x401c: //0xC000 A0 = 0, A1 = 0
writeValue = value; case 0x401d: //0xE000 A0 = 1, A1 = 0
writeAddr = 0xC002; case 0x401e: //0xC002 A0 = 0, A1 = 1
} case 0x401f: //0xE002 A0 = 1, A1 = 1
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 a0 = !!(addr & 0x1); //const uint8_t a0 = (addr & 0xF000) == 0xE000;
const uint8_t a14016 = !!(writeAddr & 0xF); const uint8_t a1 = !!(addr & 0x2); //const uint8_t a1 = !!(addr & 0xF);
EPSMSSGAudio::WriteRegister(writeAddr, writeValue); if (a0 == 0x0) { addr = 0xC000; }
WriteToChip(a04016 | (a14016 << 1), writeValue); if (a0 == 0x1) { addr = 0xE000; }
} if (a1 == 0x0) { EPSMSSGAudio::WriteRegister(addr, value); }
}
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:
const uint8_t a0 = (addr & 0xF000) == 0xE000;
const uint8_t a1 = !!(addr & 0xF);
EPSMSSGAudio::WriteRegister(addr, value);
WriteToChip(a0 | (a1 << 1), value); WriteToChip(a0 | (a1 << 1), value);
WriteToChipIRQ(a0 | (a1 << 1), value);
break; 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);
}
} }
}; };

View file

@ -133,7 +133,7 @@ void MemoryManager::Write(uint16_t addr, uint8_t value, MemoryOperationType oper
{ {
if(_console->DebugProcessRamOperation(operationType, addr, value)) { if(_console->DebugProcessRamOperation(operationType, addr, value)) {
_ramWriteHandlers[addr]->WriteRAM(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); _ramWriteHandlers[0xE000]->WriteRAM(addr, value);
} }
} }

View file

@ -466,7 +466,7 @@ void PPU::WriteRAM(uint16_t addr, uint8_t value)
void PPU::GetInvA13() void PPU::GetInvA13()
{ {
// pull level high when PPU/VRAM addr bit 13 is low // pull level high when PPU/VRAM addr bit 13 is low
_A13pinLow = (_ppuBusAddress & 0x2000) ? 0 : 1; _A13pinLowSum += (bool)(_ppuBusAddress & 0x2000); // invert relative to 2A03
} }
uint8_t PPU::ReadPaletteRAM(uint16_t addr) uint8_t PPU::ReadPaletteRAM(uint16_t addr)

View file

@ -180,7 +180,7 @@ class PPU : public IMemoryHandler, public Snapshotable
static constexpr int32_t OutputBufferSize = 256*240*2; static constexpr int32_t OutputBufferSize = 256*240*2;
static constexpr int32_t OamDecayCycleCount = 3000; static constexpr int32_t OamDecayCycleCount = 3000;
uint8_t _A13pinLow; uint8_t _A13pinLowSum;
PPU(shared_ptr<Console> console); PPU(shared_ptr<Console> console);
virtual ~PPU(); virtual ~PPU();

View file

@ -277,8 +277,8 @@ int16_t SoundMixer::GetOutputVolume(bool forRightChannel)
#endif #endif
GetChannelOutput(AudioChannel::EPSM_L, forRightChannel) * 4 + GetChannelOutput(AudioChannel::EPSM_L, forRightChannel) * 4 +
GetChannelOutput(AudioChannel::EPSM_R, 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 GetChannelOutput(AudioChannel::InvOE1, forRightChannel) * 100
); );
} }

View file

@ -30,6 +30,7 @@ enum class IRQSource
FrameCounter = 2, FrameCounter = 2,
DMC = 4, DMC = 4,
FdsDisk = 8, FdsDisk = 8,
EPSM = 16,
}; };
enum class MemoryOperation enum class MemoryOperation

View file

@ -41,7 +41,6 @@ private:
void UpdateOutputLevel() void UpdateOutputLevel()
{ {
int16_t summedOutput = 0;
_console->GetApu()->AddExpansionAudioDelta(AudioChannel::VRC7, _currentOutput - _lastOutput); _console->GetApu()->AddExpansionAudioDelta(AudioChannel::VRC7, _currentOutput - _lastOutput);
_lastOutput = _currentOutput; _lastOutput = _currentOutput;
} }