From 9f683f353b144f6e30928c809ce123f5b8b90c0c Mon Sep 17 00:00:00 2001 From: comex Date: Mon, 3 Nov 2014 00:03:41 -0500 Subject: [PATCH] Make EXI use CoreTiming events like everything else instead of having its own slow special check. Microphone is probably wrong/mistimed because it doesn't take into account cycles late, but that's not a new issue here. --- Source/Core/Core/HW/EXI.cpp | 26 ++++++++++++++----- Source/Core/Core/HW/EXI.h | 4 +-- Source/Core/Core/HW/EXI_Channel.cpp | 13 +++------- Source/Core/Core/HW/EXI_Channel.h | 4 --- Source/Core/Core/HW/EXI_DeviceAMBaseboard.cpp | 2 ++ Source/Core/Core/HW/EXI_DeviceEthernet.cpp | 4 +++ Source/Core/Core/HW/EXI_DeviceMemoryCard.cpp | 1 + Source/Core/Core/HW/EXI_DeviceMic.cpp | 6 +++-- Source/Core/Core/PowerPC/PowerPC.cpp | 4 --- 9 files changed, 36 insertions(+), 28 deletions(-) diff --git a/Source/Core/Core/HW/EXI.cpp b/Source/Core/Core/HW/EXI.cpp index 8680b94e7c..4eb3a003e8 100644 --- a/Source/Core/Core/HW/EXI.cpp +++ b/Source/Core/Core/HW/EXI.cpp @@ -23,6 +23,10 @@ static int changeDevice; static int updateInterrupts; static CEXIChannel *g_Channels[MAX_EXI_CHANNELS]; + +static void ChangeDeviceCallback(u64 userdata, int cyclesLate); +static void UpdateInterruptsCallback(u64 userdata, int cycles_late); + void Init() { InitSRAM(); @@ -82,7 +86,7 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base) } } -void ChangeDeviceCallback(u64 userdata, int cyclesLate) +static void ChangeDeviceCallback(u64 userdata, int cyclesLate) { u8 channel = (u8)(userdata >> 32); u8 type = (u8)(userdata >> 16); @@ -116,11 +120,6 @@ IEXIDevice* FindDevice(TEXIDevices device_type, int customIndex) } void UpdateInterrupts() -{ - CoreTiming::ScheduleEvent_Threadsafe(0, updateInterrupts, 0); -} - -void UpdateInterruptsCallback(u64 userdata, int cyclesLate) { // Interrupts are mapped a bit strangely: // Channel 0 Device 0 generates interrupt on channel 0 @@ -135,4 +134,19 @@ void UpdateInterruptsCallback(u64 userdata, int cyclesLate) ProcessorInterface::SetInterrupt(ProcessorInterface::INT_CAUSE_EXI, causeInt); } +static void UpdateInterruptsCallback(u64 userdata, int cycles_late) +{ + UpdateInterrupts(); +} + +void ScheduleUpdateInterrupts_Threadsafe(int cycles_late) +{ + CoreTiming::ScheduleEvent_Threadsafe(cycles_late, updateInterrupts, 0); +} + +void ScheduleUpdateInterrupts(int cycles_late) +{ + CoreTiming::ScheduleEvent(cycles_late, updateInterrupts, 0); +} + } // end of namespace ExpansionInterface diff --git a/Source/Core/Core/HW/EXI.h b/Source/Core/Core/HW/EXI.h index 7ab87fbf74..f1bbd195cc 100644 --- a/Source/Core/Core/HW/EXI.h +++ b/Source/Core/Core/HW/EXI.h @@ -27,10 +27,10 @@ void PauseAndLock(bool doLock, bool unpauseOnUnlock); void RegisterMMIO(MMIO::Mapping* mmio, u32 base); -void UpdateInterruptsCallback(u64 userdata, int cyclesLate); void UpdateInterrupts(); +void ScheduleUpdateInterrupts_Threadsafe(int cycles_late); +void ScheduleUpdateInterrupts(int cycles_late); -void ChangeDeviceCallback(u64 userdata, int cyclesLate); void ChangeDevice(const u8 channel, const TEXIDevices device_type, const u8 device_num); CEXIChannel* GetChannel(u32 index); diff --git a/Source/Core/Core/HW/EXI_Channel.cpp b/Source/Core/Core/HW/EXI_Channel.cpp index 6061c78816..c70280f06a 100644 --- a/Source/Core/Core/HW/EXI_Channel.cpp +++ b/Source/Core/Core/HW/EXI_Channel.cpp @@ -35,8 +35,6 @@ CEXIChannel::CEXIChannel(u32 ChannelId) : for (auto& device : m_pDevices) device.reset(EXIDevice_Create(EXIDEVICE_NONE, m_ChannelId)); - - updateInterrupts = CoreTiming::RegisterEvent("EXIInterrupt", UpdateInterrupts); } CEXIChannel::~CEXIChannel() @@ -93,7 +91,7 @@ void CEXIChannel::RegisterMMIO(MMIO::Mapping* mmio, u32 base) if (pDevice != nullptr) pDevice->SetCS(m_Status.CHIP_SELECT); - CoreTiming::ScheduleEvent_Threadsafe_Immediate(updateInterrupts, 0); + ExpansionInterface::UpdateInterrupts(); }) ); @@ -156,7 +154,7 @@ void CEXIChannel::RegisterMMIO(MMIO::Mapping* mmio, u32 base) void CEXIChannel::SendTransferComplete() { m_Status.TCINT = 1; - CoreTiming::ScheduleEvent_Threadsafe_Immediate(updateInterrupts, 0); + ExpansionInterface::UpdateInterrupts(); } void CEXIChannel::RemoveDevices() @@ -185,16 +183,11 @@ void CEXIChannel::AddDevice(IEXIDevice* pDevice, const int device_num, bool noti if (m_ChannelId != 2) { m_Status.EXTINT = 1; - CoreTiming::ScheduleEvent_Threadsafe_Immediate(updateInterrupts, 0); + ExpansionInterface::UpdateInterrupts(); } } } -void CEXIChannel::UpdateInterrupts(u64 userdata, int cyclesLate) -{ - ExpansionInterface::UpdateInterrupts(); -} - bool CEXIChannel::IsCausingInterrupt() { if (m_ChannelId != 2 && GetDevice(1)->IsInterruptSet()) diff --git a/Source/Core/Core/HW/EXI_Channel.h b/Source/Core/Core/HW/EXI_Channel.h index c106a5759d..5d2436be55 100644 --- a/Source/Core/Core/HW/EXI_Channel.h +++ b/Source/Core/Core/HW/EXI_Channel.h @@ -83,10 +83,6 @@ private: // Since channels operate a bit differently from each other u32 m_ChannelId; - int updateInterrupts; - - static void UpdateInterrupts(u64 userdata, int cyclesLate); - public: // get device IEXIDevice* GetDevice(const u8 _CHIP_SELECT); diff --git a/Source/Core/Core/HW/EXI_DeviceAMBaseboard.cpp b/Source/Core/Core/HW/EXI_DeviceAMBaseboard.cpp index 9975d148de..c35e823bd3 100644 --- a/Source/Core/Core/HW/EXI_DeviceAMBaseboard.cpp +++ b/Source/Core/Core/HW/EXI_DeviceAMBaseboard.cpp @@ -4,6 +4,7 @@ #include "Core/Core.h" +#include "Core/HW/EXI.h" #include "Core/HW/EXI_Device.h" #include "Core/HW/EXI_DeviceAMBaseboard.h" @@ -87,6 +88,7 @@ void CEXIAMBaseboard::TransferByte(u8& _byte) m_have_irq = true; else if (m_command[0] == 0x82) m_have_irq = false; + ExpansionInterface::UpdateInterrupts(); } else if (m_position > 4) { diff --git a/Source/Core/Core/HW/EXI_DeviceEthernet.cpp b/Source/Core/Core/HW/EXI_DeviceEthernet.cpp index b4effff093..b92eeb7d05 100644 --- a/Source/Core/Core/HW/EXI_DeviceEthernet.cpp +++ b/Source/Core/Core/HW/EXI_DeviceEthernet.cpp @@ -4,6 +4,7 @@ #include "Common/Network.h" #include "Core/ConfigManager.h" +#include "Core/HW/EXI.h" #include "Core/HW/EXI_Device.h" #include "Core/HW/EXI_DeviceEthernet.h" #include "Core/HW/Memmap.h" @@ -123,6 +124,7 @@ void CEXIETHERNET::ImmWrite(u32 data, u32 size) exi_status.interrupt_mask = data; break; } + ExpansionInterface::UpdateInterrupts(); } else { @@ -401,6 +403,7 @@ void CEXIETHERNET::SendComplete() mBbaMem[BBA_IR] |= INT_T; exi_status.interrupt |= exi_status.TRANSFER; + ExpansionInterface::ScheduleUpdateInterrupts_Threadsafe(0); } mBbaMem[BBA_LTPS] = 0; @@ -571,6 +574,7 @@ bool CEXIETHERNET::RecvHandlePacket() mBbaMem[BBA_IR] |= INT_R; exi_status.interrupt |= exi_status.TRANSFER; + ExpansionInterface::ScheduleUpdateInterrupts_Threadsafe(0); } else { diff --git a/Source/Core/Core/HW/EXI_DeviceMemoryCard.cpp b/Source/Core/Core/HW/EXI_DeviceMemoryCard.cpp index c4eba3453f..e0f70bd64b 100644 --- a/Source/Core/Core/HW/EXI_DeviceMemoryCard.cpp +++ b/Source/Core/Core/HW/EXI_DeviceMemoryCard.cpp @@ -263,6 +263,7 @@ void CEXIMemoryCard::CmdDone() status &= ~MC_STATUS_BUSY; m_bInterruptSet = 1; + ExpansionInterface::UpdateInterrupts(); } void CEXIMemoryCard::TransferComplete() diff --git a/Source/Core/Core/HW/EXI_DeviceMic.cpp b/Source/Core/Core/HW/EXI_DeviceMic.cpp index a14e7f4d16..540b15f488 100644 --- a/Source/Core/Core/HW/EXI_DeviceMic.cpp +++ b/Source/Core/Core/HW/EXI_DeviceMic.cpp @@ -7,6 +7,7 @@ #if HAVE_PORTAUDIO #include "Core/CoreTiming.h" +#include "Core/HW/EXI.h" #include "Core/HW/EXI_Device.h" #include "Core/HW/EXI_DeviceMic.h" #include "Core/HW/GCPad.h" @@ -176,8 +177,9 @@ void CEXIMic::SetCS(int cs) void CEXIMic::UpdateNextInterruptTicks() { - next_int_ticks = CoreTiming::GetTicks() + - (SystemTimers::GetTicksPerSecond() / sample_rate) * buff_size_samples; + int diff = (SystemTimers::GetTicksPerSecond() / sample_rate) * buff_size_samples; + next_int_ticks = CoreTiming::GetTicks() + diff; + ExpansionInterface::ScheduleUpdateInterrupts(diff); } bool CEXIMic::IsInterruptSet() diff --git a/Source/Core/Core/PowerPC/PowerPC.cpp b/Source/Core/Core/PowerPC/PowerPC.cpp index 7e3a4f38ac..f75cd9f7be 100644 --- a/Source/Core/Core/PowerPC/PowerPC.cpp +++ b/Source/Core/Core/PowerPC/PowerPC.cpp @@ -303,10 +303,6 @@ void UpdatePerformanceMonitor(u32 cycles, u32 num_load_stores, u32 num_fp_inst) void CheckExceptions() { - // Make sure we are checking against the latest EXI status. This is required - // for devices which interrupt frequently, such as the gc mic - ExpansionInterface::UpdateInterrupts(); - // Read volatile data once u32 exceptions = ppcState.Exceptions;