Skip to content
This repository has been archived by the owner on Sep 11, 2023. It is now read-only.

Added basic EPSM IRQ behavior #48

Merged
merged 2 commits into from
Aug 26, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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