diff --git a/Source/Core/Core/HW/DSP.cpp b/Source/Core/Core/HW/DSP.cpp index 381b4203da..903c75e4b1 100644 --- a/Source/Core/Core/HW/DSP.cpp +++ b/Source/Core/Core/HW/DSP.cpp @@ -199,19 +199,20 @@ void DoState(PointerWrap &p) } -void UpdateInterrupts(); -void Do_ARAM_DMA(); -void WriteARAM(u8 _iValue, u32 _iAddress); -bool Update_DSP_ReadRegister(); -void Update_DSP_WriteRegister(); +static void UpdateInterrupts(); +static void Do_ARAM_DMA(); +static void GenerateDSPInterrupt(u64 DSPIntType, int cyclesLate = 0); static int et_GenerateDSPInterrupt; +static int et_CompleteARAM; -static void GenerateDSPInterrupt_Wrapper(u64 userdata, int cyclesLate) +static void CompleteARAM(u64 userdata, int cyclesLate) { - GenerateDSPInterrupt((DSPInterruptType)(userdata&0xFFFF), (bool)((userdata>>16) & 1)); + g_dspState.DSPControl.DMAState = 0; + GenerateDSPInterrupt(INT_ARAM); } + DSPEmulator *GetDSPEmulator() { return dsp_emulator; @@ -248,7 +249,8 @@ void Init(bool hle) g_AR_MODE = 1; // ARAM Controller has init'd g_AR_REFRESH = 156; // 156MHz - et_GenerateDSPInterrupt = CoreTiming::RegisterEvent("DSPint", GenerateDSPInterrupt_Wrapper); + et_GenerateDSPInterrupt = CoreTiming::RegisterEvent("DSPint", GenerateDSPInterrupt); + et_CompleteARAM = CoreTiming::RegisterEvent("ARAMint", CompleteARAM); } void Shutdown() @@ -406,7 +408,7 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base) // We make the samples ready as soon as possible void *address = Memory::GetPointer(g_audioDMA.SourceAddress); AudioCommon::SendAIBuffer((short*)address, g_audioDMA.AudioDMAControl.NumBlocks * 8); - CoreTiming::ScheduleEvent_Threadsafe(80, et_GenerateDSPInterrupt, INT_AID | (1 << 16)); + CoreTiming::ScheduleEvent_Threadsafe(80, et_GenerateDSPInterrupt, INT_AID); } }) ); @@ -429,36 +431,31 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base) } // UpdateInterrupts -void UpdateInterrupts() +static void UpdateInterrupts() { - if ((g_dspState.DSPControl.AID & g_dspState.DSPControl.AID_mask) || - (g_dspState.DSPControl.ARAM & g_dspState.DSPControl.ARAM_mask) || - (g_dspState.DSPControl.DSP & g_dspState.DSPControl.DSP_mask)) - { - ProcessorInterface::SetInterrupt(ProcessorInterface::INT_CAUSE_DSP, true); - } - else - { - ProcessorInterface::SetInterrupt(ProcessorInterface::INT_CAUSE_DSP, false); - } + // For each interrupt bit in DSP_CONTROL, the interrupt enablemask is the bit directly + // to the left of it. By doing: + // (DSP_CONTROL>>1) & DSP_CONTROL & MASK_OF_ALL_INTERRUPT_BITS + // We can check if any of the interrupts are enabled and active, all at once. + bool ints_set = (((g_dspState.DSPControl.Hex >> 1) & g_dspState.DSPControl.Hex & (INT_DSP | INT_ARAM | INT_AID)) != 0); + + ProcessorInterface::SetInterrupt(ProcessorInterface::INT_CAUSE_DSP, ints_set); } -void GenerateDSPInterrupt(DSPInterruptType type, bool _bSet) +static void GenerateDSPInterrupt(u64 DSPIntType, int cyclesLate) { - switch (type) - { - case INT_DSP: g_dspState.DSPControl.DSP = _bSet ? 1 : 0; break; - case INT_ARAM: g_dspState.DSPControl.ARAM = _bSet ? 1 : 0; if (_bSet) g_dspState.DSPControl.DMAState = 0; break; - case INT_AID: g_dspState.DSPControl.AID = _bSet ? 1 : 0; break; - } + // The INT_* enumeration members have values that reflect their bit positions in + // DSP_CONTROL - we mask by (INT_DSP | INT_ARAM | INT_AID) just to ensure people + // don't call this with bogus values. + g_dspState.DSPControl.Hex |= (DSPIntType & (INT_DSP | INT_ARAM | INT_AID)); UpdateInterrupts(); } // CALLED FROM DSP EMULATOR, POSSIBLY THREADED -void GenerateDSPInterruptFromDSPEmu(DSPInterruptType type, bool _bSet) +void GenerateDSPInterruptFromDSPEmu(DSPInterruptType type) { - CoreTiming::ScheduleEvent_Threadsafe_Immediate(et_GenerateDSPInterrupt, type | (_bSet<<16)); + CoreTiming::ScheduleEvent_Threadsafe_Immediate(et_GenerateDSPInterrupt, type); CoreTiming::ForceExceptionCheck(100); } @@ -515,19 +512,19 @@ void UpdateAudioDMA() } } -void Do_ARAM_DMA() +static void Do_ARAM_DMA() { + g_dspState.DSPControl.DMAState = 1; if (g_arDMA.Cnt.count == 32) { // Beyond Good and Evil (GGEE41) sends count 32 // Lost Kingdoms 2 needs the exception check here in DSP HLE mode - GenerateDSPInterrupt(INT_ARAM); + CompleteARAM(0, 0); CoreTiming::ForceExceptionCheck(100); } else { - g_dspState.DSPControl.DMAState = 1; - CoreTiming::ScheduleEvent_Threadsafe(0, et_GenerateDSPInterrupt, INT_ARAM | (1<<16)); + CoreTiming::ScheduleEvent_Threadsafe(0, et_CompleteARAM); // Force an early exception check on large transfers. Fixes RE2 audio. // NFS:HP2 (<= 6144) diff --git a/Source/Core/Core/HW/DSP.h b/Source/Core/Core/HW/DSP.h index 293a4a6733..5266c7f535 100644 --- a/Source/Core/Core/HW/DSP.h +++ b/Source/Core/Core/HW/DSP.h @@ -15,9 +15,9 @@ namespace DSP enum DSPInterruptType { - INT_DSP = 0, - INT_ARAM = 1, - INT_AID = 2 + INT_DSP = 0x80, + INT_ARAM = 0x20, + INT_AID = 0x08, }; // aram size and mask @@ -65,8 +65,7 @@ DSPEmulator *GetDSPEmulator(); void DoState(PointerWrap &p); -void GenerateDSPInterrupt(DSPInterruptType _DSPInterruptType, bool _bSet = true); -void GenerateDSPInterruptFromDSPEmu(DSPInterruptType _DSPInterruptType, bool _bSet = true); +void GenerateDSPInterruptFromDSPEmu(DSPInterruptType _DSPInterruptType); // Audio/DSP Helper u8 ReadARAM(const u32 _uAddress);