Skip to content

Commit

Permalink
Merge pull request NovaSquirrel#48 from Perkka2/master
Browse files Browse the repository at this point in the history
Added basic EPSM IRQ behavior
  • Loading branch information
NovaSquirrel authored Aug 26, 2021
2 parents 15cb277 + 8377b46 commit 6a91c05
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 10 deletions.
4 changes: 2 additions & 2 deletions Core/BaseMapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) { }
Expand Down Expand Up @@ -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];
Expand Down
115 changes: 109 additions & 6 deletions Core/EPSMAudio.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "BaseExpansionAudio.h"
#include "SSGAudio.h"
#include "Console.h"
#include "Cpu.h"

#include <array>
#include "ym3438.h"
Expand All @@ -19,9 +20,22 @@ class EPSMAudio : public EPSMSSGAudio
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;

Expand All @@ -39,7 +53,6 @@ class EPSMAudio : public EPSMSSGAudio

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]);
Expand Down Expand Up @@ -69,6 +82,71 @@ class EPSMAudio : public EPSMSSGAudio
};
}


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;
Expand All @@ -92,6 +170,29 @@ class EPSMAudio : public EPSMSSGAudio
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)
{
Expand All @@ -117,7 +218,6 @@ class EPSMAudio : public EPSMSSGAudio
if(input.wrote)
{
input.wrote = false;

OPN2_Write(&_chip, input.addr, input.data);
}
}
Expand All @@ -131,9 +231,9 @@ class EPSMAudio : public EPSMSSGAudio
}
}

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:
Expand All @@ -144,7 +244,10 @@ class EPSMAudio : public EPSMSSGAudio
_inputBuffer = {};

_clock = 0;
_clockIRQ = 0;

irqATimerEnable = 0;
irqBTimerEnable = 0;
OPN2_Reset(&_chip);
OPN2_SetChipType(0);
}
Expand Down Expand Up @@ -182,13 +285,13 @@ class EPSMAudio : public EPSMSSGAudio
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);
Expand Down
2 changes: 1 addition & 1 deletion Core/MemoryManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
Expand Down
1 change: 1 addition & 0 deletions Core/Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ enum class IRQSource
FrameCounter = 2,
DMC = 4,
FdsDisk = 8,
EPSM = 16,
};

enum class MemoryOperation
Expand Down
1 change: 0 additions & 1 deletion Core/Vrc7Audio.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ class Vrc7Audio : public BaseExpansionAudio

void UpdateOutputLevel()
{
int16_t summedOutput = 0;
_console->GetApu()->AddExpansionAudioDelta(AudioChannel::VRC7, _currentOutput - _lastOutput);
_lastOutput = _currentOutput;
}
Expand Down

0 comments on commit 6a91c05

Please sign in to comment.