diff --git a/Source/Core/Core/Src/HW/DSP.cpp b/Source/Core/Core/Src/HW/DSP.cpp index baf0e87d40..eb58104202 100644 --- a/Source/Core/Core/Src/HW/DSP.cpp +++ b/Source/Core/Core/Src/HW/DSP.cpp @@ -16,10 +16,13 @@ // http://code.google.com/p/dolphin-emu/ // AID / AUDIO_DMA controls pushing audio out to the SRC and then the speakers. -// The audio DMA pushes audio through a small FIFO 32 bytes at a time, as needed. +// The audio DMA pushes audio through a small FIFO 32 bytes at a time, as +// needed. + // The SRC behind the fifo eats stereo 16-bit data at a sample rate of 32khz, -// that is, 4 bytes at 32 khz, which is 32 bytes at 4 khz. We thereforce schedule an -// event that runs at 4khz, that eats audio from the fifo. Thus, we have homebrew audio. +// that is, 4 bytes at 32 khz, which is 32 bytes at 4 khz. We thereforce +// schedule an event that runs at 4khz, that eats audio from the fifo. Thus, we +// have homebrew audio. // The AID interrupt is set when the fifo STARTS a transfer. It latches address // and count into internal registers and starts copying. This means that the @@ -236,9 +239,8 @@ void Read16(u16& _uReturnValue, const u32 _iAddress) } switch (_iAddress & 0xFFFF) { - // ================================================================================== + // AI_REGS 0x5000+ - // ================================================================================== case DSP_MAIL_TO_DSP_HI: _uReturnValue = dsp_plugin->DSP_ReadMailboxHigh(true); return; @@ -260,9 +262,7 @@ void Read16(u16& _uReturnValue, const u32 _iAddress) (dsp_plugin->DSP_ReadControlRegister() & DSP_CONTROL_MASK); return; - // ================================================================================== // AR_REGS 0x501x+ - // ================================================================================== case 0x5012: _uReturnValue = g_AR_MODE; return; @@ -282,11 +282,10 @@ void Read16(u16& _uReturnValue, const u32 _iAddress) case AR_DMA_CNT_H: _uReturnValue = g_arDMA.Cnt.Hex >> 16; return; case AR_DMA_CNT_L: _uReturnValue = g_arDMA.Cnt.Hex & 0xFFFF; return; - // ================================================================================== // DMA_REGS 0x5030+ - // ================================================================================== case AUDIO_DMA_BYTES_LEFT: - // Hmm. Would be stupid to ask for bytes left. Assume it wants blocks left. + // Hmm. Would be stupid to ask for bytes left. Assume it wants + // blocks left. _uReturnValue = g_audioDMA.BlocksLeft; return; @@ -320,10 +319,8 @@ void Write16(const u16 _Value, const u32 _Address) switch(_Address & 0xFFFF) { - // ================================================================================== - // DSP Regs 0x5000+ - // ================================================================================== + // DSP Regs 0x5000+ case DSP_MAIL_TO_DSP_HI: dsp_plugin->DSP_WriteMailboxHigh(true, _Value); break; @@ -340,9 +337,7 @@ void Write16(const u16 _Value, const u32 _Address) _dbg_assert_msg_(DSPINTERFACE, 0, "W16: DSP_MAIL_FROM_DSP_LO"); break; - // ================================================================================== // Control Register - // ================================================================================== case DSP_CONTROL: { UDSPControl tmpControl; @@ -380,11 +375,8 @@ void Write16(const u16 _Value, const u32 _Address) } break; - // ================================================================================== // AR_REGS 0x501x+ // DMA back and forth between ARAM and RAM - // ================================================================================== - case 0x5012: g_AR_MODE = _Value; break; @@ -418,10 +410,8 @@ void Write16(const u16 _Value, const u32 _Address) Update_ARAM_DMA(); break; - // ================================================================================== // Audio DMA_REGS 0x5030+ // This is the DMA that goes straight out the speaker. - // ================================================================================== case AUDIO_DMA_START_HI: g_audioDMA.SourceAddress = (g_audioDMA.SourceAddress & 0xFFFF) | (_Value<<16); break; @@ -459,25 +449,27 @@ void Write16(const u16 _Value, const u32 _Address) void UpdateAudioDMA() { if (g_audioDMA.AudioDMAControl.Enabled && g_audioDMA.BlocksLeft) { - // Read audio at g_audioDMA.ReadAddress in RAM and push onto an external audio fifo in the emulator, - // to be mixed with the disc streaming output. If that audio queue fills up, we delay the emulator. + // Read audio at g_audioDMA.ReadAddress in RAM and push onto an + // external audio fifo in the emulator, to be mixed with the disc + // streaming output. If that audio queue fills up, we delay the + // emulator. // TO RESTORE OLD BEHAVIOUR, COMMENT OUT THIS LINE dsp_plugin->DSP_SendAIBuffer(g_audioDMA.ReadAddress, AudioInterface::GetDSPSampleRate()); g_audioDMA.ReadAddress += 32; g_audioDMA.BlocksLeft--; if (!g_audioDMA.BlocksLeft) { - // No need to turn off the DMA - we can only get here if we had blocks left when we - // entered this function, and no longer have any. - // Latch new parameters + // No need to turn off the DMA - we can only get here if we had + // blocks left when we entered this function, and no longer have + // any. Latch new parameters g_audioDMA.BlocksLeft = g_audioDMA.AudioDMAControl.NumBlocks; g_audioDMA.ReadAddress = g_audioDMA.SourceAddress; // DEBUG_LOG(DSPLLE, "ADMA read addresses: %08x", g_audioDMA.ReadAddress); GenerateDSPInterrupt(DSP::INT_AID); } } else { - // Send silence. Yeah, it's a bit of a waste to sample rate convert silence. - // or hm. Maybe we shouldn't do this :) + // Send silence. Yeah, it's a bit of a waste to sample rate convert + // silence. or hm. Maybe we shouldn't do this :) // dsp->DSP_SendAIBuffer(0, AudioInterface::GetDSPSampleRate()); } } @@ -504,10 +496,8 @@ void Write32(const u32 _iValue, const u32 _iAddress) switch (_iAddress & 0xFFFF) { - // ================================================================================== - // AR_REGS - i dont know why they are accessed 32 bit too ... - // ================================================================================== + // AR_REGS - i dont know why they are accessed 32 bit too ... case AR_DMA_MMADDR_H: g_arDMA.MMAddr = _iValue; break; @@ -528,9 +518,8 @@ void Write32(const u32 _iValue, const u32 _iAddress) } } -// __________________________________________________________________________________________________ + // UpdateInterrupts -// void UpdateInterrupts() { if ((g_dspState.DSPControl.AID & g_dspState.DSPControl.AID_mask) || @@ -613,21 +602,21 @@ void Update_ARAM_DMA() GenerateDSPInterrupt(INT_ARAM); } -// ============================================================= -// This is how it works: The game has written sound to RAM, the DSP will read it with -// this function. SamplePos in the plugin is double the value given here because it -// works on a nibble level. In Wii addresses can eather be for MEM1 or MEM2, when it wants -// to read from MEM2 it adds 0x2000000 (in nibble terms) to get up to the MEM2 hardware -// address. But in our case we use a second pointer and adjust the value down to 0x00... -// ------------------- + +// This is how it works: The game has written sound to RAM, the DSP will read +// it with this function. SamplePos in the plugin is double the value given +// here because it works on a nibble level. In Wii addresses can eather be for +// MEM1 or MEM2, when it wants to read from MEM2 it adds 0x2000000 (in nibble +// terms) to get up to the MEM2 hardware address. But in our case we use a +// second pointer and adjust the value down to 0x00... u8 ReadARAM(u32 _iAddress) { - //LOGV(DSPINTERFACE, 0, "ARAM (r) 0x%08x", _iAddress); + //DEBUG_LOG(DSPINTERFACE, 0, "ARAM (r) 0x%08x", _iAddress); // _dbg_assert_(DSPINTERFACE,(_iAddress) < ARAM_SIZE); if (SConfig::GetInstance().m_LocalCoreStartupParameter.bWii) { - //LOGV(DSPINTERFACE, 0, "ARAM (r) 0x%08x 0x%08x 0x%08x", WII_MASK, _iAddress, (_iAddress & WII_MASK)); + //DEBUG_LOG(DSPINTERFACE, 0, "ARAM (r) 0x%08x 0x%08x 0x%08x", WII_MASK, _iAddress, (_iAddress & WII_MASK)); // Does this make any sense? if (_iAddress > WII_MASK) @@ -649,7 +638,7 @@ void WriteARAM(u8 value, u32 _uAddress) { if (SConfig::GetInstance().m_LocalCoreStartupParameter.bWii) { - //LOGV(DSPINTERFACE, 0, "ARAM (w) 0x%08x 0x%08x 0x%08x", WII_MASK, _iAddress, (_iAddress & WII_MASK)); + //DEBUG_LOG(DSPINTERFACE, 0, "ARAM (w) 0x%08x 0x%08x 0x%08x", WII_MASK, _iAddress, (_iAddress & WII_MASK)); // Does this make any sense? if (_uAddress > WII_MASK) @@ -686,4 +675,4 @@ void WriteARAM(u8 _iValue, u32 _iAddress) }*/ } // end of namespace DSP -// =================== + diff --git a/Source/Core/DSPCore/Src/DSPAccelerator.cpp b/Source/Core/DSPCore/Src/DSPAccelerator.cpp index 96b49e5342..223d4fabf8 100644 --- a/Source/Core/DSPCore/Src/DSPAccelerator.cpp +++ b/Source/Core/DSPCore/Src/DSPAccelerator.cpp @@ -106,12 +106,12 @@ u16 dsp_read_accelerator() u16 val; - // let's do the "hardware" decode - // DSP_FORMAT is interesting - the Zelda ucode seems to indicate that the bottom - // two bits specify the "read size" and the address multiplier. - // The bits above that may be things like sign extention and do/do not use ADPCM. - // It also remains to be figured out whether there's a difference between the usual - // accelerator "read address" and 0xd3. + // let's do the "hardware" decode DSP_FORMAT is interesting - the Zelda + // ucode seems to indicate that the bottom two bits specify the "read size" + // and the address multiplier. The bits above that may be things like sign + // extention and do/do not use ADPCM. It also remains to be figured out + // whether there's a difference between the usual accelerator "read + // address" and 0xd3. switch (gdsp_ifx_regs[DSP_FORMAT]) { case 0x00: // ADPCM audio @@ -146,9 +146,9 @@ u16 dsp_read_accelerator() DSPCore_SetException(EXP_4); DSPCore_SetException(EXP_ACCOV); - // Somehow, YN1 and YN2 must be initialized with their "loop" values, so yeah, - // it seems likely that we should raise an exception to let the DSP program do that, - // at least if DSP_FORMAT == 0x0A. + // Somehow, YN1 and YN2 must be initialized with their "loop" values, + // so yeah, it seems likely that we should raise an exception to let + // the DSP program do that, at least if DSP_FORMAT == 0x0A. } gdsp_ifx_regs[DSP_ACCAH] = Address >> 16; diff --git a/Source/Core/DSPCore/Src/DSPCore.cpp b/Source/Core/DSPCore/Src/DSPCore.cpp index 0dafd25259..21f99b2a18 100644 --- a/Source/Core/DSPCore/Src/DSPCore.cpp +++ b/Source/Core/DSPCore/Src/DSPCore.cpp @@ -153,51 +153,59 @@ void DSPCore_SetException(u8 level) g_dsp.exceptions |= 1 << level; } +// Comming from the CPU void DSPCore_CheckExternalInterrupt() { // check if there is an external interrupt if (g_dsp.cr & CR_EXTERNAL_INT && !g_dsp.exception_in_progress_hack) { #ifdef DEBUG_EXP - NOTICE_LOG(DSPLLE, "trying External interupt fired"); + NOTICE_LOG(DSPLLE, "Firing external interrupt"); #endif if (dsp_SR_is_flag_set(SR_EXT_INT_ENABLE)) { -#ifdef DEBUG_EXP - NOTICE_LOG(DSPLLE, "External interupt fired"); -#endif - // level 7 is the interrupt exception + // Signal the SPU about new mail DSPCore_SetException(EXP_INT); g_dsp.cr &= ~CR_EXTERNAL_INT; + } else { +#ifdef DEBUG_EXP + ERROR_LOG(DSPLLE, "External interupt firing failed"); +#endif } + } } void DSPCore_CheckExceptions() { + // it's unclear what to do when there are two exceptions are the same time + // but for sure they should not be called together therefore the + // g_dsp.exception_in_progress_hack if (g_dsp.exceptions != 0 && !g_dsp.exception_in_progress_hack) { #ifdef DEBUG_EXP - NOTICE_LOG(DSPLLE, "trying exception %d fired", g_dsp.exceptions); + NOTICE_LOG(DSPLLE, "Firing exception %d", g_dsp.exceptions); #endif - // check exceptions + // check exceptions should it be 0..7 or 7..0? for (int i = 0; i < 8; i++) { - // Seems 7 must pass or zelda dies + // Seems exp int is not masked by sr_int_enable if (dsp_SR_is_flag_set(SR_INT_ENABLE) || i == EXP_INT) { if (g_dsp.exceptions & (1 << i)) { _assert_msg_(MASTER_LOG, !g_dsp.exception_in_progress_hack, "assert while exception"); + // store pc and sr until RTI dsp_reg_store_stack(DSP_STACK_C, g_dsp.pc); dsp_reg_store_stack(DSP_STACK_D, g_dsp.r[DSP_REG_SR]); - g_dsp.pc = i * 2; + g_dsp.pc = i * 2; g_dsp.exceptions &= ~(1 << i); -#ifdef DEBUG_EXP - NOTICE_LOG(DSPLLE, "exception %d fired"); -#endif g_dsp.exception_in_progress_hack = true; break; } + } else { +#ifdef DEBUG_EXP + ERROR_LOG(DSPLLE, "Firing exception %d failed"); +#endif } } } diff --git a/Source/Core/DSPCore/Src/DSPHWInterface.cpp b/Source/Core/DSPCore/Src/DSPHWInterface.cpp index c19730be70..34089cb1c9 100644 --- a/Source/Core/DSPCore/Src/DSPHWInterface.cpp +++ b/Source/Core/DSPCore/Src/DSPHWInterface.cpp @@ -90,14 +90,9 @@ void gdsp_mbox_write_l(u8 mbx, u16 val) #ifdef DEBUG_EXP if (mbx == GDSP_MBOX_DSP) { - NOTICE_LOG(DSPLLE, " - DSP writes mail to mbx low %i: 0x%08x (pc=0x%04x)", mbx, gdsp_mbox_peek(GDSP_MBOX_DSP), g_dsp.pc); - //DSPHost_InterruptRequest(); - //DSPCore_SetException(EXP_INT); + NOTICE_LOG(DSPLLE, "DSP(WM) B:%i M:0x%08x (pc=0x%04x)", mbx, gdsp_mbox_peek(GDSP_MBOX_DSP), g_dsp.pc); } else { - NOTICE_LOG(DSPLLE, " - CPU writes mail to mbx low %i: 0x%08x (pc=0x%04x)", mbx, gdsp_mbox_peek(GDSP_MBOX_CPU), g_dsp.pc); - - // DSPHost_InterruptRequest(); - // DSPCore_SetException(EXP_INT); + NOTICE_LOG(DSPLLE, "CPU(WM) B:%i M:0x%08x (pc=0x%04x)", mbx, gdsp_mbox_peek(GDSP_MBOX_DSP), g_dsp.pc); } #endif } @@ -124,13 +119,9 @@ u16 gdsp_mbox_read_l(u8 mbx) #ifdef DEBUG_EXP if (mbx == GDSP_MBOX_DSP) { - NOTICE_LOG(DSPLLE, "- DSP reads mail from mbx %i: %08x (pc=0x%04x)", mbx, gdsp_mbox_peek(mbx), g_dsp.pc); - // DSPCore_SetException(EXP_INT); - // DSPHost_InterruptRequest(); + NOTICE_LOG(DSPLLE, "DSP(RM) B:%i M:0x%08x (pc=0x%04x)", mbx, gdsp_mbox_peek(GDSP_MBOX_DSP), g_dsp.pc); } else { - NOTICE_LOG(DSPLLE, "- CPU reads mail from mbx %i: %08x (pc=0x%04x)", mbx, gdsp_mbox_peek(mbx), g_dsp.pc); - // DSPCore_SetException(EXP_INT); - // DSPHost_InterruptRequest(); + NOTICE_LOG(DSPLLE, "CPU(RM) B:%i M:0x%08x (pc=0x%04x)", mbx, gdsp_mbox_peek(GDSP_MBOX_DSP), g_dsp.pc); } #endif diff --git a/Source/Core/DSPCore/Src/DSPInterpreter.cpp b/Source/Core/DSPCore/Src/DSPInterpreter.cpp index a04e0654ea..1417a2ad89 100644 --- a/Source/Core/DSPCore/Src/DSPInterpreter.cpp +++ b/Source/Core/DSPCore/Src/DSPInterpreter.cpp @@ -80,6 +80,7 @@ void HandleLoop() const u16 rCallAddress = g_dsp.r[DSP_REG_ST0]; const u16 rLoopAddress = g_dsp.r[DSP_REG_ST2]; + if (g_dsp.pc == (rLoopAddress + opSize[rLoopAddress])) { rLoopCounter--; @@ -148,7 +149,8 @@ void Run() // This one has basic idle skipping, and checks breakpoints. int RunCyclesDebug(int cycles) { - // First, let's run a few cycles with no idle skipping so that things can progress a bit. + // First, let's run a few cycles with no idle skipping so that things can + // progress a bit. for (int i = 0; i < 8; i++) { if (g_dsp.cr & CR_HALT) @@ -231,7 +233,8 @@ int RunCycles(int cycles) cycles--; } - // Next, let's run a few cycles with idle skipping, so that we can skip idle loops. + // Next, let's run a few cycles with idle skipping, so that we can skip + // idle loops. for (int i = 0; i < 8; i++) { if (g_dsp.cr & CR_HALT) @@ -242,8 +245,9 @@ int RunCycles(int cycles) cycles--; } - // Now, run the rest of the block without idle skipping. It might trip into a - // idle loop and if so we waste some time here. Might be beneficial to slice even further. + // Now, run the rest of the block without idle skipping. It might trip into + // a idle loop and if so we waste some time here. Might be beneficial to + // slice even further. while (cycles > 0) { Step();