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"
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];

View file

@ -473,10 +473,10 @@ 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
_InvOE1 = !_controlManager->GetInvOE1(_controlManager->_address); // invert relative to 2A03
if (_controlManager->_strobed == true)
_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
if (addr == 0x4016)
_OE1pinLow = (_strobed) ? 0 : 1;
_OE1pinLow = !_strobed;
return _OE1pinLow;
}
void ControlManager::Reset(bool softReset)

View file

@ -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);
};

View file

@ -5,6 +5,7 @@
#include "BaseExpansionAudio.h"
#include "SSGAudio.h"
#include "Console.h"
#include "CPU.h"
#include <array>
#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 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()
{
return _console->GetSettings()->GetEPSMClockFrequency() / 6;
@ -92,6 +170,26 @@ protected:
EPSMSSGAudio::ClockAudio();
_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)
{
@ -117,7 +215,6 @@ protected:
if(input.wrote)
{
input.wrote = false;
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:
@ -144,57 +241,59 @@ public:
_inputBuffer = {};
_clock = 0;
_clockIRQ = 0;
irqATimerEnable = 0;
irqBTimerEnable = 0;
OPN2_Reset(&_chip);
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:
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);
}
}
};

View file

@ -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);
}
}

View file

@ -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 += (bool)(_ppuBusAddress & 0x2000); // invert relative to 2A03
}
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 OamDecayCycleCount = 3000;
uint8_t _A13pinLow;
uint8_t _A13pinLowSum;
PPU(shared_ptr<Console> console);
virtual ~PPU();

View file

@ -277,8 +277,8 @@ 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::InvOE1, forRightChannel) * 1000
(GetChannelOutput(AudioChannel::InvA13, forRightChannel) * 20) / 3.0 + // 3 PPU samples per CPU clock
GetChannelOutput(AudioChannel::InvOE1, forRightChannel) * 100
);
}

View file

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

View file

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