From 96560444ea60587defcf1c539c80d9f7999c3bf9 Mon Sep 17 00:00:00 2001 From: "Jake.Stine" Date: Mon, 17 Nov 2008 17:11:11 +0000 Subject: [PATCH] SPU2ghz: Fixed a memory corruption bug in the rolled back DMA write code. Hopefully this DMA write code will fix that bug without breaking Arc the Lad and similar games. git-svn-id: http://pcsx2-playground.googlecode.com/svn/trunk@334 a6443dda-0b58-4228-96e9-037be469359c --- plugins/spu2ghz/config.cpp | 2 +- plugins/spu2ghz/dma.cpp | 141 +++++++++++++++++++++++-------------- plugins/spu2ghz/spu2.cpp | 20 +++--- 3 files changed, 99 insertions(+), 64 deletions(-) diff --git a/plugins/spu2ghz/config.cpp b/plugins/spu2ghz/config.cpp index ba0c985b08..5f820bfb19 100644 --- a/plugins/spu2ghz/config.cpp +++ b/plugins/spu2ghz/config.cpp @@ -492,7 +492,7 @@ BOOL CALLBACK ConfigProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam) // Debugging / Logging Flags: SET_CHECK(IDC_EFFECTS, EffectsEnabled); SET_CHECK(IDC_DEBUG, DebugEnabled); - SET_CHECK(IDC_MSGKEY, _MsgToConsole); + SET_CHECK(IDC_MSGSHOW, _MsgToConsole); SET_CHECK(IDC_MSGKEY, _MsgKeyOnOff); SET_CHECK(IDC_MSGVOICE,_MsgVoiceOff); SET_CHECK(IDC_MSGDMA, _MsgDMA); diff --git a/plugins/spu2ghz/dma.cpp b/plugins/spu2ghz/dma.cpp index 74a6ab70d6..639dcc9ee8 100644 --- a/plugins/spu2ghz/dma.cpp +++ b/plugins/spu2ghz/dma.cpp @@ -92,9 +92,9 @@ void DMALogClose() { __forceinline u16 DmaRead(u32 core) { - Cores[core].TDA&=0xfffff; const u16 ret = (u16)spu2M_Read(Cores[core].TDA); Cores[core].TDA++; + Cores[core].TDA&=0xfffff; return ret; } @@ -189,27 +189,24 @@ void StartADMAWrite(int core,u16 *pMem, u32 sz) void DoDMAWrite(int core,u16 *pMem,u32 size) { - u32 i; + // Perform an alignment check. + // Not really important. Everything should work regardless, + // but it could be indicative of an emulation foopah elsewhere. +#ifndef PUBLIC + uptr pa = ((uptr)pMem)&7; + uptr pm = Cores[core].TSA&0x7; + + if( pa ) { - // Perform an alignment check. - // Not really important. Everything should work regardless, - // but it could be indicative of an emulation foopah elsewhere. - - uptr pa = ((uptr)pMem)&7; - uptr pm = Cores[core].TSA&0x7; - - if( pa ) - { - fprintf(stderr, "* SPU2 DMA Write > Missaligned SOURCE! Core: %d TSA: 0x%x TDA: 0x%x Size: 0x%x\n", core, Cores[core].TSA, Cores[core].TDA, size); - } - - if( pm ) - { - fprintf(stderr, "* SPU2 DMA Write > Missaligned TARGET! Core: %d TSA: 0x%x TDA: 0x%x Size: 0x%x\n", core, Cores[core].TSA, Cores[core].TDA, size ); - } + fprintf(stderr, "* SPU2 DMA Write > Missaligned SOURCE! Core: %d TSA: 0x%x TDA: 0x%x Size: 0x%x\n", core, Cores[core].TSA, Cores[core].TDA, size); } + if( pm ) + { + fprintf(stderr, "* SPU2 DMA Write > Missaligned TARGET! Core: %d TSA: 0x%x TDA: 0x%x Size: 0x%x\n", core, Cores[core].TSA, Cores[core].TDA, size ); + } +#endif if(core==0) DMA4LogWrite(pMem,size<<1); @@ -218,49 +215,91 @@ void DoDMAWrite(int core,u16 *pMem,u32 size) if(MsgDMA()) ConLog(" * SPU2: DMA%c Transfer of %d bytes to %x (%02x %x %04x).\n",(core==0)?'4':'7',size<<1,Cores[core].TSA,Cores[core].DMABits,Cores[core].AutoDMACtrl,(~Cores[core].Regs.ATTR)&0x7fff); - // Optimized! - // Instead of checking the adpcm cache for every word, we check for every block. + // split the DMA copy into two chunks if needed. + + // Instead of checking the adpcm cache for every word, we check for every ADPCM block. // That way we can use the optimized fast write instruction to commit the memory. - Cores[core].TDA = Cores[core].TSA & 0xfffff; + Cores[core].TSA &= 0xfffff; + u32 buff1end = Cores[core].TSA + size; + u32 buff2end=0; + if( buff1end > 0xfffff ) { - u32 nexta = Cores[core].TDA >> 3; - u32 flagbitmask = 1ul << ( nexta & 31 ); - nexta >>= 5; + buff2end = buff1end - 0xfffff; + buff1end = 0xfffff; + } - // Traverse from start to finish in 8 word blocks, - // and clear the pcm cache flag for each block. - u32 stmp = ( size + 7 ) >> 3; // round up - for( i=0; i> (3+3); + const u32 flagTDA = (buff1end + roundUp) >> (3 + 3); // endpoint, rounded up + u8* cache = (u8*)pcm_cache_flags; + + memset( &cache[flagTSA], 0, flagTDA - flagTSA ); + + if( buff2end > 0 ) + { + // second branch needs cleared: + // It starts at the beginning of memory and moves forward to buff2end + + const u32 endpt2 = (buff2end + roundUp) >> (3+3); + memcpy( GetMemPtr( 0 ), &pMem[buff1size], buff2end*2 ); + memset( pcm_cache_flags, 0, endpt2 ); + + Cores[core].TDA = buff2end; + + if(Cores[core].IRQEnable) { - pcm_cache_flags[nexta] &= ~flagbitmask; - flagbitmask <<= 1; - if( flagbitmask == 0 ) + // Flag interrupt? + // If IRQA occurs between start and dest, flag it. + // Since the buffer wraps, the conditional might seem odd, but it works. + + if( ( Cores[core].IRQA >= Cores[core].TSA ) || + ( Cores[core].IRQA <= Cores[core].TDA ) ) { - nexta++; - flagbitmask = 1; + Spdif.Info=4<= Cores[core].TSA ) && + ( Cores[core].IRQA <= Cores[core].TDA ) ) + { + Spdif.Info=4<0xFFFFF)||((Cores[core].TDA>=Cores[core].IRQA)&&(i<=Cores[core].IRQA))) { - if(Cores[core].IRQEnable) - { - Spdif.Info=4<=TickInterval) { - - //UpdateDebugDialog(); - if(has_to_call_irq) { ConLog(" * SPU2: Irq Called (%04x).\n",Spdif.Info); @@ -889,7 +886,7 @@ void UpdateSpdifMode() __forceinline void RegLog(int level, char *RName,u32 mem,u32 core,u16 value) { - if(level>1) + if( level > 1 ) FileLog("[%10d] SPU2 write mem %08x (core %d, register %s) value %04x\n",Cycles,mem,core,RName,value); } @@ -1601,12 +1598,11 @@ static __forceinline void SPU2_FastWrite( u32 rmem, u16 value ) break; default: - SPU2writeLog(mem,value); - *(regtable[mem>>1])=value; break; } + SPU2writeLog(mem,value); if ((mem>=0x07C0) && (mem<0x07CE)) { UpdateSpdifMode(); @@ -1932,7 +1928,7 @@ void VoiceStart(int core,int vc) { if(Cores[core].Voices[vc].StartA&7) { - printf(" *** Missaligned StartA %05x!\n",Cores[core].Voices[vc].StartA); + fprintf( stderr, " *** Missaligned StartA %05x!\n",Cores[core].Voices[vc].StartA); Cores[core].Voices[vc].StartA=(Cores[core].Voices[vc].StartA+0xFFFF8)+0x8; }