diff --git a/3rdparty/3rdparty.vsprops b/3rdparty/3rdparty.vsprops index b5d789323f..1a107abb2c 100644 --- a/3rdparty/3rdparty.vsprops +++ b/3rdparty/3rdparty.vsprops @@ -3,8 +3,8 @@ ProjectType="Visual C++" Version="8.00" Name="3rdparty" - OutputDirectory="$(ProjectDir)..\..\deps\$(PlatformName)\$(ConfigurationName)" - IntermediateDirectory="$(ProjectDir)\$(PlatformName)\$(ConfigurationName)" + OutputDirectory="..\..\deps\$(PlatformName)\$(ConfigurationName)" + IntermediateDirectory="$(PlatformName)\$(ConfigurationName)" > + + @@ -5796,10 +5800,6 @@ /> - - - - @@ -17016,6 +17012,10 @@ /> + + = 0) && (delta >= Cdvd_Contigious_Seek) ) + else if( (tbl_ContigiousSeekDelta[mode] == 0) || (delta >= tbl_ContigiousSeekDelta[mode]) ) { - CDR_LOG( "CdSeek Begin > to sector %d, from %d - delta=%d\n", cdvd.SeekToSector, cdvd.Sector, delta ); - seektime = Cdvd_Avg_SeekCycles; + // Select either Full or Fast seek depending on delta: + + if( delta >= tbl_FastSeekDelta[mode] ) + { + // Full Seek + CDR_LOG( "CdSeek Begin > to sector %d, from %d - delta=%d [FULL]\n", cdvd.SeekToSector, cdvd.Sector, delta ); + seektime = Cdvd_FullSeek_Cycles; + } + else + { + CDR_LOG( "CdSeek Begin > to sector %d, from %d - delta=%d [FAST]\n", cdvd.SeekToSector, cdvd.Sector, delta ); + seektime = Cdvd_FastSeek_Cycles; + } } else { @@ -1332,7 +1362,7 @@ void cdvdWrite04(u8 rt) { // NCOMMAND DevCon::Notice( "CdStandby : %d", params rt ); cdvd.Action = cdvdAction_Standby; cdvd.ReadTime = cdvdBlockReadTime( MODE_DVDROM ); - CDVD_INT( cdvdStartSeek( 0 ) ); + CDVD_INT( cdvdStartSeek( 0, MODE_DVDROM ) ); break; case 0x03: // CdStop @@ -1349,7 +1379,7 @@ void cdvdWrite04(u8 rt) { // NCOMMAND case 0x05: // CdSeek cdvd.Action = cdvdAction_Seek; cdvd.ReadTime = cdvdBlockReadTime( MODE_DVDROM ); - CDVD_INT( cdvdStartSeek( *(uint*)(cdvd.Param+0) ) ); + CDVD_INT( cdvdStartSeek( *(uint*)(cdvd.Param+0), MODE_DVDROM ) ); break; case 0x06: // CdRead @@ -1372,7 +1402,7 @@ void cdvdWrite04(u8 rt) { // NCOMMAND params cdvd.Sector, cdvd.nSectors,cdvd.BlockSize,cdvd.Speed); cdvd.ReadTime = cdvdBlockReadTime( MODE_CDROM ); - CDVDREAD_INT( cdvdStartSeek( cdvd.SeekToSector ) ); + CDVDREAD_INT( cdvdStartSeek( cdvd.SeekToSector,MODE_CDROM ) ); // Read-ahead by telling the plugin about the track now. // This helps improve performance on actual from-cd emulation @@ -1413,7 +1443,7 @@ void cdvdWrite04(u8 rt) { // NCOMMAND params cdvd.Sector, cdvd.nSectors,cdvd.BlockSize,cdvd.Speed); cdvd.ReadTime = cdvdBlockReadTime( MODE_CDROM ); - CDVDREAD_INT( cdvdStartSeek( cdvd.SeekToSector ) ); + CDVDREAD_INT( cdvdStartSeek( cdvd.SeekToSector, MODE_CDROM ) ); // Read-ahead by telling the plugin about the track now. // This helps improve performance on actual from-cd emulation @@ -1444,7 +1474,7 @@ void cdvdWrite04(u8 rt) { // NCOMMAND params cdvd.Sector, cdvd.nSectors,cdvd.BlockSize,cdvd.Speed); cdvd.ReadTime = cdvdBlockReadTime( MODE_DVDROM ); - CDVDREAD_INT( cdvdStartSeek( cdvd.SeekToSector ) ); + CDVDREAD_INT( cdvdStartSeek( cdvd.SeekToSector, MODE_DVDROM ) ); // Read-ahead by telling the plugin about the track now. // This helps improve performance on actual from-cd emulation diff --git a/pcsx2/CDVDlib.h b/pcsx2/CDVDlib.h index 9e74fb8d6d..b942055fbf 100644 --- a/pcsx2/CDVDlib.h +++ b/pcsx2/CDVDlib.h @@ -84,6 +84,7 @@ * Macros for sceCdGetDiskType() //comments translated from japanese;) */ +// These are already declared with different names in PS2Edefs.h. And aren't used. #define SCECdIllgalMedia 0xff // ILIMEDIA (Illegal Media) A non-PS / non-PS2 Disc. #define SCECdDVDV 0xfe // DVDV (DVD Video) A non-PS / non-PS2 Disc, but a DVD Video Disc #define SCECdCDDA 0xfd // CDDA (CD DA) A non-PS / non-PS2 Disc that include a DA track @@ -95,7 +96,6 @@ #define SCECdDETCT 0x01 // DETCT (Detecting) Disc distinction action #define SCECdNODISC 0x00 // NODISC (No disc) No disc entered - /* * Media mode */ diff --git a/pcsx2/Cache.cpp b/pcsx2/Cache.cpp index 149bad14bd..ad101b7cb9 100644 --- a/pcsx2/Cache.cpp +++ b/pcsx2/Cache.cpp @@ -27,6 +27,7 @@ namespace R5900{ namespace Interpreter { +// fixme - this code no longer compiles if PCSX2_CACHE_EMU_MEM is defined - do we need it any more? #ifdef PCSX2_CACHE_EMU_MEM int getFreeCache(u32 mem, int mode, int * way) { u8 * out; diff --git a/pcsx2/CdRom.cpp b/pcsx2/CdRom.cpp index 6947ae044a..e6ba423d3d 100644 --- a/pcsx2/CdRom.cpp +++ b/pcsx2/CdRom.cpp @@ -944,15 +944,9 @@ void cdrReset() { cdReadTime = (PSXCLK / 1757) * BIAS; } -void SaveState::cdrFreeze() { +void SaveState::cdrFreeze() +{ + FreezeTag( "cdrom" ); Freeze(cdr); - - // Alrighty! This code used to, for some reason, recalculate the pTransfer value - // even though it's being saved as part of the cdr struct. Probably a backwards - // compat fix with an earlier save version. - - int tmp; // = (int)(cdr.pTransfer - cdr.Transfer); - Freeze(tmp); - //if (Mode == 0) cdr.pTransfer = cdr.Transfer + tmp; } diff --git a/pcsx2/Counters.cpp b/pcsx2/Counters.cpp index 97c4016a11..cb148f8261 100644 --- a/pcsx2/Counters.cpp +++ b/pcsx2/Counters.cpp @@ -43,7 +43,9 @@ int gates = 0; // Counter 4 takes care of scanlines - hSync/hBlanks // Counter 5 takes care of vSync/vBlanks -Counter counters[6]; +Counter counters[4]; +SyncCounter hsyncCounter; +SyncCounter vsyncCounter; u32 nextsCounter; // records the cpuRegs.cycle value of the last call to rcntUpdate() s32 nextCounter; // delta from nextsCounter, in cycles, until the next rcntUpdate() @@ -101,7 +103,7 @@ static __forceinline void cpuRcntSet() int i; nextsCounter = cpuRegs.cycle; - nextCounter = (counters[5].sCycle + counters[5].CycleT) - cpuRegs.cycle; + nextCounter = (vsyncCounter.sCycle + vsyncCounter.CycleT) - cpuRegs.cycle; for (i = 0; i < 4; i++) _rcntSet( i ); @@ -124,10 +126,10 @@ void rcntInit() { counters[2].interrupt = 11; counters[3].interrupt = 12; - counters[4].modeval = MODE_HRENDER; - counters[4].sCycle = cpuRegs.cycle; - counters[5].modeval = MODE_VRENDER; - counters[5].sCycle = cpuRegs.cycle; + hsyncCounter.Mode = MODE_HRENDER; + hsyncCounter.sCycle = cpuRegs.cycle; + vsyncCounter.Mode = MODE_VRENDER; + vsyncCounter.sCycle = cpuRegs.cycle; UpdateVSyncRate(); @@ -136,7 +138,7 @@ void rcntInit() { } // debug code, used for stats -int g_nCounters[4]; +int g_nhsyncCounter; static uint iFrame = 0; #ifndef _WIN32 @@ -235,8 +237,8 @@ u32 UpdateVSyncRate() vSyncInfoCalc( &vSyncInfo, FRAMERATE_NTSC, SCANLINES_TOTAL_NTSC ); } - counters[4].CycleT = vSyncInfo.hRender; // Amount of cycles before the counter will be updated - counters[5].CycleT = vSyncInfo.Render; // Amount of cycles before the counter will be updated + hsyncCounter.CycleT = vSyncInfo.hRender; // Amount of cycles before the counter will be updated + vsyncCounter.CycleT = vSyncInfo.Render; // Amount of cycles before the counter will be updated if (Config.CustomFps > 0) { @@ -393,28 +395,28 @@ static int vblankinc = 0; __forceinline void rcntUpdate_hScanline() { - if( !cpuTestCycle( counters[4].sCycle, counters[4].CycleT ) ) return; + if( !cpuTestCycle( hsyncCounter.sCycle, hsyncCounter.CycleT ) ) return; //iopBranchAction = 1; - if (counters[4].modeval & MODE_HBLANK) { //HBLANK Start - rcntStartGate(false, counters[4].sCycle); + if (hsyncCounter.Mode & MODE_HBLANK) { //HBLANK Start + rcntStartGate(false, hsyncCounter.sCycle); psxCheckStartGate16(0); // Setup the hRender's start and end cycle information: - counters[4].sCycle += vSyncInfo.hBlank; // start (absolute cycle value) - counters[4].CycleT = vSyncInfo.hRender; // endpoint (delta from start value) - counters[4].modeval = MODE_HRENDER; + hsyncCounter.sCycle += vSyncInfo.hBlank; // start (absolute cycle value) + hsyncCounter.CycleT = vSyncInfo.hRender; // endpoint (delta from start value) + hsyncCounter.Mode = MODE_HRENDER; } else { //HBLANK END / HRENDER Begin if (CSRw & 0x4) GSCSRr |= 4; // signal if (!(GSIMR&0x400)) gsIrq(); - if (gates) rcntEndGate(false, counters[4].sCycle); + if (gates) rcntEndGate(false, hsyncCounter.sCycle); if (psxhblankgate) psxCheckEndGate16(0); // set up the hblank's start and end cycle information: - counters[4].sCycle += vSyncInfo.hRender; // start (absolute cycle value) - counters[4].CycleT = vSyncInfo.hBlank; // endpoint (delta from start value) - counters[4].modeval = MODE_HBLANK; + hsyncCounter.sCycle += vSyncInfo.hRender; // start (absolute cycle value) + hsyncCounter.CycleT = vSyncInfo.hBlank; // endpoint (delta from start value) + hsyncCounter.Mode = MODE_HBLANK; # ifdef VSYNC_DEBUG hsc++; @@ -424,30 +426,30 @@ __forceinline void rcntUpdate_hScanline() __forceinline bool rcntUpdate_vSync() { - s32 diff = (cpuRegs.cycle - counters[5].sCycle); - if( diff < counters[5].CycleT ) return false; + s32 diff = (cpuRegs.cycle - vsyncCounter.sCycle); + if( diff < vsyncCounter.CycleT ) return false; //iopBranchAction = 1; - if (counters[5].modeval == MODE_VSYNC) + if (vsyncCounter.Mode == MODE_VSYNC) { - VSyncEnd(counters[5].sCycle); + VSyncEnd(vsyncCounter.sCycle); - counters[5].sCycle += vSyncInfo.Blank; - counters[5].CycleT = vSyncInfo.Render; - counters[5].modeval = MODE_VRENDER; + vsyncCounter.sCycle += vSyncInfo.Blank; + vsyncCounter.CycleT = vSyncInfo.Render; + vsyncCounter.Mode = MODE_VRENDER; return true; } else // VSYNC end / VRENDER begin { - VSyncStart(counters[5].sCycle); + VSyncStart(vsyncCounter.sCycle); - counters[5].sCycle += vSyncInfo.Render; - counters[5].CycleT = vSyncInfo.Blank; - counters[5].modeval = MODE_VSYNC; + vsyncCounter.sCycle += vSyncInfo.Render; + vsyncCounter.CycleT = vSyncInfo.Blank; + vsyncCounter.Mode = MODE_VSYNC; // Accumulate hsync rounding errors: - counters[4].sCycle += vSyncInfo.hSyncError; + hsyncCounter.sCycle += vSyncInfo.hSyncError; # ifdef VSYNC_DEBUG vblankinc++; @@ -766,15 +768,12 @@ u32 __fastcall rcntCycle(int index) void SaveState::rcntFreeze() { - Freeze(counters); - Freeze(nextCounter); - Freeze(nextsCounter); - - // New in version 1 -- save the PAL/NTSC info! - if( GetVersion() >= 0x1 ) - { - Freeze( Config.PsxType ); - } + Freeze( counters ); + Freeze( hsyncCounter ); + Freeze( vsyncCounter ); + Freeze( nextCounter ); + Freeze( nextsCounter ); + Freeze( Config.PsxType ); if( IsLoading() ) { diff --git a/pcsx2/Counters.h b/pcsx2/Counters.h index f5b2d07253..f4c70776ee 100644 --- a/pcsx2/Counters.h +++ b/pcsx2/Counters.h @@ -66,7 +66,8 @@ struct EECNT_MODE // fixme: Cycle and sCycleT members are unused. // But they can't be removed without making a new savestate version. -struct Counter { +struct Counter +{ u32 count; union { @@ -75,10 +76,14 @@ struct Counter { }; u32 target, hold; u32 rate, interrupt; - u32 Cycle; + u32 sCycleT; // delta values should be signed. +}; + +struct SyncCounter +{ + u32 Mode; u32 sCycle; // start cycle of timer s32 CycleT; - u32 sCycleT; // delta values should be signed. }; //------------------------------------------------------------------ @@ -124,7 +129,10 @@ struct Counter { #define MODE_HBLANK 0x1 //Set for the remaining ~1/6 of 1 Scanline -extern Counter counters[6]; +extern Counter counters[4]; +extern SyncCounter hsyncCounter; +extern SyncCounter vsyncCounter; + extern s32 nextCounter; // delta until the next counter event (must be signed) extern u32 nextsCounter; diff --git a/pcsx2/Gif.cpp b/pcsx2/Gif.cpp index bdcbace6d7..af27c1f2c7 100644 --- a/pcsx2/Gif.cpp +++ b/pcsx2/Gif.cpp @@ -250,6 +250,13 @@ void GIFdma() GIFchain(); //Transfers the data set by the switch FreezeRegs(0); if(gif->qwc == 0 && (gif->chcr & 0xc) == 0) gspath3done = 1; + else + { + if(psHu32(GIF_MODE) & 0x4) + CPU_INT(2, min( 8, (int)gif->qwc )/** BIAS*/); + else + CPU_INT(2, gif->qwc/* * BIAS*/); + } return; } else { @@ -308,15 +315,28 @@ void GIFdma() prevcycles = 0; if (!(vif1Regs->mskpath3 || (psHu32(GIF_MODE) & 0x1))) { - if(gspath3done == 0){ - ptag = (u32*)dmaGetAddr(gif->tadr); //Set memory pointer to TADR - gif->qwc = (u16)ptag[0]; //QWC set to lower 16bits of the tag - gif->chcr = ( gif->chcr & 0xFFFF ) | ( (*ptag) & 0xFFFF0000 ); //Transfer upper part of tag to CHCR bits 31-15 - CPU_INT(2, gif->qwc * BIAS); - gif->qwc = 0; - return; + if(gspath3done == 0) + { + if((psHu32(GIF_MODE) & 0x4) && gif->qwc != 0) + { + CPU_INT(2, min( 8, (int)gif->qwc )/** BIAS*/); + } + else + { + ptag = (u32*)dmaGetAddr(gif->tadr); //Set memory pointer to TADR + gif->qwc = (u16)ptag[0]; //QWC set to lower 16bits of the tag + gif->chcr = ( gif->chcr & 0xFFFF ) | ( (*ptag) & 0xFFFF0000 ); //Transfer upper part of tag to CHCR bits 31-15 + + if(psHu32(GIF_MODE) & 0x4) + CPU_INT(2, min( 8, (int)gif->qwc )/** BIAS*/); + else + CPU_INT(2, gif->qwc /** BIAS*/); + + gif->qwc = 0; + return; + } } - //CPU_INT(2, gif->qwc * BIAS); + //CPU_INT(2, gif->qwc /** BIAS*/); gscycles = 0; } } @@ -348,7 +368,14 @@ void dmaGIF() { ptag = (u32*)dmaGetAddr(gif->tadr); gif->qwc = (u16)ptag[0]; //QWC set to lower 16bits of the tag gif->chcr = ( gif->chcr & 0xFFFF ) | ( (*ptag) & 0xFFFF0000 ); //Transfer upper part of tag to CHCR bits 31-15 - CPU_INT(2, gif->qwc * BIAS); + if((psHu32(GIF_MODE) & 0x4) && gif->qwc != 0) + { + CPU_INT(2, min( 8, (int)gif->qwc ) /** BIAS*/); + } + else + { + CPU_INT(2, gif->qwc /** BIAS*/); + } gif->qwc = 0; return; } @@ -356,15 +383,28 @@ void dmaGIF() { if(gif->qwc > 0 && (gif->chcr & 0x4) == 0x4) { //SysPrintf("HL Hack\n"); gspath3done = 1; //Halflife sets a QWC amount in chain mode, no tadr set. - CPU_INT(2, gif->qwc * BIAS); - GIFdma(); + if((psHu32(GIF_MODE) & 0x4) && gif->qwc != 0) + { + CPU_INT(2, min( 8, (int)gif->qwc ) /** BIAS*/); + } + else + { + CPU_INT(2, gif->qwc /** BIAS*/); + } return; } //GIFdma(); - CPU_INT(2, gif->qwc * BIAS); + if((psHu32(GIF_MODE) & 0x4) && gif->qwc != 0) + { + CPU_INT(2, min( 8, (int)gif->qwc ) /** BIAS*/); + } + else + { + CPU_INT(2, gif->qwc /** BIAS*/); + } } @@ -575,13 +615,12 @@ void gifMFIFOInterrupt() void SaveState::gifFreeze() { - if( GetVersion() >= 0x04 ) - { - Freeze( gifstate ); - Freeze( gifqwc ); - Freeze( gspath3done ); - Freeze( gscycles ); + FreezeTag( "GIFdma" ); - // Note: mfifocycles is not a persistent var, so no need to save it here. - } + Freeze( gifstate ); + Freeze( gifqwc ); + Freeze( gspath3done ); + Freeze( gscycles ); + + // Note: mfifocycles is not a persistent var, so no need to save it here. } diff --git a/pcsx2/HwRead.cpp b/pcsx2/HwRead.cpp index a81de37137..87cfda6934 100644 --- a/pcsx2/HwRead.cpp +++ b/pcsx2/HwRead.cpp @@ -36,8 +36,11 @@ using namespace R5900; static __forceinline void IntCHackCheck() { - cpuRegs.cycle = g_nextBranchCycle; - + // Sanity check: To protect from accidentally "rewinding" the cyclecount + // on the few times nextBranchCycle can be behind our current cycle. + s32 diff = g_nextBranchCycle - cpuRegs.cycle; + if( diff > 0 ) cpuRegs.cycle = g_nextBranchCycle; + // Threshold method, might fix games that have problems with the simple // implementation above (none known that break yet) /*if( ( g_nextBranchCycle - cpuRegs.cycle ) > 500 ) diff --git a/pcsx2/IPU/IPU.cpp b/pcsx2/IPU/IPU.cpp index 96edda1524..b7b3ad5fec 100644 --- a/pcsx2/IPU/IPU.cpp +++ b/pcsx2/IPU/IPU.cpp @@ -163,14 +163,14 @@ void ipuShutdown() // fixme - ipuFreeze looks fairly broken. Should probably take a closer look at some point. -void SaveState::ipuFreeze() { +void SaveState::ipuFreeze() +{ IPUProcessInterrupt(); - if( GetVersion() < 0x04 ) - { - // old versions saved the IPU regs, but they're already saved as part of HW! - FreezeMem(ipuRegs, sizeof(IPUregisters)); - } + FreezeTag( "IPU" ); + + // old versions saved the IPU regs, but they're already saved as part of HW! + //FreezeMem(ipuRegs, sizeof(IPUregisters)); Freeze(g_nDMATransfer); Freeze(FIreadpos); diff --git a/pcsx2/IPU/yuv2rgb.cpp b/pcsx2/IPU/yuv2rgb.cpp index 312ff8b845..1d93bc6ba9 100644 --- a/pcsx2/IPU/yuv2rgb.cpp +++ b/pcsx2/IPU/yuv2rgb.cpp @@ -215,7 +215,7 @@ ihatemsvc: jne tworows } #elif defined(__GNUC__) - asm( + __asm__( ".intel_syntax noprefix\n" "mov eax, 1\n" "xor esi, esi\n" diff --git a/pcsx2/IopCounters.cpp b/pcsx2/IopCounters.cpp index 10027f1ed5..b4f40c801f 100644 --- a/pcsx2/IopCounters.cpp +++ b/pcsx2/IopCounters.cpp @@ -751,6 +751,8 @@ void psxRcntSetGates() void SaveState::psxRcntFreeze() { + FreezeTag( "iopCounters" ); + Freeze(psxCounters); Freeze(psxNextCounter); Freeze(psxNextsCounter); diff --git a/pcsx2/IopCounters.h b/pcsx2/IopCounters.h index 8012b5ace2..69c56acd74 100644 --- a/pcsx2/IopCounters.h +++ b/pcsx2/IopCounters.h @@ -19,14 +19,10 @@ #ifndef __PSXCOUNTERS_H__ #define __PSXCOUNTERS_H__ -// fixme: sCycle, Cycle, and otarget are unused -// Can't remove them without making a new savestate version though. - struct psxCounter { u64 count, target; u32 mode; - u32 rate, interrupt, otarget; - u32 sCycle, Cycle; + u32 rate, interrupt; u32 sCycleT; s32 CycleT; }; diff --git a/pcsx2/IopMem.cpp b/pcsx2/IopMem.cpp index 0a4d04e582..e32657f704 100644 --- a/pcsx2/IopMem.cpp +++ b/pcsx2/IopMem.cpp @@ -17,319 +17,12 @@ */ #include "PrecompiledHeader.h" - #include "IopCommon.h" -#include "VU.h" -#include "iCore.h" -#include "Hw.h" -#include "iR3000A.h" - -int g_psxWriteOk=1; -static u32 writectrl; - -#ifdef PCSX2_VIRTUAL_MEM -void psxMemAlloc() -{ - // In VirtualMemory land all mem taken care by memAlloc -} - -void psxMemReset() -{ - memzero_ptr(psxM); -} - -void psxMemShutdown() -{ -} - -u8 iopMemRead8(u32 mem) -{ - u32 t = (mem >> 16) & 0x1fff; - - switch(t) { - case 0x1f80: - mem&= 0x1fffffff; - if (mem < 0x1f801000) - return psxHu8(mem); - else - return psxHwRead8(mem); - break; - -#ifdef _DEBUG - case 0x1d00: assert(0); -#endif - - case 0x1f40: - mem &= 0x1fffffff; - return psxHw4Read8(mem); - - case 0x1000: return DEV9read8(mem & 0x1FFFFFFF); - - default: - assert( g_psxWriteOk ); - return *(u8*)PSXM(mem); - } -} - -u16 iopMemRead16(u32 mem) -{ - u32 t = (mem >> 16) & 0x1fff; - - switch(t) { - case 0x1f80: - mem&= 0x1fffffff; - if (mem < 0x1f801000) - return psxHu16(mem); - else - return psxHwRead16(mem); - break; - - case 0x1d00: - SIF_LOG("Sif reg read %x value %x\n", mem, psxHu16(mem)); - switch(mem & 0xF0) - { - case 0x40: return psHu16(0x1000F240) | 0x0002; - case 0x60: return 0; - default: return *(u16*)(PS2MEM_HW+0xf200+(mem&0xf0)); - } - break; - - case 0x1f90: - return SPU2read(mem & 0x1FFFFFFF); - case 0x1000: - return DEV9read16(mem & 0x1FFFFFFF); - - default: - assert( g_psxWriteOk ); - return *(u16*)PSXM(mem); - } -} - -u32 iopMemRead32(u32 mem) -{ - u32 t = (mem >> 16) & 0x1fff; - - switch(t) { - case 0x1f80: - mem&= 0x1fffffff; - if (mem < 0x1f801000) - return psxHu32(mem); - else - return psxHwRead32(mem); - break; - - case 0x1d00: - SIF_LOG("Sif reg read %x value %x\n", mem, psxHu32(mem)); - switch(mem & 0xF0) - { - case 0x40: return psHu32(0x1000F240) | 0xF0000002; - case 0x60: return 0; - default: return *(u32*)(PS2MEM_HW+0xf200+(mem&0xf0)); - } - break; - - case 0x1fff: return g_psxWriteOk; - case 0x1000: - return DEV9read32(mem & 0x1FFFFFFF); - - default: - //assert(g_psxWriteOk); - if( mem == 0xfffe0130 ) - return writectrl; - else if( mem == 0xffffffff ) - return writectrl; - else if( g_psxWriteOk ) - return *(u32*)PSXM(mem); - else return 0; - } -} - -void iopMemWrite8(u32 mem, u8 value) -{ - u32 t = (mem >> 16) & 0x1fff; - - switch(t) { - case 0x1f80: - mem&= 0x1fffffff; - if (mem < 0x1f801000) - psxHu8(mem) = value; - else - psxHwWrite8(mem, value); - break; - - case 0x1f40: - mem&= 0x1fffffff; - psxHw4Write8(mem, value); - break; - - case 0x1d00: - SysPrintf("sw8 [0x%08X]=0x%08X\n", mem, value); - *(u8*)(PS2MEM_HW+0xf200+(mem&0xff)) = value; - break; - - case 0x1000: - DEV9write8(mem & 0x1fffffff, value); - return; - - default: - assert(g_psxWriteOk); - *(u8 *)PSXM(mem) = value; - psxCpu->Clear(mem&~3, 1); - break; - } -} - -void iopMemWrite16(u32 mem, u16 value) -{ - u32 t = (mem >> 16) & 0x1fff; - switch(t) { - case 0x1600: - //HACK: DEV9 VM crash fix - break; - case 0x1f80: - mem&= 0x1fffffff; - if (mem < 0x1f801000) - psxHu16(mem) = value; - else - psxHwWrite16(mem, value); - break; - - case 0x1d00: - switch (mem & 0xf0) { - case 0x10: - // write to ps2 mem - psHu16(0x1000F210) = value; - return; - case 0x40: - { - u32 temp = value & 0xF0; - // write to ps2 mem - if(value & 0x20 || value & 0x80) - { - psHu16(0x1000F240) &= ~0xF000; - psHu16(0x1000F240) |= 0x2000; - } - - if(psHu16(0x1000F240) & temp) psHu16(0x1000F240) &= ~temp; - else psHu16(0x1000F240) |= temp; - return; - } - case 0x60: - psHu32(0x1000F260) = 0; - return; - default: - assert(0); - } - return; - - case 0x1f90: - SPU2write(mem & 0x1FFFFFFF, value); return; - - case 0x1000: - DEV9write16(mem & 0x1fffffff, value); return; - default: - assert( g_psxWriteOk ); - *(u16 *)PSXM(mem) = value; - psxCpu->Clear(mem&~3, 1); - break; - } -} - -void iopMemWrite32(u32 mem, u32 value) -{ - u32 t = (mem >> 16) & 0x1fff; - switch(t) { - case 0x1f80: - mem&= 0x1fffffff; - if (mem < 0x1f801000) - psxHu32(mem) = value; - else - psxHwWrite32(mem, value); - break; - - case 0x1d00: - switch (mem & 0xf0) { - case 0x10: - // write to ps2 mem - psHu32(0x1000F210) = value; - return; - case 0x20: - // write to ps2 mem - psHu32(0x1000F220) &= ~value; - return; - case 0x30: - // write to ps2 mem - psHu32(0x1000F230) |= value; - return; - case 0x40: - { - u32 temp = value & 0xF0; - // write to ps2 mem - if(value & 0x20 || value & 0x80) - { - psHu32(0x1000F240) &= ~0xF000; - psHu32(0x1000F240) |= 0x2000; - } - - - if(psHu32(0x1000F240) & temp) psHu32(0x1000F240) &= ~temp; - else psHu32(0x1000F240) |= temp; - return; - } - case 0x60: - psHu32(0x1000F260) = 0; - return; - - default: - *(u32*)(PS2MEM_HW+0xf200+(mem&0xf0)) = value; - } - - return; - - case 0x1000: - DEV9write32(mem & 0x1fffffff, value); - return; - - case 0x1ffe: - if( mem == 0xfffe0130 ) { - writectrl = value; - switch (value) { - case 0x800: case 0x804: - case 0xc00: case 0xc04: - case 0xcc0: case 0xcc4: - case 0x0c4: - g_psxWriteOk = 0; - //PSXMEM_LOG("writectrl: writenot ok\n"); - break; - case 0x1e988: - case 0x1edd8: - g_psxWriteOk = 1; - //PSXMEM_LOG("writectrl: write ok\n"); - break; - default: - PSXMEM_LOG("unk %8.8lx = %x\n", mem, value); - break; - } - } - break; - - default: - - if( g_psxWriteOk ) { - *(u32 *)PSXM(mem) = value; - psxCpu->Clear(mem&~3, 1); - } - - break; - } -} - -#else u8 *psxM = NULL; u8 *psxP = NULL; -u8 *psxH = NULL; -u8 *psxS = NULL; +u8 *psxH = NULL; // standard hardware registers (0x000->0x3ff is the scratchpad) +u8 *psxS = NULL; // 'undocumented' SIF communication registers uptr *psxMemWLUT = NULL; const uptr *psxMemRLUT = NULL; @@ -339,7 +32,7 @@ static const uint m_psxMemSize = Ps2MemSize::IopRam + Ps2MemSize::IopHardware + 0x00010000 + // psxP - 0x00010000 ; // psxS + 0x00000100 ; // psxS void psxMemAlloc() { @@ -355,8 +48,8 @@ void psxMemAlloc() psxH = curpos; curpos += Ps2MemSize::IopHardware; psxS = curpos; //curpos += 0x00010000; - psxMemWLUT = (uptr*)_aligned_malloc(0x10000 * sizeof(uptr) * 2, 16); - psxMemRLUT = psxMemWLUT + 0x10000; //(uptr*)_aligned_malloc(0x10000 * sizeof(uptr),16); + psxMemWLUT = (uptr*)_aligned_malloc(0x2000 * sizeof(uptr) * 2, 16); + psxMemRLUT = psxMemWLUT + 0x2000; //(uptr*)_aligned_malloc(0x10000 * sizeof(uptr),16); } // Note! Resetting the IOP's memory state is dependent on having *all* psx memory allocated, @@ -368,53 +61,53 @@ void psxMemReset() DbgCon::Status( "psxMemReset > Resetting core memory!" ); - memzero_ptr<0x10000 * sizeof(uptr) * 2>( psxMemWLUT ); // clears both allocations, RLUT and WLUT + memzero_ptr<0x2000 * sizeof(uptr) * 2>( psxMemWLUT ); // clears both allocations, RLUT and WLUT memzero_ptr( m_psxAllMem ); // Trick! We're accessing RLUT here through WLUT, since it's the non-const pointer. - // So the ones with a 1 prefixed (ala 0x18000, etc) are RLUT tables. + // So the ones with a 0x2000 prefixed are RLUT tables. // Map IOP main memory, which is Read/Write, and mirrored three times // at 0x0, 0x8000, and 0xa000: for (int i=0; i<0x0080; i++) { psxMemWLUT[i + 0x0000] = (uptr)&psxM[(i & 0x1f) << 16]; - psxMemWLUT[i + 0x8000] = (uptr)&psxM[(i & 0x1f) << 16]; - psxMemWLUT[i + 0xa000] = (uptr)&psxM[(i & 0x1f) << 16]; + //psxMemWLUT[i + 0x8000] = (uptr)&psxM[(i & 0x1f) << 16]; + //psxMemWLUT[i + 0xa000] = (uptr)&psxM[(i & 0x1f) << 16]; // RLUTs, accessed through WLUT. - psxMemWLUT[i + 0x10000] = (uptr)&psxM[(i & 0x1f) << 16]; - psxMemWLUT[i + 0x18000] = (uptr)&psxM[(i & 0x1f) << 16]; - psxMemWLUT[i + 0x1a000] = (uptr)&psxM[(i & 0x1f) << 16]; + psxMemWLUT[i + 0x2000] = (uptr)&psxM[(i & 0x1f) << 16]; + //psxMemWLUT[i + 0x18000] = (uptr)&psxM[(i & 0x1f) << 16]; + //psxMemWLUT[i + 0x1a000] = (uptr)&psxM[(i & 0x1f) << 16]; } // A few single-page allocations for things we store in special locations. - psxMemWLUT[0x11f00] = (uptr)psxP; - psxMemWLUT[0x11f80] = (uptr)psxH; - psxMemWLUT[0x1bf80] = (uptr)psxH; + psxMemWLUT[0x2000 + 0x1f00] = (uptr)psxP; + psxMemWLUT[0x2000 + 0x1f80] = (uptr)psxH; + //psxMemWLUT[0x1bf80] = (uptr)psxH; psxMemWLUT[0x1f00] = (uptr)psxP; psxMemWLUT[0x1f80] = (uptr)psxH; - psxMemWLUT[0xbf80] = (uptr)psxH; + //psxMemWLUT[0xbf80] = (uptr)psxH; // Read-only memory areas, so don't map WLUT for these... for (int i=0; i<0x0040; i++) { - psxMemWLUT[i + 0x11fc0] = (uptr)&PS2MEM_ROM[i << 16]; - psxMemWLUT[i + 0x19fc0] = (uptr)&PS2MEM_ROM[i << 16]; - psxMemWLUT[i + 0x1bfc0] = (uptr)&PS2MEM_ROM[i << 16]; + psxMemWLUT[i + 0x2000 + 0x1fc0] = (uptr)&PS2MEM_ROM[i << 16]; + //psxMemWLUT[i + 0x19fc0] = (uptr)&PS2MEM_ROM[i << 16]; + //psxMemWLUT[i + 0x1bfc0] = (uptr)&PS2MEM_ROM[i << 16]; } for (int i=0; i<0x0004; i++) { - psxMemWLUT[i + 0x11e00] = (uptr)&PS2MEM_ROM1[i << 16]; - psxMemWLUT[i + 0x19e00] = (uptr)&PS2MEM_ROM1[i << 16]; - psxMemWLUT[i + 0x1be00] = (uptr)&PS2MEM_ROM1[i << 16]; + psxMemWLUT[i + 0x2000 + 0x1e00] = (uptr)&PS2MEM_ROM1[i << 16]; + //psxMemWLUT[i + 0x19e00] = (uptr)&PS2MEM_ROM1[i << 16]; + //psxMemWLUT[i + 0x1be00] = (uptr)&PS2MEM_ROM1[i << 16]; } - // Scratchpad! (which is read only? (air)) - psxMemWLUT[0x11d00] = (uptr)psxS; - psxMemWLUT[0x1bd00] = (uptr)psxS; + // sif!! (which is read only? (air)) + psxMemWLUT[0x2000 + 0x1d00] = (uptr)psxS; + //psxMemWLUT[0x1bd00] = (uptr)psxS; // why isn't scratchpad read/write? (air) //for (i=0; i<0x0001; i++) psxMemWLUT[i + 0x1d00] = (uptr)&psxS[i << 16]; @@ -436,48 +129,58 @@ void psxMemShutdown() psxMemRLUT = NULL; } -u8 iopMemRead8(u32 mem) { - const u8* p; - u32 t; +u8 iopMemRead8(u32 mem) +{ + mem &= 0x1fffffff; + u32 t = mem >> 16; - t = (mem >> 16) & 0x1fff; - if (t == 0x1f80) { - mem&= 0x1fffffff; + if (t == 0x1f80) + { if (mem < 0x1f801000) return psxHu8(mem); else return psxHwRead8(mem); - } else - if (t == 0x1f40) { - mem&= 0x1fffffff; + } + else if (t == 0x1f40) + { return psxHw4Read8(mem); - } else { - p = (const u8*)(psxMemRLUT[mem >> 16]); - if (p != NULL) { + } + else + { + const u8* p = (const u8*)(psxMemRLUT[mem >> 16]); + if (p != NULL) + { return *(const u8 *)(p + (mem & 0xffff)); - } else { - if (t == 0x1000) return DEV9read8(mem & 0x1FFFFFFF); + } + else + { + if (t == 0x1000) + return DEV9read8(mem); PSXMEM_LOG("err lb %8.8lx\n", mem); return 0; } } } -u16 iopMemRead16(u32 mem) { - const u8* p; - u32 t; +u16 iopMemRead16(u32 mem) +{ + mem &= 0x1fffffff; + u32 t = mem >> 16; - t = (mem >> 16) & 0x1fff; - if (t == 0x1f80) { - mem&= 0x1fffffff; + if (t == 0x1f80) + { if (mem < 0x1f801000) return psxHu16(mem); else return psxHwRead16(mem); - } else { - p = (const u8*)(psxMemRLUT[mem >> 16]); - if (p != NULL) { - if (t == 0x1d00) { + } + else + { + const u8* p = (const u8*)(psxMemRLUT[mem >> 16]); + if (p != NULL) + { + if (t == 0x1d00) + { u16 ret; switch(mem & 0xF0) { @@ -501,31 +204,38 @@ u16 iopMemRead16(u32 mem) { return ret; } return *(const u16 *)(p + (mem & 0xffff)); - } else { + } + else + { if (t == 0x1F90) - return SPU2read(mem & 0x1FFFFFFF); - if (t == 0x1000) return DEV9read16(mem & 0x1FFFFFFF); + return SPU2read(mem); + if (t == 0x1000) + return DEV9read16(mem); PSXMEM_LOG("err lh %8.8lx\n", mem); return 0; } } } -u32 iopMemRead32(u32 mem) { - const u8* p; - u32 t; - t = (mem >> 16) & 0x1fff; - if (t == 0x1f80) { - mem&= 0x1fffffff; +u32 iopMemRead32(u32 mem) +{ + mem &= 0x1fffffff; + u32 t = mem >> 16; + + if (t == 0x1f80) + { if (mem < 0x1f801000) return psxHu32(mem); else return psxHwRead32(mem); - } else { + } else + { //see also Hw.c - p = (const u8*)(psxMemRLUT[mem >> 16]); - if (p != NULL) { - if (t == 0x1d00) { + const u8* p = (const u8*)(psxMemRLUT[mem >> 16]); + if (p != NULL) + { + if (t == 0x1d00) + { u32 ret; switch(mem & 0xF0) { @@ -555,215 +265,191 @@ u32 iopMemRead32(u32 mem) { return ret; } return *(const u32 *)(p + (mem & 0xffff)); - } else { - if (t == 0x1000) return DEV9read32(mem & 0x1FFFFFFF); - - if (mem != 0xfffe0130) { - if (g_psxWriteOk) PSXMEM_LOG("err lw %8.8lx\n", mem); - } else { - return writectrl; - } + } + else + { + if (t == 0x1000) + return DEV9read32(mem); return 0; } } } -void iopMemWrite8(u32 mem, u8 value) { - char *p; - u32 t; - - t = (mem >> 16) & 0x1fff; - if (t == 0x1f80) { - mem&= 0x1fffffff; +void iopMemWrite8(u32 mem, u8 value) +{ + mem &= 0x1fffffff; + u32 t = mem >> 16; + + if (t == 0x1f80) + { if (mem < 0x1f801000) psxHu8(mem) = value; else psxHwWrite8(mem, value); - } else - if (t == 0x1f40) { - mem&= 0x1fffffff; + } + else if (t == 0x1f40) + { psxHw4Write8(mem, value); - } else { - p = (char *)(psxMemWLUT[mem >> 16]); - if (p != NULL) { + } + else + { + u8* p = (u8 *)(psxMemWLUT[mem >> 16]); + if (p != NULL && !(psxRegs.CP0.n.Status & 0x10000) ) + { *(u8 *)(p + (mem & 0xffff)) = value; psxCpu->Clear(mem&~3, 1); - } else { - if ((t & 0x1FFF)==0x1D00) SysPrintf("sw8 [0x%08X]=0x%08X\n", mem, value); + } + else + { + if (t == 0x1D00) SysPrintf("sw8 [0x%08X]=0x%08X\n", mem, value); if (t == 0x1d00) { psxSu8(mem) = value; return; } if (t == 0x1000) { - DEV9write8(mem & 0x1fffffff, value); return; + DEV9write8(mem, value); return; } PSXMEM_LOG("err sb %8.8lx = %x\n", mem, value); } } } -void iopMemWrite16(u32 mem, u16 value) { - char *p; - u32 t; +void iopMemWrite16(u32 mem, u16 value) +{ + mem &= 0x1fffffff; + u32 t = mem >> 16; - t = (mem >> 16) & 0x1fff; - if (t == 0x1f80) { - mem&= 0x1fffffff; + if (t == 0x1f80) + { if (mem < 0x1f801000) psxHu16(mem) = value; else psxHwWrite16(mem, value); - } else { - p = (char *)(psxMemWLUT[mem >> 16]); - if (p != NULL) { - if ((t & 0x1FFF)==0x1D00) SysPrintf("sw16 [0x%08X]=0x%08X\n", mem, value); + } else + { + u8* p = (u8 *)(psxMemWLUT[mem >> 16]); + if (p != NULL && !(psxRegs.CP0.n.Status & 0x10000) ) + { + if( t==0x1D00 ) SysPrintf("sw16 [0x%08X]=0x%08X\n", mem, value); *(u16 *)(p + (mem & 0xffff)) = value; psxCpu->Clear(mem&~3, 1); - } else { - if (t == 0x1d00) { - switch (mem & 0xf0) { - case 0x10: - // write to ps2 mem - psHu16(0x1000F210) = value; - return; - case 0x40: + } + else + { + if (t == 0x1d00) + { + switch (mem & 0xf0) + { + case 0x10: + // write to ps2 mem + psHu16(0x1000F210) = value; + return; + case 0x40: + { + u32 temp = value & 0xF0; + // write to ps2 mem + if(value & 0x20 || value & 0x80) { - u32 temp = value & 0xF0; - // write to ps2 mem - if(value & 0x20 || value & 0x80) - { - psHu16(0x1000F240) &= ~0xF000; - psHu16(0x1000F240) |= 0x2000; - } - - - if(psHu16(0x1000F240) & temp) psHu16(0x1000F240) &= ~temp; - else psHu16(0x1000F240) |= temp; - return; + psHu16(0x1000F240) &= ~0xF000; + psHu16(0x1000F240) |= 0x2000; } - case 0x60: - psHu32(0x1000F260) = 0; - return; + + if(psHu16(0x1000F240) & temp) psHu16(0x1000F240) &= ~temp; + else psHu16(0x1000F240) |= temp; + return; } + case 0x60: + psHu32(0x1000F260) = 0; + return; + + } psxSu16(mem) = value; return; } if (t == 0x1F90) { - SPU2write(mem & 0x1FFFFFFF, value); return; + SPU2write(mem, value); return; } if (t == 0x1000) { - DEV9write16(mem & 0x1fffffff, value); return; + DEV9write16(mem, value); return; } PSXMEM_LOG("err sh %8.8lx = %x\n", mem, value); } } } -void iopMemWrite32(u32 mem, u32 value) { - char *p; - u32 t; +void iopMemWrite32(u32 mem, u32 value) +{ + mem &= 0x1fffffff; + u32 t = mem >> 16; - t = (mem >> 16) & 0x1fff; - if (t == 0x1f80) { - mem&= 0x1fffffff; + if (t == 0x1f80) + { if (mem < 0x1f801000) psxHu32(mem) = value; else psxHwWrite32(mem, value); - } else { + } else + { //see also Hw.c - p = (char *)(psxMemWLUT[mem >> 16]); - if (p != NULL) { + u8* p = (u8 *)(psxMemWLUT[mem >> 16]); + if( p != NULL && !(psxRegs.CP0.n.Status & 0x10000) ) + { *(u32 *)(p + (mem & 0xffff)) = value; psxCpu->Clear(mem&~3, 1); - } else { - if (mem != 0xfffe0130) { - if (t == 0x1d00) { + } + else + { + if (t == 0x1d00) + { MEM_LOG("iop Sif reg write %x value %x\n", mem, value); - switch (mem & 0xf0) { - case 0x10: - // write to ps2 mem - psHu32(0x1000F210) = value; - return; - case 0x20: - // write to ps2 mem - psHu32(0x1000F220) &= ~value; - return; - case 0x30: - // write to ps2 mem - psHu32(0x1000F230) |= value; - return; - case 0x40: + switch (mem & 0xf0) + { + case 0x00: // EE write path (EE/IOP readable) + return; // this is the IOP, so read-only (do nothing) + + case 0x10: // IOP write path (EE/IOP readable) + psHu32(0x1000F210) = value; + return; + + case 0x20: // Bits cleared when written from IOP. + psHu32(0x1000F220) &= ~value; + return; + + case 0x30: // bits set when written from IOP + psHu32(0x1000F230) |= value; + return; + + case 0x40: // Control Register + { + u32 temp = value & 0xF0; + if(value & 0x20 || value & 0x80) { - u32 temp = value & 0xF0; - // write to ps2 mem - if(value & 0x20 || value & 0x80) - { - psHu32(0x1000F240) &= ~0xF000; - psHu32(0x1000F240) |= 0x2000; - } - - - if(psHu32(0x1000F240) & temp) psHu32(0x1000F240) &= ~temp; - else psHu32(0x1000F240) |= temp; - return; + psHu32(0x1000F240) &= ~0xF000; + psHu32(0x1000F240) |= 0x2000; } - case 0x60: - psHu32(0x1000F260) = 0; - return; + + if(psHu32(0x1000F240) & temp) + psHu32(0x1000F240) &= ~temp; + else + psHu32(0x1000F240) |= temp; + return; } - psxSu32(mem) = value; - // write to ps2 mem - if( (mem & 0xf0) != 0x60 ) - *(u32*)(PS2MEM_HW+0xf200+(mem&0xf0)) = value; - return; - } - if (t == 0x1000) { - DEV9write32(mem & 0x1fffffff, value); return; + case 0x60: + psHu32(0x1000F260) = 0; + return; } + psxSu32(mem) = value; - //if (!g_psxWriteOk) psxCpu->Clear(mem&~3, 1); - if (g_psxWriteOk) { PSXMEM_LOG("err sw %8.8lx = %x\n", mem, value); } - } else { - writectrl = value; - switch (value) { - case 0x800: case 0x804: - case 0xc00: case 0xc04: - case 0xcc0: case 0xcc4: - case 0x0c4: - if (g_psxWriteOk == 0) break; - g_psxWriteOk = 0; - - // Performance note: Use a for loop instead of memset/memzero - // This generates *much* more efficient code in this particular case (due to few iterations) - for (int i=0; i<0x0080; i++) - { - psxMemWLUT[i + 0x0000] = 0; - psxMemWLUT[i + 0x8000] = 0; - psxMemWLUT[i + 0xa000] = 0; - } - //PSXMEM_LOG("writectrl: writenot ok\n"); - break; - case 0x1e988: - case 0x1edd8: - if (g_psxWriteOk == 1) break; - g_psxWriteOk = 1; - for (int i=0; i<0x0080; i++) - { - psxMemWLUT[i + 0x0000] = (uptr)&psxM[(i & 0x1f) << 16]; - psxMemWLUT[i + 0x8000] = (uptr)&psxM[(i & 0x1f) << 16]; - psxMemWLUT[i + 0xa000] = (uptr)&psxM[(i & 0x1f) << 16]; - } - //PSXMEM_LOG("writectrl: write ok\n"); - break; - default: - PSXMEM_LOG("unk %8.8lx = %x\n", mem, value); - break; - } + // wtf? why were we writing to the EE's sif space? Commenting this out doesn't + // break any of my games, and should be more correct, but I guess we'll see. --air + //*(u32*)(PS2MEM_HW+0xf200+(mem&0xf0)) = value; + return; + } + else if (t == 0x1000) + { + DEV9write32(mem, value); return; } } } } - -#endif diff --git a/pcsx2/IopMem.h b/pcsx2/IopMem.h index c86baef464..21581df609 100644 --- a/pcsx2/IopMem.h +++ b/pcsx2/IopMem.h @@ -46,7 +46,8 @@ static __forceinline T* iopVirtMemW( u32 mem ) template static __forceinline const T* iopVirtMemR( u32 mem ) { - return (psxMemRLUT[(mem) >> 16] == 0) ? NULL : (const T*)(psxMemRLUT[(mem) >> 16] + ((mem) & 0xffff)); + mem &= 0x1fffffff; + return (psxMemRLUT[mem >> 16] == 0) ? NULL : (const T*)(psxMemRLUT[mem >> 16] + (mem & 0xffff)); } // Obtains a pointer to the IOP's physical mapping (bypasses the TLB) @@ -56,11 +57,11 @@ static __forceinline u8* iopPhysMem( u32 addr ) } #define psxSs8(mem) psxS[(mem) & 0xffff] -#define psxSs16(mem) (*(s16*)&psxS[(mem) & 0xffff]) -#define psxSs32(mem) (*(s32*)&psxS[(mem) & 0xffff]) -#define psxSu8(mem) (*(u8*) &psxS[(mem) & 0xffff]) -#define psxSu16(mem) (*(u16*)&psxS[(mem) & 0xffff]) -#define psxSu32(mem) (*(u32*)&psxS[(mem) & 0xffff]) +#define psxSs16(mem) (*(s16*)&psxS[(mem) & 0x00ff]) +#define psxSs32(mem) (*(s32*)&psxS[(mem) & 0x00ff]) +#define psxSu8(mem) (*(u8*) &psxS[(mem) & 0x00ff]) +#define psxSu16(mem) (*(u16*)&psxS[(mem) & 0x00ff]) +#define psxSu32(mem) (*(u32*)&psxS[(mem) & 0x00ff]) #define psxPs8(mem) psxP[(mem) & 0xffff] #define psxPs16(mem) (*(s16*)&psxP[(mem) & 0xffff]) diff --git a/pcsx2/IopSio2.cpp b/pcsx2/IopSio2.cpp index 04e704e47a..c4270b7465 100644 --- a/pcsx2/IopSio2.cpp +++ b/pcsx2/IopSio2.cpp @@ -203,6 +203,7 @@ u8 sio2_fifoOut(){ void SaveState::sio2Freeze() { + FreezeTag( "sio2" ); Freeze(sio2); } diff --git a/pcsx2/Linux/HacksDlg.cpp b/pcsx2/Linux/HacksDlg.cpp index 7d77378199..7a13ad8d83 100644 --- a/pcsx2/Linux/HacksDlg.cpp +++ b/pcsx2/Linux/HacksDlg.cpp @@ -24,9 +24,9 @@ GtkWidget *GameFixDlg, *SpeedHacksDlg; { GameFixDlg = create_GameFixDlg(); + set_checked(GameFixDlg, "check_FPU_Compare", (Config.GameFixes & FLAG_FPU_Compare)); set_checked(GameFixDlg, "check_VU_Add_Sub", (Config.GameFixes & FLAG_VU_ADD_SUB)); - set_checked(GameFixDlg, "check_VU_Clip", (Config.GameFixes & FLAG_VU_CLIP)); - set_checked(GameFixDlg, "check_FPU_Clamp", (Config.GameFixes & FLAG_FPU_CLAMP)); + set_checked(GameFixDlg, "check_FPU_Mul", (Config.GameFixes & FLAG_FPU_MUL)); gtk_widget_show_all(GameFixDlg); gtk_widget_set_sensitive(MainWindow, FALSE); @@ -37,9 +37,9 @@ void on_Game_Fix_OK(GtkButton *button, gpointer user_data) { Config.GameFixes = 0; + Config.GameFixes |= is_checked(GameFixDlg, "check_FPU_Compare") ? FLAG_FPU_Compare : 0; Config.GameFixes |= is_checked(GameFixDlg, "check_VU_Add_Sub") ? FLAG_VU_ADD_SUB : 0; - Config.GameFixes |= is_checked(GameFixDlg, "check_VU_Clip") ? FLAG_VU_CLIP : 0; - Config.GameFixes |= is_checked(GameFixDlg, "check_FPU_Clamp") ? FLAG_FPU_CLAMP : 0; + Config.GameFixes |= is_checked(GameFixDlg, "check_FPU_Mul") ? FLAG_FPU_MUL : 0; SaveConfig(); gtk_widget_destroy(GameFixDlg); diff --git a/pcsx2/Linux/Linux.h b/pcsx2/Linux/Linux.h index 3db9330c95..fc9b436e44 100644 --- a/pcsx2/Linux/Linux.h +++ b/pcsx2/Linux/Linux.h @@ -100,12 +100,12 @@ char iop_log_names[9][32] = "Cdr Log", "GPU Log" }; - +//Tri-Ace - IDC_GAMEFIX2 #define FLAG_VU_ADD_SUB 0x1 -#define FLAG_VU_CLIP 0x2 -#define FLAG_FPU_CLAMP 0x4 -#define FLAG_VU_FCOR_HACK 0x8 -#define FLAG_AVOID_DELAY_HANDLING 0x10 +// Digimon Rumble Arena - IDC_GAMEFIX3 +#define FLAG_FPU_Compare 0x4 +//Tales of Destiny - IDC_GAMEFIX5 +#define FLAG_FPU_MUL 0x8 #define FLAG_VU_NO_OVERFLOW 0x2 #define FLAG_VU_EXTRA_OVERFLOW 0x40 diff --git a/pcsx2/Linux/LnxThreads.cpp b/pcsx2/Linux/LnxThreads.cpp index 6f0c973f77..42d27dcc32 100644 --- a/pcsx2/Linux/LnxThreads.cpp +++ b/pcsx2/Linux/LnxThreads.cpp @@ -16,7 +16,6 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ -#include "Threading.h" #include "Linux.h" #include "../x86/ix86/ix86.h" diff --git a/pcsx2/Linux/callbacks.h b/pcsx2/Linux/callbacks.h index 1857e6594b..a70ca55935 100644 --- a/pcsx2/Linux/callbacks.h +++ b/pcsx2/Linux/callbacks.h @@ -109,30 +109,6 @@ void OnDebug_memWrite32 (GtkButton *button, gpointer user_data); -void -OnConfConf_Pad2Conf (GtkButton *button, - gpointer user_data); - -void -OnConfConf_Pad2Test (GtkButton *button, - gpointer user_data); - -void -OnConfConf_Pad2About (GtkButton *button, - gpointer user_data); - -void -OnConfConf_Pad1Conf (GtkButton *button, - gpointer user_data); - -void -OnConfConf_Pad1Test (GtkButton *button, - gpointer user_data); - -void -OnConfConf_Pad1About (GtkButton *button, - gpointer user_data); - void OnConfButton (GtkButton *button, gpointer user_data); diff --git a/pcsx2/Linux/interface.c b/pcsx2/Linux/interface.c index 08b6244487..62bceb6fdc 100644 --- a/pcsx2/Linux/interface.c +++ b/pcsx2/Linux/interface.c @@ -888,9 +888,9 @@ create_GameFixDlg (void) GtkWidget *GameSettings; GtkWidget *alignment5; GtkWidget *vbox30; - GtkWidget *check_FPU_Clamp; + GtkWidget *check_FPU_Compare; GtkWidget *check_VU_Add_Sub; - GtkWidget *check_VU_Clip; + GtkWidget *check_FPU_Mul; GtkWidget *label42; GtkWidget *dialog_action_area1; GtkWidget *cancelbutton1; @@ -922,20 +922,20 @@ create_GameFixDlg (void) gtk_widget_show (vbox30); gtk_container_add (GTK_CONTAINER (alignment5), vbox30); - check_FPU_Clamp = gtk_check_button_new_with_mnemonic (_("FPU Clamp Hack - Special fix for Tekken 5 and maybe other games.")); - gtk_widget_set_name (check_FPU_Clamp, "check_FPU_Clamp"); - gtk_widget_show (check_FPU_Clamp); - gtk_box_pack_start (GTK_BOX (vbox30), check_FPU_Clamp, FALSE, FALSE, 0); + check_FPU_Compare = gtk_check_button_new_with_mnemonic (_("FPU Compare Hack - Special fix for Digimon Rumble Arena 2.")); + gtk_widget_set_name (check_FPU_Compare, "check_FPU_Compare"); + gtk_widget_show (check_FPU_Compare); + gtk_box_pack_start (GTK_BOX (vbox30), check_FPU_Compare, FALSE, FALSE, 0); check_VU_Add_Sub = gtk_check_button_new_with_mnemonic (_("VU Add / Sub Hack - Special fix for Tri-Ace games!")); gtk_widget_set_name (check_VU_Add_Sub, "check_VU_Add_Sub"); gtk_widget_show (check_VU_Add_Sub); gtk_box_pack_start (GTK_BOX (vbox30), check_VU_Add_Sub, FALSE, FALSE, 0); - check_VU_Clip = gtk_check_button_new_with_mnemonic (_("VU Clip Hack - Special fix for God of War")); - gtk_widget_set_name (check_VU_Clip, "check_VU_Clip"); - gtk_widget_show (check_VU_Clip); - gtk_box_pack_start (GTK_BOX (vbox30), check_VU_Clip, FALSE, TRUE, 0); + check_FPU_Mul = gtk_check_button_new_with_mnemonic (_("FPU Mul Hack - Special fix for Tales of Destiny (possibly other games).")); + gtk_widget_set_name (check_FPU_Mul, "check_FPU_Mul"); + gtk_widget_show (check_FPU_Mul); + gtk_box_pack_start (GTK_BOX (vbox30), check_FPU_Mul, FALSE, TRUE, 0); label42 = gtk_label_new (_("Some games need special settings.\nConfigure them here.")); gtk_widget_set_name (label42, "label42"); @@ -973,9 +973,9 @@ create_GameFixDlg (void) GLADE_HOOKUP_OBJECT (GameFixDlg, GameSettings, "GameSettings"); GLADE_HOOKUP_OBJECT (GameFixDlg, alignment5, "alignment5"); GLADE_HOOKUP_OBJECT (GameFixDlg, vbox30, "vbox30"); - GLADE_HOOKUP_OBJECT (GameFixDlg, check_FPU_Clamp, "check_FPU_Clamp"); + GLADE_HOOKUP_OBJECT (GameFixDlg, check_FPU_Compare, "check_FPU_Compare"); GLADE_HOOKUP_OBJECT (GameFixDlg, check_VU_Add_Sub, "check_VU_Add_Sub"); - GLADE_HOOKUP_OBJECT (GameFixDlg, check_VU_Clip, "check_VU_Clip"); + GLADE_HOOKUP_OBJECT (GameFixDlg, check_FPU_Mul, "check_FPU_Mul"); GLADE_HOOKUP_OBJECT (GameFixDlg, label42, "label42"); GLADE_HOOKUP_OBJECT_NO_REF (GameFixDlg, dialog_action_area1, "dialog_action_area1"); GLADE_HOOKUP_OBJECT (GameFixDlg, cancelbutton1, "cancelbutton1"); @@ -3425,8 +3425,11 @@ create_PatchFinderWindow (void) GtkWidget *radiobutton6; GSList *radiobutton6_group = NULL; GtkWidget *radiobutton5; + GSList *radiobutton5_group = NULL; GtkWidget *radiobutton4; + GSList *radiobutton4_group = NULL; GtkWidget *radiobutton3; + GSList *radiobutton3_group = NULL; GtkWidget *label56; GtkWidget *frame21; GtkWidget *alignment16; @@ -3553,8 +3556,8 @@ create_PatchFinderWindow (void) gtk_table_attach (GTK_TABLE (table6), radiobutton5, 0, 1, 1, 2, (GtkAttachOptions) (0), (GtkAttachOptions) (0), 0, 0); - gtk_radio_button_set_group (GTK_RADIO_BUTTON (radiobutton5), radiobutton6_group); - radiobutton6_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radiobutton5)); + gtk_radio_button_set_group (GTK_RADIO_BUTTON (radiobutton5), radiobutton5_group); + radiobutton5_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radiobutton5)); radiobutton4 = gtk_radio_button_new_with_mnemonic (NULL, _("16 bits")); gtk_widget_set_name (radiobutton4, "radiobutton4"); @@ -3562,8 +3565,8 @@ create_PatchFinderWindow (void) gtk_table_attach (GTK_TABLE (table6), radiobutton4, 1, 2, 0, 1, (GtkAttachOptions) (0), (GtkAttachOptions) (0), 0, 0); - gtk_radio_button_set_group (GTK_RADIO_BUTTON (radiobutton4), radiobutton6_group); - radiobutton6_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radiobutton4)); + gtk_radio_button_set_group (GTK_RADIO_BUTTON (radiobutton4), radiobutton4_group); + radiobutton4_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radiobutton4)); radiobutton3 = gtk_radio_button_new_with_mnemonic (NULL, _("8 bits")); gtk_widget_set_name (radiobutton3, "radiobutton3"); @@ -3571,8 +3574,8 @@ create_PatchFinderWindow (void) gtk_table_attach (GTK_TABLE (table6), radiobutton3, 0, 1, 0, 1, (GtkAttachOptions) (0), (GtkAttachOptions) (0), 0, 0); - gtk_radio_button_set_group (GTK_RADIO_BUTTON (radiobutton3), radiobutton6_group); - radiobutton6_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radiobutton3)); + gtk_radio_button_set_group (GTK_RADIO_BUTTON (radiobutton3), radiobutton3_group); + radiobutton3_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radiobutton3)); label56 = gtk_label_new (_("Values of Size")); gtk_widget_set_name (label56, "label56"); diff --git a/pcsx2/Linux/memzero.h b/pcsx2/Linux/memzero.h index 4b1cbebe61..bdc6265c37 100644 --- a/pcsx2/Linux/memzero.h +++ b/pcsx2/Linux/memzero.h @@ -109,14 +109,14 @@ static __forceinline void memset_8( void *dest ) ( ".intel_syntax noprefix\n" "cld\n" -// "mov edi, %0\n" -// "mov eax, %1\n" +// "mov edi, %[dest]\n" +// "mov eax, %[data32]\n" "stosd\n" "stosd\n" "stosd\n" ".att_syntax\n" : - : "D"(dest), "a"(data32) + : [dest]"D"(dest), [data32]"a"(data32) // D - edi, a -- eax, c ecx : ); @@ -127,15 +127,15 @@ static __forceinline void memset_8( void *dest ) ( ".intel_syntax noprefix\n" "cld\n" -// "mov edi, %0\n" -// "mov eax, %1\n" +// "mov edi, %[dest]\n" +// "mov eax, %[data32]\n" "stosd\n" "stosd\n" "stosd\n" "stosd\n" ".att_syntax\n" : - : "D"(dest), "a"(data32) + : [dest]"D"(dest), [data32]"a"(data32) : ); @@ -146,8 +146,8 @@ static __forceinline void memset_8( void *dest ) ( ".intel_syntax noprefix\n" "cld\n" -// "mov edi, %0\n" -// "mov eax, %1\n" +// "mov edi, %[dest]\n" +// "mov eax, %[data32]\n" "stosd\n" "stosd\n" "stosd\n" @@ -155,7 +155,7 @@ static __forceinline void memset_8( void *dest ) "stosd\n" ".att_syntax\n" : - : "D"(dest), "a"(data32) + : [dest]"D"(dest), [data32]"a"(data32) : ); @@ -166,13 +166,13 @@ static __forceinline void memset_8( void *dest ) ( ".intel_syntax noprefix\n" "cld\n" -// "mov ecx, %0\n" -// "mov edi, %1\n" -// "mov eax, %2\n" +// "mov ecx, %[remdat]\n" +// "mov edi, %[dest]\n" +// "mov eax, %\[data32]n" "rep stosd\n" ".att_syntax\n" : - : "c"(remdat), "D"(dest), "a"(data32) + : [remdat]"c"(remdat), [dest]"D"(dest), [data32]"a"(data32) : ); return; diff --git a/pcsx2/Linux/pcsx2.glade b/pcsx2/Linux/pcsx2.glade index febf8721c1..103e4c2b04 100644 --- a/pcsx2/Linux/pcsx2.glade +++ b/pcsx2/Linux/pcsx2.glade @@ -1868,10 +1868,10 @@ Known to work well with a couple games, namely Shadow of the Colossus (but break 0 - + True True - FPU Clamp Hack - Special fix for Tekken 5 and maybe other games. + FPU Compare Hack - Special fix for Digimon Rumble Arena 2. True GTK_RELIEF_NORMAL True @@ -1906,10 +1906,10 @@ Known to work well with a couple games, namely Shadow of the Colossus (but break - + True True - VU Clip Hack - Special fix for God of War + FPU Mul Hack - Special fix for Tales of Destiny (possibly other games). True GTK_RELIEF_NORMAL True @@ -5063,7 +5063,7 @@ Version x.x True _Graphics True - + @@ -5072,7 +5072,7 @@ Version x.x True C_ontrollers True - + @@ -5081,7 +5081,7 @@ Version x.x True _Sound True - + @@ -5090,7 +5090,7 @@ Version x.x True _Cdvdrom True - + @@ -5099,7 +5099,7 @@ Version x.x True D_ev9 True - + @@ -5108,7 +5108,7 @@ Version x.x True U_SB True - + @@ -5117,7 +5117,7 @@ Version x.x True Fire_Wire True - + @@ -5774,7 +5774,6 @@ Version x.x False False True - radiobutton6 0 @@ -5797,7 +5796,6 @@ Version x.x False False True - radiobutton6 1 @@ -5820,7 +5818,6 @@ Version x.x False False True - radiobutton6 0 diff --git a/pcsx2/MTGS.cpp b/pcsx2/MTGS.cpp index 485ba722d7..bc94623e9b 100644 --- a/pcsx2/MTGS.cpp +++ b/pcsx2/MTGS.cpp @@ -116,6 +116,8 @@ static void _mtgsFreezeGIF( SaveState& state, GIFPath (&paths)[3] ) void SaveState::mtgsFreeze() { + FreezeTag( "mtgs" ); + if( mtgsThread != NULL ) { mtgsThread->Freeze( *this ); diff --git a/pcsx2/Memory.cpp b/pcsx2/Memory.cpp index 31c604598f..2e02c84603 100644 --- a/pcsx2/Memory.cpp +++ b/pcsx2/Memory.cpp @@ -104,11 +104,7 @@ void loadBiosRom( const char *ext, u8 *dest, long maxSize ) Bios1 = Path::Combine( Config.BiosDir, ext ) + ".bin"; if( (filesize=Path::getFileSize( Bios1 ) ) <= 0 ) { - Console::Error( "\n\n\n" - "**************\n" - "%s NOT FOUND\n" - "**************\n\n\n", params ext - ); + Console::Notice( "Bios Warning > %s not found.", params ext ); return; } } @@ -853,7 +849,7 @@ void mmap_ClearCpuBlock( uint offset ) for (u32 i=0;iClear(psMPWVA[offset][i],0x1000); + Cpu->Clear(psMPWVA[offset][i],0x400); } psMPWVA[offset].clear(); } \ No newline at end of file diff --git a/pcsx2/Misc.cpp b/pcsx2/Misc.cpp index 0ea9240e02..c45961fc16 100644 --- a/pcsx2/Misc.cpp +++ b/pcsx2/Misc.cpp @@ -141,9 +141,9 @@ u32 GetBiosVersion() { } //2002-09-22 (Florin) -int IsBIOS(char *filename, char *description) +int IsBIOS(const char *filename, char *description) { - char ROMVER[14+1], zone[12+1]; + char ROMVER[14+1]; FILE *fp; unsigned int fileOffset=0, found=FALSE; struct romdir rd; @@ -165,31 +165,38 @@ int IsBIOS(char *filename, char *description) return FALSE; //Unable to locate ROMDIR structure in file or a ioprpXXX.img } - while(strlen(rd.fileName) > 0){ - if (strcmp(rd.fileName, "ROMVER") == 0){ // found romver - unsigned int filepos=ftell(fp); + while(strlen(rd.fileName) > 0) + { + if (strcmp(rd.fileName, "ROMVER") == 0) // found romver + { + uint filepos = ftell(fp); fseek(fp, fileOffset, SEEK_SET); if (fread(&ROMVER, 14, 1, fp) == 0) break; fseek(fp, filepos, SEEK_SET);//go back - - switch(ROMVER[4]){ - case 'T':sprintf(zone, "T10K "); break; - case 'X':sprintf(zone, "Test ");break; - case 'J':sprintf(zone, "Japan "); break; - case 'A':sprintf(zone, "USA "); break; - case 'E':sprintf(zone, "Europe"); break; - case 'H':sprintf(zone, "HK "); break; - case 'P':sprintf(zone, "Free "); break; - case 'C':sprintf(zone, "China "); break; - default: sprintf(zone, "%c ",ROMVER[4]); break;//shoudn't show + + const char zonefail[2] = { ROMVER[4], '\0' }; // the default "zone" (unknown code) + const char* zone = zonefail; + + switch(ROMVER[4]) + { + case 'T': zone = "T10K "; break; + case 'X': zone = "Test "; break; + case 'J': zone = "Japan "; break; + case 'A': zone = "USA "; break; + case 'E': zone = "Europe"; break; + case 'H': zone = "HK "; break; + case 'P': zone = "Free "; break; + case 'C': zone = "China "; break; } - sprintf(description, "%s vXX.XX(XX/XX/XXXX) %s", zone, - ROMVER[5]=='C'?"Console":ROMVER[5]=='D'?"Devel":""); - strncpy(description+ 8, ROMVER+ 0, 2);//ver major - strncpy(description+11, ROMVER+ 2, 2);//ver minor - strncpy(description+14, ROMVER+12, 2);//day - strncpy(description+17, ROMVER+10, 2);//month - strncpy(description+20, ROMVER+ 6, 4);//year + + sprintf(description, "%s v%c%c.%c%c(%c%c/%c%c/%c%c%c%c) %s", zone, + ROMVER[0], ROMVER[1], // ver major + ROMVER[2], ROMVER[3], // ver minor + ROMVER[12], ROMVER[13], // day + ROMVER[10], ROMVER[11], // month + ROMVER[6], ROMVER[7], ROMVER[8], ROMVER[9], // year! + (ROMVER[5]=='C') ? "Console" : (ROMVER[5]=='D') ? "Devel" : "" + ); found = TRUE; } diff --git a/pcsx2/Misc.h b/pcsx2/Misc.h index c92754b15f..079e2a7bb7 100644 --- a/pcsx2/Misc.h +++ b/pcsx2/Misc.h @@ -73,8 +73,9 @@ extern u64 GetCPUTicks(); extern u64 GetTickFrequency(); // Used in Misc,and Windows/Linux files. -void ProcessFKeys(int fkey, int shift); // processes fkey related commands value 1-12 -int IsBIOS(char *filename, char *description); +extern void ProcessFKeys(int fkey, int shift); // processes fkey related commands value 1-12 +extern int IsBIOS(const char *filename, char *description); + extern const char *LabelAuthors; extern const char *LabelGreets; void CycleFrameLimit(int dir); diff --git a/pcsx2/NakedAsm.h b/pcsx2/NakedAsm.h index c744b2ece5..359f95183f 100644 --- a/pcsx2/NakedAsm.h +++ b/pcsx2/NakedAsm.h @@ -54,15 +54,11 @@ void svudispfn(); // aR3000A.S void iopJITCompile(); void iopJITCompileInBlock(); -void iopDispatcher(); -void iopDispatcherClear(); void iopDispatcherReg(); // aR5900-32.S void JITCompile(); void JITCompileInBlock(); -void Dispatcher(); -void DispatcherClear(); void DispatcherReg(); } diff --git a/pcsx2/NewGUI/frmLogging.cpp b/pcsx2/NewGUI/frmLogging.cpp index a10aa7e4d1..01d3394edd 100644 --- a/pcsx2/NewGUI/frmLogging.cpp +++ b/pcsx2/NewGUI/frmLogging.cpp @@ -74,7 +74,7 @@ wxDialog( parent, id, _T("Logging"), pos, size ) // Connect all the checkboxes to one function, and pass the checkbox id as user data. for (i = EE_CPU_LOG; i >= SYMS_LOG; i++) - Connect(i, wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(frmLogging::LogChecked), i); + Connect(i, wxEVT_COMMAND_CHECKBOX_CLICKED, i, wxCommandEventHandler(frmLogging::LogChecked)); } diff --git a/pcsx2/Plugins.cpp b/pcsx2/Plugins.cpp index 1238eed877..8576cf9215 100644 --- a/pcsx2/Plugins.cpp +++ b/pcsx2/Plugins.cpp @@ -71,6 +71,7 @@ _PADgsDriverInfo PAD1gsDriverInfo; _PADconfigure PAD1configure; _PADtest PAD1test; _PADabout PAD1about; +_PADfreeze PAD1freeze; // PAD2 _PADinit PAD2init; @@ -87,6 +88,7 @@ _PADgsDriverInfo PAD2gsDriverInfo; _PADconfigure PAD2configure; _PADtest PAD2test; _PADabout PAD2about; +_PADfreeze PAD2freeze; // SIO[2] _SIOinit SIOinit[2][9]; @@ -330,6 +332,7 @@ void *PAD1plugin; void CALLBACK PAD1_configure() {} void CALLBACK PAD1_about() {} s32 CALLBACK PAD1_test() { return 0; } +s32 CALLBACK PAD1_freeze(int mode, freezeData *data) { data->size = 0; return 0; } int LoadPAD1plugin(const string& filename) { void *drv; @@ -352,6 +355,7 @@ int LoadPAD1plugin(const string& filename) { MapSymbolPAD_Fallback(PAD1,PAD,configure); MapSymbolPAD_Fallback(PAD1,PAD,about); MapSymbolPAD_Fallback(PAD1,PAD,test); + MapSymbolPAD_Fallback(PAD1,PAD,freeze); return 0; } @@ -361,6 +365,7 @@ void *PAD2plugin; void CALLBACK PAD2_configure() {} void CALLBACK PAD2_about() {} s32 CALLBACK PAD2_test() { return 0; } +s32 CALLBACK PAD2_freeze(int mode, freezeData *data) { data->size = 0; return 0; } int LoadPAD2plugin(const string& filename) { void *drv; @@ -383,6 +388,7 @@ int LoadPAD2plugin(const string& filename) { MapSymbolPAD_Fallback(PAD2,PAD,configure); MapSymbolPAD_Fallback(PAD2,PAD,about); MapSymbolPAD_Fallback(PAD2,PAD,test); + MapSymbolPAD_Fallback(PAD2,PAD,freeze); return 0; } diff --git a/pcsx2/R3000A.h b/pcsx2/R3000A.h index 2c6f1cadcd..41cb4862a5 100644 --- a/pcsx2/R3000A.h +++ b/pcsx2/R3000A.h @@ -112,10 +112,10 @@ struct psxRegisters { u32 code; /* The instruction */ u32 cycle; u32 interrupt; - u32 sCycle[64]; // start cycle for signaled ints - s32 eCycle[64]; // cycle delta for signaled ints (sCycle + eCycle == branch cycle) - u32 _msflag[32]; - u32 _smflag[32]; + u32 sCycle[32]; // start cycle for signaled ints + s32 eCycle[32]; // cycle delta for signaled ints (sCycle + eCycle == branch cycle) + //u32 _msflag[32]; + //u32 _smflag[32]; }; PCSX2_ALIGNED16_EXTERN(psxRegisters psxRegs); diff --git a/pcsx2/R5900.cpp b/pcsx2/R5900.cpp index 78ad012144..b7e179f542 100644 --- a/pcsx2/R5900.cpp +++ b/pcsx2/R5900.cpp @@ -522,7 +522,7 @@ __forceinline bool _cpuBranchTest_Shared() cpuSetNextBranchDelta( ((g_psxNextBranchCycle-psxRegs.cycle)*8) - EEsCycle ); // Apply the hsync counter's nextCycle - cpuSetNextBranch( counters[4].sCycle, counters[4].CycleT ); + cpuSetNextBranch( hsyncCounter.sCycle, hsyncCounter.CycleT ); // Apply vsync and other counter nextCycles cpuSetNextBranch( nextsCounter, nextCounter ); diff --git a/pcsx2/RDebug/deci2.h b/pcsx2/RDebug/deci2.h index 05d545bdac..b35bfb9ba0 100644 --- a/pcsx2/RDebug/deci2.h +++ b/pcsx2/RDebug/deci2.h @@ -26,8 +26,6 @@ #include "deci2_netmp.h" #include "deci2_ttyp.h" -#include "Threading.h" - #define PROTO_DCMP 0x0001 #define PROTO_ITTYP 0x0110 #define PROTO_IDBGP 0x0130 diff --git a/pcsx2/RDebug/deci2_dbgp.cpp b/pcsx2/RDebug/deci2_dbgp.cpp index 09ec2f44df..6ff889c556 100644 --- a/pcsx2/RDebug/deci2_dbgp.cpp +++ b/pcsx2/RDebug/deci2_dbgp.cpp @@ -22,7 +22,6 @@ #include "VUmicro.h" #include "deci2.h" -#include "Threading.h" using namespace Threading; using namespace R5900; diff --git a/pcsx2/SPR.cpp b/pcsx2/SPR.cpp index d346f33c0e..c9b59e1a25 100644 --- a/pcsx2/SPR.cpp +++ b/pcsx2/SPR.cpp @@ -454,11 +454,9 @@ void SPRTOinterrupt() void SaveState::sprFreeze() { - // Gotta save the weird ref-style DMA timing vars! - if( GetVersion() >= 0x05 ) - { - Freeze(spr0finished); - Freeze(spr1finished); - Freeze(mfifotransferred); - } + FreezeTag( "SPRdma" ); + + Freeze(spr0finished); + Freeze(spr1finished); + Freeze(mfifotransferred); } \ No newline at end of file diff --git a/pcsx2/SaveState.cpp b/pcsx2/SaveState.cpp index ccca61f110..9de5fe2f6e 100644 --- a/pcsx2/SaveState.cpp +++ b/pcsx2/SaveState.cpp @@ -33,7 +33,6 @@ using namespace R5900; -extern int g_psxWriteOk; extern void recResetEE(); extern void recResetIOP(); @@ -54,7 +53,9 @@ string SaveState::GetFilename( int slot ) return Path::Combine( SSTATES_DIR, fmt_string( "%8.8X.%3.3d", ElfCRC, slot ) ); } -SaveState::SaveState( const char* msg, const string& destination ) : m_version( g_SaveVersion ) +SaveState::SaveState( const char* msg, const string& destination ) : + m_version( g_SaveVersion ) +, m_tagspace( 128 ) { Console::WriteLn( "%s %hs", params msg, &destination ); } @@ -78,42 +79,76 @@ s32 CALLBACK gsSafeFreeze( int mode, freezeData *data ) } } +void SaveState::FreezeTag( const char* src ) +{ + const int length = strlen( src ); + m_tagspace.MakeRoomFor( length+1 ); + + strcpy( m_tagspace.GetPtr(), src ); + FreezeMem( m_tagspace.GetPtr(), length ); + + if( strcmp( m_tagspace.GetPtr(), src ) != 0 ) + { + assert( 0 ); + throw Exception::BadSavedState( string( "Tag: " )+src ); + } +} + void SaveState::FreezeAll() { if( IsLoading() ) PreLoadPrep(); + + // Check the BIOS, and issue a warning if the bios for this state + // doesn't match the bios currently being used (chances are it'll still + // work fine, but some games are very picky). - FreezeMem(PS2MEM_BASE, Ps2MemSize::Base); // 32 MB main memory - FreezeMem(PS2MEM_ROM, Ps2MemSize::Rom); // 4 mb rom memory - FreezeMem(PS2MEM_ROM1, Ps2MemSize::Rom1); // 256kb rom1 memory + char descout[128], descin[128]; + memzero_obj( descout ); + IsBIOS( Config.Bios, descout ); + memcpy_fast( descin, descout, 128 ); + Freeze( descin ); + + if( memcmp( descin, descout, 128 ) != 0 ) + { + Console::Error( + "\n\tWarning: BIOS Version Mismatch, savestate may be unstable!\n" + "\t\tCurrent BIOS: %s\n" + "\t\tSavestate BIOS: %s\n", + params descout, descin + ); + } + + // First Block - Memory Dumps + // --------------------------- + FreezeMem(PS2MEM_BASE, Ps2MemSize::Base); // 32 MB main memory FreezeMem(PS2MEM_SCRATCH, Ps2MemSize::Scratch); // scratch pad - FreezeMem(PS2MEM_HW, Ps2MemSize::Hardware); // hardware memory + FreezeMem(PS2MEM_HW, Ps2MemSize::Hardware); // hardware memory + FreezeMem(psxM, Ps2MemSize::IopRam); // 2 MB main memory + FreezeMem(psxH, Ps2MemSize::IopHardware); // hardware memory + FreezeMem(psxS, 0x000100); // iop's sif memory + + // Second Block - Various CPU Registers and States + // ----------------------------------------------- + FreezeTag( "cpuRegs" ); Freeze(cpuRegs); // cpu regs + COP0 Freeze(psxRegs); // iop regs - if (GetVersion() >= 0x6) - Freeze(fpuRegs); - else - { - // Old versiosn didn't save the ACCflags... - FreezeLegacy(fpuRegs, sizeof(u32)); // fpu regs - fpuRegs.ACCflag = 0; - } + Freeze(fpuRegs); Freeze(tlb); // tlbs + // Third Block - Cycle Timers and Events + // ------------------------------------- + FreezeTag( "Cycles" ); Freeze(EEsCycle); Freeze(EEoCycle); - Freeze(psxRegs.cycle); // used to be IOPoCycle. This retains compatibility. Freeze(g_nextBranchCycle); Freeze(g_psxNextBranchCycle); - Freeze(s_iLastCOP0Cycle); Freeze(s_iLastPERFCycle); - Freeze(g_psxWriteOk); - - //hope didn't forgot any cpu.... - + // Fourth Block - EE-related systems + // --------------------------------- rcntFreeze(); gsFreeze(); vuMicroFreeze(); @@ -124,38 +159,27 @@ void SaveState::FreezeAll() gifFreeze(); sprFreeze(); - // iop now - FreezeMem(psxM, Ps2MemSize::IopRam); // 2 MB main memory - FreezeMem(psxH, Ps2MemSize::IopHardware); // hardware memory - //FreezeMem(psxS, 0x00010000); // sif memory - + // Fifth Block - iop-related systems + // --------------------------------- + psxRcntFreeze(); sioFreeze(); + sio2Freeze(); cdrFreeze(); cdvdFreeze(); - psxRcntFreeze(); - sio2Freeze(); + // Sixth Block - Plugins Galore! + // ----------------------------- FreezePlugin( "GS", gsSafeFreeze ); FreezePlugin( "SPU2", SPU2freeze ); FreezePlugin( "DEV9", DEV9freeze ); FreezePlugin( "USB", USBfreeze ); + FreezePlugin( "PAD1", PAD1freeze ); + FreezePlugin( "PAD2", PAD2freeze ); if( IsLoading() ) PostLoadPrep(); } -// this function is yet incomplete. Version numbers hare still < 0x12 so it won't be run. -// (which is good because it won't work :P) -void SaveState::_testCdvdCrc() -{ - /*if( GetVersion() < 0x0012 ) return; - - u32 thiscrc = ElfCRC; - Freeze( thiscrc ); - if( thiscrc != ElfCRC ) - throw Exception::StateCrcMismatch( thiscrc, ElfCRC );*/ -} - ///////////////////////////////////////////////////////////////////////////// // gzipped to/from disk state saves implementation @@ -212,8 +236,6 @@ gzLoadingState::gzLoadingState( const string& filename ) : "\tThe savestate was created with a newer version of Pcsx2. I don't know how to load it!" ); throw Exception::UnsupportedStateVersion( m_version ); } - - _testCdvdCrc(); } gzLoadingState::~gzLoadingState() { } @@ -226,34 +248,30 @@ void gzSavingState::FreezeMem( void* data, int size ) void gzLoadingState::FreezeMem( void* data, int size ) { - gzread( m_file, data, size ); - if( gzeof( m_file ) ) + if( gzread( m_file, data, size ) != size ) throw Exception::BadSavedState( m_filename ); } void gzSavingState::FreezePlugin( const char* name, s32 (CALLBACK *freezer)(int mode, freezeData *data) ) { - Console::WriteLn( "\tSaving %s", params name ); freezeData fP = { 0, NULL }; + Console::WriteLn( "\tSaving %s", params name ); + + FreezeTag( name ); if (freezer(FREEZE_SIZE, &fP) == -1) throw Exception::FreezePluginFailure( name, "saving" ); - gzwrite(m_file, &fP.size, sizeof(fP.size)); + Freeze( fP.size ); if( fP.size == 0 ) return; - fP.data = (s8*)malloc(fP.size); - if (fP.data == NULL) - throw Exception::OutOfMemory(); + SafeArray buffer( fP.size ); + fP.data = buffer.GetPtr(); if(freezer(FREEZE_SAVE, &fP) == -1) throw Exception::FreezePluginFailure( name, "saving" ); - if (fP.size) - { - gzwrite(m_file, fP.data, fP.size); - free(fP.data); - } + FreezeMem( fP.data, fP.size ); } void gzLoadingState::FreezePlugin( const char* name, s32 (CALLBACK *freezer)(int mode, freezeData *data) ) @@ -261,21 +279,17 @@ void gzLoadingState::FreezePlugin( const char* name, s32 (CALLBACK *freezer)(int freezeData fP = { 0, NULL }; Console::WriteLn( "\tLoading %s", params name ); - gzread(m_file, &fP.size, sizeof(fP.size)); + FreezeTag( name ); + Freeze( fP.size ); if( fP.size == 0 ) return; - fP.data = (s8*)malloc(fP.size); - if (fP.data == NULL) - throw Exception::OutOfMemory(); - gzread(m_file, fP.data, fP.size); + SafeArray buffer( fP.size ); + fP.data = buffer.GetPtr(); - if( gzeof( m_file ) ) - throw Exception::BadSavedState( m_filename ); + FreezeMem( fP.data, fP.size ); if(freezer(FREEZE_LOAD, &fP) == -1) throw Exception::FreezePluginFailure( name, "loading" ); - - if (fP.size) free(fP.data); } ////////////////////////////////////////////////////////////////////////////////// diff --git a/pcsx2/SaveState.h b/pcsx2/SaveState.h index d7fe5fb242..380f7185e3 100644 --- a/pcsx2/SaveState.h +++ b/pcsx2/SaveState.h @@ -24,10 +24,14 @@ #include "PS2Edefs.h" #endif #include "System.h" + // Savestate Versioning! // If you make changes to the savestate version, please increment the value below. +// If the change is minor and compatibility with old states is retained, increment +// the lower 16 bit value. IF the change is breaking of all compatibility with old +// states, increment the upper 16 bit value, and clear the lower 16 bits to 0. -static const u32 g_SaveVersion = 0x8b400006; +static const u32 g_SaveVersion = 0x8b410000; // this function is meant to be used in the place of GSfreeze, and provides a safe layer // between the GS saving function and the MTGS's needs. :) @@ -41,6 +45,7 @@ class SaveState { protected: u32 m_version; // version of the savestate being loaded. + SafeArray m_tagspace; public: SaveState( const char* msg, const string& destination ); @@ -76,6 +81,12 @@ public: FreezeMem( &data, sizeof( T ) - sizeOfNewStuff ); } + // Freezes an identifier value into the savestate for troubleshooting purposes. + // Identifiers can be used to determine where in a savestate that data has become + // skewed (if the value does not match then the error occurs somewhere prior to that + // position). + void FreezeTag( const char* src ); + // Loads or saves a plugin. Plugin name is for console logging purposes. virtual void FreezePlugin( const char* name, s32 (CALLBACK* freezer)(int mode, freezeData *data) )=0; @@ -95,11 +106,6 @@ public: protected: - // Used internally by constructors to check the cdvd's crc against the CRC of the savestate. - // This allows for proper exception handling of changed CDs on-the-fly. - void _testCdvdCrc(); - - // Load/Save functions for the various components of our glorious emulator! void rcntFreeze(); diff --git a/pcsx2/Sif.cpp b/pcsx2/Sif.cpp index 06b11b45b3..0456780b60 100644 --- a/pcsx2/Sif.cpp +++ b/pcsx2/Sif.cpp @@ -586,22 +586,13 @@ __forceinline void dmaSIF2() { } -void SaveState::sifFreeze() { +void SaveState::sifFreeze() +{ + FreezeTag( "SIFdma" ); + Freeze(sif0); Freeze(sif1); - if( GetVersion() >= 0x0002 ) - { - Freeze(eesifbusy); - Freeze(iopsifbusy); - } - else if( IsLoading() ) - { - // Old savestate, inferior data so... - // Take an educated guess on what they should be. Or well, set to 1 because - // it more or less forces them to "kick" - - iopsifbusy[0] = eesifbusy[0] = 1; - iopsifbusy[1] = eesifbusy[1] = 1; - } + Freeze(eesifbusy); + Freeze(iopsifbusy); } diff --git a/pcsx2/Sio.cpp b/pcsx2/Sio.cpp index 894ad7e180..8e17a70ccc 100644 --- a/pcsx2/Sio.cpp +++ b/pcsx2/Sio.cpp @@ -566,22 +566,15 @@ void SaveState::sioFreeze() // CRCs for memory cards. u64 m_mcdCRCs[2]; + FreezeTag( "sio" ); Freeze( sio ); - // versions prior to 3 didn't have CRCs. - if( GetVersion() >= 0x03 ) + if( IsSaving() ) { - if( IsSaving() ) - { - for( int i=0; i<2; ++i ) - m_mcdCRCs[i] = MemoryCard::GetCRC( i ); - } - Freeze( m_mcdCRCs ); - } - else - { - m_mcdCRCs[0] = m_mcdCRCs[1] = 0; + for( int i=0; i<2; ++i ) + m_mcdCRCs[i] = MemoryCard::GetCRC( i ); } + Freeze( m_mcdCRCs ); if( IsLoading() && Config.McdEnableEject ) { diff --git a/pcsx2/System.cpp b/pcsx2/System.cpp index b124da39ce..8bb3ea92d0 100644 --- a/pcsx2/System.cpp +++ b/pcsx2/System.cpp @@ -19,7 +19,6 @@ #include "PrecompiledHeader.h" #include "Common.h" -#include "Threading.h" #include "HostGui.h" #include "VUmicro.h" @@ -92,6 +91,7 @@ static void trim( string& line ) } +////////////////////////////////////////////////////////////////////////////////////////// // This function should be called once during program execution. void SysDetect() { @@ -160,6 +160,7 @@ void SysDetect() Console::ClearColor(); } +////////////////////////////////////////////////////////////////////////////////////////// // Allocates memory for all PS2 systems. bool SysAllocateMem() { @@ -187,10 +188,12 @@ bool SysAllocateMem() return true; } - +////////////////////////////////////////////////////////////////////////////////////////// // Allocates memory for all recompilers, and force-disables any recs that fail to initialize. -// This should be done asap, since the recompilers tend to demand a lot of system resources, and prefer -// to have those resources at specific address ranges. The sooner memory is allocated, the better. +// This should be done asap, since the recompilers tend to demand a lot of system resources, +// and prefer to have those resources at specific address ranges. The sooner memory is +// allocated, the better. +// // Returns FALSE on *critical* failure (GUI should issue a msg and exit). void SysAllocateDynarecs() { @@ -259,6 +262,7 @@ void SysAllocateDynarecs() } +////////////////////////////////////////////////////////////////////////////////////////// // This should be called last thing before Pcsx2 exits. void SysShutdownMem() { @@ -269,6 +273,7 @@ void SysShutdownMem() memShutdown(); } +////////////////////////////////////////////////////////////////////////////////////////// // This should generally be called right before calling SysShutdownMem(), although you can optionally // use it in conjunction with SysAllocDynarecs to allocate/free the dynarec resources on the fly (as // risky as it might be, since dynarecs could very well fail on the second attempt). @@ -285,6 +290,7 @@ void SysShutdownDynarecs() bool g_ReturnToGui = false; // set to exit the execution of the emulator and return control to the GUI bool g_EmulationInProgress = false; // Set TRUE if a game is actively running (set to false on reset) +////////////////////////////////////////////////////////////////////////////////////////// // Resets all PS2 cpu execution caches, which does not affect that actual PS2 state/condition. // This can be called at any time outside the context of a Cpu->Execute() block without // bad things happening (recompilers will slow down for a brief moment since rec code blocks diff --git a/pcsx2/System.h b/pcsx2/System.h index 5d64ad0040..1c51e8352b 100644 --- a/pcsx2/System.h +++ b/pcsx2/System.h @@ -26,6 +26,7 @@ #include "MemcpyFast.h" #include "SafeArray.h" #include "Misc.h" +#include "Threading.h" // to use threading stuff, include the Threading namespace in your file. enum PageProtectionMode diff --git a/pcsx2/ThreadTools.cpp b/pcsx2/ThreadTools.cpp index 47e1665faf..665ad569bc 100644 --- a/pcsx2/ThreadTools.cpp +++ b/pcsx2/ThreadTools.cpp @@ -44,6 +44,7 @@ namespace Threading void Thread::Close() { + if( m_terminated ) return; pthread_cancel( m_thread ); pthread_join( m_thread, NULL ); } diff --git a/pcsx2/Threading.h b/pcsx2/Threading.h index d0ed296574..a448e9a943 100644 --- a/pcsx2/Threading.h +++ b/pcsx2/Threading.h @@ -67,8 +67,7 @@ namespace Threading void Unlock(); }; - // Returns the number of available logical CPUs (cores plus - // hyperthreaded cpus) + // Returns the number of available logical CPUs (cores plus hyperthreaded cpus) extern void CountLogicalCores( int LogicalCoresPerPhysicalCPU, int PhysicalCoresPerPhysicalCPU ); // Releases a timeslice to other threads. @@ -80,6 +79,24 @@ namespace Threading // sleeps the current thread for the given number of milliseconds. extern void Sleep( int ms ); + ////////////////////////////////////////////////////////////////////////////////////////// + // Thread - Helper class for the basics of starting/managing simple threads. + // + // Use this as a base class for your threaded procedure, and implement the 'int Callback()' + // method. Use Start() and Close() to start and shutdown the thread, and use m_post_event + // internally to post/receive events for the thread (make a public accessor for it in your + // derived class if your thread utilizes the post). + // + // Notes: + // * To ensure thread safety against C++'s bizarre and not-thread-friendly object + // constructors and destructors, you *must* use Start() and Close(). There is a built- + // in Close() called on destruction, which should work for very simple threads (that + // do not have any special shutdown code of their own), but + // + // * Constructing threads as static vars isn't recommended since it can potentially con- + // fuse w32pthreads, if the static initializers are executed out-of-order (C++ offers + // no dependency options for ensuring correct static var initializations). + // class Thread : NoncopyableObject { protected: @@ -106,12 +123,135 @@ namespace Threading // on linux). static void* _internal_callback( void* func ); - // Implemented by derrived class to handle threading actions! + // Implemented by derived class to handle threading actions! virtual int Callback()=0; }; - // Our fundamental interlocking functions. All other useful interlocks can - // be derrived from these little beasties! + ////////////////////////////////////////////////////////////////////////////////////////// + // ScopedLock: Helper class for using Mutexes. + // Using this class provides an exception-safe (and generally clean) method of locking + // code inside a function or conditional block. + // + class ScopedLock : NoncopyableObject + { + protected: + MutexLock& m_lock; + + public: + virtual ~ScopedLock() + { + m_lock.Unlock(); + } + + ScopedLock( MutexLock& locker ) : + m_lock( locker ) + { + m_lock.Lock(); + } + }; + + ////////////////////////////////////////////////////////////////////////////////////////// + // BaseTaskThread - an abstract base class which provides simple parallel execution of + // single tasks. + // + // Implementation: + // To use this class your derived class will need to implement its own Task() function + // and also a "StartTask( parameters )" function which suits the need of your task, along + // with any local variables your task needs to do its job. You may additionally want to + // implement a "GetResult()" function, which would be a combination of WaitForResult() + // and a return value of the computational result. + // + // Thread Safety: + // If operating on local variables, you must execute WaitForResult() before leaving the + // variable scope -- or alternatively have your StartTask() implementation make full + // copies of dependent data. Also, by default PostTask() always assumes the previous + // task has completed. If your system can post a new task before the previous one has + // completed, then it needs to explicitly call WaitForResult() or provide a mechanism + // to cancel the previous task (which is probably more work than it's worth). + // + // Performance notes: + // * Remember that thread creation is generally slow, so you should make your object + // instance once early and then feed it tasks repeatedly over the course of program + // execution. + // + // * For threading to be a successful speedup, the task being performed should be as lock + // free as possible. For example using STL containers in parallel usually fails to + // yield any speedup due to the gratuitous amount of locking that the STL performs + // internally. + // + // * The best application of tasking threads is to divide a large loop over a linear array + // into smaller sections. For example, if you have 20,000 items to process, the task + // can be divided into two threads of 10,000 items each. + // + class BaseTaskThread : public Thread + { + protected: + volatile bool m_done; + volatile bool m_TaskComplete; + + public: + virtual ~BaseTaskThread() {} + BaseTaskThread() : + m_done( false ) + , m_TaskComplete( false ) + { + } + + // Tells the thread to exit and then waits for thread termination. + // To force-terminate the thread without "nicely" waiting for the task to complete, + // explicitly use the Thread::Close parent implementation instead. + void Close() + { + if( m_terminated ) return; + m_done = true; + m_post_event.Post(); + pthread_join( m_thread, NULL ); + } + + // Initiates the new task. This should be called after your own StartTask has + // initialized internal variables / preparations for task execution. + void PostTask() + { + jASSUME( !m_terminated ); + m_TaskComplete = false; + m_post_event.Post(); + } + + // Blocks current thread execution pending the completion of the parallel task. + void WaitForResult() const + { + if( m_terminated ) return; + while( !m_TaskComplete ) + { + Timeslice(); + SpinWait(); + } + } + + protected: + // Abstract method run when a task has been posted. Implementing classes should do + // all your necessary processing work here. + virtual void Task()=0; + + int Callback() + { + do + { + // Wait for a job! + m_post_event.Wait(); + + if( m_done ) break; + Task(); + m_TaskComplete = true; + } while( !m_done ); + + return 0; + } + }; + + ////////////////////////////////////////////////////////////////////////////////////////// + // Our fundamental interlocking functions. All other useful interlocks can be derived + // from these little beasties! extern long pcsx2_InterlockedExchange(volatile long* Target, long srcval); extern long pcsx2_InterlockedCompareExchange( volatile long* target, long srcval, long comp ); diff --git a/pcsx2/VUmicroMem.cpp b/pcsx2/VUmicroMem.cpp index 1c31f324aa..bdcef00d31 100644 --- a/pcsx2/VUmicroMem.cpp +++ b/pcsx2/VUmicroMem.cpp @@ -160,6 +160,8 @@ void vuMicroMemReset() void SaveState::vuMicroFreeze() { + FreezeTag( "vuMicro" ); + jASSUME( VU0.Mem != NULL ); jASSUME( VU1.Mem != NULL ); @@ -169,15 +171,7 @@ void SaveState::vuMicroFreeze() FreezeMem(VU0.Micro, 4*1024); Freeze(VU0.VF); - if( GetVersion() >= 0x02 ) - Freeze(VU0.VI); - else - { - // Old versions stored the VIregs as 32 bit values... - memzero_obj( VU0.VI ); - for(int i=0; i<32; i++ ) - Freeze( VU0.VI[i].UL ); - } + Freeze(VU0.VI); Freeze(VU1.ACC); Freeze(VU1.code); @@ -185,14 +179,5 @@ void SaveState::vuMicroFreeze() FreezeMem(VU1.Micro, 16*1024); Freeze(VU1.VF); - if( GetVersion() >= 0x02 ) - Freeze(VU1.VI); - else - { - // Old versions stored the VIregs as 32 bit values... - memzero_obj( VU1.VI ); - for(int i=0; i<32; i++ ) - Freeze( VU1.VI[i].UL ); - } - + Freeze(VU1.VI); } diff --git a/pcsx2/Vif.cpp b/pcsx2/Vif.cpp index 373fb37651..329f98f2d7 100644 --- a/pcsx2/Vif.cpp +++ b/pcsx2/Vif.cpp @@ -452,7 +452,10 @@ static __forceinline int mfifoVIF1chain() { int ret; /* Is QWC = 0? if so there is nothing to transfer */ - if (vif1ch->qwc == 0 && vif1.vifstalled == 0) return 0; + if (vif1ch->qwc == 0 && vif1.vifstalled == 0) { + vif1.inprogress = 0; + return 0; + } if (vif1ch->madr >= psHu32(DMAC_RBOR) && @@ -485,16 +488,30 @@ void mfifoVIF1transfer(int qwc) { g_vifCycles = 0; - mfifodmairq = 0; //Clear any previous TIE interrupt + if(qwc > 0){ vifqwc += qwc; - + if(vif1.inprogress & 0x10) + { + if (vif1ch->madr >= psHu32(DMAC_RBOR) && vif1ch->madr <= (psHu32(DMAC_RBOR)+psHu32(DMAC_RBSR))) + { + CPU_INT(10, min( (int)vifqwc, (int)vif1ch->qwc ) * BIAS); + } + else + { + CPU_INT(10, vif1ch->qwc * BIAS); + } + } + vif1.inprogress &= ~0x10; SPR_LOG("Added %x qw to mfifo, total now %x - Vif CHCR %x Stalled %x done %x\n", qwc, vifqwc, vif1ch->chcr, vif1.vifstalled, vif1.done); - - if((vif1ch->chcr & 0x100) == 0 || vif1.vifstalled == 1 || vif1.done == 1) return; + + /*if((vif1ch->chcr & 0x100) == 0 || vif1.vifstalled == 1 || vif1.done == 1 || vif1.inprogress == 1)*/ return; } + mfifodmairq = 0; //Clear any previous TIE interrupt + + if(vif1ch->qwc == 0){ ptag = (u32*)dmaGetAddr(vif1ch->tadr); @@ -505,7 +522,7 @@ void mfifoVIF1transfer(int qwc) { VIF_LOG("MFIFO Stallon tag\n"); vif1.stallontag = 1; - CPU_INT(10,cycles+g_vifCycles); + //CPU_INT(10,cycles+g_vifCycles); return; //IRQ set by VIFTransfer } } @@ -524,7 +541,7 @@ void mfifoVIF1transfer(int qwc) { switch (id) { case 0: // Refe - Transfer Packet According to ADDR field vif1ch->tadr = psHu32(DMAC_RBOR) + ((vif1ch->tadr + 16) & psHu32(DMAC_RBSR)); - vif1.done = 2; //End Transfer + vif1.done = 1; //End Transfer break; case 1: // CNT - Transfer QWC following the tag. @@ -550,31 +567,33 @@ void mfifoVIF1transfer(int qwc) { case 7: // End - Transfer QWC following the tag vif1ch->madr = psHu32(DMAC_RBOR) + ((vif1ch->tadr + 16) & psHu32(DMAC_RBSR)); //Set MADR to data following the tag vif1ch->tadr = psHu32(DMAC_RBOR) + ((vif1ch->madr + (vif1ch->qwc << 4)) & psHu32(DMAC_RBSR)); //Set TADR to QW following the data - vif1.done = 2; //End Transfer + vif1.done = 1; //End Transfer break; } - if ((vif1ch->chcr & 0x80) && (ptag[0] >> 31)) { - VIF_LOG("dmaIrq Set\n"); - vif1.done = 2; - mfifodmairq = 1; //Let the handler know we have prematurely ended MFIFO - } + if ((vif1ch->chcr & 0x80) && (ptag[0] >> 31)) + { + VIF_LOG("dmaIrq Set\n"); + vif1.done = 1; + mfifodmairq = 1; //Let the handler know we have prematurely ended MFIFO + } } - ret = mfifoVIF1chain(); - if (ret == -1) { + vif1.inprogress |= 1; + + /*if (ret == -1) { SysPrintf("VIF dmaChain error size=%d, madr=%lx, tadr=%lx\n", vif1ch->qwc, vif1ch->madr, vif1ch->tadr); vif1.done = 1; - CPU_INT(10,g_vifCycles); + //CPU_INT(10,g_vifCycles); } if(ret == -2){ VIF_LOG("MFIFO Stall\n"); - CPU_INT(10,g_vifCycles); + //CPU_INT(10,g_vifCycles); return; - } + }*/ - if(vif1.done == 2 && vif1ch->qwc == 0) vif1.done = 1; - CPU_INT(10,g_vifCycles); + //if(vif1.done == 2 && vif1ch->qwc == 0) vif1.done = 1; +//CPU_INT(10,g_vifCycles); SPR_LOG("mfifoVIF1transfer end %x madr %x, tadr %x vifqwc %x\n", vif1ch->chcr, vif1ch->madr, vif1ch->tadr, vifqwc); } @@ -582,6 +601,10 @@ void vifMFIFOInterrupt() { g_vifCycles = 0; + + + if(vif1.inprogress == 1) mfifoVIF1chain(); + if(vif1.irq && vif1.tag.size == 0) { vif1Regs->stat|= VIF1_STAT_INT; hwIntcIrq(INTC_VIF1); @@ -594,15 +617,35 @@ void vifMFIFOInterrupt() } } - if(vif1.done != 1) { + + + if(vif1.done != 1 || vif1.inprogress & 1) { + if(vifqwc <= 0){ //SysPrintf("Empty\n"); + vif1.inprogress |= 0x10; hwDmacIrq(14); return; } - mfifoVIF1transfer(0); + if(!(vif1.inprogress & 0x1)) mfifoVIF1transfer(0); + + if (vif1ch->madr >= psHu32(DMAC_RBOR) && vif1ch->madr <= (psHu32(DMAC_RBOR)+psHu32(DMAC_RBSR))) + { + CPU_INT(10, min( (int)vifqwc, (int)vif1ch->qwc ) * BIAS); + } + else + { + CPU_INT(10, vif1ch->qwc * BIAS); + } + + return; - } + } else if(vifqwc <= 0){ + //SysPrintf("Empty\n"); + //vif1.inprogress |= 0x10; + hwDmacIrq(14); + //return; + } //On a TIE break we do not clear the MFIFO (Art of Fighting) //If we dont clear it on MFIFO end, Tekken Tag breaks, understandably (Refraction) diff --git a/pcsx2/VifDma.cpp b/pcsx2/VifDma.cpp index 4bf5ff8b2a..8f3422e866 100644 --- a/pcsx2/VifDma.cpp +++ b/pcsx2/VifDma.cpp @@ -505,15 +505,15 @@ static void VIFunpack(u32 *data, vifCode *v, int size, const unsigned int VIFdma #else if( VIFdmanum ) { __asm__(".intel_syntax noprefix\n" - "movaps xmm6, xmmword ptr [%0]\n" - "movaps xmm7, xmmword ptr [%1]\n" - ".att_syntax\n" : :"r"(g_vifRow1), "r"(g_vifCol1) ); + "movaps xmm6, xmmword ptr [%[g_vifRow1]]\n" + "movaps xmm7, xmmword ptr [%[g_vifCol1]]\n" + ".att_syntax\n" : :[g_vifRow1]"r"(g_vifRow1), [g_vifCol1]"r"(g_vifCol1) ); } else { __asm__(".intel_syntax noprefix\n" - "movaps xmm6, xmmword ptr [%0]\n" - "movaps xmm7, xmmword ptr [%1]\n" - ".att_syntax\n" : : "r"(g_vifRow0), "r"(g_vifCol0) ); + "movaps xmm6, xmmword ptr [%[g_vifRow0]]\n" + "movaps xmm7, xmmword ptr [%[g_vifCol0]]\n" + ".att_syntax\n" : : [g_vifRow0]"r"(g_vifRow0), [g_vifCol0]"r"(g_vifCol0) ); } #endif @@ -1344,23 +1344,17 @@ void vif0Reset() { void SaveState::vif0Freeze() { + FreezeTag( "VIFdma" ); + // Dunno if this one is needed, but whatever, it's small. :) - if( GetVersion() >= 0x04 ) - Freeze( g_vifCycles ); + Freeze( g_vifCycles ); Freeze( vif0 ); - if( GetVersion() >= 0x04 ) - { - Freeze( g_vif0HasMask3 ); - Freeze( g_vif0Masks ); - Freeze( g_vifRow0 ); - Freeze( g_vifCol0 ); - } - else if( IsLoading() ) - { - // Hack to "help" old savestates recover... - SetNewMask(g_vif0Masks, g_vif0HasMask3, vif0Regs->mask, ~vif0Regs->mask); - } + + Freeze( g_vif0HasMask3 ); + Freeze( g_vif0Masks ); + Freeze( g_vifRow0 ); + Freeze( g_vifCol0 ); } ////////////////////////////////////////////////////////////////////////////// @@ -1856,23 +1850,23 @@ int VIF1transfer(u32 *data, int size, int istag) { transferred += size - vif1.vifpacketsize; g_vifCycles+= (transferred>>2)*BIAS; /* guessing */ + vif1.irqoffset = transferred%4; // cannot lose the offset + if (vif1.irq && vif1.cmd == 0) { vif1.vifstalled = 1; - - if(((vif1Regs->code >> 24) & 0x7f) != 0x7)vif1Regs->stat|= VIF1_STAT_VIS; // Note: commenting this out fixes WALL-E // spiderman doesn't break on qw boundaries - vif1.irqoffset = transferred%4; // cannot lose the offset - + if( istag ) { return -2; } - + transferred = transferred >> 2; vif1ch->madr+= (transferred << 4); vif1ch->qwc-= transferred; + if(vif1ch->qwc == 0 && vif1.irqoffset == 0) vif1.inprogress = 0; //SysPrintf("Stall on vif1, FromSPR = %x, Vif1MADR = %x Sif0MADR = %x STADR = %x\n", psHu32(0x1000d010), vif1ch->madr, psHu32(0x1000c010), psHu32(DMAC_STADR)); return -2; } @@ -1885,198 +1879,13 @@ int VIF1transfer(u32 *data, int size, int istag) { transferred = transferred >> 2; vif1ch->madr+= (transferred << 4); vif1ch->qwc-= transferred; + if(vif1ch->qwc == 0 && vif1.irqoffset == 0) vif1.inprogress = 0; } return 0; } -int _VIF1chain() { - u32 *pMem; - //u32 qwc = vif1ch->qwc; - u32 ret; - - if (vif1ch->qwc == 0 && vif1.vifstalled == 0) return 0; - - pMem = (u32*)dmaGetAddr(vif1ch->madr); - if (pMem == NULL) - return -1; - - VIF_LOG("VIF1chain size=%d, madr=%lx, tadr=%lx\n", - vif1ch->qwc, vif1ch->madr, vif1ch->tadr); - - if( vif1.vifstalled ) { - ret = VIF1transfer(pMem+vif1.irqoffset, vif1ch->qwc*4-vif1.irqoffset, 0); - } - else { - ret = VIF1transfer(pMem, vif1ch->qwc*4, 0); - } - /*vif1ch->madr+= (vif1ch->qwc << 4); - vif1ch->qwc-= qwc;*/ - - return ret; -} - -static int prevvifcycles = 0; -static u32* prevviftag = NULL; -u32 *vif1ptag; -int _chainVIF1() { - int id; - int ret; - - vif1ptag = (u32*)dmaGetAddr(vif1ch->tadr); //Set memory pointer to TADR - if (vif1ptag == NULL) { //Is vif0ptag empty? - SysPrintf("Vif1 Tag BUSERR\n"); - vif1ch->chcr = ( vif1ch->chcr & 0xFFFF ) | ( (*vif1ptag) & 0xFFFF0000 ); //Transfer upper part of tag to CHCR bits 31-15 - psHu32(DMAC_STAT)|= 1<<15; //If yes, set BEIS (BUSERR) in DMAC_STAT register - return -1; //Return -1 as an error has occurred - } - - id = (vif1ptag[0] >> 28) & 0x7; //ID for DmaChain copied from bit 28 of the tag - vif1ch->qwc = (u16)vif1ptag[0]; //QWC set to lower 16bits of the tag - vif1ch->madr = vif1ptag[1]; //MADR = ADDR field - g_vifCycles+=1; // Add 1 g_vifCycles from the QW read for the tag - - vif1ch->chcr = ( vif1ch->chcr & 0xFFFF ) | ( (*vif1ptag) & 0xFFFF0000 ); //Transfer upper part of tag to CHCR bits 31-15 - // Transfer dma tag if tte is set - - VIF_LOG("VIF1 Tag %8.8x_%8.8x size=%d, id=%d, madr=%lx, tadr=%lx\n", - vif1ptag[1], vif1ptag[0], vif1ch->qwc, id, vif1ch->madr, vif1ch->tadr); - - //} else - - - if (!vif1.done && (psHu32(DMAC_CTRL) & 0xC0) == 0x40 && id == 4) { // STD == VIF1 - //vif1.done |= hwDmacSrcChainWithStack(vif1ch, id); - // there are still bugs, need to also check if gif->madr +16*qwc >= stadr, if not, stall - if( (vif1ch->madr + vif1ch->qwc * 16) >= psHu32(DMAC_STADR) ) { - // stalled - - hwDmacIrq(13); - return 0; - } - } - - if (vif1ch->chcr & 0x40) { - if(vif1.vifstalled == 1) ret = VIF1transfer(vif1ptag+(2+vif1.irqoffset), 2-vif1.irqoffset, 1); //Transfer Tag on stall - else ret = VIF1transfer(vif1ptag+2, 2, 1); //Transfer Tag - if (ret == -1) return -1; //There has been an error - if (ret == -2) { - return -2; //IRQ set by VIFTransfer - } - } - - vif1.done |= hwDmacSrcChainWithStack(vif1ch, id); - - ret = _VIF1chain(); //Transfers the data set by the switch - - if ((vif1ch->chcr & 0x80) && (vif1ptag[0] >> 31)) { //Check TIE bit of CHCR and IRQ bit of tag - VIF_LOG( "dmaIrq Set\n" ); - - vif1.done = 1; - return 0; //End Transfer - } - return vif1.done;//Return Done -} - -__forceinline void vif1Interrupt() { - VIF_LOG("vif1Interrupt: %8.8x\n", cpuRegs.cycle); - - g_vifCycles = 0; - - - if(vif1.irq && vif1.tag.size == 0) { - vif1Regs->stat|= VIF1_STAT_INT; - hwIntcIrq(VIF1intc); - --vif1.irq; - if(vif1Regs->stat & (VIF1_STAT_VSS|VIF1_STAT_VIS|VIF1_STAT_VFS)) - { - vif1Regs->stat&= ~0x1F000000; // FQC=0 - // One game doesnt like vif stalling at end, cant remember what. Spiderman isnt keen on it tho - vif1ch->chcr &= ~0x100; - return; - } - - if(vif1ch->qwc > 0 || vif1.irqoffset > 0){ - if(vif1.stallontag == 1) { - _chainVIF1(); - } - else _VIF1chain();//CPU_INT(13, vif1ch->qwc * BIAS); - CPU_INT(1, g_vifCycles); - return; - } - } - - - //} - if((vif1ch->chcr & 0x100) == 0) SysPrintf("Vif1 running when CHCR == %x\n", vif1ch->chcr); - - - if ((vif1ch->chcr & 0x104) == 0x104 && vif1.done == 0) { - - if( !(psHu32(DMAC_CTRL) & 0x1) ) { - SysPrintf("vif1 dma masked\n"); - return; - } - - _chainVIF1(); - CPU_INT(1, g_vifCycles); - - return; - } -#ifdef PCSX2_DEVBUILD - if(vif1ch->qwc > 0) SysPrintf("VIF1 Ending with %x QWC left\n"); - if(vif1.cmd != 0) SysPrintf("vif1.cmd still set %x\n", vif1.cmd); -#endif - - prevviftag = NULL; - prevvifcycles = 0; - vif1ch->chcr &= ~0x100; - g_vifCycles = 0; - hwDmacIrq(DMAC_VIF1); - if(vif1Regs->mskpath3 == 0 || (vif1ch->chcr & 0x1) == 0x1)vif1Regs->stat&= ~0x1F000000; // FQC=0 -} - -#define spr0 ((DMACh*)&PS2MEM_HW[0xD000]) -void dmaVIF1() -{ - - VIF_LOG("dmaVIF1 chcr = %lx, madr = %lx, qwc = %lx\n" - " tadr = %lx, asr0 = %lx, asr1 = %lx\n", - vif1ch->chcr, vif1ch->madr, vif1ch->qwc, - vif1ch->tadr, vif1ch->asr0, vif1ch->asr1 ); - - - g_vifCycles = 0; - - if (((psHu32(DMAC_CTRL) & 0xC) == 0x8)) { // VIF MFIFO - //SysPrintf("VIFMFIFO\n"); - if(!(vif1ch->chcr & 0x4)) SysPrintf("MFIFO mode != Chain! %x\n", vif1ch->chcr); - if(vif1ch->madr != spr0->madr)vifMFIFOInterrupt(); - return; - } - -#ifdef PCSX2_DEVBUILD - if ((psHu32(DMAC_CTRL) & 0xC0) == 0x40) { // STD == VIF1 - //SysPrintf("VIF Stall Control Source = %x, Drain = %x\n", (psHu32(0xe000) >> 4) & 0x3, (psHu32(0xe000) >> 6) & 0x3); - //return; - } -#endif - - - vif1Regs->stat|= 0x10000000; // FQC=16 - - if (!(vif1ch->chcr & 0x4) || vif1ch->qwc > 0) { // Normal Mode - if ((psHu32(DMAC_CTRL) & 0xC0) == 0x40) { - SysPrintf("DMA Stall Control on VIF1 normal\n"); - } - if ((vif1ch->chcr & 0x1)) { // to Memory - if(_VIF1chain() == -2) { - SysPrintf("Stall on normal\n"); - //vif1.vifstalled = 1; - } - CPU_INT(1, g_vifCycles); - } else { - +void vif1TransferFromMemory(){ int size; u64* pMem = (u64*)dmaGetAddr(vif1ch->madr); @@ -2122,11 +1931,279 @@ void dmaVIF1() g_vifCycles += vif1ch->qwc * 2; vif1ch->madr += vif1ch->qwc * 16; // mgs3 scene changes vif1ch->qwc = 0; - CPU_INT(1, g_vifCycles); +} + +int _VIF1chain() { + u32 *pMem; + //u32 qwc = vif1ch->qwc; + u32 ret; + + if (vif1ch->qwc == 0 && vif1.vifstalled == 0 && vif1.irqoffset == 0) { + vif1.inprogress = 0; + return 0; + } + + if(vif1.dmamode == 1){ + vif1TransferFromMemory(); + vif1.inprogress = 0; + return 0; + } + + pMem = (u32*)dmaGetAddr(vif1ch->madr); + if (pMem == NULL) + return -1; + + VIF_LOG("VIF1chain size=%d, madr=%lx, tadr=%lx\n", + vif1ch->qwc, vif1ch->madr, vif1ch->tadr); + + if( vif1.vifstalled ) { + ret = VIF1transfer(pMem+vif1.irqoffset, vif1ch->qwc*4-vif1.irqoffset, 0); + } + else { + ret = VIF1transfer(pMem, vif1ch->qwc*4, 0); + } + /*vif1ch->madr+= (vif1ch->qwc << 4); + vif1ch->qwc-= qwc;*/ + + return ret; +} + +static int prevvifcycles = 0; +static u32* prevviftag = NULL; +u32 *vif1ptag; +int _chainVIF1() { + + return vif1.done;//Return Done +} + +__forceinline void vif1SetupTransfer() { + + switch(vif1.dmamode){ + case 0: //Normal + case 1: //Normal (From memory) + vif1.inprogress = 1; + vif1.done = 1; + break; + + case 2: //Chain + int id; + int ret; + + + + vif1ptag = (u32*)dmaGetAddr(vif1ch->tadr); //Set memory pointer to TADR + if (vif1ptag == NULL) { //Is vif0ptag empty? + SysPrintf("Vif1 Tag BUSERR\n"); + vif1ch->chcr = ( vif1ch->chcr & 0xFFFF ) | ( (*vif1ptag) & 0xFFFF0000 ); //Transfer upper part of tag to CHCR bits 31-15 + psHu32(DMAC_STAT)|= 1<<15; //If yes, set BEIS (BUSERR) in DMAC_STAT register + return; //Return -1 as an error has occurred + } + + id = (vif1ptag[0] >> 28) & 0x7; //ID for DmaChain copied from bit 28 of the tag + vif1ch->qwc = (u16)vif1ptag[0]; //QWC set to lower 16bits of the tag + vif1ch->madr = vif1ptag[1]; //MADR = ADDR field + g_vifCycles+=1; // Add 1 g_vifCycles from the QW read for the tag + + vif1ch->chcr = ( vif1ch->chcr & 0xFFFF ) | ( (*vif1ptag) & 0xFFFF0000 ); //Transfer upper part of tag to CHCR bits 31-15 + // Transfer dma tag if tte is set + + VIF_LOG("VIF1 Tag %8.8x_%8.8x size=%d, id=%d, madr=%lx, tadr=%lx\n", + vif1ptag[1], vif1ptag[0], vif1ch->qwc, id, vif1ch->madr, vif1ch->tadr); + + //} else + + + if (!vif1.done && (psHu32(DMAC_CTRL) & 0xC0) == 0x40 && id == 4) { // STD == VIF1 + //vif1.done |= hwDmacSrcChainWithStack(vif1ch, id); + // there are still bugs, need to also check if gif->madr +16*qwc >= stadr, if not, stall + if( (vif1ch->madr + vif1ch->qwc * 16) >= psHu32(DMAC_STADR) ) { + // stalled + + hwDmacIrq(13); + return; + } + } + + if (vif1ch->chcr & 0x40) { + if(vif1.vifstalled == 1) ret = VIF1transfer(vif1ptag+(2+vif1.irqoffset), 2-vif1.irqoffset, 1); //Transfer Tag on stall + else ret = VIF1transfer(vif1ptag+2, 2, 1); //Transfer Tag + if (ret == -1) return; //There has been an error + if (ret == -2) { + return; //IRQ set by VIFTransfer + } + } + + vif1.inprogress = 1; + vif1.done |= hwDmacSrcChainWithStack(vif1ch, id); + + + if ((vif1ch->chcr & 0x80) && (vif1ptag[0] >> 31)) { //Check TIE bit of CHCR and IRQ bit of tag + VIF_LOG( "dmaIrq Set\n" ); + + vif1.done = 1; + return; //End Transfer + } + break; + } +} +__forceinline void vif1Interrupt() { + VIF_LOG("vif1Interrupt: %8.8x\n", cpuRegs.cycle); + + g_vifCycles = 0; + + + + + + //} + if((vif1ch->chcr & 0x100) == 0) SysPrintf("Vif1 running when CHCR == %x\n", vif1ch->chcr); + + if(vif1.inprogress == 1) _VIF1chain(); + + if(vif1.irq && vif1.tag.size == 0) + { + vif1Regs->stat|= VIF1_STAT_INT; + hwIntcIrq(VIF1intc); + --vif1.irq; + if(vif1Regs->stat & (VIF1_STAT_VSS|VIF1_STAT_VIS|VIF1_STAT_VFS)) + { + vif1Regs->stat&= ~0x1F000000; // FQC=0 + // One game doesnt like vif stalling at end, cant remember what. Spiderman isnt keen on it tho + vif1ch->chcr &= ~0x100; + return; + } + else if(vif1ch->qwc > 0 || vif1.irqoffset > 0) + { + if(vif1.stallontag == 1) + { + vif1SetupTransfer(); + } + else _VIF1chain();//CPU_INT(13, vif1ch->qwc * BIAS); + } - vif1.done = 1; + } + + if (vif1.done == 0 || vif1.inprogress == 1) { + + if( !(psHu32(DMAC_CTRL) & 0x1) ) { + SysPrintf("vif1 dma masked\n"); + return; + } + + //_chainVIF1(); + if(vif1.inprogress == 0)vif1SetupTransfer(); + + CPU_INT(1, vif1ch->qwc * BIAS); return; } +#ifdef PCSX2_DEVBUILD + if(vif1ch->qwc > 0) SysPrintf("VIF1 Ending with %x QWC left\n"); + if(vif1.cmd != 0) SysPrintf("vif1.cmd still set %x\n", vif1.cmd); +#endif + + prevviftag = NULL; + prevvifcycles = 0; + vif1ch->chcr &= ~0x100; + g_vifCycles = 0; + hwDmacIrq(DMAC_VIF1); + if(vif1Regs->mskpath3 == 0 || (vif1ch->chcr & 0x1) == 0x1)vif1Regs->stat&= ~0x1F000000; // FQC=0 +} + +#define spr0 ((DMACh*)&PS2MEM_HW[0xD000]) +void dmaVIF1() +{ + + VIF_LOG("dmaVIF1 chcr = %lx, madr = %lx, qwc = %lx\n" + " tadr = %lx, asr0 = %lx, asr1 = %lx\n", + vif1ch->chcr, vif1ch->madr, vif1ch->qwc, + vif1ch->tadr, vif1ch->asr0, vif1ch->asr1 ); + + + g_vifCycles = 0; + vif1.inprogress = 0; + + if (((psHu32(DMAC_CTRL) & 0xC) == 0x8)) { // VIF MFIFO + //SysPrintf("VIFMFIFO\n"); + if(!(vif1ch->chcr & 0x4)) SysPrintf("MFIFO mode != Chain! %x\n", vif1ch->chcr); + /*if(vif1ch->madr != spr0->madr)*/vifMFIFOInterrupt(); + //else vif1.inprogress |= 0x10; + return; + } + +#ifdef PCSX2_DEVBUILD + if ((psHu32(DMAC_CTRL) & 0xC0) == 0x40) { // STD == VIF1 + //SysPrintf("VIF Stall Control Source = %x, Drain = %x\n", (psHu32(0xe000) >> 4) & 0x3, (psHu32(0xe000) >> 6) & 0x3); + //return; + } +#endif + + + vif1Regs->stat|= 0x10000000; // FQC=16 + + if (!(vif1ch->chcr & 0x4) || vif1ch->qwc > 0) { // Normal Mode + + if ((psHu32(DMAC_CTRL) & 0xC0) == 0x40) { + SysPrintf("DMA Stall Control on VIF1 normal\n"); + } + if ((vif1ch->chcr & 0x1)) { // to Memory + /*if(_VIF1chain() == -2) { + SysPrintf("Stall on normal\n"); + //vif1.vifstalled = 1; + } + CPU_INT(1, g_vifCycles);*/ + vif1.dmamode = 0; + } else { + vif1.dmamode = 1; + /*int size; + u64* pMem = (u64*)dmaGetAddr(vif1ch->madr); + + // VIF from gsMemory + + if (pMem == NULL) { //Is vif0ptag empty? + SysPrintf("Vif1 Tag BUSERR\n"); + psHu32(DMAC_STAT)|= 1<<15; //If yes, set BEIS (BUSERR) in DMAC_STAT register + vif1.done = 1; + vif1Regs->stat&= ~0x1f000000; + vif1ch->qwc = 0; + CPU_INT(1, 0); + + return; //Return -1 as an error has occurred + } + + // MTGS concerns: The MTGS is inherently disagreeable with the idea of downloading + // stuff from the GS. The *only* way to handle this case safely is to flush the GS + // completely and execute the transfer there-after. + + FreezeXMMRegs(1); + if( GSreadFIFO2 == NULL ) { + for (size=vif1ch->qwc; size>0; --size) { + if (size > 1 ) { + mtgsWaitGS(); + GSreadFIFO((u64*)&PS2MEM_HW[0x5000]); + } + pMem[0] = psHu64(0x5000); + pMem[1] = psHu64(0x5008); pMem+= 2; + } + } + else { + mtgsWaitGS(); + GSreadFIFO2(pMem, vif1ch->qwc); + + // set incase read + psHu64(0x5000) = pMem[2*vif1ch->qwc-2]; + psHu64(0x5008) = pMem[2*vif1ch->qwc-1]; + } + FreezeXMMRegs(0); + + if(vif1Regs->mskpath3 == 0)vif1Regs->stat&= ~0x1f000000; + g_vifCycles += vif1ch->qwc * 2; + vif1ch->madr += vif1ch->qwc * 16; // mgs3 scene changes + vif1ch->qwc = 0; + CPU_INT(1, g_vifCycles);*/ + } + /*vif1.done = 1; + return;*/ + } else vif1.dmamode = 2; // Chain Mode vif1.done = 0; @@ -2154,6 +2231,7 @@ void vif1Write32(u32 mem, u32 value) { psHu64(0x10005008) = 0; vif1.done = 1; vif1Regs->err = 0; + vif1.inprogress = 0; vif1Regs->stat&= ~(0x1F800000|VIF1_STAT_INT|VIF1_STAT_VSS|VIF1_STAT_VIS|VIF1_STAT_VFS|VIF1_STAT_VPS); // FQC=0 } if (value & 0x2) { @@ -2192,15 +2270,18 @@ void vif1Write32(u32 mem, u32 value) { g_vifCycles = 0; // loop necessary for spiderman if((psHu32(DMAC_CTRL) & 0xC) == 0x8){ - //SysPrintf("MFIFO Stall\n"); - CPU_INT(10, 0); - }else { - if(vif1.stallontag == 1){ - //SysPrintf("Sorting VIF Stall on tag\n"); - _chainVIF1(); - } else _VIF1chain(); - CPU_INT(1, g_vifCycles); // Gets the timing right - Flatout + //SysPrintf("MFIFO Stall\n"); + //CPU_INT(10, 0); + CPU_INT(10, vif1ch->qwc * BIAS); + }else { + /*if(vif1.stallontag == 1){ + //SysPrintf("Sorting VIF Stall on tag\n"); + vif1SetupTransfer(); + } *///else _VIF1chain(); + + //CPU_INT(1, g_vifCycles); // Gets the timing right - Flatout + CPU_INT(1, vif1ch->qwc * BIAS); } vif1ch->chcr |= 0x100; } @@ -2270,16 +2351,8 @@ void SaveState::vif1Freeze() { Freeze(vif1); - if( GetVersion() >= 0x04 ) - { - Freeze( g_vif1HasMask3 ); - Freeze( g_vif1Masks ); - Freeze( g_vifRow1 ); - Freeze( g_vifCol1 ); - } - else if( IsLoading() ) - { - SetNewMask(g_vif1Masks, g_vif1HasMask3, vif1Regs->mask, ~vif1Regs->mask); - //if(vif1ch->chcr & 0x100) vif1.done = 0; - } + Freeze( g_vif1HasMask3 ); + Freeze( g_vif1Masks ); + Freeze( g_vifRow1 ); + Freeze( g_vifCol1 ); } diff --git a/pcsx2/VifDma.h b/pcsx2/VifDma.h index e2605ec81a..86fe63f102 100644 --- a/pcsx2/VifDma.h +++ b/pcsx2/VifDma.h @@ -40,6 +40,8 @@ struct vifStruct { u8 irqoffset; // 32bit offset where next vif code is u32 savedtag; // need this for backwards compat with save states u32 vifpacketsize; + u8 inprogress; + u8 dmamode; }; extern vifStruct vif0, vif1; diff --git a/pcsx2/vssprintf.cpp b/pcsx2/vssprintf.cpp index 38c45bbcbc..234017f0e1 100644 --- a/pcsx2/vssprintf.cpp +++ b/pcsx2/vssprintf.cpp @@ -209,10 +209,21 @@ static void number(std::string& dest, T num, int base, int size, int precision, tmp[i++] = '0'; else { - while (num != 0) + if( base == 16 ) { - tmp[i++] = dig[num % (uint) base]; - num = num / (uint) base; + while (num != 0) + { + tmp[i++] = dig[num & 0xf]; + num = (uint)num >> 4; + } + } + else + { + while (num != 0) + { + tmp[i++] = dig[num % (uint) base]; + num /= (uint) base; + } } } @@ -232,10 +243,16 @@ static void number(std::string& dest, T num, int base, int size, int precision, } } - if (!(type & LEFT)) while (size-- > 0) dest += c; - while (i < precision--) dest += '0'; + + if( !(type & LEFT) && size > 0) { dest.append( size, c ); size = 0; } + if( i < precision ) dest.append( precision-i, '0' ); while (i-- > 0) dest += tmp[i]; - while (size-- > 0) dest += ' '; + if( size > 0 ) dest.append( size, ' ' ); + + //if (!(type & LEFT)) while (size-- > 0) dest += c; + //while (i < precision--) dest += '0'; + //while (i-- > 0) dest += tmp[i]; + //while (size-- > 0) dest += ' '; } static void eaddr( std::string& dest, unsigned char *addr, int size, int precision, int type) @@ -451,7 +468,7 @@ static void flt( std::string& dest, double num, int size, int precision, char fm { char tmp[80]; char c, sign; - int n, i; + int n; // Left align means no zero padding if (flags & LEFT) flags &= ~ZEROPAD; @@ -498,11 +515,12 @@ static void flt( std::string& dest, double num, int size, int precision, char fm // Output number with alignment and padding size -= n; - if (!(flags & (ZEROPAD | LEFT))) while (size-- > 0) dest += ' '; + + if (!(flags & (ZEROPAD | LEFT)) && size > 0) { dest.append( size, ' ' ); size = 0; } if (sign) dest += sign; - if (!(flags & LEFT)) while (size-- > 0) dest += c; - for (i = 0; i < n; i++) dest += tmp[i]; - while (size-- > 0) dest += ' '; + if (!(flags & LEFT) && size > 0) { dest.append( size, c ); size = 0; } + dest.append( tmp, n ); + if(size > 0) dest.append( size, ' ' ); } #endif @@ -520,11 +538,7 @@ void vssappendf(std::string& dest, const char* format, va_list args) int precision; // Min. # of digits for integers; max number of chars for from string int qualifier; // 'h', 'l', or 'L' for integer fields - // Optimization: Memory is cheap. Allocating it on the fly is not. Allocate more room - // than we'll likely need right upfront! - dest.reserve( strlen( format ) * 2 ); - - for( const char* fmt = format; *fmt; fmt++ ) + for( const char* fmt = format; *fmt; ++fmt ) { if (*fmt != '%') { @@ -607,16 +621,26 @@ repeat: if( precision < 0 ) { // no precision override so just copy the whole string. - if (!(flags & LEFT)) while (len < field_width--) dest += ' '; + if (!(flags & LEFT) && (len < field_width)) + { + dest.append( field_width - len, ' ' ); + field_width = 0; + } dest += *ss; } else { if( len > precision ) len = precision; - if (!(flags & LEFT)) while (len < field_width--) dest += ' '; + if (!(flags & LEFT) && (len < field_width)) + { + dest.append( field_width - len, ' ' ); + field_width = 0; + } dest.append( ss->begin(), ss->begin()+len ); } - while (len < field_width--) dest += ' '; + + if( len < field_width ) + dest.append( field_width - len, ' ' ); } else { @@ -736,7 +760,12 @@ repeat: void vssprintf( std::string& dest, const char* format, va_list args ) { + // Optimization: Memory is cheap. Allocating it on the fly is not. Allocate more room + // than we'll likely need right upfront! Also, strlen is slow, so better to just pick an + // arbitrarily generous value to reserve instead of basing it on string length. + dest.clear(); + dest.reserve( 96 ); vssappendf( dest, format, args ); } @@ -807,6 +836,5 @@ std::string vfmt_string( const char* fmt, va_list args ) std::string retval; vssprintf( retval, fmt, args ); - return retval; } diff --git a/pcsx2/vtlb.cpp b/pcsx2/vtlb.cpp index b10b3dbfb2..5bc06b18a9 100644 --- a/pcsx2/vtlb.cpp +++ b/pcsx2/vtlb.cpp @@ -50,13 +50,7 @@ using namespace vtlb_private; namespace vtlb_private { - s32 pmap[VTLB_PMAP_ITEMS]; //512KB - s32 vmap[VTLB_VMAP_ITEMS]; //4MB - - // first indexer -- 8/16/32/64/128 bit tables [values 0-4] - // second indexer -- read/write [0 or 1] - // third indexer -- 128 pages of memory! - void* RWFT[5][2][128]; + PCSX2_ALIGNED( 64, MapData vtlbdata ); } vtlbHandler vtlbHandlerCount=0; @@ -97,11 +91,11 @@ callfunction: // Interpreter Implementations of VTLB Memory Operations. // See recVTLB.cpp for the dynarec versions. -// Interpreterd VTLB lookup for 8, 16, and 32 bit accesses +// Interpreted VTLB lookup for 8, 16, and 32 bit accesses template __forceinline DataType __fastcall MemOp_r0(u32 addr) { - u32 vmv=vmap[addr>>VTLB_PAGE_BITS]; + u32 vmv=vtlbdata.vmap[addr>>VTLB_PAGE_BITS]; s32 ppf=addr+vmv; if (!(ppf<0)) @@ -111,13 +105,13 @@ __forceinline DataType __fastcall MemOp_r0(u32 addr) u32 hand=(u8)vmv; u32 paddr=ppf-hand+0x80000000; //SysPrintf("Translated 0x%08X to 0x%08X\n",addr,paddr); - //return reinterpret_cast::HandlerType*>(RWFT[TemplateHelper::sidx][0][hand])(paddr,data); + //return reinterpret_cast::HandlerType*>(vtlbdata.RWFT[TemplateHelper::sidx][0][hand])(paddr,data); switch( DataSize ) { - case 8: return ((vtlbMemR8FP*)RWFT[0][0][hand])(paddr); - case 16: return ((vtlbMemR16FP*)RWFT[1][0][hand])(paddr); - case 32: return ((vtlbMemR32FP*)RWFT[2][0][hand])(paddr); + case 8: return ((vtlbMemR8FP*)vtlbdata.RWFT[0][0][hand])(paddr); + case 16: return ((vtlbMemR16FP*)vtlbdata.RWFT[1][0][hand])(paddr); + case 32: return ((vtlbMemR32FP*)vtlbdata.RWFT[2][0][hand])(paddr); jNO_DEFAULT; } @@ -127,7 +121,7 @@ __forceinline DataType __fastcall MemOp_r0(u32 addr) template __forceinline void __fastcall MemOp_r1(u32 addr, DataType* data) { - u32 vmv=vmap[addr>>VTLB_PAGE_BITS]; + u32 vmv=vtlbdata.vmap[addr>>VTLB_PAGE_BITS]; s32 ppf=addr+vmv; if (!(ppf<0)) @@ -146,8 +140,8 @@ __forceinline void __fastcall MemOp_r1(u32 addr, DataType* data) switch( DataSize ) { - case 64: ((vtlbMemR64FP*)RWFT[3][0][hand])(paddr, data); break; - case 128: ((vtlbMemR128FP*)RWFT[4][0][hand])(paddr, data); break; + case 64: ((vtlbMemR64FP*)vtlbdata.RWFT[3][0][hand])(paddr, data); break; + case 128: ((vtlbMemR128FP*)vtlbdata.RWFT[4][0][hand])(paddr, data); break; jNO_DEFAULT; } @@ -157,7 +151,7 @@ __forceinline void __fastcall MemOp_r1(u32 addr, DataType* data) template __forceinline void __fastcall MemOp_w0(u32 addr, DataType data) { - u32 vmv=vmap[addr>>VTLB_PAGE_BITS]; + u32 vmv=vtlbdata.vmap[addr>>VTLB_PAGE_BITS]; s32 ppf=addr+vmv; if (!(ppf<0)) { @@ -172,9 +166,9 @@ __forceinline void __fastcall MemOp_w0(u32 addr, DataType data) switch( DataSize ) { - case 8: return ((vtlbMemW8FP*)RWFT[0][1][hand])(paddr, (u8)data); - case 16: return ((vtlbMemW16FP*)RWFT[1][1][hand])(paddr, (u16)data); - case 32: return ((vtlbMemW32FP*)RWFT[2][1][hand])(paddr, (u32)data); + case 8: return ((vtlbMemW8FP*)vtlbdata.RWFT[0][1][hand])(paddr, (u8)data); + case 16: return ((vtlbMemW16FP*)vtlbdata.RWFT[1][1][hand])(paddr, (u16)data); + case 32: return ((vtlbMemW32FP*)vtlbdata.RWFT[2][1][hand])(paddr, (u32)data); jNO_DEFAULT; } @@ -184,7 +178,7 @@ template __forceinline void __fastcall MemOp_w1(u32 addr,const DataType* data) { verify(DataSize==128 || DataSize==64); - u32 vmv=vmap[addr>>VTLB_PAGE_BITS]; + u32 vmv=vtlbdata.vmap[addr>>VTLB_PAGE_BITS]; s32 ppf=addr+vmv; if (!(ppf<0)) { @@ -200,8 +194,8 @@ __forceinline void __fastcall MemOp_w1(u32 addr,const DataType* data) //SysPrintf("Translated 0x%08X to 0x%08X\n",addr,paddr); switch( DataSize ) { - case 64: return ((vtlbMemW64FP*)RWFT[3][1][hand])(paddr, data); - case 128: return ((vtlbMemW128FP*)RWFT[4][1][hand])(paddr, data); + case 64: return ((vtlbMemW64FP*)vtlbdata.RWFT[3][1][hand])(paddr, data); + case 128: return ((vtlbMemW128FP*)vtlbdata.RWFT[4][1][hand])(paddr, data); jNO_DEFAULT; } @@ -352,17 +346,17 @@ vtlbHandler vtlb_RegisterHandler( vtlbMemR8FP* r8,vtlbMemR16FP* r16,vtlbMemR32FP //write the code :p vtlbHandler rv=vtlbHandlerCount++; - RWFT[0][0][rv] = (r8!=0) ? r8:vtlbDefaultPhyRead8; - RWFT[1][0][rv] = (r16!=0) ? r16:vtlbDefaultPhyRead16; - RWFT[2][0][rv] = (r32!=0) ? r32:vtlbDefaultPhyRead32; - RWFT[3][0][rv] = (r64!=0) ? r64:vtlbDefaultPhyRead64; - RWFT[4][0][rv] = (r128!=0) ? r128:vtlbDefaultPhyRead128; + vtlbdata.RWFT[0][0][rv] = (r8!=0) ? r8:vtlbDefaultPhyRead8; + vtlbdata.RWFT[1][0][rv] = (r16!=0) ? r16:vtlbDefaultPhyRead16; + vtlbdata.RWFT[2][0][rv] = (r32!=0) ? r32:vtlbDefaultPhyRead32; + vtlbdata.RWFT[3][0][rv] = (r64!=0) ? r64:vtlbDefaultPhyRead64; + vtlbdata.RWFT[4][0][rv] = (r128!=0) ? r128:vtlbDefaultPhyRead128; - RWFT[0][1][rv] = (w8!=0) ? w8:vtlbDefaultPhyWrite8; - RWFT[1][1][rv] = (w16!=0) ? w16:vtlbDefaultPhyWrite16; - RWFT[2][1][rv] = (w32!=0) ? w32:vtlbDefaultPhyWrite32; - RWFT[3][1][rv] = (w64!=0) ? w64:vtlbDefaultPhyWrite64; - RWFT[4][1][rv] = (w128!=0) ? w128:vtlbDefaultPhyWrite128; + vtlbdata.RWFT[0][1][rv] = (w8!=0) ? w8:vtlbDefaultPhyWrite8; + vtlbdata.RWFT[1][1][rv] = (w16!=0) ? w16:vtlbDefaultPhyWrite16; + vtlbdata.RWFT[2][1][rv] = (w32!=0) ? w32:vtlbDefaultPhyWrite32; + vtlbdata.RWFT[3][1][rv] = (w64!=0) ? w64:vtlbDefaultPhyWrite64; + vtlbdata.RWFT[4][1][rv] = (w128!=0) ? w128:vtlbDefaultPhyWrite128; return rv; } @@ -382,7 +376,7 @@ void vtlb_MapHandler(vtlbHandler handler,u32 start,u32 size) while(size>0) { - pmap[start>>VTLB_PAGE_BITS]=value; + vtlbdata.pmap[start>>VTLB_PAGE_BITS]=value; start+=VTLB_PAGE_SIZE; size-=VTLB_PAGE_SIZE; @@ -407,7 +401,7 @@ void vtlb_MapBlock(void* base,u32 start,u32 size,u32 blocksize) while(blocksz>0) { - pmap[start>>VTLB_PAGE_BITS]=ptr; + vtlbdata.pmap[start>>VTLB_PAGE_BITS]=ptr; start+=VTLB_PAGE_SIZE; ptr+=VTLB_PAGE_SIZE; @@ -425,7 +419,7 @@ void vtlb_Mirror(u32 new_region,u32 start,u32 size) while(size>0) { - pmap[start>>VTLB_PAGE_BITS]=pmap[new_region>>VTLB_PAGE_BITS]; + vtlbdata.pmap[start>>VTLB_PAGE_BITS]=vtlbdata.pmap[new_region>>VTLB_PAGE_BITS]; start+=VTLB_PAGE_SIZE; new_region+=VTLB_PAGE_SIZE; @@ -435,10 +429,10 @@ void vtlb_Mirror(u32 new_region,u32 start,u32 size) __forceinline void* vtlb_GetPhyPtr(u32 paddr) { - if (paddr>=VTLB_PMAP_SZ || pmap[paddr>>VTLB_PAGE_BITS]<0) + if (paddr>=VTLB_PMAP_SZ || vtlbdata.pmap[paddr>>VTLB_PAGE_BITS]<0) return NULL; else - return reinterpret_cast(pmap[paddr>>VTLB_PAGE_BITS]+(paddr&VTLB_PAGE_MASK)); + return reinterpret_cast(vtlbdata.pmap[paddr>>VTLB_PAGE_BITS]+(paddr&VTLB_PAGE_MASK)); } //virtual mappings @@ -462,11 +456,11 @@ void vtlb_VMap(u32 vaddr,u32 paddr,u32 sz) } else { - pme=pmap[paddr>>VTLB_PAGE_BITS]; + pme=vtlbdata.pmap[paddr>>VTLB_PAGE_BITS]; if (pme<0) pme|=paddr;// top bit is set anyway ... } - vmap[vaddr>>VTLB_PAGE_BITS]=pme-vaddr; + vtlbdata.vmap[vaddr>>VTLB_PAGE_BITS]=pme-vaddr; vaddr+=VTLB_PAGE_SIZE; paddr+=VTLB_PAGE_SIZE; sz-=VTLB_PAGE_SIZE; @@ -480,7 +474,7 @@ void vtlb_VMapBuffer(u32 vaddr,void* buffer,u32 sz) u32 bu8=(u32)buffer; while(sz>0) { - vmap[vaddr>>VTLB_PAGE_BITS]=bu8-vaddr; + vtlbdata.vmap[vaddr>>VTLB_PAGE_BITS]=bu8-vaddr; vaddr+=VTLB_PAGE_SIZE; bu8+=VTLB_PAGE_SIZE; sz-=VTLB_PAGE_SIZE; @@ -500,7 +494,7 @@ void vtlb_VMapUnmap(u32 vaddr,u32 sz) } handl|=vaddr; // top bit is set anyway ... handl|=0x80000000; - vmap[vaddr>>VTLB_PAGE_BITS]=handl-vaddr; + vtlbdata.vmap[vaddr>>VTLB_PAGE_BITS]=handl-vaddr; vaddr+=VTLB_PAGE_SIZE; sz-=VTLB_PAGE_SIZE; } @@ -510,7 +504,7 @@ void vtlb_VMapUnmap(u32 vaddr,u32 sz) void vtlb_Init() { vtlbHandlerCount=0; - memzero_obj(RWFT); + memzero_obj(vtlbdata.RWFT); //Register default handlers //Unmapped Virt handlers _MUST_ be registered first. diff --git a/pcsx2/vtlb.h b/pcsx2/vtlb.h index 84ba374d08..5571d6b835 100644 --- a/pcsx2/vtlb.h +++ b/pcsx2/vtlb.h @@ -75,9 +75,18 @@ namespace vtlb_private static const uint VTLB_PMAP_SZ = 0x20000000; static const uint VTLB_VMAP_ITEMS = 0x100000000ULL / VTLB_PAGE_SIZE; - extern void* RWFT[5][2][128]; - extern s32 pmap[VTLB_PMAP_ITEMS]; //512KB - extern s32 vmap[VTLB_VMAP_ITEMS]; //4MB + struct MapData + { + s32 pmap[VTLB_PMAP_ITEMS]; //512KB + s32 vmap[VTLB_VMAP_ITEMS]; //4MB + + // first indexer -- 8/16/32/64/128 bit tables [values 0-4] + // second indexer -- read/write [0 or 1] + // third indexer -- 128 possible handlers! + void* RWFT[5][2][128]; + }; + + PCSX2_ALIGNED_EXTERN( 64, MapData vtlbdata ); } #endif diff --git a/pcsx2/windows/AdvancedDlg.cpp b/pcsx2/windows/AdvancedDlg.cpp index 1546ae31e7..16a6f0d3aa 100644 --- a/pcsx2/windows/AdvancedDlg.cpp +++ b/pcsx2/windows/AdvancedDlg.cpp @@ -35,8 +35,6 @@ static void InitRoundClampModes( HWND hDlg, u32 new_eeopt, u32 new_vuopt ) else if (new_vuopt & 0x1) CheckRadioButton(hDlg, IDC_VU_CLAMPMODE0, IDC_VU_CLAMPMODE3, IDC_VU_CLAMPMODE0 + 1); else CheckRadioButton(hDlg, IDC_VU_CLAMPMODE0, IDC_VU_CLAMPMODE3, IDC_VU_CLAMPMODE0 + 0); - CheckDlgButton(hDlg, IDC_EE_CHECK3, (new_eeopt & 0x8) ? TRUE : FALSE); - if (new_eeopt & 0x4) CheckRadioButton(hDlg, IDC_EE_CLAMPMODE0, IDC_EE_CLAMPMODE3, IDC_EE_CLAMPMODE0 + 3); else if (new_eeopt & 0x2) CheckRadioButton(hDlg, IDC_EE_CLAMPMODE0, IDC_EE_CLAMPMODE3, IDC_EE_CLAMPMODE0 + 2); else if (new_eeopt & 0x1) CheckRadioButton(hDlg, IDC_EE_CLAMPMODE0, IDC_EE_CLAMPMODE3, IDC_EE_CLAMPMODE0 + 1); @@ -96,8 +94,6 @@ BOOL APIENTRY AdvancedOptionsProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM new_eeopt |= IsDlgButtonChecked(hDlg, IDC_EE_CLAMPMODE2) ? 0x3 : 0; new_eeopt |= IsDlgButtonChecked(hDlg, IDC_EE_CLAMPMODE3) ? 0x7 : 0; - new_eeopt |= IsDlgButtonChecked(hDlg, IDC_EE_CHECK3) ? 0x8 : 0; - new_vuopt |= IsDlgButtonChecked(hDlg, IDC_VU_CLAMPMODE0) ? 0x0 : 0; new_vuopt |= IsDlgButtonChecked(hDlg, IDC_VU_CLAMPMODE1) ? 0x1 : 0; new_vuopt |= IsDlgButtonChecked(hDlg, IDC_VU_CLAMPMODE2) ? 0x3 : 0; diff --git a/pcsx2/windows/VCprojects/pcsx2_2008.vcproj b/pcsx2/windows/VCprojects/pcsx2_2008.vcproj index e2f88e6db5..d39992012f 100644 --- a/pcsx2/windows/VCprojects/pcsx2_2008.vcproj +++ b/pcsx2/windows/VCprojects/pcsx2_2008.vcproj @@ -106,7 +106,7 @@ UseOfMFC="0" ATLMinimizesCRunTimeLibraryUsage="false" CharacterSet="2" - WholeProgramOptimization="1" + WholeProgramOptimization="0" > + + + + diff --git a/pcsx2/windows/WinMain.cpp b/pcsx2/windows/WinMain.cpp index 9e250994e6..24b87466c3 100644 --- a/pcsx2/windows/WinMain.cpp +++ b/pcsx2/windows/WinMain.cpp @@ -529,7 +529,7 @@ BOOL APIENTRY GameFixes(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) case WM_INITDIALOG: if(Config.GameFixes & 0x1) CheckDlgButton(hDlg, IDC_GAMEFIX2, TRUE);//Tri-Ace fix if(Config.GameFixes & 0x4) CheckDlgButton(hDlg, IDC_GAMEFIX3, TRUE);//Digimon FPU compare fix - if(Config.GameFixes & 0x2) CheckDlgButton(hDlg, IDC_GAMEFIX4, TRUE);//GoW fix + if(Config.GameFixes & 0x8) CheckDlgButton(hDlg, IDC_GAMEFIX5, TRUE);//Tales of Destiny fix return TRUE; case WM_COMMAND: @@ -538,7 +538,7 @@ BOOL APIENTRY GameFixes(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) uint newfixes = 0; newfixes |= IsDlgButtonChecked(hDlg, IDC_GAMEFIX2) ? 0x1 : 0; newfixes |= IsDlgButtonChecked(hDlg, IDC_GAMEFIX3) ? 0x4 : 0; - newfixes |= IsDlgButtonChecked(hDlg, IDC_GAMEFIX4) ? 0x2 : 0; + newfixes |= IsDlgButtonChecked(hDlg, IDC_GAMEFIX5) ? 0x8 : 0; EndDialog(hDlg, TRUE); diff --git a/pcsx2/windows/WinThreads.cpp b/pcsx2/windows/WinThreads.cpp index 1cea832f6b..658aab7a0a 100644 --- a/pcsx2/windows/WinThreads.cpp +++ b/pcsx2/windows/WinThreads.cpp @@ -20,7 +20,6 @@ #include "Win32.h" #include "System.h" -#include "Threading.h" #include "ix86/ix86_types.h" #ifdef _WIN32 @@ -110,7 +109,7 @@ namespace Threading __forceinline long pcsx2_InterlockedExchangeAdd( volatile long* target, long srcval ) { - long result; + //long result; // Use our own implementation... // Pcsx2 won't use threads unless it's a multicore cpu, so no need to use @@ -120,30 +119,26 @@ namespace Threading { __asm { - //PUSH ecx mov ecx,dword ptr [target] mov eax,dword ptr [srcval] lock xadd dword ptr [ecx],eax - mov dword ptr [result], eax - //POP ecx + + // msvc smartly returns eax for us without so much as a compiler warning even... + //mov dword ptr [result], eax } } else { __asm { - //PUSH ecx - //PUSH edx mov ecx,dword ptr [target] - //L1: mov eax,dword ptr [srcval] xadd dword ptr [ecx],eax - //jnz L1 - mov dword ptr [result], eax - //POP edx - //POP ecx + + // msvc smartly returns eax for us without so much as a compiler warning even... + //mov dword ptr [result], eax } } - return result; +// return result; } } diff --git a/pcsx2/windows/pcsx2.rc b/pcsx2/windows/pcsx2.rc index bd892dca42..523f912ea4 100644 --- a/pcsx2/windows/pcsx2.rc +++ b/pcsx2/windows/pcsx2.rc @@ -74,21 +74,21 @@ LANGUAGE LANG_GERMAN, SUBLANG_GERMAN // Dialog // -IDD_GAMEFIXES DIALOGEX 0, 0, 278, 127 +IDD_GAMEFIXES DIALOGEX 0, 0, 279, 118 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Game Special Fixes" FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN - DEFPUSHBUTTON "OK",IDOK,85,91,50,14 - PUSHBUTTON "Cancel",IDCANCEL,139,91,50,14 - CTEXT "Some games need special settings.\nConfigure them here.",IDC_STATIC,7,7,264,17 - GROUPBOX "PCSX2 Gamefixes",IDC_STATIC,7,31,264,89 + DEFPUSHBUTTON "OK",IDOK,87,89,50,14 + PUSHBUTTON "Cancel",IDCANCEL,142,89,50,14 + CTEXT "Some games need special settings.\nConfigure them here.",IDC_STATIC,7,7,265,17 + GROUPBOX "PCSX2 Gamefixes",IDC_STATIC,7,28,265,83 CONTROL "FPU Compare Hack - Special fix for Digimon Rumble Arena 2.",IDC_GAMEFIX3, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,47,249,10 - CONTROL "VU Add / Sub Hack - Special fix for Tri-Ace games!",IDC_GAMEFIX2, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,61,252,10 - CONTROL "VU Clip Hack - Special fix for God of War",IDC_GAMEFIX4, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,75,144,10 + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,43,249,10 + CONTROL "VU Add Hack - Special fix for Tri-Ace games!",IDC_GAMEFIX2, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,72,252,10 + CONTROL "FPU Mul Hack - Special fix for Tales of Destiny (possibly other games).",IDC_GAMEFIX5, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,57,249,10 END @@ -103,10 +103,11 @@ BEGIN IDD_GAMEFIXES, DIALOG BEGIN LEFTMARGIN, 7 - RIGHTMARGIN, 271 - VERTGUIDE, 12 + RIGHTMARGIN, 272 + VERTGUIDE, 14 TOPMARGIN, 7 - BOTTOMMARGIN, 120 + BOTTOMMARGIN, 111 + HORZGUIDE, 103 END END #endif // APSTUDIO_INVOKED @@ -195,31 +196,30 @@ BEGIN RADIOBUTTON "Chop / Zero",IDC_EE_ROUNDMODE3,156,36,54,16 CONTROL " Flush to Zero",IDC_EE_CHECK1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,20,105,58,13 CONTROL " Denormals are Zero",IDC_EE_CHECK2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,111,105,79,13 - CONTROL " Flush to Zero",IDC_VU_CHECK1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,20,232,58,13 - CONTROL " Denormals are Zero",IDC_VU_CHECK2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,111,232,81,13 - RADIOBUTTON "Nearest",IDC_VU_ROUNDMODE0,20,172,44,12 - RADIOBUTTON "Negative",IDC_VU_ROUNDMODE1,64,172,47,12 - RADIOBUTTON "Positive",IDC_VU_ROUNDMODE2,111,172,45,12 - RADIOBUTTON "Chop / Zero",IDC_VU_ROUNDMODE3,156,172,52,12 + CONTROL " Flush to Zero",IDC_VU_CHECK1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,20,217,58,13 + CONTROL " Denormals are Zero",IDC_VU_CHECK2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,111,217,81,13 + RADIOBUTTON "Nearest",IDC_VU_ROUNDMODE0,20,157,44,12 + RADIOBUTTON "Negative",IDC_VU_ROUNDMODE1,64,157,47,12 + RADIOBUTTON "Positive",IDC_VU_ROUNDMODE2,111,157,45,12 + RADIOBUTTON "Chop / Zero",IDC_VU_ROUNDMODE3,156,157,52,12 PUSHBUTTON "Defaults",IDDEFAULT,346,254,50,14 - GROUPBOX "VU Recs Options",IDC_STATIC,7,146,250,122,BS_CENTER - GROUPBOX "EE Recs Options",IDC_STATIC,7,12,250,129,BS_CENTER - GROUPBOX "Round Mode",IDC_STATIC,11,159,236,32 + GROUPBOX "VU Recs Options",IDC_STATIC,7,133,250,118,BS_CENTER + GROUPBOX "EE Recs Options",IDC_STATIC,7,12,250,113,BS_CENTER + GROUPBOX "Round Mode",IDC_STATIC,11,144,236,32 GROUPBOX "Round Mode",IDC_STATIC,11,26,236,36 - GROUPBOX "Help",IDC_STATIC,271,12,251,238,BS_CENTER - GROUPBOX "Clamp Mode",IDC_STATIC,11,196,236,31 - RADIOBUTTON "None",IDC_VU_CLAMPMODE0,20,207,44,12 - RADIOBUTTON "Normal",IDC_VU_CLAMPMODE1,64,207,47,12 - RADIOBUTTON "Extra",IDC_VU_CLAMPMODE2,111,207,45,12 - RADIOBUTTON "Extra + Preserve Sign",IDC_VU_CLAMPMODE3,156,207,85,12 - CONTROL " Set O and U Flags",IDC_VU_CHECK3,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,20,250,91,13 - CONTROL " Software Emulate DaZ",IDC_VU_CHECK4,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,111,250,116,13 + GROUPBOX "Help",IDC_STATIC,271,12,251,239,BS_CENTER + GROUPBOX "Clamp Mode",IDC_STATIC,11,181,236,31 + RADIOBUTTON "None",IDC_VU_CLAMPMODE0,20,192,44,12 + RADIOBUTTON "Normal",IDC_VU_CLAMPMODE1,64,192,47,12 + RADIOBUTTON "Extra",IDC_VU_CLAMPMODE2,111,192,45,12 + RADIOBUTTON "Extra + Preserve Sign",IDC_VU_CLAMPMODE3,156,192,85,12 + CONTROL " Set O and U Flags",IDC_VU_CHECK3,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,20,235,91,13 + CONTROL " Software Emulate DaZ",IDC_VU_CHECK4,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,111,235,116,13 GROUPBOX "Clamp Mode",IDC_STATIC,11,67,236,31 RADIOBUTTON "None",IDC_EE_CLAMPMODE0,20,76,44,16 RADIOBUTTON "Normal",IDC_EE_CLAMPMODE1,64,76,47,16 RADIOBUTTON "Extra + Preserve Sign",IDC_EE_CLAMPMODE2,111,76,91,16 RADIOBUTTON "Full",IDC_EE_CLAMPMODE3,202,76,38,16 - CONTROL " Software Emulate MUL",IDC_EE_CHECK3,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,20,123,116,13 LTEXT "These options specify how your CPU rounds floating point values.\n\nTry changing the roundmode for EE if your game hangs, it could make it work again.",IDC_STATIC,287,33,216,35 GROUPBOX "Round Mode",IDC_STATIC,281,22,235,51,BS_LEFT GROUPBOX "Clamp Mode",IDC_STATIC,281,80,236,127,BS_LEFT diff --git a/pcsx2/x86/BaseblockEx.cpp b/pcsx2/x86/BaseblockEx.cpp index 6a72251330..22a6765e60 100644 --- a/pcsx2/x86/BaseblockEx.cpp +++ b/pcsx2/x86/BaseblockEx.cpp @@ -19,7 +19,7 @@ #include "PrecompiledHeader.h" #include "BaseblockEx.h" -BASEBLOCKEX* BaseBlocks::New(u32 startpc) +BASEBLOCKEX* BaseBlocks::New(u32 startpc, uptr fnptr) { if (blocks.size() == size) return 0; @@ -28,6 +28,7 @@ BASEBLOCKEX* BaseBlocks::New(u32 startpc) std::vector::iterator iter; memset(&newblock, 0, sizeof newblock); newblock.startpc = startpc; + newblock.fnptr = fnptr; int imin = 0, imax = blocks.size(), imid; @@ -42,10 +43,15 @@ BASEBLOCKEX* BaseBlocks::New(u32 startpc) assert(imin == blocks.size() || blocks[imin].startpc > startpc); iter = blocks.insert(blocks.begin() + imin, newblock); + + std::pair range = links.equal_range(startpc); + for (linkiter_t i = range.first; i != range.second; ++i) + *(u32*)i->second = fnptr - (i->second + 4); + return &*iter; } -int BaseBlocks::Index(u32 startpc) const +int BaseBlocks::LastIndex(u32 startpc) const { if (0 == blocks.size()) return -1; @@ -61,9 +67,21 @@ int BaseBlocks::Index(u32 startpc) const imin = imid; } - if (startpc < blocks[imin].startpc || - startpc >= blocks[imin].startpc + blocks[imin].size*4) - return -1; - else - return imin; + return imin; } + +BASEBLOCKEX* BaseBlocks::GetByX86(uptr ip) const +{ + // TODO + return 0; +} + +void BaseBlocks::Link(u32 pc, uptr jumpptr) +{ + BASEBLOCKEX *targetblock = Get(pc); + if (targetblock && targetblock->startpc == pc) + *(u32*)jumpptr = targetblock->fnptr - (jumpptr + 4); + else + *(u32*)jumpptr = recompiler - (jumpptr + 4); + links.insert(std::pair(pc, jumpptr)); +} \ No newline at end of file diff --git a/pcsx2/x86/BaseblockEx.h b/pcsx2/x86/BaseblockEx.h index 7d94533af7..6d32ed0f05 100644 --- a/pcsx2/x86/BaseblockEx.h +++ b/pcsx2/x86/BaseblockEx.h @@ -20,6 +20,8 @@ #include "PrecompiledHeader.h" #include +#include +#include // used to keep block information #define BLOCKTYPE_DELAYSLOT 1 // if bit set, delay slot @@ -38,9 +40,10 @@ struct BASEBLOCK // extra block info (only valid for start of fn) struct BASEBLOCKEX { - u16 size; // size in dwords - u16 dummy; u32 startpc; + uptr fnptr; + u16 size; // size in dwords + u16 x86size; #ifdef PCSX2_DEVBUILD u32 visited; // number of times called @@ -53,18 +56,34 @@ class BaseBlocks { private: std::vector blocks; + // switch to a hash map later? + std::multimap links; + typedef std::multimap::iterator linkiter_t; unsigned long size; + uptr recompiler; public: - BaseBlocks(unsigned long max) : - size(max), + BaseBlocks(unsigned long size_, uptr recompiler_) : + size(size_), + recompiler(recompiler_), blocks(0) { blocks.reserve(size); } - BASEBLOCKEX* New(u32 startpc); - int Index (u32 startpc) const; + BASEBLOCKEX* New(u32 startpc, uptr fnptr); + int LastIndex (u32 startpc) const; + BASEBLOCKEX* GetByX86(uptr ip) const; + + inline int Index (u32 startpc) const + { + int idx = LastIndex(startpc); + if (idx == -1 || startpc < blocks[idx].startpc || + blocks[idx].size && (startpc >= blocks[idx].startpc + blocks[idx].size * 4)) + return -1; + else + return idx; + } inline BASEBLOCKEX* operator[](int idx) { @@ -80,12 +99,20 @@ public: inline void Remove(int idx) { + u32 startpc = blocks[idx].startpc; + std::pair range = links.equal_range(blocks[idx].startpc); + for (linkiter_t i = range.first; i != range.second; ++i) + *(u32*)i->second = recompiler - (i->second + 4); + // TODO: remove links from this block? blocks.erase(blocks.begin() + idx); } + void Link(u32 pc, uptr jumpptr); + inline void Reset() { blocks.clear(); + links.clear(); } }; diff --git a/pcsx2/x86/aR3000A.S b/pcsx2/x86/aR3000A.S index 9af67a3c52..90b755025e 100644 --- a/pcsx2/x86/aR3000A.S +++ b/pcsx2/x86/aR3000A.S @@ -18,11 +18,6 @@ .extern RECLUT .extern iopRecRecompile -#define BLOCKTYPE_STARTPC 4 // startpc offset -#define BLOCKTYPE_DELAYSLOT 1 // if bit set, delay slot - -#define BASEBLOCK_SIZE 2 // in dwords - ////////////////////////////////////////////////////////////////////////// // The address for all cleared blocks. It recompiles the current pc and then // dispatches to the recompiled block address. @@ -42,87 +37,6 @@ iopJITCompile: iopJITCompileInBlock: jmp iopJITCompile - -////////////////////////////////////////////////////////////////////////// -// Recompiles the next block, and links the old block directly to it. -// This is a on-shot execution for any block which uses it. Once the block -// has been statically linked to the new block, this function will be bypassed -// -// edx - jump address to modify -.globl iopDispatcher -iopDispatcher: - - # calc PC_GETBLOCK - # ((BASEBLOCK*)(reclut[((u32)(x)) >> 16] + (x)*(sizeof(BASEBLOCK)/4))) - - mov eax, dword ptr [REGINFO + PCOFFSET] - mov ebx, eax - shr eax, 16 - mov ecx, dword ptr [RECLUT+eax*4] - mov eax, dword ptr [ecx+ebx] - - cmp eax, offset iopJITCompile - je Dispatch_notcompiled - cmp eax, offset iopJITCompileInBlock - je Dispatch_notcompiled - lea ebx, [eax-4] - sub ebx, edx - mov dword ptr [edx], ebx - jmp eax - - .align 16 -Dispatch_notcompiled: - mov esi, edx - lea edi, [ecx+ebx] - push ebx - call iopRecRecompile - add esp, 4 - - mov eax, dword ptr [edi] - lea ebx, [eax-4] - sub ebx, esi - mov dword ptr [esi], ebx - jmp eax - - -////////////////////////////////////////////////////////////////////////// -// edx - baseblock->startpc -// stack - x86Ptr -.globl iopDispatcherClear -iopDispatcherClear: - mov [REGINFO + PCOFFSET], edx - - # calc PC_GETBLOCK - # ((BASEBLOCK*)(reclut[((u32)(x)) >> 16] + (x)*(sizeof(BASEBLOCK)/4))) - - mov ebx, edx - shr edx, 16 - mov ecx, dword ptr [RECLUT+edx*4] - mov eax, dword ptr [ecx+ebx] - - cmp eax, offset iopJITCompile - je Clear_notcompiled - cmp eax, offset iopJITCompileInBlock - je Clear_notcompiled - add esp, 4 - jmp eax - - .align 16 -Clear_notcompiled: - lea edi, [ecx+ebx] - push ebx - call iopRecRecompile - add esp, 4 - mov eax, dword ptr [edi] - - pop ecx - mov byte ptr [ecx], 0xe9 // jmp32 - lea ebx, [eax-5] - sub ebx, ecx - mov dword ptr [ecx+1], ebx - - jmp eax - ////////////////////////////////////////////////////////////////////////// // called when jumping to variable pc address. diff --git a/pcsx2/x86/iCOP0.cpp b/pcsx2/x86/iCOP0.cpp index e4885568cf..658df14948 100644 --- a/pcsx2/x86/iCOP0.cpp +++ b/pcsx2/x86/iCOP0.cpp @@ -165,8 +165,12 @@ void recMFC0( void ) break; case 1: + CALLFunc( (uptr)COP0_UpdatePCCR ); + MOV32MtoR(EAX, (uptr)&cpuRegs.PERF.n.pcr0); + break; case 3: CALLFunc( (uptr)COP0_UpdatePCCR ); + MOV32MtoR(EAX, (uptr)&cpuRegs.PERF.n.pcr1); break; } _deleteEEreg(_Rt_, 0); diff --git a/pcsx2/x86/iFPU.cpp b/pcsx2/x86/iFPU.cpp index fcfdc6a140..7e02e4877c 100644 --- a/pcsx2/x86/iFPU.cpp +++ b/pcsx2/x86/iFPU.cpp @@ -592,7 +592,7 @@ void FPU_SUB(int regd, int regt) { // FPU_MUL (Used to approximate PS2's FPU mul behavior) //------------------------------------------------------------------ // PS2's multiplication uses some modification (possibly not the one used in this function) -// of booth multiplication with wallace trees (not used in this function) +// of booth multiplication with wallace trees (not used in this function) // it cuts of some bits, resulting in inaccurate and non-commutative results. // This function attempts to replicate this. It is currently inaccurate. But still not too bad. //------------------------------------------------------------------ @@ -653,7 +653,7 @@ u32 __fastcall FPU_MUL_MANTISSA(u32 s, u32 t) void FPU_MUL(int regd, int regt) { - if (CHECK_FPU_ATTEMPT_MUL) + if (CHECK_FPUMULHACK) { SSE2_MOVD_XMM_to_R(ECX, regd); SSE2_MOVD_XMM_to_R(EDX, regt); diff --git a/pcsx2/x86/iFPUd.cpp b/pcsx2/x86/iFPUd.cpp index 12b887fbe0..7b9e0edb68 100644 --- a/pcsx2/x86/iFPUd.cpp +++ b/pcsx2/x86/iFPUd.cpp @@ -391,7 +391,7 @@ void FPU_ADD_SUB(int tempd, int tempt) //tempd and tempt are overwritten, they a void FPU_MUL(int info, int regd, int sreg, int treg, bool acc) { - if (CHECK_FPU_ATTEMPT_MUL) + if (CHECK_FPUMULHACK) { SSE2_MOVD_XMM_to_R(ECX, sreg); SSE2_MOVD_XMM_to_R(EDX, treg); diff --git a/pcsx2/x86/iR3000A.cpp b/pcsx2/x86/iR3000A.cpp index 4fa5df94cd..db7ede34c4 100644 --- a/pcsx2/x86/iR3000A.cpp +++ b/pcsx2/x86/iR3000A.cpp @@ -60,7 +60,8 @@ static u8 *recMem = NULL; // the recompiled blocks will be here static BASEBLOCK *recRAM = NULL; // and the ptr to the blocks here static BASEBLOCK *recROM = NULL; // and here static BASEBLOCK *recROM1 = NULL; // also here -static BaseBlocks recBlocks(PSX_NUMBLOCKS); +void iopJITCompile(); +static BaseBlocks recBlocks(PSX_NUMBLOCKS, (uptr)iopJITCompile); static u8 *recPtr = NULL; u32 psxpc; // recompiler psxpc int psxbranch; // set for branch @@ -74,8 +75,8 @@ static BASEBLOCKEX* s_pCurBlockEx = NULL; static u32 s_nEndBlock = 0; // what psxpc the current block ends -static u32 s_ConstGPRreg; -static u32 s_saveConstGPRreg = 0, s_saveHasConstReg = 0, s_saveFlushedConstReg = 0; +static u32 s_saveConstRegs[32]; +static u32 s_saveHasConstReg = 0, s_saveFlushedConstReg = 0; static EEINST* s_psaveInstInfo = NULL; u32 s_psxBlockCycles = 0; // cycles of current block recompiling @@ -334,7 +335,7 @@ void _psxFlushCall(int flushtype) void psxSaveBranchState() { s_savenBlockCycles = s_psxBlockCycles; - s_saveConstGPRreg = 0xffffffff; // indicate searching + memcpy(s_saveConstRegs, g_psxConstRegs, sizeof(g_psxConstRegs)); s_saveHasConstReg = g_psxHasConstReg; s_saveFlushedConstReg = g_psxFlushedConstReg; s_psaveInstInfo = g_pCurInstInfo; @@ -347,18 +348,7 @@ void psxLoadBranchState() { s_psxBlockCycles = s_savenBlockCycles; - if( s_saveConstGPRreg != 0xffffffff ) { - assert( s_saveConstGPRreg > 0 ); - - // make sure right GPR was saved - assert( g_psxHasConstReg == s_saveHasConstReg || (g_psxHasConstReg ^ s_saveHasConstReg) == (1<startpc >= upperextent) break; - pblock = PSX_GETBLOCK(pexblock->startpc); - x86Ptr[_EmitterId_] = (u8*)pblock->GetFnptr(); - - jASSUME((u8*)iopJITCompile != x86Ptr[_EmitterId_]); - // jASSUME((u8*)iopJITCompileInside != x86Ptr[_EmitterId_]); - - // This is breaking things currently, rather than figure it out - // I'm just using DispatcherReg, it's fast enough now. - // Actually, if we want to do this at all maybe keeping a hash - // table of const jumps and modifying the jumps straight from - // here is the way to go. -#if 1 - // there is a small problem: mem can be ored with 0xa<<28 or 0x8<<28, and don't know which - MOV32ItoR(EDX, pexblock->startpc); - assert((uptr)x86Ptr[_EmitterId_] <= 0xffffffff); - PUSH32I((uptr)x86Ptr[_EmitterId_]); // will be replaced by JMP32 - JMP32((uptr)iopDispatcherClear - ((uptr)x86Ptr[_EmitterId_] + 5)); -#else - MOV32ItoM((uptr)&psxRegs.pc, pexblock->startpc); - JMP32((uptr)iopDispatcherReg - ((uptr)x86Ptr[_EmitterId_] + 5)); -#endif - lowerextent = min(lowerextent, pexblock->startpc); upperextent = max(upperextent, pexblock->startpc + pexblock->size * 4); recBlocks.Remove(blockidx); @@ -907,9 +786,8 @@ void psxSetBranchImm( u32 imm ) _psxFlushCall(FLUSH_EVERYTHING); iPsxBranchTest(imm, imm <= psxpc); - MOV32ItoR(EDX, 0); - ptr = (u32*)(x86Ptr[0]-4); - *ptr = (uptr)JMP32((uptr)iopDispatcher - ( (uptr)x86Ptr[0] + 5 )); + ptr = JMP32(0); + recBlocks.Link(HWADDR(imm), (uptr)ptr); } //fixme : this is all a huge hack, we base the counter advancements on the average an opcode should take (wtf?) @@ -967,7 +845,7 @@ static void checkcodefn() #ifdef _MSC_VER __asm mov pctemp, eax; #else - __asm__("movl %%eax, %0" : : "m"(pctemp) ); + __asm__("movl %%eax, %[pctemp]" : : [pctemp]"m"(pctemp) ); #endif SysPrintf("iop code changed! %x\n", pctemp); } @@ -1018,24 +896,6 @@ void psxRecompileNextInstruction(int delayslot) BASEBLOCK* pblock = PSX_GETBLOCK(psxpc); - // need *ppblock != s_pCurBlock because of branches - if (HWADDR(psxpc) != s_pCurBlockEx->startpc - && pblock->GetFnptr() != (uptr)iopJITCompile - && pblock->GetFnptr() != (uptr)iopJITCompileInBlock ) - { - if(!delayslot) - { - // code already in place, so jump to it and exit recomp - assert( recBlocks.Get(HWADDR(psxpc))->startpc == HWADDR(psxpc) ); - - _psxFlushCall(FLUSH_EVERYTHING); - MOV32ItoM((uptr)&psxRegs.pc, psxpc); - JMP32((uptr)pblock->GetFnptr() - ((uptr)x86Ptr[0] + 5)); - psxbranch = 3; - return; - } - } - #ifdef _DEBUG MOV32ItoR(EAX, psxpc); #endif @@ -1130,7 +990,6 @@ void iopRecRecompile(u32 startpc) u32 i; u32 branchTo; u32 willbranch3 = 0; - u32* ptr; #ifdef _DEBUG if( psxdump & 4 ) @@ -1143,6 +1002,10 @@ void iopRecRecompile(u32 startpc) if (((uptr)recPtr - (uptr)recMem) >= (RECMEM_SIZE - 0x10000)) recResetIOP(); + x86SetPtr( recPtr ); + x86Align(16); + recPtr = x86Ptr[_EmitterId_]; + s_pCurBlock = PSX_GETBLOCK(startpc); assert(s_pCurBlock->GetFnptr() == (uptr)iopJITCompile @@ -1150,19 +1013,16 @@ void iopRecRecompile(u32 startpc) s_pCurBlockEx = recBlocks.Get(HWADDR(startpc)); if(!s_pCurBlockEx || s_pCurBlockEx->startpc != HWADDR(startpc)) { - s_pCurBlockEx = recBlocks.New(HWADDR(startpc)); + s_pCurBlockEx = recBlocks.New(HWADDR(startpc), (uptr)recPtr); if( s_pCurBlockEx == NULL ) { DevCon::WriteLn("IOP Recompiler data reset"); recResetIOP(); - s_pCurBlockEx = recBlocks.New(HWADDR(startpc)); + x86SetPtr( recPtr ); + s_pCurBlockEx = recBlocks.New(HWADDR(startpc), (uptr)recPtr); } } - x86SetPtr( recPtr ); - x86Align(16); - recPtr = x86Ptr[0]; - psxbranch = 0; s_pCurBlock->SetFnptr( (uptr)x86Ptr[0] ); @@ -1170,7 +1030,6 @@ void iopRecRecompile(u32 startpc) // reset recomp state variables psxpc = startpc; - s_saveConstGPRreg = 0; g_psxHasConstReg = g_psxFlushedConstReg = 1; _initX86regs(); @@ -1304,7 +1163,6 @@ StartRecomp: JMP32((uptr)iopDispatcherReg - ( (uptr)x86Ptr[0] + 5 )); } else { - assert( psxbranch != 3 ); if( psxbranch ) assert( !willbranch3 ); else { @@ -1312,42 +1170,27 @@ StartRecomp: SUB32ItoM((uptr)&psxCycleEE, psxScaleBlockCycles()*8 ); } - if( willbranch3 ) { - BASEBLOCK* pblock = PSX_GETBLOCK(s_nEndBlock); + if (willbranch3 || !psxbranch) { assert( psxpc == s_nEndBlock ); _psxFlushCall(FLUSH_EVERYTHING); - MOV32ItoM((uptr)&psxRegs.pc, psxpc); - JMP32((uptr)pblock->GetFnptr() - ((uptr)x86Ptr[0] + 5)); + MOV32ItoM((uptr)&psxRegs.pc, psxpc); + u32 *ptr = JMP32(0); + recBlocks.Link(HWADDR(s_nEndBlock), (uptr)ptr); psxbranch = 3; } - else if( !psxbranch ) { - // didn't branch, but had to stop - MOV32ItoM( (uptr)&psxRegs.pc, psxpc ); - - _psxFlushCall(FLUSH_EVERYTHING); - - ptr = JMP32(0); - //JMP32((uptr)psxDispatcherReg - ( (uptr)x86Ptr[0] + 5 )); - } } assert( x86Ptr[0] < recMem+RECMEM_SIZE ); + assert(x86Ptr[_EmitterId_] - recPtr < 0x10000); + s_pCurBlockEx->x86size = x86Ptr[_EmitterId_] - recPtr; + recPtr = x86Ptr[0]; assert( (g_psxHasConstReg&g_psxFlushedConstReg) == g_psxHasConstReg ); - if( !psxbranch ) { - assert( ptr != NULL ); - s_pCurBlock = PSX_GETBLOCK(psxpc); - - if (s_pCurBlock->GetFnptr() == (uptr)iopJITCompile - || s_pCurBlock->GetFnptr() == (uptr)iopJITCompileInBlock){ - iopRecRecompile(psxpc); - } - - *ptr = s_pCurBlock->GetFnptr() - ((u32)ptr + 4); - } + s_pCurBlock = NULL; + s_pCurBlockEx = NULL; } R3000Acpu psxRec = { diff --git a/pcsx2/x86/iR3000A.h b/pcsx2/x86/iR3000A.h index 7f19f1440d..ebf78ec3cb 100644 --- a/pcsx2/x86/iR3000A.h +++ b/pcsx2/x86/iR3000A.h @@ -58,8 +58,6 @@ void _psxMoveGPRtoR(x86IntRegType to, int fromgpr); void _psxMoveGPRtoM(u32 to, int fromgpr); void _psxMoveGPRtoRm(x86IntRegType to, int fromgpr); -void PSX_CHECK_SAVE_REG(int reg); - extern u32 psxpc; // recompiler pc extern int psxbranch; // set for branch extern u32 g_iopCyclePenalty; diff --git a/pcsx2/x86/iR5900.h b/pcsx2/x86/iR5900.h index ad102f4801..6624cd2342 100644 --- a/pcsx2/x86/iR5900.h +++ b/pcsx2/x86/iR5900.h @@ -58,8 +58,6 @@ extern u32 pc; // recompiler pc (also used by the SuperVU! .. why? (a extern int branch; // set for branch (also used by the SuperVU! .. why? (air)) extern u32 target; // branch target extern u32 s_nBlockCycles; // cycles of current block recompiling -extern u32 s_saveConstGPRreg; -extern GPR_reg64 s_ConstGPRreg; #define REC_FUNC( f ) \ void rec##f( void ) \ diff --git a/pcsx2/x86/iVUzerorec.cpp b/pcsx2/x86/iVUzerorec.cpp index 7cf66ef529..f4998b113e 100644 --- a/pcsx2/x86/iVUzerorec.cpp +++ b/pcsx2/x86/iVUzerorec.cpp @@ -3000,23 +3000,24 @@ void VuInstruction::Recompile(list::iterator& itinst, u32 vuxyz) if( type & INST_CLIP_WRITE ) { if( nParentPc < s_pCurBlock->startpc || nParentPc >= (int)pc ) { - if( !CHECK_VUCLIPFLAGHACK && pparentinst != NULL ) { - - if( pparentinst->pClipWrite == 0 ) { - pparentinst->pClipWrite = (uptr)SuperVUStaticAlloc(4); - } + if( pparentinst != NULL ) { if( nParentCheckForExecution >= 0 ) { + if( pparentinst->pClipWrite == 0 ) + pparentinst->pClipWrite = (uptr)SuperVUStaticAlloc(4); + if( s_ClipRead == 0 ) s_ClipRead = (uptr)&VU->VI[REG_CLIP_FLAG]; CMP32ItoM((uptr)&g_nLastBlockExecuted, nParentCheckForExecution); u8* jptr = JNE8(0); + CMP32ItoM((uptr)&s_ClipRead, (uptr)&VU->VI[REG_CLIP_FLAG]); + u8* jptr2 = JE8(0); MOV32MtoR(EAX, pparentinst->pClipWrite); MOV32RtoM(s_ClipRead, EAX); x86SetJ8(jptr); + x86SetJ8(jptr2); } - else s_ClipRead = (uptr)&VU->VI[REG_CLIP_FLAG]; } else s_ClipRead = (uptr)&VU->VI[REG_CLIP_FLAG]; } diff --git a/pcsx2/x86/ix86-32/aR5900-32.S b/pcsx2/x86/ix86-32/aR5900-32.S index 92fad3a2c2..457ad43fb2 100644 --- a/pcsx2/x86/ix86-32/aR5900-32.S +++ b/pcsx2/x86/ix86-32/aR5900-32.S @@ -18,11 +18,6 @@ .extern RECLUT .extern recRecompile -#define BLOCKTYPE_STARTPC 4 // startpc offset -#define BLOCKTYPE_DELAYSLOT 1 // if bit set, delay slot - -#define BASEBLOCK_SIZE 2 // in dwords - ////////////////////////////////////////////////////////////////////////// // The address for all cleared blocks. It recompiles the current pc and then // dispatches to the recompiled block address. @@ -41,87 +36,6 @@ JITCompile: .global JITCompileInBlock JITCompileInBlock: jmp JITCompile - -////////////////////////////////////////////////////////////////////////// -// Recompiles the next block, and links the old block directly to it. -// This is a on-shot execution for any block which uses it. Once the block -// has been statically linked to the new block, this function will be bypassed -// -// edx - jump address to modify -.globl Dispatcher -Dispatcher: - - # calc PC_GETBLOCK - # ((BASEBLOCK*)(reclut[((u32)(x)) >> 16] + (x)*(sizeof(BASEBLOCK)/4))) - - mov eax, dword ptr [REGINFO + PCOFFSET] - mov ebx, eax - shr eax, 16 - mov ecx, dword ptr [RECLUT+eax*4] - mov eax, dword ptr [ecx+ebx] - - cmp eax, offset JITCompile - je Dispatch_notcompiled - cmp eax, offset JITCompileInBlock - je Dispatch_notcompiled - lea ebx, [eax-4] - sub ebx, edx - mov dword ptr [edx], ebx - jmp eax - - .align 16 -Dispatch_notcompiled: - mov esi, edx - lea edi, [ecx+ebx] - push ebx - call recRecompile - add esp, 4 - - mov eax, dword ptr [edi] - lea ebx, [eax-4] - sub ebx, esi - mov dword ptr [esi], ebx - jmp eax - - -////////////////////////////////////////////////////////////////////////// -// edx - baseblock->startpc -// stack - x86Ptr -.globl DispatcherClear -DispatcherClear: - mov [REGINFO + PCOFFSET], edx - - # calc PC_GETBLOCK - # ((BASEBLOCK*)(reclut[((u32)(x)) >> 16] + (x)*(sizeof(BASEBLOCK)/4))) - - mov ebx, edx - shr edx, 16 - mov ecx, dword ptr [RECLUT+edx*4] - mov eax, dword ptr [ecx+ebx] - - cmp eax, offset JITCompile - je Clear_notcompiled - cmp eax, offset JITCompileInBlock - je Clear_notcompiled - add esp, 4 - jmp eax - - .align 16 -Clear_notcompiled: - lea edi, [ecx+ebx] - push ebx - call recRecompile - add esp, 4 - mov eax, dword ptr [edi] - - pop ecx - mov byte ptr [ecx], 0xe9 // jmp32 - lea ebx, [eax-5] - sub ebx, ecx - mov dword ptr [ecx+1], ebx - - jmp eax - ////////////////////////////////////////////////////////////////////////// // called when jumping to variable pc address. diff --git a/pcsx2/x86/ix86-32/iCore-32.cpp b/pcsx2/x86/ix86-32/iCore-32.cpp index 2a8411d4cf..d3557228e0 100644 --- a/pcsx2/x86/ix86-32/iCore-32.cpp +++ b/pcsx2/x86/ix86-32/iCore-32.cpp @@ -139,17 +139,63 @@ void _flushConstReg(int reg) void _flushConstRegs() { - int i; + int i, j; + int zero_cnt = 0, minusone_cnt = 0; + int eaxval = 1; // 0, -1 + unsigned long done[4] = {0, 0, 0, 0}; + u8* rewindPtr; // flush constants + // flush 0 and -1 first // ignore r0 - for(i = 1; i < 32; ++i) { - if( g_cpuHasConstReg & (1< 0) + XOR32RtoR(EAX, EAX), eaxval = 0; +#else + if (eaxval > 0) + MOV32ItoR(EAX, -1), eaxval = -1; +#endif + if (eaxval == 0) + NOT32R(EAX), eaxval = -1; + MOV32RtoM((uptr)&cpuRegs.GPR.r[i].SL[j], EAX); + done[j + 2] |= 1<> 16] + mem)) - return recClearMem(mem); - else - return 4; -} - -void recClear( u32 Addr, u32 Size ) -{ - u32 pc = Addr; - while (pc < Addr + Size*4) - pc += REC_CLEARM(pc); -} - // Clears the recLUT table so that all blocks are mapped to the JIT recompiler by default. static void ClearRecLUT(BASEBLOCK* base, int count) { @@ -906,7 +819,7 @@ static void ClearRecLUT(BASEBLOCK* base, int count) } // Returns the offset to the next instruction after any cleared memory -u32 recClearMem(u32 pc) +void recClear(u32 addr, u32 size) { BASEBLOCKEX* pexblock; BASEBLOCK* pblock; @@ -928,61 +841,61 @@ u32 recClearMem(u32 pc) #endif #endif - pblock = PC_GETBLOCK(pc); - if (pblock->GetFnptr() == (uptr)JITCompile) - return 4; + if ((addr) >= maxrecmem || !(recLUT[(addr) >> 16] + (addr & ~0xFFFFUL))) + return; + addr = HWADDR(addr); - pc = HWADDR(pc); + int blockidx = recBlocks.LastIndex(addr + size * 4 - 4); - u32 lowerextent = pc, upperextent = pc + 4; - int blockidx = recBlocks.Index(pc); + if (blockidx == -1) + return; - jASSUME(blockidx != -1); + u32 lowerextent = (u32)-1, upperextent = 0, ceiling = (u32)-1; - while (pexblock = recBlocks[blockidx - 1]) { - if (pexblock->startpc + pexblock->size*4 <= lowerextent) - break; - - lowerextent = min(lowerextent, pexblock->startpc); - blockidx--; - } + pexblock = recBlocks[blockidx + 1]; + if (pexblock) + ceiling = pexblock->startpc; while (pexblock = recBlocks[blockidx]) { - if (pexblock->startpc >= upperextent) + u32 blockstart = pexblock->startpc; + u32 blockend = pexblock->startpc + pexblock->size * 4; + pblock = PC_GETBLOCK(blockstart); + + if (pblock == s_pCurBlock) { + blockidx--; + continue; + } + + if (blockend <= addr) { + lowerextent = max(lowerextent, blockend); break; + } - pblock = PC_GETBLOCK(pexblock->startpc); - x86Ptr[_EmitterId_] = (u8*)pblock->GetFnptr(); - - jASSUME((u8*)JITCompile != x86Ptr[_EmitterId_]); - jASSUME((u8*)JITCompileInBlock != x86Ptr[_EmitterId_]); - - // Actually, if we want to do this at all maybe keeping a hash - // table of const jumps and modifying the jumps straight from - // here is the way to go. - - // there is a small problem: mem can be ored with 0xa<<28 or 0x8<<28, and don't know which - MOV32ItoR(EDX, pexblock->startpc); - assert((uptr)x86Ptr[_EmitterId_] <= 0xffffffff); - PUSH32I((uptr)x86Ptr[_EmitterId_]); // will be replaced by JMP32 - JMP32((uptr)DispatcherClear - ((uptr)x86Ptr[_EmitterId_] + 5)); - - lowerextent = min(lowerextent, pexblock->startpc); - upperextent = max(upperextent, pexblock->startpc + pexblock->size * 4); - recBlocks.Remove(blockidx); + lowerextent = min(lowerextent, blockstart); + upperextent = max(upperextent, blockend); + // This might end up inside a block that doesn't contain the clearing range, + // so set it to recompile now. This will become JITCompile if we clear it. + pblock->SetFnptr((uptr)JITCompileInBlock); + recBlocks.Remove(blockidx--); } + upperextent = min(upperextent, ceiling); + #ifdef PCSX2_DEVBUILD - for (int i = 0; pexblock = recBlocks[i]; i++) - if (pc >= pexblock->startpc && pc < pexblock->startpc + pexblock->size * 4) { + for (int i = 0; pexblock = recBlocks[i]; i++) { + if (s_pCurBlock == PC_GETBLOCK(pexblock->startpc)) + continue; + u32 blockend = pexblock->startpc + pexblock->size * 4; + if (pexblock->startpc >= addr && pexblock->startpc < addr + size * 4 + || pexblock->startpc < addr && blockend > addr) { Console::Error("Impossible block clearing failure"); jASSUME(0); } + } #endif - ClearRecLUT(PC_GETBLOCK(lowerextent), (upperextent - lowerextent) / 4); - - return upperextent - pc; + if (upperextent > lowerextent) + ClearRecLUT(PC_GETBLOCK(lowerextent), (upperextent - lowerextent) / 4); } // check for end of bios @@ -1055,7 +968,7 @@ void SetBranchReg( u32 reg ) iFlushCall(FLUSH_EVERYTHING); - iBranchTest(0xffffffff); + iBranchTest(); } void SetBranchImm( u32 imm ) @@ -1065,9 +978,7 @@ void SetBranchImm( u32 imm ) assert( imm ); // end the current block - MOV32ItoM( (uptr)&cpuRegs.pc, imm ); iFlushCall(FLUSH_EVERYTHING); - iBranchTest(imm); } @@ -1076,7 +987,7 @@ void SaveBranchState() s_savex86FpuState = x86FpuState; s_saveiCWstate = iCWstate; s_savenBlockCycles = s_nBlockCycles; - s_saveConstGPRreg = 0xffffffff; // indicate searching + memcpy(s_saveConstRegs, g_cpuConstRegs, sizeof(g_cpuConstRegs)); s_saveHasConstReg = g_cpuHasConstReg; s_saveFlushedConstReg = g_cpuFlushedConstReg; s_psaveInstInfo = g_pCurInstInfo; @@ -1094,19 +1005,7 @@ void LoadBranchState() iCWstate = s_saveiCWstate; s_nBlockCycles = s_savenBlockCycles; - if( s_saveConstGPRreg != 0xffffffff ) { - assert( s_saveConstGPRreg > 0 ); - - // make sure right GPR was saved - assert( g_cpuHasConstReg == s_saveHasConstReg || (g_cpuHasConstReg ^ s_saveHasConstReg) == (1<> (3+2); } +static void iBranch(u32 newpc, int type) +{ + u32* ptr; + + MOV32ItoM((uptr)&cpuRegs.pc, newpc); + if (type == 0) + ptr = JMP32(0); + else if (type == 1) + ptr = JS32(0); + + recBlocks.Link(HWADDR(newpc), (uptr)ptr); +} + // Generates dynarec code for Event tests followed by a block dispatch (branch). // Parameters: // newpc - address to jump to at the end of the block. If newpc == 0xffffffff then @@ -1224,41 +1136,23 @@ static void iBranchTest(u32 newpc, bool noDispatch) #ifdef _DEBUG //CALLFunc((uptr)testfpu); #endif - u32* ptr; if( bExecBIOS ) CheckForBIOSEnd(); - MOV32MtoR(EAX, (uptr)&cpuRegs.cycle); - if( !noDispatch && newpc != 0xffffffff ) - { - // Optimization note: Instructions order to pair EDX with EAX's load above. - - // Load EDX with the address of the JS32 jump below. - // We do this because the the Dispatcher will use this info to modify - // the JS instruction later on with the address of the block it's jumping - // to; creating a static link of blocks that doesn't require the overhead - // of a dispatcher. - MOV32ItoR(EDX, 0); - ptr = (u32*)(x86Ptr[0]-4); - } - // Check the Event scheduler if our "cycle target" has been reached. // Equiv code to: // cpuRegs.cycle += blockcycles; // if( cpuRegs.cycle > g_nextBranchCycle ) { DoEvents(); } + MOV32MtoR(EAX, (uptr)&cpuRegs.cycle); ADD32ItoR(EAX, eeScaleBlockCycles()); MOV32RtoM((uptr)&cpuRegs.cycle, EAX); // update cycles SUB32MtoR(EAX, (uptr)&g_nextBranchCycle); - if( newpc != 0xffffffff ) - { - // This is the jump instruction which gets modified by Dispatcher. - *ptr = (u32)JS32((u32)Dispatcher - ( (u32)x86Ptr[0] + 6 )); - } - else if( !noDispatch ) - { - // This instruction is a dynamic link, so it's never modified. - JS32((uptr)DispatcherReg - ( (uptr)x86Ptr[0] + 6 )); + if (!noDispatch) { + if (newpc == 0xffffffff) + JS32((uptr)DispatcherReg - ( (uptr)x86Ptr[0] + 6 )); + else + iBranch(newpc, 1); } RET(); @@ -1271,7 +1165,7 @@ static void checkcodefn() #ifdef _MSC_VER __asm mov pctemp, eax; #else - __asm__("movl %%eax, %0" : "=m"(pctemp) ); + __asm__("movl %%eax, %[pctemp]" : [pctemp]"=m"(pctemp) ); #endif Console::Error("code changed! %x", params pctemp); @@ -1283,54 +1177,39 @@ void recompileNextInstruction(int delayslot) static u8 s_bFlushReg = 1; int i, count; - BASEBLOCK* pblock = PC_GETBLOCK(pc); - - // need *ppblock != s_pCurBlock because of branches - if (HWADDR(pc) != s_pCurBlockEx->startpc && pblock->GetFnptr() != (uptr)JITCompile && pblock->GetFnptr() != (uptr)JITCompileInBlock) - { - if (!delayslot) - { - // code already in place, so jump to it and exit recomp - assert( recBlocks.Get(HWADDR(pc))->startpc == HWADDR(pc) ); - - iFlushCall(FLUSH_EVERYTHING); - MOV32ItoM((uptr)&cpuRegs.pc, pc); - JMP32((uptr)pblock->GetFnptr() - ((uptr)x86Ptr[0] + 5)); - branch = 3; - return; - } - } - s_pCode = (int *)PSM( pc ); assert(s_pCode); + // why? #ifdef _DEBUG MOV32ItoR(EAX, pc); #endif cpuRegs.code = *(int *)s_pCode; pc += 4; - -//#ifdef _DEBUG -// CMP32ItoM((u32)s_pCode, cpuRegs.code); -// j8Ptr[0] = JE8(0); -// MOV32ItoR(EAX, pc); -// CALLFunc((uptr)checkcodefn); -// x86SetJ8( j8Ptr[ 0 ] ); -// -// if( !delayslot ) { -// CMP32ItoM((u32)&cpuRegs.pc, s_pCurBlockEx->startpc); -// j8Ptr[0] = JB8(0); -// CMP32ItoM((u32)&cpuRegs.pc, pc); -// j8Ptr[1] = JA8(0); -// j8Ptr[2] = JMP8(0); -// x86SetJ8( j8Ptr[ 0 ] ); -// x86SetJ8( j8Ptr[ 1 ] ); -// PUSH32I(s_pCurBlockEx->startpc); -// ADD32ItoR(ESP, 4); -// x86SetJ8( j8Ptr[ 2 ] ); -// } -//#endif + +#if 0 +#ifdef _DEBUG + CMP32ItoM((u32)s_pCode, cpuRegs.code); + j8Ptr[0] = JE8(0); + MOV32ItoR(EAX, pc); + CALLFunc((uptr)checkcodefn); + x86SetJ8( j8Ptr[ 0 ] ); + + if( !delayslot ) { + CMP32ItoM((u32)&cpuRegs.pc, s_pCurBlockEx->startpc); + j8Ptr[0] = JB8(0); + CMP32ItoM((u32)&cpuRegs.pc, pc); + j8Ptr[1] = JA8(0); + j8Ptr[2] = JMP8(0); + x86SetJ8( j8Ptr[ 0 ] ); + x86SetJ8( j8Ptr[ 1 ] ); + PUSH32I(s_pCurBlockEx->startpc); + ADD32ItoR(ESP, 4); + x86SetJ8( j8Ptr[ 2 ] ); + } +#endif +#endif g_pCurInstInfo++; @@ -1476,13 +1355,12 @@ void recRecompile( const u32 startpc ) u32 i = 0; u32 branchTo; u32 willbranch3 = 0; - u32* ptr; u32 usecop2; #ifdef _DEBUG //dumplog |= 4; if( dumplog & 4 ) - iDumpRegisters(startpc, 0); + iDumpRegisters(startpc, 0); #endif assert( startpc ); @@ -1497,29 +1375,29 @@ void recRecompile( const u32 startpc ) recResetEE(); } + x86SetPtr( recPtr ); + x86Align(16); + recPtr = x86Ptr[_EmitterId_]; + s_pCurBlock = PC_GETBLOCK(startpc); assert(s_pCurBlock->GetFnptr() == (uptr)JITCompile || s_pCurBlock->GetFnptr() == (uptr)JITCompileInBlock); s_pCurBlockEx = recBlocks.Get(HWADDR(startpc)); - if (!s_pCurBlockEx || s_pCurBlockEx->startpc != HWADDR(startpc)) { - s_pCurBlockEx = recBlocks.New(HWADDR(startpc)); + assert(!s_pCurBlockEx || s_pCurBlockEx->startpc != HWADDR(startpc)); - if( s_pCurBlockEx == NULL ) { - //SysPrintf("ee reset (blocks)\n"); - recResetEE(); - s_pCurBlockEx = recBlocks.New(HWADDR(startpc)); - } + s_pCurBlockEx = recBlocks.New(HWADDR(startpc), (uptr)recPtr); + + if( s_pCurBlockEx == NULL ) { + //SysPrintf("ee reset (blocks)\n"); + recResetEE(); + x86SetPtr( recPtr ); + s_pCurBlockEx = recBlocks.New(HWADDR(startpc), (uptr)recPtr); } assert(s_pCurBlockEx); - x86SetPtr( recPtr ); - x86Align(16); - recPtr = x86Ptr[0]; - s_pCurBlock->SetFnptr( (uptr)x86Ptr[0] ); - branch = 0; // reset recomp state variables @@ -1527,7 +1405,6 @@ void recRecompile( const u32 startpc ) pc = startpc; x86FpuState = FPU_STATE; iCWstate = 0; - s_saveConstGPRreg = 0; g_cpuHasConstReg = g_cpuFlushedConstReg = 1; g_cpuPrevRegHasLive1 = g_cpuRegHasLive1 = 0xffffffff; g_cpuPrevRegHasSignExt = g_cpuRegHasSignExt = 0; @@ -1815,40 +1692,25 @@ StartRecomp: #endif u32 sz=(s_nEndBlock-startpc)>>2; -#ifdef lulz - /* - Block checking (ADDED BY RAZ-TEMP) - */ - - MOV32ItoR(ECX,startpc); - MOV32ItoR(EDX,sz); -#endif - - u32 inpage_offs=startpc&0xFFF; u32 inpage_ptr=startpc; u32 inpage_sz=sz*4; - MOV32ItoR(ECX,startpc); - MOV32ItoR(EDX,sz); - while(inpage_sz) { - int PageType=mmap_GetRamPageInfo((u32*)PSM(inpage_ptr)); - u32 pgsz=std::min(0x1000-inpage_offs,inpage_sz); + int PageType = mmap_GetRamPageInfo((u32*)PSM(inpage_ptr)); + u32 inpage_offs = inpage_ptr & 0xFFF; + u32 pgsz = std::min(0x1000 - inpage_offs, inpage_sz); if(PageType!=-1) { if (PageType==0) - { - //MOV32ItoR(EAX,*pageVer); - //CMP32MtoR(EAX,(uptr)pageVer); - //JNE32(((u32)dyna_block_discard_recmem)- ( (u32)x86Ptr[0] + 6 )); - mmap_MarkCountedRamPage(PSM(inpage_ptr),inpage_ptr&~0xFFF); - } else { + MOV32ItoR(ECX, startpc); + MOV32ItoR(EDX, sz); + u32 lpc=inpage_ptr; u32 stg=pgsz; while(stg>0) @@ -1866,7 +1728,6 @@ StartRecomp: } inpage_ptr+=pgsz; inpage_sz-=pgsz; - inpage_offs=inpage_ptr&0xFFF; } // finally recompile // @@ -1883,6 +1744,32 @@ StartRecomp: assert( (pc-startpc)>>2 <= 0xffff ); s_pCurBlockEx->size = (pc-startpc)>>2; + if (HWADDR(pc) <= Ps2MemSize::Base) { + BASEBLOCKEX *oldBlock; + int i; + + i = recBlocks.LastIndex(HWADDR(pc) - 4); + while (oldBlock = recBlocks[i--]) { + if (oldBlock == s_pCurBlockEx) + continue; + if (oldBlock->startpc >= HWADDR(pc)) + continue; + if (oldBlock->startpc + oldBlock->size * 4 <= HWADDR(startpc)) + break; + if (memcmp(&recRAMCopy[oldBlock->startpc / 4], PSM(oldBlock->startpc), + oldBlock->size * 4)) { + recClear(startpc, (pc - startpc) / 4); + s_pCurBlockEx = recBlocks.Get(HWADDR(startpc)); + assert(s_pCurBlockEx->startpc == HWADDR(startpc)); + break; + } + } + + memcpy(&recRAMCopy[HWADDR(startpc) / 4], PSM(startpc), pc - startpc); + } + + s_pCurBlock->SetFnptr((uptr)recPtr); + for(i = 1; i < (u32)s_pCurBlockEx->size; i++) { if ((uptr)JITCompile == s_pCurBlock[i].GetFnptr()) s_pCurBlock[i].SetFnptr((uptr)JITCompileInBlock); @@ -1910,21 +1797,9 @@ StartRecomp: else ADD32ItoM((int)&cpuRegs.cycle, eeScaleBlockCycles() ); - if( willbranch3 ) { - BASEBLOCK* pblock = PC_GETBLOCK(s_nEndBlock); - assert( pc == s_nEndBlock ); + if( willbranch3 || !branch) { iFlushCall(FLUSH_EVERYTHING); - MOV32ItoM((uptr)&cpuRegs.pc, pc); - JMP32((uptr)pblock->GetFnptr() - ((uptr)x86Ptr[0] + 5)); - branch = 3; - } - else if( !branch ) { - // didn't branch, but had to stop - MOV32ItoM( (uptr)&cpuRegs.pc, pc ); - - iFlushCall(FLUSH_EVERYTHING); - - ptr = JMP32(0); + iBranch(pc, 0); } } @@ -1932,20 +1807,15 @@ StartRecomp: assert( recStackPtr < recStack+RECSTACK_SIZE ); assert( x86FpuState == 0 ); + assert(x86Ptr[_EmitterId_] - recPtr < 0x10000); + s_pCurBlockEx->x86size = x86Ptr[_EmitterId_] - recPtr; + recPtr = x86Ptr[0]; assert( (g_cpuHasConstReg&g_cpuFlushedConstReg) == g_cpuHasConstReg ); - if( !branch ) { - assert( ptr != NULL ); - s_pCurBlock = PC_GETBLOCK(pc); - - if (s_pCurBlock->GetFnptr() == (uptr)JITCompile - || s_pCurBlock->GetFnptr() == (uptr)JITCompileInBlock) - recRecompile(pc); - - *ptr = s_pCurBlock->GetFnptr() - ((u32)ptr + 4); - } + s_pCurBlock = NULL; + s_pCurBlockEx = NULL; } R5900cpu recCpu = { diff --git a/pcsx2/x86/ix86-32/iR5900LoadStore.cpp b/pcsx2/x86/ix86-32/iR5900LoadStore.cpp index 01ffb2198b..e3e3664a5a 100644 --- a/pcsx2/x86/ix86-32/iR5900LoadStore.cpp +++ b/pcsx2/x86/ix86-32/iR5900LoadStore.cpp @@ -2077,13 +2077,6 @@ void recLoad64( u32 bits, bool sign ) //no int 3? i love to get my hands dirty ;p - Raz //write8(0xCC); - _deleteEEreg(_Rs_, 1); - _eeOnLoadWrite(_Rt_); - - EEINST_RESETSIGNEXT(_Rt_); // remove the sign extension - - _deleteEEreg(_Rt_, 0); - // Load EDX with the destination. // 64/128 bit modes load the result directly into the cpuRegs.GPR struct. @@ -2092,16 +2085,23 @@ void recLoad64( u32 bits, bool sign ) else MOV32ItoR(EDX, (uptr)&dummyValue[0] ); - if( IS_EECONSTREG( _Rs_ ) ) + if( GPR_IS_CONST1( _Rs_ ) ) { + _eeOnLoadWrite(_Rt_); + EEINST_RESETSIGNEXT(_Rt_); // remove the sign extension + _deleteEEreg(_Rt_, 0); u32 srcadr = g_cpuConstRegs[_Rs_].UL[0] + _Imm_; if( bits == 128 ) srcadr &= ~0x0f; vtlb_DynGenRead64_Const( bits, srcadr ); } else { + _deleteEEreg(_Rs_, 1); // Load ECX with the source memory address that we're reading from. MOV32MtoR( ECX, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + _eeOnLoadWrite(_Rt_); + EEINST_RESETSIGNEXT(_Rt_); // remove the sign extension + _deleteEEreg(_Rt_, 0); if ( _Imm_ != 0 ) ADD32ItoR( ECX, _Imm_ ); @@ -2119,21 +2119,23 @@ void recLoad32(u32 bits,bool sign) //no int 3? i love to get my hands dirty ;p - Raz //write8(0xCC); - _deleteEEreg(_Rs_, 1); - _eeOnLoadWrite(_Rt_); - _deleteEEreg(_Rt_, 0); - // 8/16/32 bit modes return the loaded value in EAX. - if( IS_EECONSTREG( _Rs_ ) ) + if( GPR_IS_CONST1( _Rs_ ) ) { + _eeOnLoadWrite(_Rt_); + _deleteEEreg(_Rt_, 0); + u32 srcadr = g_cpuConstRegs[_Rs_].UL[0] + _Imm_; vtlb_DynGenRead32_Const( bits, sign, srcadr ); } else { + _deleteEEreg(_Rs_, 1); // Load ECX with the source memory address that we're reading from. MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + _eeOnLoadWrite(_Rt_); + _deleteEEreg(_Rt_, 0); if ( _Imm_ != 0 ) ADD32ItoR( ECX, _Imm_ ); @@ -2463,7 +2465,6 @@ void recStore(u32 sz) //no int 3? i love to get my hands dirty ;p - Raz //write8(0xCC); - _deleteEEreg(_Rs_, 1); _deleteEEreg(_Rt_, 1); // Performance note: Const prop for the store address is good, always. @@ -2498,6 +2499,7 @@ void recStore(u32 sz) } else { + _deleteEEreg(_Rs_, 1); MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); if ( _Imm_ != 0 ) ADD32ItoR(ECX, _Imm_); diff --git a/pcsx2/x86/ix86-32/iR5900Move.cpp b/pcsx2/x86/ix86-32/iR5900Move.cpp index 8554f58eee..20ec6ade16 100644 --- a/pcsx2/x86/ix86-32/iR5900Move.cpp +++ b/pcsx2/x86/ix86-32/iR5900Move.cpp @@ -425,13 +425,7 @@ void recMTLO1( void ) //// MOVZ void recMOVZtemp_const() { - GPR_DEL_CONST(_Rd_); - _deleteEEreg(_Rd_, 1); - _eeOnWriteReg(_Rd_, 0); - if (g_cpuConstRegs[_Rt_].UD[0] == 0) { - MOV32ItoM((uptr)&cpuRegs.GPR.r[_Rd_].UL[0], g_cpuConstRegs[_Rs_].UL[0]); - MOV32ItoM((uptr)&cpuRegs.GPR.r[_Rd_].UL[1], g_cpuConstRegs[_Rs_].UL[1]); - } + g_cpuConstRegs[_Rd_].UD[0] = g_cpuConstRegs[_Rs_].UD[0]; } //static PCSX2_ALIGNED16(u32 s_zero[4]) = {0,0,0xffffffff, 0xffffffff}; @@ -475,24 +469,22 @@ void recMOVZtemp_consts(int info) void recMOVZtemp_constt(int info) { - if (g_cpuConstRegs[_Rt_].UD[0] == 0) { - if( info & PROCESS_EE_MMX ) { - if( EEREC_D != EEREC_S ) MOVQRtoR(EEREC_D, EEREC_S); - return; - } - - if( _hasFreeXMMreg() ) { - int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); - MOVQMtoR(t0reg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); - MOVQRtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], t0reg); - _freeMMXreg(t0reg); - } - else { - MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); - MOV32MtoR(EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ]); - MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX); - MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX); - } + if( info & PROCESS_EE_MMX ) { + if( EEREC_D != EEREC_S ) MOVQRtoR(EEREC_D, EEREC_S); + return; + } + + if( _hasFreeXMMreg() ) { + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQMtoR(t0reg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + MOVQRtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], t0reg); + _freeMMXreg(t0reg); + } + else { + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + MOV32MtoR(EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ]); + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX); + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX); } } @@ -546,22 +538,11 @@ void recMOVZ() if( _Rs_ == _Rd_ ) return; - if( GPR_IS_CONST1(_Rd_) ) { - - if( !GPR_IS_CONST2(_Rs_, _Rt_) ) { - // remove the const, since move is conditional - _deleteEEreg(_Rd_, 0); - MOV32ItoM((uptr)&cpuRegs.GPR.r[_Rd_].UL[0], g_cpuConstRegs[_Rd_].UL[0]); - MOV32ItoM((uptr)&cpuRegs.GPR.r[_Rd_].UL[1], g_cpuConstRegs[_Rd_].UL[1]); - } - else { - if (g_cpuConstRegs[_Rt_].UD[0] == 0) { - g_cpuConstRegs[_Rd_].UL[0] = g_cpuConstRegs[_Rs_].UL[0]; - g_cpuConstRegs[_Rd_].UL[1] = g_cpuConstRegs[_Rs_].UL[1]; - } + if(GPR_IS_CONST1(_Rt_)) { + if (g_cpuConstRegs[_Rt_].UD[0] != 0) return; - } - } + } else if (GPR_IS_CONST1(_Rd_)) + _deleteEEreg(_Rd_, 1); recMOVZtemp(); } @@ -569,13 +550,7 @@ void recMOVZ() //// MOVN void recMOVNtemp_const() { - GPR_DEL_CONST(_Rd_); - _deleteEEreg(_Rd_, 1); - _eeOnWriteReg(_Rd_, 0); - if (g_cpuConstRegs[_Rt_].UD[0] != 0) { - MOV32ItoM((uptr)&cpuRegs.GPR.r[_Rd_].UL[0], g_cpuConstRegs[_Rs_].UL[0]); - MOV32ItoM((uptr)&cpuRegs.GPR.r[_Rd_].UL[1], g_cpuConstRegs[_Rs_].UL[1]); - } + g_cpuConstRegs[_Rd_].UD[0] = g_cpuConstRegs[_Rs_].UD[0]; } void recMOVNtemp_consts(int info) @@ -618,19 +593,17 @@ void recMOVNtemp_consts(int info) void recMOVNtemp_constt(int info) { - if (g_cpuConstRegs[_Rt_].UD[0] != 0) { - if( _hasFreeXMMreg() ) { - int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); - MOVQMtoR(t0reg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); - MOVQRtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], t0reg); - _freeMMXreg(t0reg); - } - else { - MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); - MOV32MtoR(EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ]); - MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX); - MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX); - } + if( _hasFreeXMMreg() ) { + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQMtoR(t0reg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + MOVQRtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], t0reg); + _freeMMXreg(t0reg); + } + else { + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + MOV32MtoR(EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ]); + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX); + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX); } } @@ -685,22 +658,11 @@ void recMOVN() if( _Rs_ == _Rd_ ) return; - if( GPR_IS_CONST1(_Rd_) ) { - - if( !GPR_IS_CONST2(_Rs_, _Rt_) ) { - // remove the const, since move is conditional - _deleteEEreg(_Rd_, 0); - MOV32ItoM((uptr)&cpuRegs.GPR.r[_Rd_].UL[0], g_cpuConstRegs[_Rd_].UL[0]); - MOV32ItoM((uptr)&cpuRegs.GPR.r[_Rd_].UL[1], g_cpuConstRegs[_Rd_].UL[1]); - } - else { - if (g_cpuConstRegs[_Rt_].UD[0] != 0) { - g_cpuConstRegs[_Rd_].UL[0] = g_cpuConstRegs[_Rs_].UL[0]; - g_cpuConstRegs[_Rd_].UL[1] = g_cpuConstRegs[_Rs_].UL[1]; - } + if (GPR_IS_CONST1(_Rt_)) { + if (g_cpuConstRegs[_Rt_].UD[0] == 0) return; - } - } + } else if (GPR_IS_CONST1(_Rd_)) + _deleteEEreg(_Rd_, 1); recMOVNtemp(); } diff --git a/pcsx2/x86/ix86-32/iR5900Templates.cpp b/pcsx2/x86/ix86-32/iR5900Templates.cpp index f4db1133ae..2149848dfc 100644 --- a/pcsx2/x86/ix86-32/iR5900Templates.cpp +++ b/pcsx2/x86/ix86-32/iR5900Templates.cpp @@ -38,19 +38,6 @@ // Code Templates // //////////////////// -void CHECK_SAVE_REG(int reg) -{ - if( s_saveConstGPRreg == 0xffffffff ) { - if( GPR_IS_CONST1(reg) ) { - s_saveConstGPRreg = reg; - s_ConstGPRreg = g_cpuConstRegs[reg]; - } - } - else { - assert( s_saveConstGPRreg == 0 || s_saveConstGPRreg == reg ); - } -} - void _eeProcessHasLive(int reg, int signext) { g_cpuPrevRegHasLive1 = g_cpuRegHasLive1; @@ -68,7 +55,6 @@ void _eeProcessHasLive(int reg, int signext) void _eeOnWriteReg(int reg, int signext) { - CHECK_SAVE_REG(reg); GPR_DEL_CONST(reg); _eeProcessHasLive(reg, signext); } @@ -109,7 +95,6 @@ void eeRecompileCode0(R5900FNPTR constcode, R5900FNPTR_INFO constscode, R5900FNP if ( ! _Rd_ && (xmminfo&XMMINFO_WRITED) ) return; if( xmminfo&XMMINFO_WRITED) { - CHECK_SAVE_REG(_Rd_); _eeProcessHasLive(_Rd_, 0); EEINST_RESETSIGNEXT(_Rd_); } @@ -421,7 +406,6 @@ void eeRecompileCode1(R5900FNPTR constcode, R5900FNPTR_INFO noconstcode) int mmreg1, mmreg2; if ( ! _Rt_ ) return; - CHECK_SAVE_REG(_Rt_); _eeProcessHasLive(_Rt_, 0); EEINST_RESETSIGNEXT(_Rt_); @@ -522,7 +506,6 @@ void eeRecompileCode2(R5900FNPTR constcode, R5900FNPTR_INFO noconstcode) int mmreg1, mmreg2; if ( ! _Rd_ ) return; - CHECK_SAVE_REG(_Rd_); _eeProcessHasLive(_Rd_, 0); EEINST_RESETSIGNEXT(_Rd_); @@ -651,7 +634,6 @@ void eeRecompileCodeConst0(R5900FNPTR constcode, R5900FNPTR_INFO constscode, R59 if ( ! _Rd_ ) return; // for now, don't support xmm - CHECK_SAVE_REG(_Rd_); _deleteGPRtoXMMreg(_Rs_, 1); _deleteGPRtoXMMreg(_Rt_, 1); @@ -689,7 +671,6 @@ void eeRecompileCodeConst1(R5900FNPTR constcode, R5900FNPTR_INFO noconstcode) return; // for now, don't support xmm - CHECK_SAVE_REG(_Rt_); _deleteGPRtoXMMreg(_Rs_, 1); _deleteGPRtoXMMreg(_Rt_, 0); @@ -710,7 +691,6 @@ void eeRecompileCodeConst2(R5900FNPTR constcode, R5900FNPTR_INFO noconstcode) if ( ! _Rd_ ) return; // for now, don't support xmm - CHECK_SAVE_REG(_Rd_); _deleteGPRtoXMMreg(_Rt_, 1); _deleteGPRtoXMMreg(_Rd_, 0); @@ -731,7 +711,6 @@ void eeRecompileCodeConstSPECIAL(R5900FNPTR constcode, R5900FNPTR_INFO multicode assert(0); // for now, don't support xmm if( MULT ) { - CHECK_SAVE_REG(_Rd_); _deleteGPRtoXMMreg(_Rd_, 0); } @@ -767,7 +746,6 @@ int eeRecompileCodeXMM(int xmminfo) // save state if( xmminfo & XMMINFO_WRITED ) { - CHECK_SAVE_REG(_Rd_); _eeProcessHasLive(_Rd_, 0); EEINST_RESETSIGNEXT(_Rd_); } diff --git a/pcsx2/x86/ix86-32/recVTLB.cpp b/pcsx2/x86/ix86-32/recVTLB.cpp index 05889e7ce3..90047888b2 100644 --- a/pcsx2/x86/ix86-32/recVTLB.cpp +++ b/pcsx2/x86/ix86-32/recVTLB.cpp @@ -173,7 +173,7 @@ static void _vtlb_DynGen_IndirectRead( u32 bits ) MOVZX32R8toR(EAX,EAX); SUB32RtoR(ECX,EAX); //eax=[funct+eax] - MOV32RmSOffsettoR(EAX,EAX,(int)RWFT[szidx][0],2); + MOV32RmSOffsettoR(EAX,EAX,(int)vtlbdata.RWFT[szidx][0],2); SUB32ItoR(ECX,0x80000000); CALL32R(EAX); } @@ -187,7 +187,7 @@ void vtlb_DynGenRead64(u32 bits) MOV32RtoR(EAX,ECX); SHR32ItoR(EAX,VTLB_PAGE_BITS); - MOV32RmSOffsettoR(EAX,EAX,(int)vmap,2); + MOV32RmSOffsettoR(EAX,EAX,(int)vtlbdata.vmap,2); ADD32RtoR(ECX,EAX); u8* _fullread = JS8(0); @@ -209,7 +209,7 @@ void vtlb_DynGenRead32(u32 bits, bool sign) MOV32RtoR(EAX,ECX); SHR32ItoR(EAX,VTLB_PAGE_BITS); - MOV32RmSOffsettoR(EAX,EAX,(int)vmap,2); + MOV32RmSOffsettoR(EAX,EAX,(int)vtlbdata.vmap,2); ADD32RtoR(ECX,EAX); u8* _fullread = JS8(0); @@ -243,7 +243,7 @@ void vtlb_DynGenRead64_Const( u32 bits, u32 addr_const ) { jASSUME( bits == 64 || bits == 128 ); - void* vmv_ptr = &vmap[addr_const>>VTLB_PAGE_BITS]; + void* vmv_ptr = &vtlbdata.vmap[addr_const>>VTLB_PAGE_BITS]; MOV32MtoR(EAX,(uptr)vmv_ptr); MOV32ItoR(ECX,addr_const); @@ -266,7 +266,7 @@ void vtlb_DynGenRead32_Const( u32 bits, bool sign, u32 addr_const ) { jASSUME( bits <= 32 ); - void* vmv_ptr = &vmap[addr_const>>VTLB_PAGE_BITS]; + void* vmv_ptr = &vtlbdata.vmap[addr_const>>VTLB_PAGE_BITS]; MOV32MtoR(EAX,(uptr)vmv_ptr); MOV32ItoR(ECX,addr_const); @@ -368,7 +368,7 @@ static void _vtlb_DynGen_IndirectWrite( u32 bits ) MOVZX32R8toR(EAX,EAX); SUB32RtoR(ECX,EAX); //eax=[funct+eax] - MOV32RmSOffsettoR(EAX,EAX,(int)RWFT[szidx][1],2); + MOV32RmSOffsettoR(EAX,EAX,(int)vtlbdata.RWFT[szidx][1],2); SUB32ItoR(ECX,0x80000000); CALL32R(EAX); } @@ -377,7 +377,7 @@ void vtlb_DynGenWrite(u32 sz) { MOV32RtoR(EAX,ECX); SHR32ItoR(EAX,VTLB_PAGE_BITS); - MOV32RmSOffsettoR(EAX,EAX,(int)vmap,2); + MOV32RmSOffsettoR(EAX,EAX,(int)vtlbdata.vmap,2); ADD32RtoR(ECX,EAX); u8* _full=JS8(0); @@ -398,7 +398,7 @@ void vtlb_DynGenWrite_Const( u32 bits, u32 addr_const ) // the VTLB could feasibly be remapped by other recompiled code at any time. // So we're limited in exactly how much we can pre-calcuate. - void* vmv_ptr = &vmap[addr_const>>VTLB_PAGE_BITS]; + void* vmv_ptr = &vtlbdata.vmap[addr_const>>VTLB_PAGE_BITS]; MOV32MtoR(EAX,(uptr)vmv_ptr); MOV32ItoR(ECX,addr_const); diff --git a/pcsx2/x86/ix86/ix86.inl b/pcsx2/x86/ix86/ix86.inl index 15068f4823..606eaed417 100644 --- a/pcsx2/x86/ix86/ix86.inl +++ b/pcsx2/x86/ix86/ix86.inl @@ -41,7 +41,7 @@ emitterT void WriteRmOffset(x86IntRegType to, s32 offset) ModRM( 0, 0, 4 ); SibSB( 0, ESP, 4 ); } - else if( offset < 128 && offset >= -128 ) { + else if( offset <= 127 && offset >= -128 ) { ModRM( 1, 0, 4 ); SibSB( 0, ESP, 4 ); write8(offset); @@ -56,7 +56,7 @@ emitterT void WriteRmOffset(x86IntRegType to, s32 offset) if( offset == 0 ) { ModRM( 0, 0, to ); } - else if( offset < 128 && offset >= -128 ) { + else if( offset <= 127 && offset >= -128 ) { ModRM( 1, 0, to ); write8(offset); } @@ -74,7 +74,7 @@ emitterT void WriteRmOffsetFrom(x86IntRegType to, x86IntRegType from, int offset ModRM( 0, to, 0x4 ); SibSB( 0, 0x4, 0x4 ); } - else if( offset < 128 && offset >= -128 ) { + else if( offset <= 127 && offset >= -128 ) { ModRM( 1, to, 0x4 ); SibSB( 0, 0x4, 0x4 ); write8(offset); @@ -89,7 +89,7 @@ emitterT void WriteRmOffsetFrom(x86IntRegType to, x86IntRegType from, int offset if( offset == 0 ) { ModRM( 0, to, from ); } - else if( offset < 128 && offset >= -128 ) { + else if( offset <= 127 && offset >= -128 ) { ModRM( 1, to, from ); write8(offset); } @@ -401,8 +401,12 @@ emitterT void eMOV32RtoR( x86IntRegType to, x86IntRegType from ) emitterT void eMOV32RtoM( uptr to, x86IntRegType from ) { RexR(0, from); - write8( 0x89 ); - ModRM( 0, from, DISP32 ); + if (from == EAX) { + write8(0xA3); + } else { + write8( 0x89 ); + ModRM( 0, from, DISP32 ); + } write32( MEMADDR(to, 4) ); } @@ -410,8 +414,12 @@ emitterT void eMOV32RtoM( uptr to, x86IntRegType from ) emitterT void eMOV32MtoR( x86IntRegType to, uptr from ) { RexR(0, to); - write8( 0x8B ); - ModRM( 0, to, DISP32 ); + if (to == EAX) { + write8(0xA1); + } else { + write8( 0x8B ); + ModRM( 0, to, DISP32 ); + } write32( MEMADDR(from, 4) ); } @@ -1038,69 +1046,69 @@ emitterT void eADD64RtoR( x86IntRegType to, x86IntRegType from ) } /* add imm32 to EAX */ -emitterT void eADD32ItoEAX( u32 from ) +emitterT void eADD32ItoEAX( s32 imm ) { write8( 0x05 ); - write32( from ); + write32( imm ); } /* add imm32 to r32 */ -emitterT void eADD32ItoR( x86IntRegType to, u32 from ) +emitterT void eADD32ItoR( x86IntRegType to, s32 imm ) { RexB(0, to); - if(from < 0x80) + if (imm <= 127 && imm >= -128) { write8( 0x83 ); ModRM( 3, 0, to ); - write8( from ); + write8( (s8)imm ); } else { if ( to == EAX ) { - eADD32ItoEAX(from); + eADD32ItoEAX(imm); } else { write8( 0x81 ); ModRM( 3, 0, to ); - write32( from ); + write32( imm ); } } } /* add imm32 to m32 */ -emitterT void eADD32ItoM( uptr to, u32 from ) +emitterT void eADD32ItoM( uptr to, s32 imm ) { - /*if(from < 0x80) // crashes games in 64bit build; TODO: figure out why. + if(imm <= 127 && imm >= -128) { write8( 0x83 ); ModRM( 0, 0, DISP32 ); write32( MEMADDR(to, 8) ); - write8( from ); - } - else*/ + write8( imm ); + } + else { write8( 0x81 ); ModRM( 0, 0, DISP32 ); write32( MEMADDR(to, 8) ); - write32( from ); + write32( imm ); } } // add imm32 to [r32+off] -emitterT void eADD32ItoRmOffset( x86IntRegType to, u32 from, s32 offset) +emitterT void eADD32ItoRmOffset( x86IntRegType to, s32 imm, s32 offset) { RexB(0,to); - if(from < 0x80) + if(imm <= 127 && imm >= -128) { write8( 0x83 ); WriteRmOffset(to,offset); - write8(from); + write8(imm); } else { write8( 0x81 ); WriteRmOffset(to,offset); - write32(from); + write32(imm); } } @@ -1140,7 +1148,7 @@ emitterT void eADD16RtoR( x86IntRegType to , x86IntRegType from ) } /* add imm16 to r16 */ -emitterT void eADD16ItoR( x86IntRegType to, u16 from ) +emitterT void eADD16ItoR( x86IntRegType to, s16 imm ) { write8( 0x66 ); RexB(0,to); @@ -1148,39 +1156,39 @@ emitterT void eADD16ItoR( x86IntRegType to, u16 from ) if ( to == EAX) { write8( 0x05 ); - write16( from ); + write16( imm ); } - else if(from < 0x80) + else if(imm <= 127 && imm >= -128) { write8( 0x83 ); ModRM( 3, 0, to ); - write8((u8)from ); + write8((u8)imm ); } else { write8( 0x81 ); ModRM( 3, 0, to ); - write16( from ); + write16( imm ); } } /* add imm16 to m16 */ -emitterT void eADD16ItoM( uptr to, u16 from ) +emitterT void eADD16ItoM( uptr to, s16 imm ) { write8( 0x66 ); - if(from < 0x80) + if(imm <= 127 && imm >= -128) { write8( 0x83 ); ModRM( 0, 0, DISP32 ); write32( MEMADDR(to, 6) ); - write8((u8)from ); + write8((u8)imm ); } else { write8( 0x81 ); ModRM( 0, 0, DISP32 ); write32( MEMADDR(to, 6) ); - write16( from ); + write16( imm ); } } @@ -3250,7 +3258,7 @@ emitterT void eLEA16RtoR(x86IntRegType to, x86IntRegType from, u16 offset) eLEA32RtoR(to, from, offset); } -emitterT void eLEA32RtoR(x86IntRegType to, x86IntRegType from, u32 offset) +emitterT void eLEA32RtoR(x86IntRegType to, x86IntRegType from, s32 offset) { RexRB(0,to,from); write8(0x8d); @@ -3260,7 +3268,7 @@ emitterT void eLEA32RtoR(x86IntRegType to, x86IntRegType from, u32 offset) ModRM(1, to, from); write8(0x24); } - else if( offset < 128 ) { + else if( offset <= 127 && offset >= -128 ) { ModRM(1, to, from); write8(0x24); write8(offset); @@ -3275,7 +3283,7 @@ emitterT void eLEA32RtoR(x86IntRegType to, x86IntRegType from, u32 offset) if( offset == 0 && from != EBP && from!=ESP ) { ModRM(0, to, from); } - else if( offset < 128 ) { + else if( offset <= 127 && offset >= -128 ) { ModRM(1, to, from); write8(offset); } diff --git a/pcsx2/x86/ix86/ix86_cpudetect.cpp b/pcsx2/x86/ix86/ix86_cpudetect.cpp index 6c0d91838e..bf88feeb32 100644 --- a/pcsx2/x86/ix86/ix86_cpudetect.cpp +++ b/pcsx2/x86/ix86/ix86_cpudetect.cpp @@ -115,7 +115,7 @@ extern s32 iCpuId( u32 cmd, u32 *regs ) "pushf\n" "pop %%eax\n" "xor %%edx, %%eax\n" - "mov %%eax, %0\n" + "mov %%eax, %[flag]\n" "add $0x18, %%esp\n" "cmpl $0x0,%%eax\n" "jne 1f\n" @@ -123,7 +123,7 @@ extern s32 iCpuId( u32 cmd, u32 *regs ) "leave\n" "ret\n" "1:\n" - : "=r"(flag) : + : [flag]"=r"(flag) : ); cpuid(cmd, regs[0], regs[1], regs[2], regs[3]); diff --git a/pcsx2/x86/ix86/ix86_tools.cpp b/pcsx2/x86/ix86/ix86_tools.cpp index 1ea1f9eaa9..5ef532ffcd 100644 --- a/pcsx2/x86/ix86/ix86_tools.cpp +++ b/pcsx2/x86/ix86/ix86_tools.cpp @@ -61,7 +61,7 @@ void SetCPUState(u32 sseMXCSR, u32 sseVUMXCSR) #ifdef _MSC_VER __asm ldmxcsr g_sseMXCSR; // set the new sse control #else - __asm__("ldmxcsr %0" : : "m"(g_sseMXCSR) ); + __asm__("ldmxcsr %[g_sseMXCSR]" : : [g_sseMXCSR]"m"(g_sseMXCSR) ); #endif //g_sseVUMXCSR = g_sseMXCSR|0x6000; } @@ -108,16 +108,16 @@ __forceinline void FreezeMMXRegs_(int save) #else __asm__( ".intel_syntax noprefix\n" - "movq [%0+0x00], mm0\n" - "movq [%0+0x08], mm1\n" - "movq [%0+0x10], mm2\n" - "movq [%0+0x18], mm3\n" - "movq [%0+0x20], mm4\n" - "movq [%0+0x28], mm5\n" - "movq [%0+0x30], mm6\n" - "movq [%0+0x38], mm7\n" + "movq [%[g_globalMMXData]+0x00], mm0\n" + "movq [%[g_globalMMXData]+0x08], mm1\n" + "movq [%[g_globalMMXData]+0x10], mm2\n" + "movq [%[g_globalMMXData]+0x18], mm3\n" + "movq [%[g_globalMMXData]+0x20], mm4\n" + "movq [%[g_globalMMXData]+0x28], mm5\n" + "movq [%[g_globalMMXData]+0x30], mm6\n" + "movq [%[g_globalMMXData]+0x38], mm7\n" "emms\n" - ".att_syntax\n" : : "r"(g_globalMMXData) + ".att_syntax\n" : : [g_globalMMXData]"r"(g_globalMMXData) ); #endif @@ -148,16 +148,16 @@ __forceinline void FreezeMMXRegs_(int save) #else __asm__( ".intel_syntax noprefix\n" - "movq mm0, [%0+0x00]\n" - "movq mm1, [%0+0x08]\n" - "movq mm2, [%0+0x10]\n" - "movq mm3, [%0+0x18]\n" - "movq mm4, [%0+0x20]\n" - "movq mm5, [%0+0x28]\n" - "movq mm6, [%0+0x30]\n" - "movq mm7, [%0+0x38]\n" + "movq mm0, [%[g_globalMMXData]+0x00]\n" + "movq mm1, [%[g_globalMMXData]+0x08]\n" + "movq mm2, [%[g_globalMMXData]+0x10]\n" + "movq mm3, [%[g_globalMMXData]+0x18]\n" + "movq mm4, [%[g_globalMMXData]+0x20]\n" + "movq mm5, [%[g_globalMMXData]+0x28]\n" + "movq mm6, [%[g_globalMMXData]+0x30]\n" + "movq mm7, [%[g_globalMMXData]+0x38]\n" "emms\n" - ".att_syntax\n" : : "r"(g_globalMMXData) + ".att_syntax\n" : : [g_globalMMXData]"r"(g_globalMMXData) ); #endif } @@ -195,15 +195,15 @@ __forceinline void FreezeXMMRegs_(int save) #else __asm__( ".intel_syntax noprefix\n" - "movaps [%0+0x00], xmm0\n" - "movaps [%0+0x10], xmm1\n" - "movaps [%0+0x20], xmm2\n" - "movaps [%0+0x30], xmm3\n" - "movaps [%0+0x40], xmm4\n" - "movaps [%0+0x50], xmm5\n" - "movaps [%0+0x60], xmm6\n" - "movaps [%0+0x70], xmm7\n" - ".att_syntax\n" : : "r"(g_globalXMMData) + "movaps [%[g_globalXMMData]+0x00], xmm0\n" + "movaps [%[g_globalXMMData]+0x10], xmm1\n" + "movaps [%[g_globalXMMData]+0x20], xmm2\n" + "movaps [%[g_globalXMMData]+0x30], xmm3\n" + "movaps [%[g_globalXMMData]+0x40], xmm4\n" + "movaps [%[g_globalXMMData]+0x50], xmm5\n" + "movaps [%[g_globalXMMData]+0x60], xmm6\n" + "movaps [%[g_globalXMMData]+0x70], xmm7\n" + ".att_syntax\n" : : [g_globalXMMData]"r"(g_globalXMMData) ); #endif // _MSC_VER @@ -237,15 +237,15 @@ __forceinline void FreezeXMMRegs_(int save) #else __asm__( ".intel_syntax noprefix\n" - "movaps xmm0, [%0+0x00]\n" - "movaps xmm1, [%0+0x10]\n" - "movaps xmm2, [%0+0x20]\n" - "movaps xmm3, [%0+0x30]\n" - "movaps xmm4, [%0+0x40]\n" - "movaps xmm5, [%0+0x50]\n" - "movaps xmm6, [%0+0x60]\n" - "movaps xmm7, [%0+0x70]\n" - ".att_syntax\n" : : "r"(g_globalXMMData) + "movaps xmm0, [%[g_globalXMMData]+0x00]\n" + "movaps xmm1, [%[g_globalXMMData]+0x10]\n" + "movaps xmm2, [%[g_globalXMMData]+0x20]\n" + "movaps xmm3, [%[g_globalXMMData]+0x30]\n" + "movaps xmm4, [%[g_globalXMMData]+0x40]\n" + "movaps xmm5, [%[g_globalXMMData]+0x50]\n" + "movaps xmm6, [%[g_globalXMMData]+0x60]\n" + "movaps xmm7, [%[g_globalXMMData]+0x70]\n" + ".att_syntax\n" : : [g_globalXMMData]"r"(g_globalXMMData) ); #endif // _MSC_VER diff --git a/pcsx2/x86/microVU.cpp b/pcsx2/x86/microVU.cpp index 2ce53e7a8c..cd96ba9259 100644 --- a/pcsx2/x86/microVU.cpp +++ b/pcsx2/x86/microVU.cpp @@ -29,42 +29,12 @@ PCSX2_ALIGNED16(microVU microVU0); PCSX2_ALIGNED16(microVU microVU1); -PCSX2_ALIGNED16(const u32 mVU_absclip[4]) = {0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff}; -PCSX2_ALIGNED16(const u32 mVU_signbit[4]) = {0x80000000, 0x80000000, 0x80000000, 0x80000000}; -PCSX2_ALIGNED16(const u32 mVU_minvals[4]) = {0xff7fffff, 0xff7fffff, 0xff7fffff, 0xff7fffff}; -PCSX2_ALIGNED16(const u32 mVU_maxvals[4]) = {0x7f7fffff, 0x7f7fffff, 0x7f7fffff, 0x7f7fffff}; -PCSX2_ALIGNED16(const u32 mVU_one[4]) = {0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000}; -PCSX2_ALIGNED16(const u32 mVU_T1[4]) = {0x3f7ffff5, 0x3f7ffff5, 0x3f7ffff5, 0x3f7ffff5}; -PCSX2_ALIGNED16(const u32 mVU_T2[4]) = {0xbeaaa61c, 0xbeaaa61c, 0xbeaaa61c, 0xbeaaa61c}; -PCSX2_ALIGNED16(const u32 mVU_T3[4]) = {0x3e4c40a6, 0x3e4c40a6, 0x3e4c40a6, 0x3e4c40a6}; -PCSX2_ALIGNED16(const u32 mVU_T4[4]) = {0xbe0e6c63, 0xbe0e6c63, 0xbe0e6c63, 0xbe0e6c63}; -PCSX2_ALIGNED16(const u32 mVU_T5[4]) = {0x3dc577df, 0x3dc577df, 0x3dc577df, 0x3dc577df}; -PCSX2_ALIGNED16(const u32 mVU_T6[4]) = {0xbd6501c4, 0xbd6501c4, 0xbd6501c4, 0xbd6501c4}; -PCSX2_ALIGNED16(const u32 mVU_T7[4]) = {0x3cb31652, 0x3cb31652, 0x3cb31652, 0x3cb31652}; -PCSX2_ALIGNED16(const u32 mVU_T8[4]) = {0xbb84d7e7, 0xbb84d7e7, 0xbb84d7e7, 0xbb84d7e7}; -PCSX2_ALIGNED16(const u32 mVU_Pi4[4]) = {0x3f490fdb, 0x3f490fdb, 0x3f490fdb, 0x3f490fdb}; -PCSX2_ALIGNED16(const u32 mVU_S2[4]) = {0xbe2aaaa4, 0xbe2aaaa4, 0xbe2aaaa4, 0xbe2aaaa4}; -PCSX2_ALIGNED16(const u32 mVU_S3[4]) = {0x3c08873e, 0x3c08873e, 0x3c08873e, 0x3c08873e}; -PCSX2_ALIGNED16(const u32 mVU_S4[4]) = {0xb94fb21f, 0xb94fb21f, 0xb94fb21f, 0xb94fb21f}; -PCSX2_ALIGNED16(const u32 mVU_S5[4]) = {0x362e9c14, 0x362e9c14, 0x362e9c14, 0x362e9c14}; -PCSX2_ALIGNED16(const u32 mVU_E1[4]) = {0x3e7fffa8, 0x3e7fffa8, 0x3e7fffa8, 0x3e7fffa8}; -PCSX2_ALIGNED16(const u32 mVU_E2[4]) = {0x3d0007f4, 0x3d0007f4, 0x3d0007f4, 0x3d0007f4}; -PCSX2_ALIGNED16(const u32 mVU_E3[4]) = {0x3b29d3ff, 0x3b29d3ff, 0x3b29d3ff, 0x3b29d3ff}; -PCSX2_ALIGNED16(const u32 mVU_E4[4]) = {0x3933e553, 0x3933e553, 0x3933e553, 0x3933e553}; -PCSX2_ALIGNED16(const u32 mVU_E5[4]) = {0x36b63510, 0x36b63510, 0x36b63510, 0x36b63510}; -PCSX2_ALIGNED16(const u32 mVU_E6[4]) = {0x353961ac, 0x353961ac, 0x353961ac, 0x353961ac}; -PCSX2_ALIGNED16(const float mVU_FTOI_4[4]) = {16.0, 16.0, 16.0, 16.0}; -PCSX2_ALIGNED16(const float mVU_FTOI_12[4]) = {4096.0, 4096.0, 4096.0, 4096.0}; -PCSX2_ALIGNED16(const float mVU_FTOI_15[4]) = {32768.0, 32768.0, 32768.0, 32768.0}; -PCSX2_ALIGNED16(const float mVU_ITOF_4[4]) = {0.0625f, 0.0625f, 0.0625f, 0.0625f}; -PCSX2_ALIGNED16(const float mVU_ITOF_12[4]) = {0.000244140625, 0.000244140625, 0.000244140625, 0.000244140625}; -PCSX2_ALIGNED16(const float mVU_ITOF_15[4]) = {0.000030517578125, 0.000030517578125, 0.000030517578125, 0.000030517578125}; - +declareAllVariables // Declares All Global Variables :D //------------------------------------------------------------------ // Micro VU - Main Functions //------------------------------------------------------------------ -// Only run this once! ;) +// Only run this once per VU! ;) microVUt(void) mVUinit(VURegs* vuRegsPtr) { microVU* mVU = mVUx; @@ -86,7 +56,7 @@ microVUt(void) mVUreset() { // Create Block Managers for (int i; i <= mVU->prog.max; i++) { - for (u32 j; j < mVU->progSize; j++) { + for (u32 j; j < (mVU->progSize / 2); j++) { mVU->prog.prog[i].block[j] = new microBlockManager(); } } @@ -112,7 +82,7 @@ microVUt(void) mVUclose() { // Delete Block Managers for (int i; i <= mVU->prog.max; i++) { - for (u32 j; j < mVU->progSize; j++) { + for (u32 j; j < (mVU->progSize / 2); j++) { if (mVU->prog.prog[i].block[j]) delete mVU->prog.prog[i].block[j]; } } @@ -142,8 +112,8 @@ microVUt(void*) __fastcall mVUexecute(u32 startPC, u32 cycles) { */ microVU* mVU = mVUx; if ( mVUsearchProg(mVU) ) { // Found Program - microBlock* block = mVU->prog.prog[mVU->prog.cur].block[startPC]->search(mVU->prog.lastPipelineState); - if (block) return block->x86ptrStart; // Found Block + //microBlock* block = mVU->prog.prog[mVU->prog.cur].block[startPC]->search(mVU->prog.lastPipelineState); + //if (block) return block->x86ptrStart; // Found Block } // Recompile code return NULL; @@ -163,7 +133,7 @@ void* __fastcall mVUexecuteVU1(u32 startPC, u32 cycles) { // Clears program data (Sets used to 1 because calling this function implies the program will be used at least once) __forceinline void mVUclearProg(microVU* mVU, int progIndex) { mVU->prog.prog[progIndex].used = 1; - for (u32 i = 0; i < mVU->progSize; i++) { + for (u32 i = 0; i < (mVU->progSize / 2); i++) { mVU->prog.prog[progIndex].block[i]->reset(); } } diff --git a/pcsx2/x86/microVU.h b/pcsx2/x86/microVU.h index dcae7f4377..d755d28b61 100644 --- a/pcsx2/x86/microVU.h +++ b/pcsx2/x86/microVU.h @@ -17,18 +17,21 @@ */ #pragma once +#define mVUdebug // Prints Extra Info to Console #define _EmitterId_ (vuIndex+1) #include "Common.h" #include "VU.h" +#include "GS.h" #include "ix86/ix86.h" #include "microVU_Alloc.h" struct microBlock { - u32 pipelineState; // FMACx|y|z|w | FDiv | EFU | IALU | BRANCH // Still thinking of how I'm going to do this - u8* x86ptrStart; - u8* x86ptrEnd; - u8* x86ptrBranch; - //u32 size; + microRegInfo pState; // Detailed State of Pipeline + u32 pipelineState; // | FDiv x 4 | EFU x 6 | Needs pState Info? x 1 | // Simple State of Pipeline + u8* x86ptrStart; // Start of code + u8* x86ptrEnd; // End of code (first byte outside of block) + u8* x86ptrBranch; // + u32 size; // Number of 64bit VU Instructions in Block }; #define mMaxBlocks 32 // Max Blocks With Different Pipeline States (For n = 1, 2, 4, 8, 16, etc...) @@ -53,17 +56,24 @@ public: } void reset() { init(); }; void close() {}; // Can be Omitted? - void add(u32 pipelineState, u8* x86ptrStart) { + /*void add(u32 pipelineState, u8* x86ptrStart) { if (!search(pipelineState)) { listSize++; listSize &= MaxBlocks; blockList[listSize].pipelineState = pipelineState; blockList[listSize].x86ptrStart = x86ptrStart; } - } - microBlock* search(u32 pipelineState) { - for (int i = 0; i < listSize; i++) { - if (blockList[i].pipelineState == pipelineState) return &blockList[i]; + }*/ + microBlock* search(u32 pipelineState, microRegInfo* pState) { + if (pipelineState & 1) { // Needs Detailed Search (Exact Match of Pipeline State) + for (int i = 0; i < listSize; i++) { + if (!memcmp(pState, &blockList[i].pState, sizeof(microRegInfo))) return &blockList[i]; + } + } + else { // Can do Simple Search (Only Matches the Important Pipeline Stuff) + for (int i = 0; i < listSize; i++) { + if (blockList[i].pipelineState == pipelineState) return &blockList[i]; + } } return NULL; } @@ -81,9 +91,9 @@ public: template struct microProgram { - u8 data[progSize]; + u32 data[progSize]; u32 used; // Number of times its been used - microBlockManager* block[progSize]; + microBlockManager* block[progSize / 2]; microAllocInfo allocInfo; }; @@ -104,15 +114,16 @@ struct microVU { u32 microSize; // VU Micro Memory Size u32 progSize; // VU Micro Program Size (microSize/8) u32 cacheAddr; // VU Cache Start Address - static const u32 cacheSize = 0x400000; // VU Cache Size + static const u32 cacheSize = 0x500000; // VU Cache Size - microProgManager<0x800> prog; // Micro Program Data + microProgManager<0x1000> prog; // Micro Program Data - VURegs* regs; // VU Regs Struct - u8* cache; // Dynarec Cache Start (where we will start writing the recompiled code to) - u8* ptr; // Pointer to next place to write recompiled code to - u32 code; // Contains the current Instruction - u32 iReg; // iReg + VURegs* regs; // VU Regs Struct + u8* cache; // Dynarec Cache Start (where we will start writing the recompiled code to) + u8* ptr; // Pointer to next place to write recompiled code to + u32 code; // Contains the current Instruction + u32 iReg; // iReg (only used in recompilation, not execution) + u32 clipFlag[4]; // 4 instances of clip flag (used in execution) /* uptr x86eax; // Accumulator register. Used in arithmetic operations. @@ -147,3 +158,4 @@ microVUt(void) mVUclose(); #include "microVU_Misc.h" #include "microVU_Alloc.inl" #include "microVU_Tables.inl" +#include "microVU_Compile.inl" diff --git a/pcsx2/x86/microVU_Alloc.h b/pcsx2/x86/microVU_Alloc.h index 51ce87b21d..81e1ce9fa0 100644 --- a/pcsx2/x86/microVU_Alloc.h +++ b/pcsx2/x86/microVU_Alloc.h @@ -28,8 +28,7 @@ union regInfo { }; }; -template -struct microAllocInfo { +struct microRegInfo { regInfo VF[32]; regInfo Acc; u8 VI[32]; @@ -37,22 +36,34 @@ struct microAllocInfo { u8 q; u8 p; u8 r; - u16 info[pSize];// bit 0 = NOP? - // bit 1 = Used with bit 2 to make a 2-bit key for ACC write instance - // bit 2 = (00 = instance #0, 01 = instance #1, 10 = instance #2, 11 = instance #3) - // bit 3 = Used with bit 4 to make a 2-bit key for ACC read instance - // bit 4 = (00 = instance #0, 01 = instance #1, 10 = instance #2, 11 = instance #3) - // bit 5 = Write to Q1 or Q2? - // bit 6 = Read Q1 or Q2? - // bit 7 = Read/Write to P1 or P2? - // bit 8 = Update Mac Flags? - // bit 9 = Update Status Flags? - // bit 10 = Used with bit 11 to make a 2-bit key for mac flag instance - // bit 11 = (00 = instance #0, 01 = instance #1, 10 = instance #2, 11 = instance #3) - // bit 12 = Used with bit 13 to make a 2-bit key for status flag instance - // bit 13 = (00 = instance #0, 01 = instance #1, 10 = instance #2, 11 = instance #3) - // bit 14 = Read VI(Fs) from backup memory? - // bit 15 = Read VI(Ft) from backup memory? - u32 curPC; }; +template +struct microAllocInfo { + microRegInfo regs; + u8 branch; // 0 = No Branch, 1 = Branch, 2 = Conditional Branch, 3 = Jump (JALR/JR) + u32 curPC; // Current PC + u32 cycles; // Cycles for current block + u32 info[pSize];// bit 00 = Lower Instruction is NOP + // bit 01 + // bit 02 + // bit 03 + // bit 04 + // bit 05 = Write to Q1 or Q2? + // bit 06 = Read Q1 or Q2? + // bit 07 = Read/Write to P1 or P2? + // bit 08 = Update Mac Flags? + // bit 09 = Update Status Flags? + // bit 10 = Used with bit 11 to make a 2-bit key for mac flag instance + // bit 11 + // bit 12 = Used with bit 13 to make a 2-bit key for status flag instance + // bit 13 + // bit 14 = Used with bit 15 to make a 2-bit key for clip flag instance + // bit 15 + // bit 16 = Used with bit 17 to make a 2-bit key for mac flag instance + // bit 17 + // bit 18 = Used with bit 19 to make a 2-bit key for status flag instance + // bit 19 + // bit 20 = Read VI(Fs) from backup memory? + // bit 21 = Read VI(Ft) from backup memory? +}; diff --git a/pcsx2/x86/microVU_Alloc.inl b/pcsx2/x86/microVU_Alloc.inl index ccea38603b..ccd8a9221c 100644 --- a/pcsx2/x86/microVU_Alloc.inl +++ b/pcsx2/x86/microVU_Alloc.inl @@ -146,18 +146,18 @@ microVUt(void) mVUallocFMAC3b(int& Fd) { if (_W) { mVUloadReg(reg, (uptr)&mVU->regs->VF[0].UL[0], _xyzw_ACC); } \ else { SSE_XORPS_XMM_to_XMM(reg, reg); } \ } - +/* #define getACC(reg) { \ reg = xmmACC0 + writeACC; \ if (_X_Y_Z_W != 15) { SSE_MOVAPS_XMM_to_XMM(reg, (xmmACC0 + prevACC)); } \ } - +*/ microVUt(void) mVUallocFMAC4a(int& ACC, int& Fs, int& Ft) { microVU* mVU = mVUx; - Fs = xmmFs; + ACC = xmmACC; + Fs = (_X_Y_Z_W == 15) ? xmmACC : xmmFs; Ft = xmmFt; - getACC(ACC); - if (_XYZW_SS && _X) { + if (_X_Y_Z_W == 8) { getReg6(Fs, _Fs_); if (_Ft_ == _Fs_) { Ft = Fs; } else { getReg6(Ft, _Ft_); } @@ -184,10 +184,10 @@ microVUt(void) mVUallocFMAC4b(int& ACC, int& Fs) { microVUt(void) mVUallocFMAC5a(int& ACC, int& Fs, int& Ft) { microVU* mVU = mVUx; - Fs = xmmFs; + ACC = xmmACC; + Fs = (_X_Y_Z_W == 15) ? xmmACC : xmmFs; Ft = xmmFt; - getACC(ACC); - if (_XYZW_SS && _X) { + if (_X_Y_Z_W == 8) { getReg6(Fs, _Fs_); if ((_Ft_ == _Fs_) && _bc_x) { Ft = Fs; } else if (!_Ft_) { getZero3SS(Ft); } @@ -236,11 +236,11 @@ microVUt(void) mVUallocFMAC6b(int& Fd) { microVUt(void) mVUallocFMAC7a(int& ACC, int& Fs, int& Ft) { microVU* mVU = mVUx; - Fs = xmmFs; + ACC = xmmACC; + Fs = (_X_Y_Z_W == 15) ? xmmACC : xmmFs; Ft = xmmFt; - getACC(ACC); getIreg(Ft); - if (_XYZW_SS && _X) { getReg6(Fs, _Fs_); } + if (_X_Y_Z_W == 8) { getReg6(Fs, _Fs_); } else if (!_Fs_) { getZero4(Fs); } else { getReg4(Fs, _Fs_); } } @@ -253,13 +253,13 @@ microVUt(void) mVUallocFMAC7b(int& ACC, int& Fs) { // FMAC8 - MADD FMAC Opcode Storing Result to Fd //------------------------------------------------------------------ -microVUt(void) mVUallocFMAC8a(int& Fd, int&ACC, int& Fs, int& Ft) { +microVUt(void) mVUallocFMAC8a(int& Fd, int& ACC, int& Fs, int& Ft) { microVU* mVU = mVUx; Fs = xmmFs; Ft = xmmFt; Fd = xmmFs; - ACC = xmmACC0 + readACC; - if (_XYZW_SS && _X) { + ACC = xmmACC; + if (_X_Y_Z_W == 8) { getReg6(Fs, _Fs_); if (_Ft_ == _Fs_) { Ft = Fs; } else { getReg6(Ft, _Ft_); } @@ -285,14 +285,14 @@ microVUt(void) mVUallocFMAC8b(int& Fd) { // FMAC9 - MSUB FMAC Opcode Storing Result to Fd //------------------------------------------------------------------ -microVUt(void) mVUallocFMAC9a(int& Fd, int&ACC, int& Fs, int& Ft) { +microVUt(void) mVUallocFMAC9a(int& Fd, int& ACC, int& Fs, int& Ft) { microVU* mVU = mVUx; Fs = xmmFs; Ft = xmmFt; Fd = xmmT1; ACC = xmmT1; - SSE_MOVAPS_XMM_to_XMM(ACC, xmmACC0 + readACC); - if (_XYZW_SS && _X) { + SSE_MOVAPS_XMM_to_XMM(ACC, xmmACC); + if (_X_Y_Z_W == 8) { getReg6(Fs, _Fs_); if (_Ft_ == _Fs_) { Ft = Fs; } else { getReg6(Ft, _Ft_); } @@ -323,8 +323,8 @@ microVUt(void) mVUallocFMAC10a(int& Fd, int& ACC, int& Fs, int& Ft) { Fs = xmmFs; Ft = xmmFt; Fd = xmmFs; - ACC = xmmACC0 + readACC; - if (_XYZW_SS && _X) { + ACC = xmmACC; + if (_X_Y_Z_W == 8) { getReg6(Fs, _Fs_); if ( (_Ft_ == _Fs_) && _bc_x) { Ft = Fs; } else if (!_Ft_) { getZero3SS(Ft); } @@ -353,8 +353,8 @@ microVUt(void) mVUallocFMAC11a(int& Fd, int& ACC, int& Fs, int& Ft) { Ft = xmmFt; Fd = xmmT1; ACC = xmmT1; - SSE_MOVAPS_XMM_to_XMM(ACC, xmmACC0 + readACC); - if (_XYZW_SS && _X) { + SSE_MOVAPS_XMM_to_XMM(ACC, xmmACC); + if (_X_Y_Z_W == 8) { getReg6(Fs, _Fs_); if ( (_Ft_ == _Fs_) && _bc_x) { Ft = Fs; } else if (!_Ft_) { getZero3SS(Ft); } @@ -377,14 +377,14 @@ microVUt(void) mVUallocFMAC11b(int& Fd) { // FMAC12 - MADD FMAC Opcode Storing Result to Fd (I Reg) //------------------------------------------------------------------ -microVUt(void) mVUallocFMAC12a(int& Fd, int&ACC, int& Fs, int& Ft) { +microVUt(void) mVUallocFMAC12a(int& Fd, int& ACC, int& Fs, int& Ft) { microVU* mVU = mVUx; Fs = xmmFs; Ft = xmmFt; Fd = xmmFs; - ACC = xmmACC0 + readACC; + ACC = xmmACC; getIreg(Ft); - if (_XYZW_SS && _X) { getReg6(Fs, _Fs_); } + if (_X_Y_Z_W == 8) { getReg6(Fs, _Fs_); } else if (!_Fs_) { getZero4(Fs); } else { getReg4(Fs, _Fs_); } } @@ -397,15 +397,15 @@ microVUt(void) mVUallocFMAC12b(int& Fd) { // FMAC13 - MSUB FMAC Opcode Storing Result to Fd (I Reg) //------------------------------------------------------------------ -microVUt(void) mVUallocFMAC13a(int& Fd, int&ACC, int& Fs, int& Ft) { +microVUt(void) mVUallocFMAC13a(int& Fd, int& ACC, int& Fs, int& Ft) { microVU* mVU = mVUx; Fs = xmmFs; Ft = xmmFt; Fd = xmmT1; ACC = xmmT1; - SSE_MOVAPS_XMM_to_XMM(ACC, xmmACC0 + readACC); + SSE_MOVAPS_XMM_to_XMM(ACC, xmmACC); getIreg(Ft); - if (_XYZW_SS && _X) { getReg6(Fs, _Fs_); } + if (_X_Y_Z_W == 8) { getReg6(Fs, _Fs_); } else if (!_Fs_) { getZero4(Fs); } else { getReg4(Fs, _Fs_); } } @@ -415,16 +415,18 @@ microVUt(void) mVUallocFMAC13b(int& Fd) { } //------------------------------------------------------------------ -// FMAC14 - MADDA FMAC Opcode +// FMAC14 - MADDA/MSUBA FMAC Opcodes //------------------------------------------------------------------ -microVUt(void) mVUallocFMAC14a(int& ACCw, int&ACCr, int& Fs, int& Ft) { +microVUt(void) mVUallocFMAC14a(int& ACCw, int& ACCr, int& Fs, int& Ft) { microVU* mVU = mVUx; - getACC(ACCw); - Fs = (_X_Y_Z_W == 15) ? ACCw : xmmFs; + Fs = xmmFs; Ft = xmmFt; - ACCr = xmmACC0 + readACC; - if (_XYZW_SS && _X) { + ACCw = xmmACC; + ACCr = ((_X_Y_Z_W == 15) || (_X_Y_Z_W == 8)) ? xmmACC : xmmT1; + SSE_MOVAPS_XMM_to_XMM(ACCr, xmmACC); + + if (_X_Y_Z_W == 8) { getReg6(Fs, _Fs_); if (_Ft_ == _Fs_) { Ft = Fs; } else { getReg6(Ft, _Ft_); } @@ -439,39 +441,25 @@ microVUt(void) mVUallocFMAC14a(int& ACCw, int&ACCr, int& Fs, int& Ft) { } } -microVUt(void) mVUallocFMAC14b(int& ACCw, int& Fs) { - microVU* mVU = mVUx; - if (CHECK_VU_OVERFLOW) mVUclamp1(Fs, xmmT1, _xyzw_ACC); - mVUmergeRegs(ACCw, Fs, _X_Y_Z_W); -} - -//------------------------------------------------------------------ -// FMAC15 - MSUBA FMAC Opcode -//------------------------------------------------------------------ - -microVUt(void) mVUallocFMAC15a(int& ACCw, int&ACCr, int& Fs, int& Ft) { - mVUallocFMAC14a(ACCw, ACCr, Fs, Ft); - SSE_MOVAPS_XMM_to_XMM(xmmT1, ACCr); - ACCr = xmmT1; -} - -microVUt(void) mVUallocFMAC15b(int& ACCw, int& ACCr) { +microVUt(void) mVUallocFMAC14b(int& ACCw, int& ACCr) { microVU* mVU = mVUx; if (CHECK_VU_OVERFLOW) mVUclamp1(ACCr, xmmFt, _xyzw_ACC); mVUmergeRegs(ACCw, ACCr, _X_Y_Z_W); } //------------------------------------------------------------------ -// FMAC16 - MADDA BC(xyzw) FMAC Opcode +// FMAC15 - MADDA/MSUBA BC(xyzw) FMAC Opcode //------------------------------------------------------------------ -microVUt(void) mVUallocFMAC16a(int& ACCw, int&ACCr, int& Fs, int& Ft) { +microVUt(void) mVUallocFMAC15a(int& ACCw, int& ACCr, int& Fs, int& Ft) { microVU* mVU = mVUx; - getACC(ACCw); - Fs = (_X_Y_Z_W == 15) ? ACCw : xmmFs; + Fs = xmmFs; Ft = xmmFt; - ACCr = xmmACC0 + readACC; - if (_XYZW_SS && _X) { + ACCw = xmmACC; + ACCr = ((_X_Y_Z_W == 15) || (_X_Y_Z_W == 8)) ? xmmACC : xmmT1; + SSE_MOVAPS_XMM_to_XMM(ACCr, xmmACC); + + if (_X_Y_Z_W == 8) { getReg6(Fs, _Fs_); if ((_Ft_ == _Fs_) && _bc_x) { Ft = Fs; } else if (!_Ft_) { getZero3SS(Ft); } @@ -486,22 +474,29 @@ microVUt(void) mVUallocFMAC16a(int& ACCw, int&ACCr, int& Fs, int& Ft) { } } -microVUt(void) mVUallocFMAC16b(int& ACCw, int& Fs) { - mVUallocFMAC14b(ACCw, Fs); +microVUt(void) mVUallocFMAC15b(int& ACCw, int& ACCr) { + mVUallocFMAC14b(ACCw, ACCr); } //------------------------------------------------------------------ -// FMAC17 - MSUBA BC(xyzw) FMAC Opcode +// FMAC16 - MADDA/MSUBA FMAC Opcode (I Reg) //------------------------------------------------------------------ -microVUt(void) mVUallocFMAC17a(int& ACCw, int&ACCr, int& Fs, int& Ft) { - mVUallocFMAC16a(ACCw, ACCr, Fs, Ft); - SSE_MOVAPS_XMM_to_XMM(xmmT1, ACCr); - ACCr = xmmT1; +microVUt(void) mVUallocFMAC16a(int& ACCw, int& ACCr, int& Fs, int& Ft) { + microVU* mVU = mVUx; + Fs = xmmFs; + Ft = xmmFt; + ACCw = xmmACC; + ACCr = ((_X_Y_Z_W == 15) || (_X_Y_Z_W == 8)) ? xmmACC : xmmT1; + SSE_MOVAPS_XMM_to_XMM(ACCr, xmmACC); + getIreg(Ft); + if (_X_Y_Z_W == 8) { getReg6(Fs, _Fs_); } + else if (!_Fs_) { getZero4(Fs); } + else { getReg4(Fs, _Fs_); } } -microVUt(void) mVUallocFMAC17b(int& ACCw, int& ACCr) { - mVUallocFMAC15b(ACCw, ACCr); +microVUt(void) mVUallocFMAC16b(int& ACCw, int& ACCr) { + mVUallocFMAC14b(ACCw, ACCr); } //------------------------------------------------------------------ @@ -512,7 +507,7 @@ microVUt(void) mVUallocFMAC18a(int& ACC, int& Fs, int& Ft) { microVU* mVU = mVUx; Fs = xmmFs; Ft = xmmFt; - getACC(ACC); + ACC = xmmACC; if (!_Fs_) { getZero4(Fs); } else { getReg4(Fs, _Fs_); } @@ -532,13 +527,13 @@ microVUt(void) mVUallocFMAC18b(int& ACC, int& Fs) { // FMAC19 - OPMULA FMAC Opcode //------------------------------------------------------------------ -microVUt(void) mVUallocFMAC19a(int& Fd, int&ACC, int& Fs, int& Ft) { +microVUt(void) mVUallocFMAC19a(int& Fd, int& ACC, int& Fs, int& Ft) { microVU* mVU = mVUx; Fs = xmmFs; Ft = xmmFt; Fd = xmmT1; ACC = xmmT1; - SSE_MOVAPS_XMM_to_XMM(ACC, xmmACC0 + readACC); + SSE_MOVAPS_XMM_to_XMM(ACC, xmmACC); if (!_Fs_) { getZero4(Fs); } else { getReg4(Fs, _Fs_); } @@ -554,40 +549,6 @@ microVUt(void) mVUallocFMAC19b(int& Fd) { mVUallocFMAC9b(Fd); } -//------------------------------------------------------------------ -// FMAC20 - MADDA FMAC Opcode (I Reg) -//------------------------------------------------------------------ - -microVUt(void) mVUallocFMAC20a(int& ACCw, int&ACCr, int& Fs, int& Ft) { - microVU* mVU = mVUx; - getACC(ACCw); - Fs = (_X_Y_Z_W == 15) ? ACCw : xmmFs; - Ft = xmmFt; - ACCr = xmmACC0 + readACC; - getIreg(Ft); - if (_XYZW_SS && _X) { getReg6(Fs, _Fs_); } - else if (!_Fs_) { getZero4(Fs); } - else { getReg4(Fs, _Fs_); } -} - -microVUt(void) mVUallocFMAC20b(int& ACCw, int& Fs) { - mVUallocFMAC14b(ACCw, Fs); -} - -//------------------------------------------------------------------ -// FMAC21 - MSUBA FMAC Opcode (I Reg) -//------------------------------------------------------------------ - -microVUt(void) mVUallocFMAC21a(int& ACCw, int&ACCr, int& Fs, int& Ft) { - mVUallocFMAC20a(ACCw, ACCr, Fs, Ft); - SSE_MOVAPS_XMM_to_XMM(xmmT1, ACCr); - ACCr = xmmT1; -} - -microVUt(void) mVUallocFMAC21b(int& ACCw, int& ACCr) { - mVUallocFMAC15b(ACCw, ACCr); -} - //------------------------------------------------------------------ // FMAC22 - Normal FMAC Opcodes (Q Reg) //------------------------------------------------------------------ @@ -616,11 +577,11 @@ microVUt(void) mVUallocFMAC22b(int& Fd) { microVUt(void) mVUallocFMAC23a(int& ACC, int& Fs, int& Ft) { microVU* mVU = mVUx; - Fs = xmmFs; + ACC = xmmACC; + Fs = (_X_Y_Z_W == 15) ? xmmACC : xmmFs; Ft = xmmFt; - getACC(ACC); getQreg(Ft); - if (_XYZW_SS && _X) { getReg6(Fs, _Fs_); } + if (_X_Y_Z_W == 8) { getReg6(Fs, _Fs_); } else if (!_Fs_) { getZero4(Fs); } else { getReg4(Fs, _Fs_); } } @@ -633,14 +594,14 @@ microVUt(void) mVUallocFMAC23b(int& ACC, int& Fs) { // FMAC24 - MADD FMAC Opcode Storing Result to Fd (Q Reg) //------------------------------------------------------------------ -microVUt(void) mVUallocFMAC24a(int& Fd, int&ACC, int& Fs, int& Ft) { +microVUt(void) mVUallocFMAC24a(int& Fd, int& ACC, int& Fs, int& Ft) { microVU* mVU = mVUx; Fs = xmmFs; Ft = xmmFt; Fd = xmmFs; - ACC = xmmACC0 + readACC; + ACC = xmmACC; getQreg(Ft); - if (_XYZW_SS && _X) { getReg6(Fs, _Fs_); } + if (_X_Y_Z_W == 8) { getReg6(Fs, _Fs_); } else if (!_Fs_) { getZero4(Fs); } else { getReg4(Fs, _Fs_); } } @@ -653,15 +614,15 @@ microVUt(void) mVUallocFMAC24b(int& Fd) { // FMAC25 - MSUB FMAC Opcode Storing Result to Fd (Q Reg) //------------------------------------------------------------------ -microVUt(void) mVUallocFMAC25a(int& Fd, int&ACC, int& Fs, int& Ft) { +microVUt(void) mVUallocFMAC25a(int& Fd, int& ACC, int& Fs, int& Ft) { microVU* mVU = mVUx; Fs = xmmFs; Ft = xmmFt; Fd = xmmT1; ACC = xmmT1; - SSE_MOVAPS_XMM_to_XMM(ACC, xmmACC0 + readACC); + SSE_MOVAPS_XMM_to_XMM(ACC, xmmACC); getQreg(Ft); - if (_XYZW_SS && _X) { getReg6(Fs, _Fs_); } + if (_X_Y_Z_W == 8) { getReg6(Fs, _Fs_); } else if (!_Fs_) { getZero4(Fs); } else { getReg4(Fs, _Fs_); } } @@ -671,37 +632,24 @@ microVUt(void) mVUallocFMAC25b(int& Fd) { } //------------------------------------------------------------------ -// FMAC26 - MADDA FMAC Opcode (Q Reg) +// FMAC26 - MADDA/MSUBA FMAC Opcode (Q Reg) //------------------------------------------------------------------ -microVUt(void) mVUallocFMAC26a(int& ACCw, int&ACCr, int& Fs, int& Ft) { +microVUt(void) mVUallocFMAC26a(int& ACCw, int& ACCr, int& Fs, int& Ft) { microVU* mVU = mVUx; - getACC(ACCw); - Fs = (_X_Y_Z_W == 15) ? ACCw : xmmFs; + Fs = xmmFs; Ft = xmmFt; - ACCr = xmmACC0 + readACC; + ACCw = xmmACC; + ACCr = ((_X_Y_Z_W == 15) || (_X_Y_Z_W == 8)) ? xmmACC : xmmT1; + SSE_MOVAPS_XMM_to_XMM(ACCr, xmmACC); getQreg(Ft); - if (_XYZW_SS && _X) { getReg6(Fs, _Fs_); } + if (_X_Y_Z_W == 8) { getReg6(Fs, _Fs_); } else if (!_Fs_) { getZero4(Fs); } else { getReg4(Fs, _Fs_); } } -microVUt(void) mVUallocFMAC26b(int& ACCw, int& Fs) { - mVUallocFMAC14b(ACCw, Fs); -} - -//------------------------------------------------------------------ -// FMAC27 - MSUBA FMAC Opcode (Q Reg) -//------------------------------------------------------------------ - -microVUt(void) mVUallocFMAC27a(int& ACCw, int&ACCr, int& Fs, int& Ft) { - mVUallocFMAC26a(ACCw, ACCr, Fs, Ft); - SSE_MOVAPS_XMM_to_XMM(xmmT1, ACCr); - ACCr = xmmT1; -} - -microVUt(void) mVUallocFMAC27b(int& ACCw, int& ACCr) { - mVUallocFMAC15b(ACCw, ACCr); +microVUt(void) mVUallocFMAC26b(int& ACCw, int& ACCr) { + mVUallocFMAC14b(ACCw, ACCr); } //------------------------------------------------------------------ @@ -741,6 +689,16 @@ microVUt(void) mVUallocMFLAGb(int reg, int fInstance) { OR32RtoR(fInstance, reg); } +microVUt(void) mVUallocCFLAGa(int reg, int fInstance) { + microVU* mVU = mVUx; + MOV32MtoR(reg, mVU->clipFlag[fInstance]); +} + +microVUt(void) mVUallocCFLAGb(int reg, int fInstance) { + microVU* mVU = mVUx; + MOV32RtoM(mVU->clipFlag[fInstance], reg); +} + //------------------------------------------------------------------ // VI Reg Allocators //------------------------------------------------------------------ @@ -788,4 +746,10 @@ microVUt(void) mVUallocVIb(int GPRreg, int _reg_) { if (!_reg_) { getZero(reg); } \ else { mVUloadReg(reg, (uptr)&mVU->regs->VF[_reg_].UL[0], _X_Y_Z_W); } \ } + +// VF to GPR +#define getReg8(GPRreg, _reg_, _fxf_) { \ + if (!_reg_ && (_fxf_ < 3)) { XOR32RtoR(GPRreg, GPRreg); } \ + else { MOV32MtoR(GPRreg, (uptr)&mVU->regs->VF[_reg_].UL[0]); } \ +} #endif //PCSX2_MICROVU diff --git a/pcsx2/x86/microVU_Compile.inl b/pcsx2/x86/microVU_Compile.inl index e674aaf8df..0574d9faa3 100644 --- a/pcsx2/x86/microVU_Compile.inl +++ b/pcsx2/x86/microVU_Compile.inl @@ -19,4 +19,78 @@ #pragma once #ifdef PCSX2_MICROVU -#endif //PCSX2_MICROVU \ No newline at end of file +#ifdef mVUdebug +#define mVUdebugStuff1() { \ + if (curI & _Ibit_) { SysPrintf("microVU: I-bit set!\n"); } \ + if (curI & _Ebit_) { SysPrintf("microVU: E-bit set!\n"); } \ + if (curI & _Mbit_) { SysPrintf("microVU: M-bit set!\n"); } \ + if (curI & _Dbit_) { SysPrintf("microVU: D-bit set!\n"); } \ + if (curI & _Tbit_) { SysPrintf("microVU: T-bit set!\n"); } \ +} +#else +#define mVUdebugStuff1() {} +#endif + +#define curI mVUcurProg.data[iPC] +#define setCode() { mVU->code = curI; } +#define incPC(x) { iPC = ((iPC + x) & (mVU->progSize-1)); setCode(); } + +#define createBlock(blockEndPtr) { \ + block.pipelineState = pipelineState; \ + block.x86ptrStart = x86ptrStart; \ + block.x86ptrEnd = blockEndPtr; \ + /*block.x86ptrBranch;*/ \ + if (!(pipelineState & 1)) { \ + memcpy_fast(&block.pState, pState, sizeof(microRegInfo)); \ + } \ +} + +microVUx(void) mVUcompile(u32 startPC, u32 pipelineState, microRegInfo* pState, u8* x86ptrStart) { + microVU* mVU = mVUx; + microBlock block; + iPC = startPC / 4; + + // Searches for Existing Compiled Block (if found, then returns; else, compile) + microBlock* pblock = mVUblock[iPC]->search(pipelineState, pState); + if (block) { x86SetPtr(pblock->x86ptrEnd); return; } + + // First Pass + setCode(); + for (;;) { + mVUdebugStuff1(); + mVUopU(); + if (curI & _Ebit_) { mVUbranch = 5; } + if (curI & _MDTbit_) { mVUbranch = 4; } + if (curI & _Ibit_) { incPC(1); mVUinfo |= _isNOP; } + else { incPC(1); mVUopL(); } + if (mVUbranch == 4) { mVUbranch = 0; mVUinfo |= _isEOB; break; } + else if (mVUbranch == 5) { mVUbranch = 4; } + else if (mVUbranch) { mVUbranch = 4; mVUinfo |= _isBranch; } + incPC(1); + } + + // Second Pass + iPC = startPC; + setCode(); + for (bool x = 1; x==1; ) { + if (isEOB) { x = 0; } + else if (isBranch) { mVUopU(); incPC(2); } + + mVUopU(); + if (isNop) { incPC(1); } + else { incPC(1); mVUopL(); } + if (!isBdelay) { incPC(1); } + else { + incPC(-2); // Go back to Branch Opcode + mVUopL(); // Run Branch Opcode + switch (mVUbranch) { + case 1: break; + case 2: break; + case 3: break; + } + break; + } + } +} + +#endif //PCSX2_MICROVU diff --git a/pcsx2/x86/microVU_Lower.inl b/pcsx2/x86/microVU_Lower.inl index 9a3579aae5..817cc46b1d 100644 --- a/pcsx2/x86/microVU_Lower.inl +++ b/pcsx2/x86/microVU_Lower.inl @@ -56,7 +56,7 @@ microVUf(void) mVU_DIV() { SSE_XORPS_XMM_to_XMM(xmmFs, xmmFt); SSE_ANDPS_M128_to_XMM(xmmFs, (uptr)mVU_signbit); - SSE_ORPS_M128_to_XMM(xmmFs, (uptr)mVU_maxvals); // If division by zero, then xmmFs = +/- fmax + SSE_ORPS_XMM_to_XMM(xmmFs, xmmMax); // If division by zero, then xmmFs = +/- fmax bjmp32 = JMP32(0); x86SetJ32(ajmp32); @@ -86,7 +86,7 @@ microVUf(void) mVU_SQRT() { //x86SetJ8(pjmp); SSE_ANDPS_M128_to_XMM(xmmFt, (uptr)mVU_absclip); // Do a cardinal sqrt - if (CHECK_VU_OVERFLOW) SSE_MINSS_M32_to_XMM(xmmFt, (uptr)mVU_maxvals); // Clamp infinities (only need to do positive clamp since xmmFt is positive) + if (CHECK_VU_OVERFLOW) SSE_MINSS_XMM_to_XMM(xmmFt, xmmMax); // Clamp infinities (only need to do positive clamp since xmmFt is positive) SSE_SQRTSS_XMM_to_XMM(xmmFt, xmmFt); mVUunpack_xyzw(xmmFt, xmmFt, 0); mVUmergeRegs(xmmPQ, xmmFt, writeQ ? 4 : 8); @@ -122,7 +122,7 @@ microVUf(void) mVU_RSQRT() { ajmp8 = JZ8(0); // Skip if none are //OR32ItoM(VU_VI_ADDR(REG_STATUS_FLAG, 2), 0x820); // Zero divide flag SSE_ANDPS_M128_to_XMM(xmmFs, (uptr)mVU_signbit); - SSE_ORPS_M128_to_XMM(xmmFs, (uptr)mVU_maxvals); // EEREC_TEMP = +/-Max + SSE_ORPS_XMM_to_XMM(xmmFs, xmmMax); // EEREC_TEMP = +/-Max bjmp8 = JMP8(0); x86SetJ8(ajmp8); SSE_DIVSS_XMM_to_XMM(xmmFs, xmmFt); @@ -207,11 +207,11 @@ microVUf(void) mVU_EATANxz() { mVU_EATAN_(); } } -#define eexpHelper(addr) { \ - SSE_MULSS_XMM_to_XMM(xmmT1, xmmFs); \ - SSE_MOVAPS_XMM_to_XMM(xmmFt, xmmT1); \ - SSE_MULSS_M32_to_XMM(xmmFt, (uptr)addr); \ - SSE_ADDSS_XMM_to_XMM(xmmPQ, xmmFt); \ +#define eexpHelper(addr) { \ + SSE_MULSS_XMM_to_XMM(xmmT1, xmmFs); \ + SSE_MOVAPS_XMM_to_XMM(xmmFt, xmmT1); \ + SSE_MULSS_M32_to_XMM(xmmFt, (uptr)addr); \ + SSE_ADDSS_XMM_to_XMM(xmmPQ, xmmFt); \ } microVUf(void) mVU_EEXP() { microVU* mVU = mVUx; @@ -334,11 +334,11 @@ microVUf(void) mVU_ESADD() { SSE2_PSHUFD_XMM_to_XMM(xmmPQ, xmmPQ, writeP ? 0x27 : 0xC6); // Flip back } } -#define esinHelper(addr) { \ - SSE_MULSS_XMM_to_XMM(xmmT1, xmmFt); \ - SSE_MOVAPS_XMM_to_XMM(xmmFs, xmmT1); \ - SSE_MULSS_M32_to_XMM(xmmFs, (uptr)addr); \ - SSE_ADDSS_XMM_to_XMM(xmmPQ, xmmFs); \ +#define esinHelper(addr) { \ + SSE_MULSS_XMM_to_XMM(xmmT1, xmmFt); \ + SSE_MOVAPS_XMM_to_XMM(xmmFs, xmmT1); \ + SSE_MULSS_M32_to_XMM(xmmFs, (uptr)addr); \ + SSE_ADDSS_XMM_to_XMM(xmmPQ, xmmFs); \ } microVUf(void) mVU_ESIN() { microVU* mVU = mVUx; @@ -390,11 +390,56 @@ microVUf(void) mVU_ESUM() { } } -microVUf(void) mVU_FCAND() {} -microVUf(void) mVU_FCEQ() {} -microVUf(void) mVU_FCOR() {} -microVUf(void) mVU_FCSET() {} -microVUf(void) mVU_FCGET() {} +microVUf(void) mVU_FCAND() { + microVU* mVU = mVUx; + if (recPass == 0) {} + else { + mVUallocCFLAGa(gprT1, fvcInstance); + AND32ItoR(gprT1, _Imm24_); + ADD32ItoR(gprT1, 0xffffff); + SHR32ItoR(gprT1, 24); + mVUallocVIb(gprT1, 1); + } +} +microVUf(void) mVU_FCEQ() { + microVU* mVU = mVUx; + if (recPass == 0) {} + else { + mVUallocCFLAGa(gprT1, fvcInstance); + XOR32ItoR(gprT1, _Imm24_); + SUB32ItoR(gprT1, 1); + SHR32ItoR(gprT1, 31); + mVUallocVIb(gprT1, 1); + } +} +microVUf(void) mVU_FCGET() { + microVU* mVU = mVUx; + if (recPass == 0) {} + else { + mVUallocCFLAGa(gprT1, fvcInstance); + AND32ItoR(gprT1, 0xfff); + mVUallocVIb(gprT1, _Ft_); + } +} +microVUf(void) mVU_FCOR() { + microVU* mVU = mVUx; + if (recPass == 0) {} + else { + mVUallocCFLAGa(gprT1, fvcInstance); + OR32ItoR(gprT1, _Imm24_); + ADD32ItoR(gprT1, 1); // If 24 1's will make 25th bit 1, else 0 + SHR32ItoR(gprT1, 24); // Get the 25th bit (also clears the rest of the garbage in the reg) + mVUallocVIb(gprT1, 1); + } +} +microVUf(void) mVU_FCSET() { + microVU* mVU = mVUx; + if (recPass == 0) {} + else { + MOV32ItoR(gprT1, _Imm24_); + mVUallocCFLAGb(gprT1, fcInstance); + } +} microVUf(void) mVU_FMAND() { microVU* mVU = mVUx; @@ -412,9 +457,9 @@ microVUf(void) mVU_FMEQ() { else { mVUallocMFLAGa(gprT1, fvmInstance); mVUallocVIa(gprT2, _Fs_); - CMP16RtoR(gprT1, gprT2); - SETE8R(gprT1); - AND16ItoR(gprT1, 0x1); + XOR32RtoR(gprT1, gprT2); + SUB32ItoR(gprT1, 1); + SHR32ItoR(gprT1, 31); mVUallocVIb(gprT1, _Ft_); } } @@ -443,9 +488,9 @@ microVUf(void) mVU_FSEQ() { if (recPass == 0) {} else { mVUallocSFLAGa(gprT1, fvsInstance); - CMP16ItoR(gprT1, _Imm12_); - SETE8R(gprT1); - AND16ItoR(gprT1, 0x1); + XOR16ItoR(gprT1, _Imm12_); + SUB16ItoR(gprT1, 1); + SHR16ItoR(gprT1, 15); mVUallocVIb(gprT1, _Ft_); } } @@ -549,17 +594,6 @@ microVUf(void) mVU_ISUBIU() { } } -microVUf(void) mVU_B() {} -microVUf(void) mVU_BAL() {} -microVUf(void) mVU_IBEQ() {} -microVUf(void) mVU_IBGEZ() {} -microVUf(void) mVU_IBGTZ() {} -microVUf(void) mVU_IBLTZ() {} -microVUf(void) mVU_IBLEZ() {} -microVUf(void) mVU_IBNE() {} -microVUf(void) mVU_JR() {} -microVUf(void) mVU_JALR() {} - microVUf(void) mVU_MOVE() { microVU* mVU = mVUx; if (recPass == 0) { /*If (!_Ft_ || (_Ft_ == _Fs_)) nop();*/ } @@ -800,15 +834,76 @@ microVUf(void) mVU_SQI() { } } -microVUf(void) mVU_RINIT() {} -microVUf(void) mVU_RGET() {} -microVUf(void) mVU_RNEXT() {} -microVUf(void) mVU_RXOR() {} +microVUf(void) mVU_RINIT() { + microVU* mVU = mVUx; + if (recPass == 0) {} + else { + if (_Fs_ || (_Fsf_ == 3)) { + getReg8(gprR, _Fs_, _Fsf_); + AND32ItoR(gprR, 0x007fffff); + OR32ItoR (gprR, 0x3f800000); + } + else MOV32ItoR(gprR, 0x3f800000); + } +} +microVUt(void) mVU_RGET_() { + microVU* mVU = mVUx; + if (_Ft_) { + if (_X) MOV32RtoM((uptr)&mVU->regs->VF[_Ft_].UL[0], gprR); + if (_Y) MOV32RtoM((uptr)&mVU->regs->VF[_Ft_].UL[1], gprR); + if (_Z) MOV32RtoM((uptr)&mVU->regs->VF[_Ft_].UL[2], gprR); + if (_W) MOV32RtoM((uptr)&mVU->regs->VF[_Ft_].UL[3], gprR); + } +} +microVUf(void) mVU_RGET() { + microVU* mVU = mVUx; + if (recPass == 0) { /*if (!_Ft_) nop();*/ } + else { mVU_RGET_(); } +} +microVUf(void) mVU_RNEXT() { + microVU* mVU = mVUx; + if (recPass == 0) { /*if (!_Ft_) nop();*/ } + else { + // algorithm from www.project-fao.org + MOV32RtoR(gprT1, gprR); + SHR32ItoR(gprT1, 4); + AND32ItoR(gprT1, 1); -microVUf(void) mVU_WAITP() {} -microVUf(void) mVU_WAITQ() {} + MOV32RtoR(gprT2, gprR); + SHR32ItoR(gprT2, 22); + AND32ItoR(gprT2, 1); + + SHL32ItoR(gprR, 1); + XOR32RtoR(gprT1, gprT2); + XOR32RtoR(gprR, gprT1); + AND32ItoR(gprR, 0x007fffff); + OR32ItoR (gprR, 0x3f800000); + mVU_RGET_(); + } +} +microVUf(void) mVU_RXOR() { + microVU* mVU = mVUx; + if (recPass == 0) {} + else { + if (_Fs_ || (_Fsf_ == 3)) { + getReg8(gprT1, _Fs_, _Fsf_); + AND32ItoR(gprT1, 0x7fffff); + XOR32RtoR(gprR, gprT1); + } + } +} + +microVUf(void) mVU_WAITP() { + microVU* mVU = mVUx; + if (recPass == 0) {} + else {} +} +microVUf(void) mVU_WAITQ() { + microVU* mVU = mVUx; + if (recPass == 0) {} + else {} +} -microVUf(void) mVU_XGKICK() {} microVUf(void) mVU_XTOP() { microVU* mVU = mVUx; if (recPass == 0) {} @@ -825,4 +920,75 @@ microVUf(void) mVU_XITOP() { mVUallocVIb(gprT1, _Ft_); } } + +microVUt(void) __fastcall mVU_XGKICK_(u32 addr) { + microVU* mVU = mVUx; + u32 *data = (u32*)(mVU->regs->Mem + (addr&0x3fff)); + u32 size = mtgsThread->PrepDataPacket( GIF_PATH_1, data, (0x4000-(addr&0x3fff)) >> 4); + u8 *pDest = mtgsThread->GetDataPacketPtr(); + memcpy_aligned(pDest, mVU->regs->Mem + addr, size<<4); + mtgsThread->SendDataPacket(); +} +void __fastcall mVU_XGKICK0(u32 addr) { mVU_XGKICK_<0>(addr); } +void __fastcall mVU_XGKICK1(u32 addr) { mVU_XGKICK_<1>(addr); } + +microVUf(void) mVU_XGKICK() { + microVU* mVU = mVUx; + if (recPass == 0) {} + else { + mVUallocVIa(gprT2, _Fs_); // gprT2 = ECX for __fastcall + if (!vuIndex) CALLFunc((uptr)mVU_XGKICK0); + else CALLFunc((uptr)mVU_XGKICK1); + } +} + +//------------------------------------------------------------------ +// Branches +//------------------------------------------------------------------ + +microVUf(void) mVU_B() { + microVU* mVU = mVUx; + mVUbranch = 1; +} +microVUf(void) mVU_BAL() { + microVU* mVU = mVUx; + mVUbranch = 1; + if (recPass) { + MOV32ItoR(gprT1, (xPC + (2 * 8)) & 0xffff); + mVUallocVIb(gprT1, _Ft_); + } +} +microVUf(void) mVU_IBEQ() { + microVU* mVU = mVUx; + mVUbranch = 2; +} +microVUf(void) mVU_IBGEZ() { + microVU* mVU = mVUx; + mVUbranch = 2; +} +microVUf(void) mVU_IBGTZ() { + microVU* mVU = mVUx; + mVUbranch = 2; +} +microVUf(void) mVU_IBLTZ() { + microVU* mVU = mVUx; + mVUbranch = 2; +} +microVUf(void) mVU_IBLEZ() { + microVU* mVU = mVUx; + mVUbranch = 2; +} +microVUf(void) mVU_IBNE() { + microVU* mVU = mVUx; + mVUbranch = 2; +} +microVUf(void) mVU_JR() { + microVU* mVU = mVUx; + mVUbranch = 3; +} +microVUf(void) mVU_JALR() { + microVU* mVU = mVUx; + mVUbranch = 3; +} + #endif //PCSX2_MICROVU diff --git a/pcsx2/x86/microVU_Misc.h b/pcsx2/x86/microVU_Misc.h index a7cfc6330d..47558d2d3c 100644 --- a/pcsx2/x86/microVU_Misc.h +++ b/pcsx2/x86/microVU_Misc.h @@ -22,35 +22,46 @@ // Global Variables //------------------------------------------------------------------ -PCSX2_ALIGNED16_EXTERN(const u32 mVU_absclip[4]); -PCSX2_ALIGNED16_EXTERN(const u32 mVU_signbit[4]); -PCSX2_ALIGNED16_EXTERN(const u32 mVU_minvals[4]); -PCSX2_ALIGNED16_EXTERN(const u32 mVU_maxvals[4]); -PCSX2_ALIGNED16_EXTERN(const u32 mVU_T1[4]); -PCSX2_ALIGNED16_EXTERN(const u32 mVU_T2[4]); -PCSX2_ALIGNED16_EXTERN(const u32 mVU_T3[4]); -PCSX2_ALIGNED16_EXTERN(const u32 mVU_T4[4]); -PCSX2_ALIGNED16_EXTERN(const u32 mVU_T5[4]); -PCSX2_ALIGNED16_EXTERN(const u32 mVU_T6[4]); -PCSX2_ALIGNED16_EXTERN(const u32 mVU_T7[4]); -PCSX2_ALIGNED16_EXTERN(const u32 mVU_T8[4]); -PCSX2_ALIGNED16_EXTERN(const u32 mVU_Pi4[4]); -PCSX2_ALIGNED16_EXTERN(const u32 mVU_S2[4]); -PCSX2_ALIGNED16_EXTERN(const u32 mVU_S3[4]); -PCSX2_ALIGNED16_EXTERN(const u32 mVU_S4[4]); -PCSX2_ALIGNED16_EXTERN(const u32 mVU_S5[4]); -PCSX2_ALIGNED16_EXTERN(const u32 mVU_E1[4]); -PCSX2_ALIGNED16_EXTERN(const u32 mVU_E2[4]); -PCSX2_ALIGNED16_EXTERN(const u32 mVU_E3[4]); -PCSX2_ALIGNED16_EXTERN(const u32 mVU_E4[4]); -PCSX2_ALIGNED16_EXTERN(const u32 mVU_E5[4]); -PCSX2_ALIGNED16_EXTERN(const u32 mVU_E6[4]); -PCSX2_ALIGNED16_EXTERN(const float mVU_FTOI_4[4]); -PCSX2_ALIGNED16_EXTERN(const float mVU_FTOI_12[4]); -PCSX2_ALIGNED16_EXTERN(const float mVU_FTOI_15[4]); -PCSX2_ALIGNED16_EXTERN(const float mVU_ITOF_4[4]); -PCSX2_ALIGNED16_EXTERN(const float mVU_ITOF_12[4]); -PCSX2_ALIGNED16_EXTERN(const float mVU_ITOF_15[4]); +#define declareAllVariables \ +initVariable( _somePrefix_, u32, mVU_absclip, 0x7fffffff ); \ +initVariable( _somePrefix_, u32, mVU_signbit, 0x80000000 ); \ +initVariable( _somePrefix_, u32, mVU_minvals, 0xff7fffff ); \ +initVariable( _somePrefix_, u32, mVU_maxvals, 0x7f7fffff ); \ +initVariable( _somePrefix_, u32, mVU_one, 0x3f800000 ); \ +initVariable( _somePrefix_, u32, mVU_T1, 0x3f7ffff5 ); \ +initVariable( _somePrefix_, u32, mVU_T2, 0xbeaaa61c ); \ +initVariable( _somePrefix_, u32, mVU_T3, 0x3e4c40a6 ); \ +initVariable( _somePrefix_, u32, mVU_T4, 0xbe0e6c63 ); \ +initVariable( _somePrefix_, u32, mVU_T5, 0x3dc577df ); \ +initVariable( _somePrefix_, u32, mVU_T6, 0xbd6501c4 ); \ +initVariable( _somePrefix_, u32, mVU_T7, 0x3cb31652 ); \ +initVariable( _somePrefix_, u32, mVU_T8, 0xbb84d7e7 ); \ +initVariable( _somePrefix_, u32, mVU_Pi4, 0x3f490fdb ); \ +initVariable( _somePrefix_, u32, mVU_S2, 0xbe2aaaa4 ); \ +initVariable( _somePrefix_, u32, mVU_S3, 0x3c08873e ); \ +initVariable( _somePrefix_, u32, mVU_S4, 0xb94fb21f ); \ +initVariable( _somePrefix_, u32, mVU_S5, 0x362e9c14 ); \ +initVariable( _somePrefix_, u32, mVU_E1, 0x3e7fffa8 ); \ +initVariable( _somePrefix_, u32, mVU_E2, 0x3d0007f4 ); \ +initVariable( _somePrefix_, u32, mVU_E3, 0x3b29d3ff ); \ +initVariable( _somePrefix_, u32, mVU_E4, 0x3933e553 ); \ +initVariable( _somePrefix_, u32, mVU_E5, 0x36b63510 ); \ +initVariable( _somePrefix_, u32, mVU_E6, 0x353961ac ); \ +initVariable( _somePrefix_, float, mVU_FTOI_4, 16.0 ); \ +initVariable( _somePrefix_, float, mVU_FTOI_12, 4096.0 ); \ +initVariable( _somePrefix_, float, mVU_FTOI_15, 32768.0 ); \ +initVariable( _somePrefix_, float, mVU_ITOF_4, 0.0625f ); \ +initVariable( _somePrefix_, float, mVU_ITOF_12, 0.000244140625 ); \ +initVariable( _somePrefix_, float, mVU_ITOF_15, 0.000030517578125 ); + +#define _somePrefix_ PCSX2_ALIGNED16_EXTERN +#define initVariable(aprefix, atype, aname, avalue) aprefix (const atype aname [4]); +declareAllVariables +#undef _somePrefix_ +#undef initVariable + +#define _somePrefix_ PCSX2_ALIGNED16 +#define initVariable(aprefix, atype, aname, avalue) aprefix (const atype aname [4]) = {avalue, avalue, avalue, avalue}; //------------------------------------------------------------------ // Helper Macros @@ -59,15 +70,14 @@ PCSX2_ALIGNED16_EXTERN(const float mVU_ITOF_15[4]); #define _Fs_ ((mVU->code >> 11) & 0x1F) // The rd part of the instruction register #define _Fd_ ((mVU->code >> 6) & 0x1F) // The sa part of the instruction register -#define _X ((mVU->code>>24) & 0x1) -#define _Y ((mVU->code>>23) & 0x1) -#define _Z ((mVU->code>>22) & 0x1) -#define _W ((mVU->code>>21) & 0x1) +#define _X ((mVU->code>>24) & 0x1) +#define _Y ((mVU->code>>23) & 0x1) +#define _Z ((mVU->code>>22) & 0x1) +#define _W ((mVU->code>>21) & 0x1) -#define _XYZW_SS (_X+_Y+_Z+_W==1) - -#define _X_Y_Z_W (((mVU->code >> 21 ) & 0xF )) -#define _xyzw_ACC ((_XYZW_SS && !_X) ? 15 : _X_Y_Z_W) +#define _XYZW_SS (_X+_Y+_Z+_W==1) +#define _X_Y_Z_W (((mVU->code >> 21 ) & 0xF )) +#define _xyzw_ACC ((_XYZW_SS && !_X) ? 15 : _X_Y_Z_W) #define _bc_ (mVU->code & 0x03) #define _bc_x ((mVU->code & 0x03) == 0) @@ -78,11 +88,18 @@ PCSX2_ALIGNED16_EXTERN(const float mVU_ITOF_15[4]); #define _Fsf_ ((mVU->code >> 21) & 0x03) #define _Ftf_ ((mVU->code >> 23) & 0x03) -#define _Imm11_ (s32)(mVU->code & 0x400 ? 0xfffffc00 | (mVU->code & 0x3ff) : mVU->code & 0x3ff) -#define _UImm11_ (s32)(mVU->code & 0x7ff) -#define _Imm12_ (((mVU->code >> 21 ) & 0x1) << 11) | (mVU->code & 0x7ff) -#define _Imm5_ (((mVU->code & 0x400) ? 0xfff0 : 0) | ((mVU->code >> 6) & 0xf)) -#define _Imm15_ (((mVU->code >> 10) & 0x7800) | (mVU->code & 0x7ff)) +#define _Imm5_ (((mVU->code & 0x400) ? 0xfff0 : 0) | ((mVU->code >> 6) & 0xf)) +#define _Imm11_ (s32)(mVU->code & 0x400 ? 0xfffffc00 | (mVU->code & 0x3ff) : mVU->code & 0x3ff) +#define _Imm12_ (((mVU->code >> 21 ) & 0x1) << 11) | (mVU->code & 0x7ff) +#define _Imm15_ (((mVU->code >> 10) & 0x7800) | (mVU->code & 0x7ff)) +#define _Imm24_ (u32)(mVU->code & 0xffffff) + +#define _Ibit_ (1<<31) +#define _Ebit_ (1<<30) +#define _Mbit_ (1<<29) +#define _Dbit_ (1<<28) +#define _Tbit_ (1<<27) +#define _MDTbit_ ( _Mbit_ | _Dbit_ | _Tbit_ ) #define getVUmem(x) (((vuIndex == 1) ? (x & 0x3ff) : ((x >= 0x400) ? (x & 0x43f) : (x & 0xff))) * 16) #define offsetSS ((_X) ? (0) : ((_Y) ? (4) : ((_Z) ? 8: 12))) @@ -90,10 +107,10 @@ PCSX2_ALIGNED16_EXTERN(const float mVU_ITOF_15[4]); #define xmmT1 0 // Temp Reg #define xmmFs 1 // Holds the Value of Fs (writes back result Fd) #define xmmFt 2 // Holds the Value of Ft -#define xmmACC0 3 // Holds ACC Instance #0 -#define xmmACC1 4 // Holds ACC Instance #1 -#define xmmACC2 5 // Holds ACC Instance #2 -#define xmmACC3 6 // Holds ACC Instance #3 +#define xmmACC 3 // Holds ACC +#define xmmMax 4 // Holds mVU_maxvals +#define xmmMin 5 // Holds mVU_minvals +#define xmmT2 6 // Temp Reg? #define xmmPQ 7 // Holds the Value and Backup Values of P and Q regs #define mmxVI1 0 // Holds VI 1 @@ -107,7 +124,7 @@ PCSX2_ALIGNED16_EXTERN(const float mVU_ITOF_15[4]); #define gprT1 0 // Temp Reg #define gprT2 1 // Temp Reg -#define gprT3 2 // Temp Reg? +#define gprR 2 // R Reg #define gprF0 3 // MAC Flag::Status Flag 0 #define gprESP 4 // Don't use? #define gprF1 5 // MAC Flag::Status Flag 1 @@ -121,27 +138,56 @@ PCSX2_ALIGNED16_EXTERN(const float mVU_ITOF_15[4]); #define microVUf(aType) template aType #define microVUq(aType) template __forceinline aType +#define mVUcurProg mVU->prog.prog[mVU->prog.cur] +#define mVUblock mVU->prog.prog[mVU->prog.cur].block #define mVUallocInfo mVU->prog.prog[mVU->prog.cur].allocInfo +#define mVUbranch mVUallocInfo.branch +#define mVUinfo mVUallocInfo.info[mVUallocInfo.curPC / 2] +#define iPC mVUallocInfo.curPC +#define xPC ((iPC / 2) * 8) -#define isNOP (mVUallocInfo.info[mVUallocInfo.curPC] & (1<<0)) -#define writeACC ((mVUallocInfo.info[mVUallocInfo.curPC] & (3<<1)) >> 1) -#define prevACC (((u8)((mVUallocInfo.info[mVUallocInfo.curPC] & (3<<1)) >> 1) - 1) & 0x3) -#define readACC ((mVUallocInfo.info[mVUallocInfo.curPC] & (3<<3)) >> 3) -#define writeQ ((mVUallocInfo.info[mVUallocInfo.curPC] & (1<<5)) >> 5) -#define readQ ((mVUallocInfo.info[mVUallocInfo.curPC] & (1<<6)) >> 6) -#define writeP ((mVUallocInfo.info[mVUallocInfo.curPC] & (1<<7)) >> 7) -#define readP ((mVUallocInfo.info[mVUallocInfo.curPC] & (1<<7)) >> 7) // same as write -#define doFlags (mVUallocInfo.info[mVUallocInfo.curPC] & (3<<8)) -#define doMac (mVUallocInfo.info[mVUallocInfo.curPC] & (1<<8)) -#define doStatus (mVUallocInfo.info[mVUallocInfo.curPC] & (1<<9)) -#define fmInstance ((mVUallocInfo.info[mVUallocInfo.curPC] & (3<<10)) >> 10) -#define fsInstance ((mVUallocInfo.info[mVUallocInfo.curPC] & (3<<12)) >> 12) -#define fpmInstance (((u8)((mVUallocInfo.info[mVUallocInfo.curPC] & (3<<10)) >> 10) - 1) & 0x3) -#define fpsInstance (((u8)((mVUallocInfo.info[mVUallocInfo.curPC] & (3<<12)) >> 12) - 1) & 0x3) -#define fvmInstance ((mVUallocInfo.info[mVUallocInfo.curPC] & (3<<14)) >> 14) -#define fvsInstance ((mVUallocInfo.info[mVUallocInfo.curPC] & (3<<16)) >> 16) -//#define getFs (mVUallocInfo.info[mVUallocInfo.curPC] & (1<<13)) -//#define getFt (mVUallocInfo.info[mVUallocInfo.curPC] & (1<<14)) +#define _isNOP (1<<0) // Skip Lower Instruction +#define _isBranch (1<<1) // Cur Instruction is a Branch +#define _isEOB (1<<2) // End of Block +#define _isBdelay (1<<3) // Cur Instruction in Branch Delay slot +#define _writeQ (1<<5) +#define _readQ (1<<6) +#define _writeP (1<<7) +#define _readP (1<<7) // same as writeP +#define _doFlags (3<<8) +#define _doMac (1<<8) +#define _doStatus (1<<9) +#define _fmInstance (3<<10) +#define _fsInstance (3<<12) +#define _fcInstance (3<<14) +#define _fpmInstance (3<<10) +#define _fpsInstance (3<<12) +#define _fvmInstance (3<<16) +#define _fvsInstance (3<<18) +#define _fvcInstance (3<<14) + +#define isNOP (mVUinfo & (1<<0)) +#define isBranch (mVUinfo & (1<<1)) +#define isEOB (mVUinfo & (1<<2)) +#define isBdelay (mVUinfo & (1<<3)) +#define writeQ ((mVUinfo >> 5) & 1) +#define readQ ((mVUinfo >> 6) & 1) +#define writeP ((mVUinfo >> 7) & 1) +#define readP ((mVUinfo >> 7) & 1) // same as writeP +#define doFlags (mVUinfo & (3<<8)) +#define doMac (mVUinfo & (1<<8)) +#define doStatus (mVUinfo & (1<<9)) +#define fmInstance ((mVUinfo >> 10) & 3) +#define fsInstance ((mVUinfo >> 12) & 3) +#define fpsInstance ((((mVUinfo>>12) & 3) - 1) & 0x3) +#define fcInstance ((mVUinfo >> 14) & 3) +#define fvcInstance ((mVUinfo >> 14) & 3) +#define fvmInstance ((mVUinfo >> 16) & 3) +#define fvsInstance ((mVUinfo >> 18) & 3) + +//#define getFs (mVUinfo & (1<<13)) +//#define getFt (mVUinfo & (1<<14)) +//#define fpmInstance (((u8)((mVUinfo & (3<<10)) >> 10) - 1) & 0x3) #define isMMX(_VIreg_) (_VIreg_ >= 1 && _VIreg_ <=9) #define mmVI(_VIreg_) (_VIreg_ - 1) diff --git a/pcsx2/x86/microVU_Misc.inl b/pcsx2/x86/microVU_Misc.inl index e229a09dae..6977b765e1 100644 --- a/pcsx2/x86/microVU_Misc.inl +++ b/pcsx2/x86/microVU_Misc.inl @@ -27,12 +27,12 @@ microVUx(void) mVUclamp1(int reg, int regT1, int xyzw) { switch (xyzw) { case 1: case 2: case 4: case 8: - SSE_MINSS_M32_to_XMM(reg, (uptr)mVU_maxvals); - SSE_MAXSS_M32_to_XMM(reg, (uptr)mVU_minvals); + SSE_MINSS_XMM_to_XMM(reg, xmmMax); + SSE_MAXSS_XMM_to_XMM(reg, xmmMin); break; default: - SSE_MINPS_M128_to_XMM(reg, (uptr)mVU_maxvals); - SSE_MAXPS_M128_to_XMM(reg, (uptr)mVU_minvals); + SSE_MINPS_XMM_to_XMM(reg, xmmMax); + SSE_MAXPS_XMM_to_XMM(reg, xmmMin); break; } } @@ -44,15 +44,15 @@ microVUx(void) mVUclamp2(int reg, int regT1, int xyzw) { case 1: case 2: case 4: case 8: SSE_MOVSS_XMM_to_XMM(regT1, reg); SSE_ANDPS_M128_to_XMM(regT1, (uptr)mVU_signbit); - SSE_MINSS_M32_to_XMM(reg, (uptr)mVU_maxvals); - SSE_MAXSS_M32_to_XMM(reg, (uptr)mVU_minvals); + SSE_MINSS_XMM_to_XMM(reg, xmmMax); + SSE_MAXSS_XMM_to_XMM(reg, xmmMin); SSE_ORPS_XMM_to_XMM(reg, regT1); break; default: SSE_MOVAPS_XMM_to_XMM(regT1, reg); SSE_ANDPS_M128_to_XMM(regT1, (uptr)mVU_signbit); - SSE_MINPS_M128_to_XMM(reg, (uptr)mVU_maxvals); - SSE_MAXPS_M128_to_XMM(reg, (uptr)mVU_minvals); + SSE_MINPS_XMM_to_XMM(reg, xmmMax); + SSE_MAXPS_XMM_to_XMM(reg, xmmMin); SSE_ORPS_XMM_to_XMM(reg, regT1); break; } diff --git a/pcsx2/x86/microVU_Tables.inl b/pcsx2/x86/microVU_Tables.inl index a0ea34cae0..22af9f2aaa 100644 --- a/pcsx2/x86/microVU_Tables.inl +++ b/pcsx2/x86/microVU_Tables.inl @@ -750,4 +750,7 @@ microVUf(void) mVULowerOP_T3_01() { doTableStuff(mVULowerOP_T3_01_OPCODE, ((mVUg microVUf(void) mVULowerOP_T3_10() { doTableStuff(mVULowerOP_T3_10_OPCODE, ((mVUgetCode >> 6) & 0x1f)); } microVUf(void) mVULowerOP_T3_11() { doTableStuff(mVULowerOP_T3_11_OPCODE, ((mVUgetCode >> 6) & 0x1f)); } microVUf(void) mVUunknown() { SysPrintf("mVUunknown<%d,%d> : Unknown Micro VU opcode called\n", vuIndex, recPass); } +microVUf(void) mVUopU() { doTableStuff(mVU_UPPER_OPCODE, (mVUgetCode & 0x3f)); } // Gets Upper Opcode +microVUf(void) mVUopL() { doTableStuff(mVULOWER_OPCODE, (mVUgetCode >> 25)); } // Gets Lower Opcode + #endif //PCSX2_MICROVU diff --git a/pcsx2/x86/microVU_Upper.inl b/pcsx2/x86/microVU_Upper.inl index 651ef92048..df8e7aa406 100644 --- a/pcsx2/x86/microVU_Upper.inl +++ b/pcsx2/x86/microVU_Upper.inl @@ -111,7 +111,7 @@ microVUt(void) mVUupdateFlags(int reg, int regT1, int regT2, int xyzw, bool modX else { \ int ACC, Fs, Ft; \ mVUallocFMAC4a(ACC, Fs, Ft); \ - if (_XYZW_SS && _X) SSE_##operation##SS_XMM_to_XMM(Fs, Ft); \ + if (_X_Y_Z_W == 8) SSE_##operation##SS_XMM_to_XMM(Fs, Ft); \ else SSE_##operation##PS_XMM_to_XMM(Fs, Ft); \ mVUupdateFlags(Fs, xmmT1, Ft, _X_Y_Z_W, 0); \ mVUallocFMAC4b(ACC, Fs); \ @@ -124,7 +124,7 @@ microVUt(void) mVUupdateFlags(int reg, int regT1, int regT2, int xyzw, bool modX else { \ int ACC, Fs, Ft; \ mVUallocFMAC5a(ACC, Fs, Ft); \ - if (_XYZW_SS && _X) SSE_##operation##SS_XMM_to_XMM(Fs, Ft); \ + if (_X_Y_Z_W == 8) SSE_##operation##SS_XMM_to_XMM(Fs, Ft); \ else SSE_##operation##PS_XMM_to_XMM(Fs, Ft); \ mVUupdateFlags(Fs, xmmT1, Ft, _X_Y_Z_W, 0); \ mVUallocFMAC5b(ACC, Fs); \ @@ -150,7 +150,7 @@ microVUt(void) mVUupdateFlags(int reg, int regT1, int regT2, int xyzw, bool modX else { \ int ACC, Fs, Ft; \ mVUallocFMAC7a(ACC, Fs, Ft); \ - if (_XYZW_SS && _X) SSE_##operation##SS_XMM_to_XMM(Fs, Ft); \ + if (_X_Y_Z_W == 8) SSE_##operation##SS_XMM_to_XMM(Fs, Ft); \ else SSE_##operation##PS_XMM_to_XMM(Fs, Ft); \ mVUupdateFlags(Fs, xmmT1, Ft, _X_Y_Z_W, 0); \ mVUallocFMAC7b(ACC, Fs); \ @@ -163,7 +163,7 @@ microVUt(void) mVUupdateFlags(int reg, int regT1, int regT2, int xyzw, bool modX else { \ int Fd, ACC, Fs, Ft; \ mVUallocFMAC8a(Fd, ACC, Fs, Ft); \ - if (_XYZW_SS && _X) { \ + if (_X_Y_Z_W == 8) { \ SSE_MULSS_XMM_to_XMM(Fs, Ft); \ SSE_##operation##SS_XMM_to_XMM(Fs, ACC); \ } \ @@ -182,7 +182,7 @@ microVUt(void) mVUupdateFlags(int reg, int regT1, int regT2, int xyzw, bool modX else { \ int Fd, ACC, Fs, Ft; \ mVUallocFMAC9a(Fd, ACC, Fs, Ft); \ - if (_XYZW_SS && _X) { \ + if (_X_Y_Z_W == 8) { \ SSE_MULSS_XMM_to_XMM(Fs, Ft); \ SSE_##operation##SS_XMM_to_XMM(ACC, Fs); \ } \ @@ -201,11 +201,11 @@ microVUt(void) mVUupdateFlags(int reg, int regT1, int regT2, int xyzw, bool modX else { \ int Fd, ACC, Fs, Ft; \ mVUallocFMAC10a(Fd, ACC, Fs, Ft); \ - if (_XYZW_SS && _X) { \ + if (_X_Y_Z_W == 8) { \ SSE_MULSS_XMM_to_XMM(Fs, Ft); \ SSE_##operation##SS_XMM_to_XMM(Fs, ACC); \ } \ - else { \ + else { \ SSE_MULPS_XMM_to_XMM(Fs, Ft); \ SSE_##operation##PS_XMM_to_XMM(Fs, ACC); \ } \ @@ -220,7 +220,7 @@ microVUt(void) mVUupdateFlags(int reg, int regT1, int regT2, int xyzw, bool modX else { \ int Fd, ACC, Fs, Ft; \ mVUallocFMAC11a(Fd, ACC, Fs, Ft); \ - if (_XYZW_SS && _X) { \ + if (_X_Y_Z_W == 8) { \ SSE_MULSS_XMM_to_XMM(Fs, Ft); \ SSE_##operation##SS_XMM_to_XMM(ACC, Fs); \ } \ @@ -239,7 +239,7 @@ microVUt(void) mVUupdateFlags(int reg, int regT1, int regT2, int xyzw, bool modX else { \ int Fd, ACC, Fs, Ft; \ mVUallocFMAC12a(Fd, ACC, Fs, Ft); \ - if (_XYZW_SS && _X) { \ + if (_X_Y_Z_W == 8) { \ SSE_MULSS_XMM_to_XMM(Fs, Ft); \ SSE_##operation##SS_XMM_to_XMM(Fs, ACC); \ } \ @@ -258,7 +258,7 @@ microVUt(void) mVUupdateFlags(int reg, int regT1, int regT2, int xyzw, bool modX else { \ int Fd, ACC, Fs, Ft; \ mVUallocFMAC13a(Fd, ACC, Fs, Ft); \ - if (_XYZW_SS && _X) { \ + if (_X_Y_Z_W == 8) { \ SSE_MULSS_XMM_to_XMM(Fs, Ft); \ SSE_##operation##SS_XMM_to_XMM(ACC, Fs); \ } \ @@ -270,33 +270,33 @@ microVUt(void) mVUupdateFlags(int reg, int regT1, int regT2, int xyzw, bool modX mVUallocFMAC13b(Fd); \ } \ } -// FMAC14 - MADDA FMAC Opcode +// FMAC14 - MADDA/MSUBA FMAC Opcode #define mVU_FMAC14(operation) { \ microVU* mVU = mVUx; \ if (recPass == 0) {} \ else { \ int ACCw, ACCr, Fs, Ft; \ mVUallocFMAC14a(ACCw, ACCr, Fs, Ft); \ - if (_XYZW_SS && _X) { \ + if (_X_Y_Z_W == 8) { \ SSE_MULSS_XMM_to_XMM(Fs, Ft); \ - SSE_##operation##SS_XMM_to_XMM(Fs, ACCr); \ + SSE_##operation##SS_XMM_to_XMM(ACCr, Fs); \ } \ else { \ SSE_MULPS_XMM_to_XMM(Fs, Ft); \ - SSE_##operation##PS_XMM_to_XMM(Fs, ACCr); \ + SSE_##operation##PS_XMM_to_XMM(ACCr, Fs); \ } \ - mVUupdateFlags(Fs, xmmT1, Ft, _X_Y_Z_W, 0); \ - mVUallocFMAC14b(ACCw, Fs); \ + mVUupdateFlags(ACCr, Fs, Ft, _X_Y_Z_W, 0); \ + mVUallocFMAC14b(ACCw, ACCr); \ } \ } -// FMAC15 - MSUBA FMAC Opcode +// FMAC15 - MADDA/MSUBA BC(xyzw) FMAC Opcode #define mVU_FMAC15(operation) { \ microVU* mVU = mVUx; \ if (recPass == 0) {} \ else { \ int ACCw, ACCr, Fs, Ft; \ mVUallocFMAC15a(ACCw, ACCr, Fs, Ft); \ - if (_XYZW_SS && _X) { \ + if (_X_Y_Z_W == 8) { \ SSE_MULSS_XMM_to_XMM(Fs, Ft); \ SSE_##operation##SS_XMM_to_XMM(ACCr, Fs); \ } \ @@ -308,33 +308,14 @@ microVUt(void) mVUupdateFlags(int reg, int regT1, int regT2, int xyzw, bool modX mVUallocFMAC15b(ACCw, ACCr); \ } \ } -// FMAC16 - MADDA BC(xyzw) FMAC Opcode +// FMAC16 - MADDA/MSUBA FMAC Opcode (I Reg) #define mVU_FMAC16(operation) { \ microVU* mVU = mVUx; \ if (recPass == 0) {} \ else { \ int ACCw, ACCr, Fs, Ft; \ mVUallocFMAC16a(ACCw, ACCr, Fs, Ft); \ - if (_XYZW_SS && _X) { \ - SSE_MULSS_XMM_to_XMM(Fs, Ft); \ - SSE_##operation##SS_XMM_to_XMM(Fs, ACCr); \ - } \ - else { \ - SSE_MULPS_XMM_to_XMM(Fs, Ft); \ - SSE_##operation##PS_XMM_to_XMM(Fs, ACCr); \ - } \ - mVUupdateFlags(Fs, xmmT1, Ft, _X_Y_Z_W, 0); \ - mVUallocFMAC16b(ACCw, Fs); \ - } \ -} -// FMAC17 - MSUBA BC(xyzw) FMAC Opcode -#define mVU_FMAC17(operation) { \ - microVU* mVU = mVUx; \ - if (recPass == 0) {} \ - else { \ - int ACCw, ACCr, Fs, Ft; \ - mVUallocFMAC17a(ACCw, ACCr, Fs, Ft); \ - if (_XYZW_SS && _X) { \ + if (_X_Y_Z_W == 8) { \ SSE_MULSS_XMM_to_XMM(Fs, Ft); \ SSE_##operation##SS_XMM_to_XMM(ACCr, Fs); \ } \ @@ -343,7 +324,7 @@ microVUt(void) mVUupdateFlags(int reg, int regT1, int regT2, int xyzw, bool modX SSE_##operation##PS_XMM_to_XMM(ACCr, Fs); \ } \ mVUupdateFlags(ACCr, Fs, Ft, _X_Y_Z_W, 0); \ - mVUallocFMAC17b(ACCw, ACCr); \ + mVUallocFMAC16b(ACCw, ACCr); \ } \ } // FMAC18 - OPMULA FMAC Opcode @@ -371,44 +352,6 @@ microVUt(void) mVUupdateFlags(int reg, int regT1, int regT2, int xyzw, bool modX mVUallocFMAC19b(Fd); \ } \ } -// FMAC20 - MADDA FMAC Opcode (I Reg) -#define mVU_FMAC20(operation) { \ - microVU* mVU = mVUx; \ - if (recPass == 0) {} \ - else { \ - int ACCw, ACCr, Fs, Ft; \ - mVUallocFMAC20a(ACCw, ACCr, Fs, Ft); \ - if (_XYZW_SS && _X) { \ - SSE_MULSS_XMM_to_XMM(Fs, Ft); \ - SSE_##operation##SS_XMM_to_XMM(Fs, ACCr); \ - } \ - else { \ - SSE_MULPS_XMM_to_XMM(Fs, Ft); \ - SSE_##operation##PS_XMM_to_XMM(Fs, ACCr); \ - } \ - mVUupdateFlags(Fs, xmmT1, Ft, _X_Y_Z_W, 0); \ - mVUallocFMAC20b(ACCw, Fs); \ - } \ -} -// FMAC21 - MSUBA FMAC Opcode (I Reg) -#define mVU_FMAC21(operation) { \ - microVU* mVU = mVUx; \ - if (recPass == 0) {} \ - else { \ - int ACCw, ACCr, Fs, Ft; \ - mVUallocFMAC21a(ACCw, ACCr, Fs, Ft); \ - if (_XYZW_SS && _X) { \ - SSE_MULSS_XMM_to_XMM(Fs, Ft); \ - SSE_##operation##SS_XMM_to_XMM(ACCr, Fs); \ - } \ - else { \ - SSE_MULPS_XMM_to_XMM(Fs, Ft); \ - SSE_##operation##PS_XMM_to_XMM(ACCr, Fs); \ - } \ - mVUupdateFlags(ACCr, Fs, Ft, _X_Y_Z_W, 0); \ - mVUallocFMAC21b(ACCw, ACCr); \ - } \ -} // FMAC22 - Normal FMAC Opcodes (Q Reg) #define mVU_FMAC22(operation) { \ microVU* mVU = mVUx; \ @@ -429,7 +372,7 @@ microVUt(void) mVUupdateFlags(int reg, int regT1, int regT2, int xyzw, bool modX else { \ int ACC, Fs, Ft; \ mVUallocFMAC23a(ACC, Fs, Ft); \ - if (_XYZW_SS && _X) SSE_##operation##SS_XMM_to_XMM(Fs, Ft); \ + if (_X_Y_Z_W == 8) SSE_##operation##SS_XMM_to_XMM(Fs, Ft); \ else SSE_##operation##PS_XMM_to_XMM(Fs, Ft); \ mVUupdateFlags(Fs, xmmT1, Ft, _X_Y_Z_W, 0); \ mVUallocFMAC23b(ACC, Fs); \ @@ -442,7 +385,7 @@ microVUt(void) mVUupdateFlags(int reg, int regT1, int regT2, int xyzw, bool modX else { \ int Fd, ACC, Fs, Ft; \ mVUallocFMAC24a(Fd, ACC, Fs, Ft); \ - if (_XYZW_SS && _X) { \ + if (_X_Y_Z_W == 8) { \ SSE_MULSS_XMM_to_XMM(Fs, Ft); \ SSE_##operation##SS_XMM_to_XMM(Fs, ACC); \ } \ @@ -461,7 +404,7 @@ microVUt(void) mVUupdateFlags(int reg, int regT1, int regT2, int xyzw, bool modX else { \ int Fd, ACC, Fs, Ft; \ mVUallocFMAC25a(Fd, ACC, Fs, Ft); \ - if (_XYZW_SS && _X) { \ + if (_X_Y_Z_W == 8) { \ SSE_MULSS_XMM_to_XMM(Fs, Ft); \ SSE_##operation##SS_XMM_to_XMM(ACC, Fs); \ } \ @@ -473,33 +416,14 @@ microVUt(void) mVUupdateFlags(int reg, int regT1, int regT2, int xyzw, bool modX mVUallocFMAC25b(Fd); \ } \ } -// FMAC26 - MADDA FMAC Opcode (Q Reg) +// FMAC26 - MADDA/MSUBA FMAC Opcode (Q Reg) #define mVU_FMAC26(operation) { \ microVU* mVU = mVUx; \ if (recPass == 0) {} \ else { \ int ACCw, ACCr, Fs, Ft; \ mVUallocFMAC26a(ACCw, ACCr, Fs, Ft); \ - if (_XYZW_SS && _X) { \ - SSE_MULSS_XMM_to_XMM(Fs, Ft); \ - SSE_##operation##SS_XMM_to_XMM(Fs, ACCr); \ - } \ - else { \ - SSE_MULPS_XMM_to_XMM(Fs, Ft); \ - SSE_##operation##PS_XMM_to_XMM(Fs, ACCr); \ - } \ - mVUupdateFlags(Fs, xmmT1, Ft, _X_Y_Z_W, 0); \ - mVUallocFMAC26b(ACCw, Fs); \ - } \ -} -// FMAC27 - MSUBA FMAC Opcode (Q Reg) -#define mVU_FMAC27(operation) { \ - microVU* mVU = mVUx; \ - if (recPass == 0) {} \ - else { \ - int ACCw, ACCr, Fs, Ft; \ - mVUallocFMAC27a(ACCw, ACCr, Fs, Ft); \ - if (_XYZW_SS && _X) { \ + if (_X_Y_Z_W == 8) { \ SSE_MULSS_XMM_to_XMM(Fs, Ft); \ SSE_##operation##SS_XMM_to_XMM(ACCr, Fs); \ } \ @@ -508,7 +432,7 @@ microVUt(void) mVUupdateFlags(int reg, int regT1, int regT2, int xyzw, bool modX SSE_##operation##PS_XMM_to_XMM(ACCr, Fs); \ } \ mVUupdateFlags(ACCr, Fs, Ft, _X_Y_Z_W, 0); \ - mVUallocFMAC27b(ACCw, ACCr); \ + mVUallocFMAC26b(ACCw, ACCr); \ } \ } @@ -576,12 +500,12 @@ microVUf(void) mVU_MADDy() { mVU_FMAC10(ADD); } microVUf(void) mVU_MADDz() { mVU_FMAC10(ADD); } microVUf(void) mVU_MADDw() { mVU_FMAC10(ADD); } microVUf(void) mVU_MADDA() { mVU_FMAC14(ADD); } -microVUf(void) mVU_MADDAi() { mVU_FMAC20(ADD); } +microVUf(void) mVU_MADDAi() { mVU_FMAC16(ADD); } microVUf(void) mVU_MADDAq() { mVU_FMAC26(ADD); } -microVUf(void) mVU_MADDAx() { mVU_FMAC16(ADD); } -microVUf(void) mVU_MADDAy() { mVU_FMAC16(ADD); } -microVUf(void) mVU_MADDAz() { mVU_FMAC16(ADD); } -microVUf(void) mVU_MADDAw() { mVU_FMAC16(ADD); } +microVUf(void) mVU_MADDAx() { mVU_FMAC15(ADD); } +microVUf(void) mVU_MADDAy() { mVU_FMAC15(ADD); } +microVUf(void) mVU_MADDAz() { mVU_FMAC15(ADD); } +microVUf(void) mVU_MADDAw() { mVU_FMAC15(ADD); } microVUf(void) mVU_MSUB() { mVU_FMAC9(SUB); } microVUf(void) mVU_MSUBi() { mVU_FMAC13(SUB); } microVUf(void) mVU_MSUBq() { mVU_FMAC25(SUB); } @@ -590,12 +514,12 @@ microVUf(void) mVU_MSUBy() { mVU_FMAC11(SUB); } microVUf(void) mVU_MSUBz() { mVU_FMAC11(SUB); } microVUf(void) mVU_MSUBw() { mVU_FMAC11(SUB); } microVUf(void) mVU_MSUBA() { mVU_FMAC14(SUB); } -microVUf(void) mVU_MSUBAi() { mVU_FMAC21(SUB); } -microVUf(void) mVU_MSUBAq() { mVU_FMAC27(SUB); } -microVUf(void) mVU_MSUBAx() { mVU_FMAC17(SUB); } -microVUf(void) mVU_MSUBAy() { mVU_FMAC17(SUB); } -microVUf(void) mVU_MSUBAz() { mVU_FMAC17(SUB); } -microVUf(void) mVU_MSUBAw() { mVU_FMAC17(SUB); } +microVUf(void) mVU_MSUBAi() { mVU_FMAC16(SUB); } +microVUf(void) mVU_MSUBAq() { mVU_FMAC26(SUB); } +microVUf(void) mVU_MSUBAx() { mVU_FMAC15(SUB); } +microVUf(void) mVU_MSUBAy() { mVU_FMAC15(SUB); } +microVUf(void) mVU_MSUBAz() { mVU_FMAC15(SUB); } +microVUf(void) mVU_MSUBAw() { mVU_FMAC15(SUB); } microVUf(void) mVU_MAX() { mVU_FMAC1(MAX); } microVUf(void) mVU_MAXi() { mVU_FMAC6(MAX); } microVUf(void) mVU_MAXx() { mVU_FMAC3(MAX); } diff --git a/pcsx2_suite_2008.sln b/pcsx2_suite_2008.sln index e87a5e8853..7084a22005 100644 --- a/pcsx2_suite_2008.sln +++ b/pcsx2_suite_2008.sln @@ -9,18 +9,18 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pcsx2", "pcsx2\windows\VCpr {2F6C0388-20CB-4242-9F6C-A6EBB6A83F47} = {2F6C0388-20CB-4242-9F6C-A6EBB6A83F47} EndProjectSection EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ZeroGS", "plugins\zerogs\dx\Win32\zerogs_2008.vcproj", "{5C6B7D28-E73D-4F71-8FC0-17ADA640EBD8}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ZeroGS", "plugins\zerogs\dx\Windows\zerogs_2008.vcproj", "{5C6B7D28-E73D-4F71-8FC0-17ADA640EBD8}" ProjectSection(ProjectDependencies) = postProject {2F6C0388-20CB-4242-9F6C-A6EBB6A83F47} = {2F6C0388-20CB-4242-9F6C-A6EBB6A83F47} EndProjectSection EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CDVDiso", "plugins\CDVDiso\src\Win32\CDVDiso_vs2008.vcproj", "{5F78E90B-BD22-47B1-9CA5-7A80F4DF5EF3}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CDVDiso", "plugins\CDVDiso\src\Windows\CDVDiso_vs2008.vcproj", "{5F78E90B-BD22-47B1-9CA5-7A80F4DF5EF3}" ProjectSection(ProjectDependencies) = postProject {2F6C0388-20CB-4242-9F6C-A6EBB6A83F47} = {2F6C0388-20CB-4242-9F6C-A6EBB6A83F47} {F4EB4AB2-C595-4B05-8BC0-059024BC796C} = {F4EB4AB2-C595-4B05-8BC0-059024BC796C} EndProjectSection EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SPU2-X", "plugins\spu2-x\src\Win32\Spu2-X_vs2008.vcproj", "{5307BBB7-EBB9-4AA4-8CB6-A94EC473C8C4}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SPU2-X", "plugins\spu2-x\src\Windows\Spu2-X_vs2008.vcproj", "{5307BBB7-EBB9-4AA4-8CB6-A94EC473C8C4}" ProjectSection(ProjectDependencies) = postProject {E9B51944-7E6D-4BCD-83F2-7BBD5A46182D} = {E9B51944-7E6D-4BCD-83F2-7BBD5A46182D} EndProjectSection @@ -37,7 +37,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LilyPad", "plugins\LilyPad\ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pthreads", "3rdparty\w32pthreads\pthreads_2008.vcproj", "{26511268-2902-4997-8421-ECD7055F9E28}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ZeroSPU2", "plugins\zerospu2\Win32\ZeroSPU2_2008.vcproj", "{7F059854-568D-4E08-9D00-1E78E203E4DC}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ZeroSPU2", "plugins\zerospu2\Windows\ZeroSPU2_2008.vcproj", "{7F059854-568D-4E08-9D00-1E78E203E4DC}" ProjectSection(ProjectDependencies) = postProject {E9B51944-7E6D-4BCD-83F2-7BBD5A46182D} = {E9B51944-7E6D-4BCD-83F2-7BBD5A46182D} {26511268-2902-4997-8421-ECD7055F9E28} = {26511268-2902-4997-8421-ECD7055F9E28} @@ -49,9 +49,9 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CDVDolio", "plugins\CDVDoli EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CDVDnull", "plugins\CDVDnull\Src\CDVDnull_vs2008.vcproj", "{F38D9DF0-F68D-49D9-B3A0-932E74FB74A0}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "USBnull", "plugins\USBnull\Win32\USBnull_vc2008.vcproj", "{BF7B81A5-E348-4F7C-A69F-F74C8EEEAD70}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "USBnull", "plugins\USBnull\Windows\USBnull_vc2008.vcproj", "{BF7B81A5-E348-4F7C-A69F-F74C8EEEAD70}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FWnull", "plugins\FWnull\Win32\FWnull_vc2008.vcproj", "{3D0EB14D-32F3-4D82-9C6D-B806ADBB859C}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FWnull", "plugins\FWnull\Windows\FWnull_vc2008.vcproj", "{3D0EB14D-32F3-4D82-9C6D-B806ADBB859C}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DEV9null", "plugins\dev9null\src\DEV9null_vc2008.vcproj", "{04439C5F-05FB-4A9C-AAD1-5388C25377DB}" EndProject diff --git a/plugins/CDVDiso/src/Win32/CDVDiso.def b/plugins/CDVDiso/src/Windows/CDVDiso.def similarity index 100% rename from plugins/CDVDiso/src/Win32/CDVDiso.def rename to plugins/CDVDiso/src/Windows/CDVDiso.def diff --git a/plugins/CDVDiso/src/Win32/CDVDiso.rc b/plugins/CDVDiso/src/Windows/CDVDiso.rc similarity index 100% rename from plugins/CDVDiso/src/Win32/CDVDiso.rc rename to plugins/CDVDiso/src/Windows/CDVDiso.rc diff --git a/plugins/CDVDiso/src/Win32/CDVDiso_vs2008.vcproj b/plugins/CDVDiso/src/Windows/CDVDiso_vs2008.vcproj similarity index 93% rename from plugins/CDVDiso/src/Win32/CDVDiso_vs2008.vcproj rename to plugins/CDVDiso/src/Windows/CDVDiso_vs2008.vcproj index 11e46d2720..652155f757 100644 --- a/plugins/CDVDiso/src/Win32/CDVDiso_vs2008.vcproj +++ b/plugins/CDVDiso/src/Windows/CDVDiso_vs2008.vcproj @@ -48,7 +48,7 @@ UsePrecompiledHeader="0" BrowseInformation="1" WarningLevel="3" - DebugInformationFormat="3" + DebugInformationFormat="4" CompileAs="0" /> (); + int dx = p.extract32<1>(); + if(side) { while(1) { do { - if((top % m_threads) == m_id) + int xi = x >> 16; + int xf = x & 0xffff; + + if(scissor.x <= xi && xi < scissor.z && (xi % m_threads) == m_id) { - GSVector4 p = edge.p.ceil(); - - if(((fscissor.xxxx() < p) & (p <= fscissor.zzzz())).mask() & 1) - { - GSVector4 coverage = (p - edge.p).xxxx(); + m_stats.pixels++; - edge.t = edge.t.xyxy(edge.t.uph(coverage * 0x80)); // coverage => t.w + edge.t.u32[3] = (0x10000 - xf) & 0xffff; - int x = GSVector4i(p).extract32<0>() - 1; - - m_stats.pixels++; - - m_dsf.ssle(x + 1, x, top, edge); - } + m_dsf.ssle(xi + 1, xi, top, edge); + + edge.t.u32[3] = 0; } } while(0); @@ -696,6 +701,7 @@ void GSRasterizer::DrawEdge(const GSVertexSW& v0, const GSVertexSW& v1, const GS if(++top >= bottom) break; edge += dedge; + x += dx; } } else @@ -704,22 +710,18 @@ void GSRasterizer::DrawEdge(const GSVertexSW& v0, const GSVertexSW& v1, const GS { do { - if((top % m_threads) == m_id) + int xi = (x >> 16) + 1; + int xf = x & 0xffff; + + if(scissor.x <= xi && xi < scissor.z && (xi % m_threads) == m_id) { - GSVector4 p = edge.p.floor(); - - if(((fscissor.xxxx() <= p) & (p < fscissor.zzzz())).mask() & 1) - { - GSVector4 coverage = (edge.p - p).xxxx(); + m_stats.pixels++; - edge.t = edge.t.xyxy(edge.t.uph(coverage * 0x80)); // coverage => t.w + edge.t.u32[3] = xf; - int x = GSVector4i(p).extract32<0>() + 1; + m_dsf.ssle(xi + 1, xi, top, edge); - m_stats.pixels++; - - m_dsf.ssle(x + 1, x, top, edge); - } + edge.t.u32[3] = 0; } } while(0); @@ -727,6 +729,7 @@ void GSRasterizer::DrawEdge(const GSVertexSW& v0, const GSVertexSW& v1, const GS if(++top >= bottom) break; edge += dedge; + x += dx; } } } @@ -766,28 +769,29 @@ void GSRasterizer::DrawEdge(const GSVertexSW& v0, const GSVertexSW& v1, const GS edge += dedge * (lrmax.yyyy() - edge.p.xxxx()); } + GSVector4i p = GSVector4i(edge.p.upl(dedge.p) * 0x10000); + + int y = p.extract32<2>(); + int dy = p.extract32<3>(); + if(side) { while(1) { do { - GSVector4 p = edge.p.ceil(); - - if(((fscissor.yyyy() < p) & (p <= fscissor.wwww())).mask() & 2) + int yi = y >> 16; + int yf = y & 0xffff; + + if(scissor.y <= yi && yi < scissor.w && (yi % m_threads) == m_id) { - int y = GSVector4i(p).extract32<1>() - 1; + m_stats.pixels++; - if((y % m_threads) == m_id) - { - GSVector4 coverage = (p - edge.p).yyyy(); + edge.t.u32[3] = (0x10000 - yf) & 0xffff; - edge.t = edge.t.xyxy(edge.t.uph(coverage * 0x80)); // coverage => t.w - - m_stats.pixels++; - - m_dsf.ssle(left + 1, left, y, edge); - } + m_dsf.ssle(left + 1, left, yi, edge); + + edge.t.u32[3] = 0; } } while(0); @@ -795,6 +799,7 @@ void GSRasterizer::DrawEdge(const GSVertexSW& v0, const GSVertexSW& v1, const GS if(++left >= right) break; edge += dedge; + y += dy; } } else @@ -803,22 +808,18 @@ void GSRasterizer::DrawEdge(const GSVertexSW& v0, const GSVertexSW& v1, const GS { do { - GSVector4 p = edge.p.floor(); - - if(((fscissor.yyyy() <= p) & (p < fscissor.wwww())).mask() & 2) + int yi = (y >> 16) + 1; + int yf = y & 0xffff; + + if(scissor.y <= yi && yi < scissor.w && (yi % m_threads) == m_id) { - int y = GSVector4i(p).extract32<1>() + 1; + m_stats.pixels++; - if((y % m_threads) == m_id) - { - GSVector4 coverage = (edge.p - p).yyyy(); + edge.t.u32[3] = yf; - edge.t = edge.t.xyxy(edge.t.uph(coverage * 0x80)); // coverage => t.w - - m_stats.pixels++; - - m_dsf.ssle(left + 1, left, y, edge); - } + m_dsf.ssle(left + 1, left, yi, edge); + + edge.t.u32[3] = 0; } } while(0); @@ -826,6 +827,7 @@ void GSRasterizer::DrawEdge(const GSVertexSW& v0, const GSVertexSW& v1, const GS if(++left >= right) break; edge += dedge; + y += dy; } } } diff --git a/plugins/GSdx/GSState.cpp b/plugins/GSdx/GSState.cpp index 3920f19301..e3f98cb122 100644 --- a/plugins/GSdx/GSState.cpp +++ b/plugins/GSdx/GSState.cpp @@ -107,6 +107,8 @@ GSState::GSState(BYTE* base, bool mt, void (*irq)(), int nloophack) BUSDIR = (GSRegBUSDIR*)(base + GS_BUSDIR); SIGLBLID = (GSRegSIGLBLID*)(base + GS_SIGLBLID); + memset(PMODE, 0, 0x1100); + PRIM = &m_env.PRIM; // CSR->rREV = 0x20; m_env.PRMODECONT.AC = 1; diff --git a/plugins/LilyPad/Config.cpp b/plugins/LilyPad/Config.cpp index 21d3855697..2b956fefd1 100644 --- a/plugins/LilyPad/Config.cpp +++ b/plugins/LilyPad/Config.cpp @@ -29,10 +29,41 @@ HWND hWndProp = 0; int selected = 0; -HWND hWnds[2] = {0,0}; +HWND hWnds[2][4]; HWND hWndGeneral = 0; -void Populate(int pad); +struct GeneralSettingsBool { + wchar_t *name; + unsigned int ControlId; + u8 defaultValue; +}; + +// Ties together config data structure, config files, and general config +// dialog. +const GeneralSettingsBool BoolOptionsInfo[] = { + {L"Force Cursor Hide", IDC_FORCE_HIDE, 0}, + {L"Mouse Unfocus", IDC_MOUSE_UNFOCUS, 1}, + {L"Background", IDC_BACKGROUND, 1}, + {L"Multiple Bindings", IDC_MULTIPLE_BINDING, 0}, + + {L"DirectInput Game Devices", IDC_G_DI, 1}, + {L"XInput", IDC_G_XI, 1}, + + {L"Multitap 1", IDC_MULTITAP1, 0}, + {L"Multitap 2", IDC_MULTITAP2, 0}, + + {L"GS Thread Updates", IDC_GS_THREAD_INPUT, 1}, + {L"Escape Fullscreen Hack", IDC_ESCAPE_FULLSCREEN_HACK, 1}, + {L"Disable Screen Saver", IDC_DISABLE_SCREENSAVER, 1}, + {L"Logging", IDC_DEBUG_FILE, 0}, + + {L"Save State in Title", IDC_SAVE_STATE_TITLE, 1}, + {L"GH2", IDC_GH2_HACK, 0}, + + {L"Vista Volume", IDC_VISTA_VOLUME, 1}, +}; + +void Populate(int port, int slot); void SetupLogSlider(HWND hWndSlider) { SendMessage(hWndSlider, TBM_SETRANGEMIN, 0, 1); @@ -122,18 +153,6 @@ void RefreshEnabledDevices(int updateDeviceList) { else dm->DisableDevice(i); } - - // Older code. Newer version is a bit uglier, but doesn't - // release devices that are enabled both before and afterwards. - // So a bit nicer, in theory. - /* - dm->DisableAllDevices(); - dm->EnableDevices(KEYBOARD, config.keyboardApi); - dm->EnableDevices(MOUSE, config.mouseApi); - if (config.gameApis.directInput) { - dm->EnableDevices(OTHER, DI); - } - //*/ } // Disables/enables devices as necessary. Also updates diagnostic list @@ -173,28 +192,17 @@ void RefreshEnabledDevicesAndDisplay(int updateDeviceList = 0, HWND hWnd = 0, in } } if (populate) { - Populate(0); - Populate(1); + for (int i=0; i<8; i++) { + Populate(i&1, i>>1); + } } } -wchar_t *GetCommandStringW(u8 command, int pad) { +wchar_t *GetCommandStringW(u8 command, int port, int slot) { static wchar_t temp[34]; - if (command >= 0x30 && command <= 0x35) { - if (config.guitar[pad] && (command == 0x31 || command == 0x33)) { - HWND hWnd = GetDlgItem(hWnds[pad], 0x10F0+command); - int res = GetWindowTextW(hWnd, temp, 20); - if ((unsigned int)res-1 <= 18) return temp; - } - static wchar_t *axisCommands[] = { - L"D-Pad Horiz", L"D-Pad Vert", - L"L-Stick Horiz", L"L-Stick Vert", - L"R-Stick Horiz", L"R-Stick Vert"}; - return axisCommands[command-0x30]; - } if (command >= 0x20 && command <= 0x27) { - if (config.guitar[pad] && (command == 0x20 || command == 0x22)) { - HWND hWnd = GetDlgItem(hWnds[pad], 0x10F0+command); + if (config.padConfigs[port][slot].type == GuitarPad && (command == 0x20 || command == 0x22)) { + HWND hWnd = GetDlgItem(hWnds[port][slot], 0x10F0+command); int res = GetWindowTextW(hWnd, temp, 20); if ((unsigned int)res-1 <= 18) return temp; } @@ -206,9 +214,42 @@ wchar_t *GetCommandStringW(u8 command, int pad) { return temp; } /* Get text from the buttons. */ - if (command >= 0x0B && command <=0x28 || - (command >= 0x36 && command <=0x38)) { - HWND hWnd = GetDlgItem(hWnds[pad], 0x10F0+command); + if (command >= 0x0C && command <=0x28) { + HWND hWnd = GetDlgItem(hWnds[port][slot], 0x10F0+command); + if (!hWnd) { + wchar_t *strings[] = { + L"Lock Buttons", + L"Lock Input", + L"Lock Direction", + L"Mouse", + L"Select", + L"L3", + L"R3", + L"Start", + L"Up", + L"Right", + L"Down", + L"Left", + L"L2", + L"R2", + L"L1", + L"R1", + L"Triangle", + L"Circle", + L"Square", + L"Cross", + L"L-Stick Up", + L"L-Stick Right", + L"L-Stick Down", + L"L-Stick Left", + L"R-Stick Up", + L"R-Stick Right", + L"R-Stick Down", + L"R-Stick Left", + L"Analog", + }; + return strings[command - 0xC]; + } int res = GetWindowTextW(hWnd, temp, 20); if ((unsigned int)res-1 <= 18) return temp; } @@ -222,13 +263,13 @@ inline void GetSettingsFileName(wchar_t *out) { wcscpy(out, L"inis\\LilyPad.ini"); } -int GetBinding(int pad, int index, Device *&dev, Binding *&b, ForceFeedbackBinding *&ffb); -int BindCommand(Device *dev, unsigned int uid, unsigned int pad, int command, int sensitivity, int turbo); +int GetBinding(int port, int slot, int index, Device *&dev, Binding *&b, ForceFeedbackBinding *&ffb); +int BindCommand(Device *dev, unsigned int uid, unsigned int port, unsigned int slot, int command, int sensitivity, int turbo); -int CreateEffectBinding(Device *dev, wchar_t *effectName, unsigned int pad, unsigned int motor, ForceFeedbackBinding **binding); +int CreateEffectBinding(Device *dev, wchar_t *effectName, unsigned int port, unsigned int slot, unsigned int motor, ForceFeedbackBinding **binding); -void SelChanged(int pad) { - HWND hWnd = hWnds[pad]; +void SelChanged(int port, int slot) { + HWND hWnd = hWnds[port][slot]; if (!hWnd) return; HWND hWndTemp, hWndList = GetDlgItem(hWnd, IDC_LIST); int j, i = ListView_GetSelectedCount(hWndList); @@ -241,32 +282,53 @@ void SelChanged(int pad) { // Set if sensitivity != 0, but need to disable flip anyways. // Only used to relative axes. int disableFlip = 0; - wchar_t temp[3][1000]; + wchar_t temp[4][1000]; Device *dev; int bFound = 0; int ffbFound = 0; ForceFeedbackBinding *ffb = 0; + Binding *b = 0; if (i >= 1) { int index = -1; int flipped = 0; - Binding *b; while (1) { index = ListView_GetNextItem(hWndList, index, LVNI_SELECTED); if (index < 0) break; LVITEMW item; item.iItem = index; item.mask = LVIF_TEXT; + item.pszText = temp[3]; for (j=0; j<3; j++) { - item.pszText = temp[j]; item.iSubItem = j; - item.cchTextMax = sizeof(temp[0])/sizeof(temp[0][0]); + item.cchTextMax = sizeof(temp[0])/sizeof(temp[3][0]); if (!ListView_GetItem(hWndList, &item)) break; + if (!bFound && !ffbFound) + wcscpy(temp[j], temp[3]); + else if (wcsicmp(temp[j], temp[3])) { + int q = 0; + while (temp[j][q] == temp[3][q]) q++; + if (q && temp[j][q-1] == ' ' && temp[j][q] && temp[j][q+1] == 0) q--; + if (j == 1) { + // Really ugly, but merges labels for multiple directions for same axis. + if ((temp[j][q] == 0 || (temp[j][q] == ' ' && temp[j][q+2] == 0)) && + (temp[3][q] == 0 || (temp[3][q] == ' ' && temp[3][q+2] == 0))) { + temp[j][q] = 0; + continue; + } + } + // Merge different directions for same stick. + else if (j == 2 && q > 4) { + temp[j][q] = 0; + continue; + } + wcscpy(temp[j], L"*"); + } } if (j == 3) { devName = temp[0]; key = temp[1]; command = temp[2]; - if (GetBinding(pad, index, dev, b, ffb)) { + if (GetBinding(port, slot, index, dev, b, ffb)) { if (b) { bFound ++; VirtualControl *control = &dev->virtualControls[b->controlIndex]; @@ -352,10 +414,6 @@ void SelChanged(int pad) { } } if (!ffb) { - SetWindowText(GetDlgItem(hWnd, IDC_AXIS_DEVICE1), devName); - SetWindowText(GetDlgItem(hWnd, IDC_AXIS1), key); - SetWindowText(GetDlgItem(hWnd, IDC_AXIS_CONTROL1), command); - SetLogSliderVal(hWnd, IDC_SLIDER1, GetDlgItem(hWnd, IDC_AXIS_SENSITIVITY1), sensitivity); if (disableFlip) EnableWindow(GetDlgItem(hWnd, IDC_FLIP1), 0); @@ -369,11 +427,45 @@ void SelChanged(int pad) { SendMessage(GetDlgItem(hWnd, IDC_TURBO), BM_SETSTYLE, BS_AUTOCHECKBOX, 0); CheckDlgButton(hWnd, IDC_TURBO, BST_CHECKED * (bFound && turbo == bFound)); } + HWND hWndCombo = GetDlgItem(hWnd, IDC_AXIS_DIRECTION); + int enableCombo = 0; + SendMessage(hWndCombo, CB_RESETCONTENT, 0, 0); + if (b && bFound == 1) { + VirtualControl *control = &dev->virtualControls[b->controlIndex]; + unsigned int uid = control->uid; + if (((uid>>16) & 0xFF) == ABSAXIS) { + enableCombo = 1; + wchar_t *endings[3] = {L" -", L" +", L""}; + wchar_t *string = temp[3]; + wcscpy(string, key); + wchar_t *end = wcschr(string, 0); + int sel = 2; + if (!(uid & UID_AXIS)) { + end[-2] = 0; + sel = (end[-1] == '+'); + end -= 2; + } + for (int i=0; i<3; i++) { + wcscpy(end, endings[i]); + SendMessage(hWndCombo, CB_ADDSTRING, 0, (LPARAM) string); + if (i == sel) + SendMessage(hWndCombo, CB_SETCURSEL, i, 0); + } + } + } + EnableWindow(hWndCombo, enableCombo); + if (!enableCombo) { + SendMessage(hWndCombo, CB_ADDSTRING, 0, (LPARAM) key); + SendMessage(hWndCombo, CB_SELECTSTRING, i, (LPARAM) key); + } + + SetDlgItemText(hWnd, IDC_AXIS_DEVICE1, devName); + SetDlgItemText(hWnd, IDC_AXIS_CONTROL1, command); } else { wchar_t temp2[2000]; wsprintfW(temp2, L"%s / %s", devName, command); - SetWindowText(GetDlgItem(hWnd, ID_FF), temp2); + SetDlgItemText(hWnd, ID_FF, temp2); hWndTemp = GetDlgItem(hWnd, IDC_FF_EFFECT); SendMessage(hWndTemp, CB_RESETCONTENT, 0, 0); @@ -394,40 +486,40 @@ void UnselectAll(HWND hWnd) { } -int GetItemIndex(int pad, Device *dev, ForceFeedbackBinding *binding) { +int GetItemIndex(int port, int slot, Device *dev, ForceFeedbackBinding *binding) { int count = 0; for (int i = 0; inumDevices; i++) { Device *dev2 = dm->devices[i]; if (!dev2->enabled) continue; if (dev2 != dev) { - count += dev2->pads[pad].numBindings + dev2->pads[pad].numFFBindings; + count += dev2->pads[port][slot].numBindings + dev2->pads[port][slot].numFFBindings; continue; } - return count += dev2->pads[pad].numBindings + (binding - dev2->pads[pad].ffBindings); + return count += dev2->pads[port][slot].numBindings + (binding - dev2->pads[port][slot].ffBindings); } return -1; } -int GetItemIndex(int pad, Device *dev, Binding *binding) { +int GetItemIndex(int port, int slot, Device *dev, Binding *binding) { int count = 0; for (int i = 0; inumDevices; i++) { Device *dev2 = dm->devices[i]; if (!dev2->enabled) continue; if (dev2 != dev) { - count += dev2->pads[pad].numBindings + dev2->pads[pad].numFFBindings; + count += dev2->pads[port][slot].numBindings + dev2->pads[port][slot].numFFBindings; continue; } - return count += binding - dev->pads[pad].bindings; + return count += binding - dev->pads[port][slot].bindings; } return -1; } // Doesn't check if already displayed. -int ListBoundCommand(int pad, Device *dev, Binding *b) { - if (!hWnds[pad]) return -1; - HWND hWndList = GetDlgItem(hWnds[pad], IDC_LIST); +int ListBoundCommand(int port, int slot, Device *dev, Binding *b) { + if (!hWnds[port][slot]) return -1; + HWND hWndList = GetDlgItem(hWnds[port][slot], IDC_LIST); int index = -1; if (hWndList) { - index = GetItemIndex(pad, dev, b); + index = GetItemIndex(port, slot, dev, b); if (index >= 0) { LVITEM item; item.mask = LVIF_TEXT; @@ -440,19 +532,19 @@ int ListBoundCommand(int pad, Device *dev, Binding *b) { item.pszText = dev->GetVirtualControlName(&dev->virtualControls[b->controlIndex]); SendMessage(hWndList, LVM_SETITEM, 0, (LPARAM)&item); item.iSubItem = 2; - item.pszText = GetCommandStringW(b->command, pad); + item.pszText = GetCommandStringW(b->command, port, slot); SendMessage(hWndList, LVM_SETITEM, 0, (LPARAM)&item); } } return index; } -int ListBoundEffect(int pad, Device *dev, ForceFeedbackBinding *b) { - if (!hWnds[pad]) return -1; - HWND hWndList = GetDlgItem(hWnds[pad], IDC_LIST); +int ListBoundEffect(int port, int slot, Device *dev, ForceFeedbackBinding *b) { + if (!hWnds[port][slot]) return -1; + HWND hWndList = GetDlgItem(hWnds[port][slot], IDC_LIST); int index = -1; if (hWndList) { - index = GetItemIndex(pad, dev, b); + index = GetItemIndex(port, slot, dev, b); if (index >= 0) { LVITEM item; item.mask = LVIF_TEXT; @@ -474,9 +566,9 @@ int ListBoundEffect(int pad, Device *dev, ForceFeedbackBinding *b) { } // Only for use with control bindings. Affects all highlighted bindings. -void ChangeValue(int pad, int *newSensitivity, int *turbo) { - if (!hWnds[pad]) return; - HWND hWndList = GetDlgItem(hWnds[pad], IDC_LIST); +void ChangeValue(int port, int slot, int *newSensitivity, int *turbo) { + if (!hWnds[port][slot]) return; + HWND hWndList = GetDlgItem(hWnds[port][slot], IDC_LIST); int count = ListView_GetSelectedCount(hWndList); if (count < 1) return; int index = -1; @@ -486,7 +578,7 @@ void ChangeValue(int pad, int *newSensitivity, int *turbo) { Device *dev; Binding *b; ForceFeedbackBinding *ffb; - if (!GetBinding(pad, index, dev, b, ffb) || ffb) return; + if (!GetBinding(port, slot, index, dev, b, ffb) || ffb) return; if (newSensitivity) { // Don't change flip state when modifying multiple controls. if (count > 1 && b->sensitivity < 0) @@ -498,21 +590,21 @@ void ChangeValue(int pad, int *newSensitivity, int *turbo) { b->turbo = *turbo; } } - PropSheet_Changed(hWndProp, hWnds[pad]); - SelChanged(pad); + PropSheet_Changed(hWndProp, hWnds[port][slot]); + SelChanged(port, slot); } // Only for use with effect bindings. -void ChangeEffect(int pad, int id, int *newForce, unsigned int *newEffectType) { - if (!hWnds[pad]) return; - HWND hWndList = GetDlgItem(hWnds[pad], IDC_LIST); +void ChangeEffect(int port, int slot, int id, int *newForce, unsigned int *newEffectType) { + if (!hWnds[port][slot]) return; + HWND hWndList = GetDlgItem(hWnds[port][slot], IDC_LIST); int i = ListView_GetSelectedCount(hWndList); if (i != 1) return; int index = ListView_GetNextItem(hWndList, -1, LVNI_SELECTED); Device *dev; Binding *b; ForceFeedbackBinding *ffb; - if (!GetBinding(pad, index, dev, b, ffb) || b) return; + if (!GetBinding(port, slot, index, dev, b, ffb) || b) return; if (newForce) { unsigned int axisIndex = (id - IDC_FF_AXIS1_ENABLED)/16; if (axisIndex < (unsigned int)dev->numFFAxes) { @@ -522,18 +614,18 @@ void ChangeEffect(int pad, int id, int *newForce, unsigned int *newEffectType) { if (newEffectType && *newEffectType < (unsigned int)dev->numFFEffectTypes) { ffb->effectIndex = *newEffectType; ListView_DeleteItem(hWndList, index); - index = ListBoundEffect(pad, dev, ffb); + index = ListBoundEffect(port, slot, dev, ffb); ListView_SetItemState(hWndList, index, LVIS_SELECTED, LVIS_SELECTED); } - PropSheet_Changed(hWndProp, hWnds[pad]); - SelChanged(pad); + PropSheet_Changed(hWndProp, hWnds[port][slot]); + SelChanged(port, slot); } -void Populate(int pad) { - if (!hWnds[pad]) return; - HWND hWnd = GetDlgItem(hWnds[pad], IDC_LIST); +void Populate(int port, int slot) { + if (!hWnds[port][slot]) return; + HWND hWnd = GetDlgItem(hWnds[port][slot], IDC_LIST); ListView_DeleteAllItems(hWnd); int i, j; @@ -542,16 +634,16 @@ void Populate(int pad) { for (j=0; jnumDevices; j++) { Device *dev = dm->devices[j]; if (!dev->enabled) continue; - for (i=0; ipads[pad].numBindings; i++) { - ListBoundCommand(pad, dev, dev->pads[pad].bindings+i); + for (i=0; ipads[port][slot].numBindings; i++) { + ListBoundCommand(port, slot, dev, dev->pads[port][slot].bindings+i); } - for (i=0; ipads[pad].numFFBindings; i++) { - ListBoundEffect(pad, dev, dev->pads[pad].ffBindings+i); + for (i=0; ipads[port][slot].numFFBindings; i++) { + ListBoundEffect(port, slot, dev, dev->pads[port][slot].ffBindings+i); } } config.multipleBinding = multipleBinding; - hWnd = GetDlgItem(hWnds[pad], IDC_FORCEFEEDBACK); + hWnd = GetDlgItem(hWnds[port][slot], IDC_FORCEFEEDBACK); SendMessage(hWnd, CB_RESETCONTENT, 0, 0); int added = 0; for (i=0; inumDevices; i++) { @@ -564,10 +656,10 @@ void Populate(int pad) { } SendMessage(hWnd, CB_SETCURSEL, 0, 0); EnableWindow(hWnd, added!=0); - EnableWindow(GetDlgItem(hWnds[pad], ID_BIG_MOTOR), added!=0); - EnableWindow(GetDlgItem(hWnds[pad], ID_SMALL_MOTOR), added!=0); + EnableWindow(GetDlgItem(hWnds[port][slot], ID_BIG_MOTOR), added!=0); + EnableWindow(GetDlgItem(hWnds[port][slot], ID_SMALL_MOTOR), added!=0); - SelChanged(pad); + SelChanged(port, slot); } int WritePrivateProfileInt(wchar_t *s1, wchar_t *s2, int v, wchar_t *ini) { @@ -576,7 +668,21 @@ int WritePrivateProfileInt(wchar_t *s1, wchar_t *s2, int v, wchar_t *ini) { return WritePrivateProfileStringW(s1, s2, temp, ini); } -int SaveSettings(wchar_t *file = 0) { +void SetVolume(int volume) { + if (volume > 100) volume = 100; + if (volume < 0) volume = 0; + config.volume = volume; + unsigned int val = 0xFFFF * volume/100; + val = val | (val<<16); + for (int i=waveOutGetNumDevs()-1; i>=0; i--) { + waveOutSetVolume((HWAVEOUT)i, val); + } + wchar_t ini[MAX_PATH+20]; + GetSettingsFileName(ini); + WritePrivateProfileInt(L"General Settings", L"Volume", config.volume, ini); +} + +int SaveSettings(wchar_t *file=0) { wchar_t ini[MAX_PATH+20]; // Need this either way for saving path. @@ -598,32 +704,28 @@ int SaveSettings(wchar_t *file = 0) { WritePrivateProfileStringW(L"General Settings", L"Last Config Path", config.lastSaveConfigPath, ini); WritePrivateProfileStringW(L"General Settings", L"Last Config Name", config.lastSaveConfigFileName, ini); - WritePrivateProfileInt(L"General Settings", L"Force Cursor Hide", config.forceHide, file); + // Just check first, last, and all pad bindings. Should be more than enough. No real need to check + // config path. + int noError = 1; + + for (int i=0; inumDevices; i++) { wchar_t id[50]; @@ -644,33 +746,36 @@ int SaveSettings(wchar_t *file = 0) { } WritePrivateProfileInt(id, L"API", dev->api, file); WritePrivateProfileInt(id, L"Type", dev->type, file); + int ffBindingCount = 0; int bindingCount = 0; - for (int pad=0; pad<2; pad++) { - for (int j=0; jpads[pad].numBindings; j++) { - Binding *b = dev->pads[pad].bindings+j; - VirtualControl *c = &dev->virtualControls[b->controlIndex]; - wsprintfW(temp, L"Binding %i", bindingCount++); - wsprintfW(temp2, L"0x%08X, %i, %i, %i, %i", c->uid, pad, b->command, b->sensitivity, b->turbo); - WritePrivateProfileStringW(id, temp, temp2, file); - } - } - bindingCount = 0; - for (int pad=0; pad<2; pad++) { - for (int j=0; jpads[pad].numFFBindings; j++) { - ForceFeedbackBinding *b = dev->pads[pad].ffBindings+j; - ForceFeedbackEffectType *eff = &dev->ffEffectTypes[b->effectIndex]; - wsprintfW(temp, L"FF Binding %i", bindingCount++); - wsprintfW(temp2, L"%s %i, %i", eff->effectID, pad, b->motor); - for (int k=0; knumFFAxes; k++) { - ForceFeedbackAxis *axis = dev->ffAxes + k; - AxisEffectInfo *info = b->axes + k; - wsprintfW(wcschr(temp2,0), L", %i, %i", axis->id, info->force); + for (int port=0; port<2; port++) { + for (int slot=0; slot<4; slot++) { + for (int j=0; jpads[port][slot].numBindings; j++) { + Binding *b = dev->pads[port][slot].bindings+j; + VirtualControl *c = &dev->virtualControls[b->controlIndex]; + wsprintfW(temp, L"Binding %i", bindingCount++); + wsprintfW(temp2, L"0x%08X, %i, %i, %i, %i, %i", c->uid, port, b->command, b->sensitivity, b->turbo, slot); + noError &= WritePrivateProfileStringW(id, temp, temp2, file); + } + for (int j=0; jpads[port][slot].numFFBindings; j++) { + ForceFeedbackBinding *b = dev->pads[port][slot].ffBindings+j; + ForceFeedbackEffectType *eff = &dev->ffEffectTypes[b->effectIndex]; + wsprintfW(temp, L"FF Binding %i", ffBindingCount++); + wsprintfW(temp2, L"%s %i, %i, %i", eff->effectID, port, b->motor, slot); + for (int k=0; knumFFAxes; k++) { + ForceFeedbackAxis *axis = dev->ffAxes + k; + AxisEffectInfo *info = b->axes + k; + wsprintfW(wcschr(temp2,0), L", %i, %i", axis->id, info->force); + } + noError &= WritePrivateProfileStringW(id, temp, temp2, file); } - WritePrivateProfileStringW(id, temp, temp2, file); } } } - return 0; + if (!noError) { + MessageBoxA(hWndProp, "Unable to save settings. Make sure the disk is not full or write protected, the file isn't write protected, and that the app has permissions to write to the directory. On Vista, try running in administrator mode.", "Error Writing Configuration File", MB_OK | MB_ICONERROR); + } + return !noError; } static int loaded = 0; @@ -706,34 +811,28 @@ int LoadSettings(int force, wchar_t *file) { } } - config.GSThreadUpdates = GetPrivateProfileBool(L"General Settings", L"GS Thread Updates", 1, file); + for (int i=0; i= 5 && type) { VirtualControl *c = dev->GetVirtualControl(uid); if (!c) c = dev->AddVirtualControl(uid, -1); if (c) { - BindCommand(dev, uid, pad, command, sensitivity, turbo); + BindCommand(dev, uid, port, slot, command, sensitivity, turbo); } } } @@ -818,7 +922,7 @@ int LoadSettings(int force, wchar_t *file) { continue; } last = 1; - int pad, motor; + int port, slot, motor; int w = 0; char string[1000]; char effect[1000]; @@ -829,8 +933,8 @@ int LoadSettings(int force, wchar_t *file) { string[w] = 0; // wcstok not in ntdll. More effore than its worth to shave off // whitespace without it. - if (sscanf(string, " %s %i , %i", effect, &pad, &motor) == 3) { - char *s = strchr(strchr(string, ',')+1, ','); + if (sscanf(string, " %s %i , %i , %i", effect, &port, &motor, &slot) == 4) { + char *s = strchr(strchr(strchr(string, ',')+1, ',')+1, ','); if (!s) continue; s++; w = 0; @@ -847,7 +951,7 @@ int LoadSettings(int force, wchar_t *file) { // eff = &dev->ffEffectTypes[dev->numFFEffectTypes-1]; } ForceFeedbackBinding *b; - int res = CreateEffectBinding(dev, temp2, pad, motor, &b); + CreateEffectBinding(dev, temp2, port, slot, motor, &b); if (b) { while (1) { int axisID = atoi(s); @@ -876,10 +980,14 @@ int LoadSettings(int force, wchar_t *file) { return 0; } -inline int GetPAD(HWND hWnd) { - for (int i=0; i>1] == hWnd) { + *slot = i>>1; + return i&1; + } } + *slot = 0; return 0; } @@ -898,95 +1006,94 @@ void Diagnostics(HWND hWnd) { RefreshEnabledDevicesAndDisplay(0, hWnd, 1); } -int GetBinding(int pad, int index, Device *&dev, Binding *&b, ForceFeedbackBinding *&ffb) { +int GetBinding(int port, int slot, int index, Device *&dev, Binding *&b, ForceFeedbackBinding *&ffb) { ffb = 0; b = 0; for (int i = 0; inumDevices; i++) { dev = dm->devices[i]; if (!dev->enabled) continue; - if (index < dev->pads[pad].numBindings) { - b = dev->pads[pad].bindings + index; + if (index < dev->pads[port][slot].numBindings) { + b = dev->pads[port][slot].bindings + index; return 1; } - index -= dev->pads[pad].numBindings; + index -= dev->pads[port][slot].numBindings; - if (index < dev->pads[pad].numFFBindings) { - ffb = dev->pads[pad].ffBindings + index; + if (index < dev->pads[port][slot].numFFBindings) { + ffb = dev->pads[port][slot].ffBindings + index; return 1; } - index -= dev->pads[pad].numFFBindings; + index -= dev->pads[port][slot].numFFBindings; } return 0; } // Only used when deleting things from ListView. Will remove from listview if needed. -void DeleteBinding(int pad, Device *dev, Binding *b) { - if (dev->enabled && hWnds[pad]) { - int count = GetItemIndex(pad, dev, b); +void DeleteBinding(int port, int slot, Device *dev, Binding *b) { + if (dev->enabled && hWnds[port][slot]) { + int count = GetItemIndex(port, slot, dev, b); if (count >= 0) { - HWND hWndList = GetDlgItem(hWnds[pad], IDC_LIST); + HWND hWndList = GetDlgItem(hWnds[port][slot], IDC_LIST); if (hWndList) { ListView_DeleteItem(hWndList, count); } } } - Binding *bindings = dev->pads[pad].bindings; + Binding *bindings = dev->pads[port][slot].bindings; int i = b - bindings; - memmove(bindings+i, bindings+i+1, sizeof(Binding) * (dev->pads[pad].numBindings - i - 1)); - dev->pads[pad].numBindings--; + memmove(bindings+i, bindings+i+1, sizeof(Binding) * (dev->pads[port][slot].numBindings - i - 1)); + dev->pads[port][slot].numBindings--; } -void DeleteBinding(int pad, Device *dev, ForceFeedbackBinding *b) { - if (dev->enabled && hWnds[pad]) { - int count = GetItemIndex(pad, dev, b); +void DeleteBinding(int port, int slot, Device *dev, ForceFeedbackBinding *b) { + if (dev->enabled && hWnds[port][slot]) { + int count = GetItemIndex(port, slot, dev, b); if (count >= 0) { - HWND hWndList = GetDlgItem(hWnds[pad], IDC_LIST); + HWND hWndList = GetDlgItem(hWnds[port][slot], IDC_LIST); if (hWndList) { ListView_DeleteItem(hWndList, count); } } } - ForceFeedbackBinding *bindings = dev->pads[pad].ffBindings; + ForceFeedbackBinding *bindings = dev->pads[port][slot].ffBindings; int i = b - bindings; - memmove(bindings+i, bindings+i+1, sizeof(Binding) * (dev->pads[pad].numFFBindings - i - 1)); - dev->pads[pad].numFFBindings--; + memmove(bindings+i, bindings+i+1, sizeof(Binding) * (dev->pads[port][slot].numFFBindings - i - 1)); + dev->pads[port][slot].numFFBindings--; } -int DeleteByIndex(int pad, int index) { +int DeleteByIndex(int port, int slot, int index) { ForceFeedbackBinding *ffb; Binding *b; Device *dev; - if (GetBinding(pad, index, dev, b, ffb)) { + if (GetBinding(port, slot, index, dev, b, ffb)) { if (b) { - DeleteBinding(pad, dev, b); + DeleteBinding(port, slot, dev, b); } else { - DeleteBinding(pad, dev, ffb); + DeleteBinding(port, slot, dev, ffb); } return 1; } return 0; } -int DeleteSelected(int pad) { - if (!hWnds[pad]) return 0; - HWND hWnd = GetDlgItem(hWnds[pad], IDC_LIST); - int i = ListView_GetSelectedCount(hWnd); +int DeleteSelected(int port, int slot) { + if (!hWnds[port][slot]) return 0; + HWND hWnd = GetDlgItem(hWnds[port][slot], IDC_LIST); int changes = 0; - while (i-- > 0) { + while (1) { int index = ListView_GetNextItem(hWnd, -1, LVNI_SELECTED); - if (index >= 0) { - changes += DeleteByIndex(pad, index); - } + if (index < 0) break; + changes += DeleteByIndex(port, slot, index); } //ShowScrollBar(hWnd, SB_VERT, 1); return changes; } -int CreateEffectBinding(Device *dev, wchar_t *effectID, unsigned int pad, unsigned int motor, ForceFeedbackBinding **binding) { +int CreateEffectBinding(Device *dev, wchar_t *effectID, unsigned int port, unsigned int slot, unsigned int motor, ForceFeedbackBinding **binding) { // Checks needed because I use this directly when loading bindings. // Note: dev->numFFAxes *can* be 0, for loading from file. - if (pad > 1 || motor > 1 || !dev->numFFEffectTypes) { + *binding = 0; + if (port > 1 || slot>3 || motor > 1 || !dev->numFFEffectTypes) { return -1; } if (!effectID) { @@ -995,24 +1102,24 @@ int CreateEffectBinding(Device *dev, wchar_t *effectID, unsigned int pad, unsign ForceFeedbackEffectType *eff = dev->GetForcefeedbackEffect(effectID); if (!eff) return -1; int effectIndex = eff - dev->ffEffectTypes; - dev->pads[pad].ffBindings = (ForceFeedbackBinding*) realloc(dev->pads[pad].ffBindings, (dev->pads[pad].numFFBindings+1) * sizeof(ForceFeedbackBinding)); - int newIndex = dev->pads[pad].numFFBindings; - while (newIndex && dev->pads[pad].ffBindings[newIndex-1].motor >= motor) { - dev->pads[pad].ffBindings[newIndex] = dev->pads[pad].ffBindings[newIndex-1]; + dev->pads[port][slot].ffBindings = (ForceFeedbackBinding*) realloc(dev->pads[port][slot].ffBindings, (dev->pads[port][slot].numFFBindings+1) * sizeof(ForceFeedbackBinding)); + int newIndex = dev->pads[port][slot].numFFBindings; + while (newIndex && dev->pads[port][slot].ffBindings[newIndex-1].motor >= motor) { + dev->pads[port][slot].ffBindings[newIndex] = dev->pads[port][slot].ffBindings[newIndex-1]; newIndex--; } - ForceFeedbackBinding *b = dev->pads[pad].ffBindings + newIndex; + ForceFeedbackBinding *b = dev->pads[port][slot].ffBindings + newIndex; b->axes = (AxisEffectInfo*) calloc(dev->numFFAxes, sizeof(AxisEffectInfo)); b->motor = motor; b->effectIndex = effectIndex; - dev->pads[pad].numFFBindings++; + dev->pads[port][slot].numFFBindings++; if (binding) *binding = b; - return ListBoundEffect(pad, dev, b); + return ListBoundEffect(port, slot, dev, b); } -int BindCommand(Device *dev, unsigned int uid, unsigned int pad, int command, int sensitivity, int turbo) { +int BindCommand(Device *dev, unsigned int uid, unsigned int port, unsigned int slot, int command, int sensitivity, int turbo) { // Checks needed because I use this directly when loading bindings. - if (pad > 1) { + if (port > 1 || slot>3) { return -1; } if (!sensitivity) sensitivity = BASE_SENSITIVITY; @@ -1025,7 +1132,7 @@ int BindCommand(Device *dev, unsigned int uid, unsigned int pad, int command, in // Add before deleting. Means I won't scroll up one line when scrolled down to bottom. int controlIndex = c - dev->virtualControls; int index = 0; - PadBindings *p = dev->pads+pad; + PadBindings *p = dev->pads[port]+slot; p->bindings = (Binding*) realloc(p->bindings, (p->numBindings+1) * sizeof(Binding)); for (index = p->numBindings; index > 0; index--) { if (p->bindings[index-1].controlIndex < controlIndex) break; @@ -1038,7 +1145,7 @@ int BindCommand(Device *dev, unsigned int uid, unsigned int pad, int command, in b->turbo = turbo; b->sensitivity = sensitivity; // Where it appears in listview. - int count = ListBoundCommand(pad, dev, b); + int count = ListBoundCommand(port, slot, dev, b); int newBindingIndex = index; index = 0; @@ -1066,7 +1173,23 @@ int BindCommand(Device *dev, unsigned int uid, unsigned int pad, int command, in newBindingIndex--; count --; } - DeleteBinding(pad, dev, b); + DeleteBinding(port, slot, dev, b); + } + if (!config.multipleBinding) { + for (int port2=0; port2<2; port2++) { + for (int slot2=0; slot2<4; slot2++) { + if (port2==port && slot2 == slot) continue; + PadBindings *p = dev->pads[port2]+slot2; + for (int i=0; i < p->numBindings; i++) { + Binding *b = p->bindings+i; + int uid2 = dev->virtualControls[b->controlIndex].uid; + if (b->controlIndex == controlIndex || (!((uid2^uid) & 0xFFFFFF) && ((uid|uid2) & (UID_POV | UID_AXIS)))) { + DeleteBinding(port2, slot2, dev, b); + i--; + } + } + } + } } return count; @@ -1105,7 +1228,8 @@ void EndBinding(HWND hWnd) { INT_PTR CALLBACK DialogProc(HWND hWnd, unsigned int msg, WPARAM wParam, LPARAM lParam) { int index = (hWnd == PropSheet_IndexToHwnd(hWndProp, 1)); - int pad = GetPAD(hWnd); + int slot; + int port = GetPort(hWnd, &slot); HWND hWndList = GetDlgItem(hWnd, IDC_LIST); switch (msg) { case WM_INITDIALOG: @@ -1123,14 +1247,16 @@ INT_PTR CALLBACK DialogProc(HWND hWnd, unsigned int msg, WPARAM wParam, LPARAM l c.pszText = L"PS2 Control"; ListView_InsertColumn(hWndList, 2, &c); selected = 0; - hWnds[pad = (int)((PROPSHEETPAGE *)lParam)->lParam] = hWnd; + port = (int)((PROPSHEETPAGE *)lParam)->lParam & 1; + slot = (int)((PROPSHEETPAGE *)lParam)->lParam >> 1; + hWnds[port][slot] = hWnd; SendMessage(hWndList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT); HWND hWndSlider = GetDlgItem(hWnd, IDC_SLIDER1); SetupLogSlider(hWndSlider); - if (pad == 1) + if (port || slot) EnableWindow(GetDlgItem(hWnd, ID_IGNORE), 0); - Populate(pad); + Populate(port, slot); } break; case WM_DEVICECHANGE: @@ -1149,16 +1275,7 @@ INT_PTR CALLBACK DialogProc(HWND hWnd, unsigned int msg, WPARAM wParam, LPARAM l unsigned int uid; int value; InitInfo info = {selected==0x7F, hWndProp, hWnd, GetDlgItem(hWnd, selected)}; - int hint = 0; - if (selected < 0x30) { - // 1 will accept absolute axes, in addition to buttons. - hint = config.axisButtons; - } - else if (selected < 0x7F) { - // 2 will accept relative axes, absolute axes, and POV controls. - hint = 2; - } - Device *dev = dm->GetActiveDevice(&info, hint, &uid, &index, &value); + Device *dev = dm->GetActiveDevice(&info, &uid, &index, &value); if (dev) { int command = selected; // Good idea to do this first, as BindCommand modifies the ListView, which will @@ -1166,89 +1283,15 @@ INT_PTR CALLBACK DialogProc(HWND hWnd, unsigned int msg, WPARAM wParam, LPARAM l EndBinding(hWnd); UnselectAll(hWndList); int index = -1; - if (command == 0x7F) { - if (dev->api == IGNORE_KEYBOARD) { - index = BindCommand(dev, uid, 0, command, BASE_SENSITIVITY, 0); - } + if (command == 0x7F && dev->api == IGNORE_KEYBOARD) { + index = BindCommand(dev, uid, 0, 0, command, BASE_SENSITIVITY, 0); } else if (command < 0x30) { - if (!(uid & UID_POV)) { - index = BindCommand(dev, uid, pad, command, BASE_SENSITIVITY, 0); - } - } - else { - int v[4]; - int base = 0; - if (command == 0x30 || command == 0x31) { - base = 0x14; - } - else if (command == 0x32 || command == 0x33) { - base = 0x20; - } - else if (command == 0x34 || command == 0x35) { - base = 0x24; - } - else if (command == 0x36) { - base = 0x1B; - } - else if (command == 0x37) { - base = 0x19; - } - else if (command == 0x38) { - base = 0x12; - } - if (base) { - // Lx/Rx - if (base & 3) { - v[0] = base; - v[2] = base-1; - v[1]=v[3] = 0; - } - else { - if (command & 1) { - v[0] = base; - v[1] = base+1; - v[2] = base+2; - v[3] = base+3; - } - else { - v[0] = base+1; - v[1] = base+2; - v[2] = base+3; - v[3] = base; - } - } - if (uid & UID_POV) { - int rotate = 0; - while (value > 4500) { - rotate++; - value -= 9000; - } - index = BindCommand(dev, (uid&~UID_POV)|UID_POV_N, pad, v[(4-rotate)%4], BASE_SENSITIVITY, 0); - ListView_SetItemState(hWndList, index, LVIS_SELECTED, LVIS_SELECTED); - index = BindCommand(dev, (uid&~UID_POV)|UID_POV_E, pad, v[(5-rotate)%4], BASE_SENSITIVITY, 0); - ListView_SetItemState(hWndList, index, LVIS_SELECTED, LVIS_SELECTED); - index = BindCommand(dev, (uid&~UID_POV)|UID_POV_S, pad, v[(6-rotate)%4], BASE_SENSITIVITY, 0); - ListView_SetItemState(hWndList, index, LVIS_SELECTED, LVIS_SELECTED); - index = BindCommand(dev, (uid&~UID_POV)|UID_POV_W, pad, v[(7-rotate)%4], BASE_SENSITIVITY, 0); - } - else if (uid & UID_AXIS) { - int b1 = v[0]; - int b2 = v[2]; - if (value < 0) { - b1 = v[2]; - b2 = v[0]; - } - index = BindCommand(dev, (uid&~UID_AXIS)|UID_AXIS_POS, pad, b1, BASE_SENSITIVITY, 0); - ListView_SetItemState(hWndList, index, LVIS_SELECTED, LVIS_SELECTED); - index = BindCommand(dev, (uid&~UID_AXIS)|UID_AXIS_NEG, pad, b2, BASE_SENSITIVITY, 0); - } - } + index = BindCommand(dev, uid, port, slot, command, BASE_SENSITIVITY, 0); } if (index >= 0) { - PropSheet_Changed(hWndProp, hWnds[pad]); - if (index >= 0) - ListView_SetItemState(hWndList, index, LVIS_SELECTED, LVIS_SELECTED); + PropSheet_Changed(hWndProp, hWnds[port][slot]); + ListView_SetItemState(hWndList, index, LVIS_SELECTED, LVIS_SELECTED); } } } @@ -1278,6 +1321,7 @@ INT_PTR CALLBACK DialogProc(HWND hWnd, unsigned int msg, WPARAM wParam, LPARAM l SetWindowLong(hWnd, DWL_MSGRESULT, PSNRET_NOERROR); return 1; } + break; } else if (n->hdr.idFrom == IDC_LIST) { static int NeedUpdate = 0; @@ -1286,7 +1330,7 @@ INT_PTR CALLBACK DialogProc(HWND hWnd, unsigned int msg, WPARAM wParam, LPARAM l if (key->wVKey == VK_DELETE || key->wVKey == VK_BACK) { - if (DeleteSelected(pad)) + if (DeleteSelected(port, slot)) PropSheet_Changed(hWndProp, hWnds[0]); } } @@ -1299,13 +1343,11 @@ INT_PTR CALLBACK DialogProc(HWND hWnd, unsigned int msg, WPARAM wParam, LPARAM l } else if (n->hdr.code == NM_CUSTOMDRAW && NeedUpdate) { NeedUpdate = 0; - SelChanged(pad); + SelChanged(port, slot); } - EndBinding(hWnd); - } - else { - EndBinding(hWnd); } + // Stop binding when user does something else. + EndBinding(hWnd); } break; case WM_HSCROLL: @@ -1313,31 +1355,49 @@ INT_PTR CALLBACK DialogProc(HWND hWnd, unsigned int msg, WPARAM wParam, LPARAM l int id = GetDlgCtrlID((HWND)lParam); int val = GetLogSliderVal(hWnd, id); if (id == IDC_SLIDER1) { - ChangeValue(pad, &val, 0); + ChangeValue(port, slot, &val, 0); } else { - ChangeEffect(pad, id, &val, 0); + ChangeEffect(port, slot, id, &val, 0); } } break; case WM_COMMAND: - if (HIWORD(wParam)==CBN_SELCHANGE && LOWORD(wParam) == IDC_FF_EFFECT) { - unsigned int typeIndex = SendMessage((HWND)lParam, CB_GETCURSEL, 0, 0); + if (HIWORD(wParam)==CBN_SELCHANGE && LOWORD(wParam) == IDC_AXIS_DIRECTION) { + int index = ListView_GetNextItem(hWndList, -1, LVNI_SELECTED); + if (index >= 0) { + int cbsel = SendMessage((HWND)lParam, CB_GETCURSEL, 0, 0); + if (cbsel >= 0) { + ForceFeedbackBinding *ffb; + Binding *b; + Device *dev; + if (GetBinding(port, slot, index, dev, b, ffb)) { + const static unsigned int axisUIDs[3] = {UID_AXIS_NEG, UID_AXIS_POS, UID_AXIS}; + int uid = dev->virtualControls[b->controlIndex].uid; + uid = (uid&0x00FFFFFF) | axisUIDs[cbsel]; + Binding backup = *b; + DeleteSelected(port, slot); + int index = BindCommand(dev, uid, port, slot, backup.command, backup.sensitivity, backup.turbo); + ListView_SetItemState(hWndList, index, LVIS_SELECTED, LVIS_SELECTED); + PropSheet_Changed(hWndProp, hWnd); + } + } + } + } + else if (HIWORD(wParam)==CBN_SELCHANGE && LOWORD(wParam) == IDC_FF_EFFECT) { + int typeIndex = SendMessage((HWND)lParam, CB_GETCURSEL, 0, 0); if (typeIndex >= 0) - ChangeEffect(pad, 0, 0, &typeIndex); + ChangeEffect(port, slot, 0, 0, (unsigned int*)&typeIndex); } else if (HIWORD(wParam)==BN_CLICKED) { EndBinding(hWnd); int cmd = LOWORD(wParam); if (cmd == ID_DELETE) { - if (DeleteSelected(pad)) + if (DeleteSelected(port, slot)) PropSheet_Changed(hWndProp, hWnd); } else if (cmd == ID_CLEAR) { - int changed=0; - while (DeleteByIndex(pad, 0)) changed++; - if (changed) - PropSheet_Changed(hWndProp, hWnd); + while (DeleteByIndex(port, slot, 0)) PropSheet_Changed(hWndProp, hWnd); } else if (cmd == ID_BIG_MOTOR || cmd == ID_SMALL_MOTOR) { int i = (int)SendMessage(GetDlgItem(hWnd, IDC_FORCEFEEDBACK), CB_GETCURSEL, 0, 0); @@ -1345,7 +1405,7 @@ INT_PTR CALLBACK DialogProc(HWND hWnd, unsigned int msg, WPARAM wParam, LPARAM l unsigned int index = (unsigned int)SendMessage(GetDlgItem(hWnd, IDC_FORCEFEEDBACK), CB_GETITEMDATA, i, 0); if (index < (unsigned int) dm->numDevices) { ForceFeedbackBinding *b; - int count = CreateEffectBinding(dm->devices[index], 0, pad, cmd-ID_BIG_MOTOR, &b); + int count = CreateEffectBinding(dm->devices[index], 0, port, slot, cmd-ID_BIG_MOTOR, &b); if (b) { for (int j=0; j<2 && j devices[index]->numFFAxes; j++) { b->axes[j].force = BASE_SENSITIVITY; @@ -1368,7 +1428,7 @@ INT_PTR CALLBACK DialogProc(HWND hWnd, unsigned int msg, WPARAM wParam, LPARAM l ForceFeedbackBinding *ffb = 0; int selIndex = ListView_GetNextItem(hWndList, -1, LVNI_SELECTED); if (selIndex >= 0) { - if (GetBinding(pad, selIndex, dev, b, ffb)) { + if (GetBinding(port, slot, selIndex, dev, b, ffb)) { selected = 0xFF; InitInfo info = {0, hWndProp, hWnd, GetDlgItem(hWnd, cmd)}; EatWndProc(info.hWndButton, DoNothingWndProc); @@ -1384,7 +1444,7 @@ INT_PTR CALLBACK DialogProc(HWND hWnd, unsigned int msg, WPARAM wParam, LPARAM l } } } - else if ((cmd >= ID_GUITAR_HERO && cmd <= ID_L3R3) || cmd == ID_IGNORE) {// || cmd == ID_FORCE_FEEDBACK) { + else if ((cmd >= ID_GUITAR_HERO && cmd <= ID_ANALOG) || cmd == ID_IGNORE) {// || cmd == ID_FORCE_FEEDBACK) { // Messes up things, unfortunately. // End binding on a bunch of notification messages, and // this will send a bunch. @@ -1407,23 +1467,28 @@ INT_PTR CALLBACK DialogProc(HWND hWnd, unsigned int msg, WPARAM wParam, LPARAM l InitInfo info = {selected==0x7F, hWndProp, hWnd, GetDlgItem(hWnd, cmd)}; EatWndProc(info.hWndButton, DoNothingWndProc); + int w = timeGetTime(); dm->Update(&info); dm->PostRead(); // Workaround for things that return 0 on first poll and something else ever after. - Sleep(200); + Sleep(40); dm->Update(&info); dm->PostRead(); - SetTimer(hWnd, 1, 100, 0); + int w2 = timeGetTime(); + if (dm->devices[0xe]->oldVirtualControlState[6] != 0x8000) { + dm->devices[0xe]->oldVirtualControlState[6]=dm->devices[0xe]->oldVirtualControlState[6]; + } + SetTimer(hWnd, 1, 30, 0); } if (cmd == IDC_TURBO) { // Don't allow setting it back to indeterminate. SendMessage(GetDlgItem(hWnd, IDC_TURBO), BM_SETSTYLE, BS_AUTOCHECKBOX, 0); int turbo = (IsDlgButtonChecked(hWnd, IDC_TURBO) == BST_CHECKED); - ChangeValue(pad, 0, &turbo); + ChangeValue(port, slot, 0, &turbo); } else if (cmd == IDC_FLIP1 || cmd == IDC_TURBO) { int val = GetLogSliderVal(hWnd, IDC_SLIDER1); - ChangeValue(pad, &val, 0); + ChangeValue(port, slot, &val, 0); } else if (cmd >= IDC_FF_AXIS1_ENABLED && cmd < IDC_FF_AXIS8_ENABLED + 16) { int index = (cmd - IDC_FF_AXIS1_ENABLED)/16; @@ -1431,7 +1496,7 @@ INT_PTR CALLBACK DialogProc(HWND hWnd, unsigned int msg, WPARAM wParam, LPARAM l if (IsDlgButtonChecked(hWnd, 16*index + IDC_FF_AXIS1_ENABLED) != BST_CHECKED) { val = 0; } - ChangeEffect(pad, cmd, &val, 0); + ChangeEffect(port, slot, cmd, &val, 0); } } break; @@ -1441,29 +1506,45 @@ INT_PTR CALLBACK DialogProc(HWND hWnd, unsigned int msg, WPARAM wParam, LPARAM l return 0; } -int CreatePadPages(HPROPSHEETPAGE *pages) { +void UpdatePadPages() { + HPROPSHEETPAGE pages[10]; int count = 0; - for (int pad=0; pad<2; pad++) { - if (config.disablePad[pad]) continue; - PROPSHEETPAGE psp; - ZeroMemory(&psp, sizeof(psp)); - psp.dwSize = sizeof(psp); - psp.dwFlags = PSP_USETITLE | PSP_PREMATURE; - psp.hInstance = hInst; - psp.pfnDlgProc = (DLGPROC) DialogProc; - psp.lParam = pad; - if (pad == 0) - psp.pszTitle = L"Pad 1"; - else - psp.pszTitle = L"Pad 2"; - if (!config.guitar[pad]) - psp.pszTemplate = MAKEINTRESOURCE(IDD_CONFIG); - else - psp.pszTemplate = MAKEINTRESOURCE(IDD_CONFIG_GUITAR); - pages[count] = CreatePropertySheetPage(&psp); - if (pages[count]) count++; + memset(hWnds, 0, sizeof(hWnds)); + int slot = 0; + for (int port=0; port<2; port++) { + for (int slot=0; slot<4; slot++) { + if (config.padConfigs[port][slot].type == DisabledPad) continue; + wchar_t title[20]; + if (!slot) { + wsprintfW(title, L"Pad %i", port+1); + } + else { + if (!config.multitap[port]) continue; + wsprintfW(title, L"Pad %i-%i", port+1, slot+1); + } + + PROPSHEETPAGE psp; + ZeroMemory(&psp, sizeof(psp)); + psp.dwSize = sizeof(psp); + psp.dwFlags = PSP_USETITLE | PSP_PREMATURE; + psp.hInstance = hInst; + psp.pfnDlgProc = (DLGPROC) DialogProc; + psp.lParam = port | (slot<<1); + psp.pszTitle = title; + if (config.padConfigs[port][slot].type != GuitarPad) + psp.pszTemplate = MAKEINTRESOURCE(IDD_CONFIG); + else + psp.pszTemplate = MAKEINTRESOURCE(IDD_CONFIG_GUITAR); + pages[count] = CreatePropertySheetPage(&psp); + if (pages[count]) count++; + } + } + while (SendMessage(hWndProp, PSM_INDEXTOPAGE, 1, 0)) { + PropSheet_RemovePage(hWndProp, 1, 0); + } + for (int i=0; i= 2 + 3*(config.multitap[0]+config.multitap[1])) { + *port = 0; + *slot = 0; + return 0; + } + if (index < 1 + 3*config.multitap[0]) { + *port = 0; + *slot = index; + } + else { + *port = 1; + *slot = index-1-3*config.multitap[0]; + } + return 1; +} + +void UpdatePadList(HWND hWnd) { + HWND hWndList = GetDlgItem(hWnd, IDC_PAD_LIST); + HWND hWndCombo = GetDlgItem(hWnd, IDC_PAD_TYPE); + HWND hWndAnalog = GetDlgItem(hWnd, IDC_ANALOG_START1); + int slot; + int port; + int index = 0; + wchar_t *strings[] = {L"Disabled", L"Dualshock 2", L"Guitar"}; + for (port=0; port<2; port++) { + for (slot = 0; slot<4; slot++) { + wchar_t text[100]; + if (!slot) + wsprintf(text, L"Pad %i", port+1); + else { + if (!config.multitap[port]) continue; + wsprintf(text, L"Pad %i-%i", port+1, slot+1); + } + LVITEM item; + item.iItem = index; + item.iSubItem = 0; + item.mask = LVIF_TEXT; + item.pszText = text; + if (SendMessage(hWndList, LVM_GETITEMCOUNT, 0, 0) <= index) { + ListView_InsertItem(hWndList, &item); + } + else { + ListView_SetItem(hWndList, &item); + } + + item.iSubItem = 1; + if (2 < (unsigned int)config.padConfigs[port][slot].type) config.padConfigs[port][slot].type = Dualshock2Pad; + item.pszText = strings[config.padConfigs[port][slot].type]; + ListView_SetItem(hWndList, &item); + + item.iSubItem = 2; + int count = 0; + for (int i = 0; inumDevices; i++) { + Device *dev = dm->devices[i]; + if (!dev->enabled) continue; + count += dev->pads[port][slot].numBindings + dev->pads[port][slot].numFFBindings; + } + wsprintf(text, L"%i", count); + item.pszText = text; + ListView_SetItem(hWndList, &item); + index++; + } + } + while (ListView_DeleteItem(hWndList, index)); + int sel = ListView_GetNextItem(hWndList, -1, LVNI_SELECTED); + + int enable; + if (!ListIndexToPortAndSlot(sel, &port, &slot)) { + enable = 0; + SendMessage(hWndCombo, CB_SETCURSEL, -1, 0); + CheckDlgButton(hWnd, IDC_ANALOG_START1, BST_UNCHECKED); + } + else { + enable = 1; + SendMessage(hWndCombo, CB_SETCURSEL, config.padConfigs[port][slot].type, 0); + CheckDlgButton(hWnd, IDC_ANALOG_START1, BST_CHECKED*config.padConfigs[port][slot].autoAnalog); + } + EnableWindow(hWndCombo, enable); + EnableWindow(hWndAnalog, enable); +} INT_PTR CALLBACK GeneralDialogProc(HWND hWnd, unsigned int msg, WPARAM wParam, LPARAM lParam) { int i; + HWND hWndList = GetDlgItem(hWnd, IDC_PAD_LIST); switch (msg) { case WM_INITDIALOG: { - HPROPSHEETPAGE pages[10]; - int count = CreatePadPages(pages); - while (SendMessage(hWndProp, PSM_INDEXTOPAGE, 1, 0)) { - PropSheet_RemovePage(hWndProp, 1, 0); - } - for (int i=0; i>1)); - CheckDlgButton(hWnd, IDC_CLOSE_HACK3, BST_CHECKED * ((config.closeHacks&4)>>2)); - CheckDlgButton(hWnd, IDC_DISABLE_PAD1, BST_CHECKED * config.disablePad[0]); - CheckDlgButton(hWnd, IDC_DISABLE_PAD2, BST_CHECKED * config.disablePad[1]); - CheckDlgButton(hWnd, IDC_MOUSE_UNFOCUS, BST_CHECKED * config.mouseUnfocus); - CheckDlgButton(hWnd, IDC_GS_THREAD_INPUT, BST_CHECKED * config.GSThreadUpdates); if (!ps2e) { EnableWindow(GetDlgItem(hWnd, IDC_GS_THREAD_INPUT), 0); } - CheckDlgButton(hWnd, IDC_ESCAPE_FULLSCREEN_HACK, BST_CHECKED * config.escapeFullscreenHack); - CheckDlgButton(hWnd, IDC_DISABLE_SCREENSAVER, BST_CHECKED * config.disableScreenSaver); - CheckDlgButton(hWnd, IDC_GH2_HACK, BST_CHECKED * config.GH2); - CheckDlgButton(hWnd, IDC_SAVE_STATE_TITLE, BST_CHECKED * config.saveStateTitle); - - CheckDlgButton(hWnd, IDC_GUITAR1, BST_CHECKED * config.guitar[0]); - CheckDlgButton(hWnd, IDC_GUITAR2, BST_CHECKED * config.guitar[1]); - CheckDlgButton(hWnd, IDC_ANALOG_START1, BST_CHECKED * config.AutoAnalog[0]); - CheckDlgButton(hWnd, IDC_ANALOG_START2, BST_CHECKED * config.AutoAnalog[1]); - CheckDlgButton(hWnd, IDC_DEBUG_FILE, BST_CHECKED * config.debug); - CheckDlgButton(hWnd, IDC_AXIS_BUTTONS, BST_CHECKED * config.axisButtons); - CheckDlgButton(hWnd, IDC_MULTIPLE_BINDING, BST_CHECKED * config.multipleBinding); + if (config.osVersion < 6) EnableWindow(GetDlgItem(hWnd, IDC_VISTA_VOLUME), 0); if (config.keyboardApi < 0 || config.keyboardApi > 3) config.keyboardApi = NO_API; CheckRadioButton(hWnd, IDC_KB_DISABLE, IDC_KB_RAW, IDC_KB_DISABLE + config.keyboardApi); if (config.mouseApi < 0 || config.mouseApi > 3) config.mouseApi = NO_API; CheckRadioButton(hWnd, IDC_M_DISABLE, IDC_M_RAW, IDC_M_DISABLE + config.mouseApi); - CheckDlgButton(hWnd, IDC_G_DI, BST_CHECKED * config.gameApis.directInput); - CheckDlgButton(hWnd, IDC_G_XI, BST_CHECKED * config.gameApis.xInput); - if (!InitializeRawInput()) { EnableWindow(GetDlgItem(hWnd, IDC_KB_RAW), 0); @@ -1542,10 +1702,27 @@ INT_PTR CALLBACK GeneralDialogProc(HWND hWnd, unsigned int msg, WPARAM wParam, L case WM_DEVICECHANGE: if (wParam == DBT_DEVNODES_CHANGED) { RefreshEnabledDevicesAndDisplay(1, hWndGeneral, 1); + UpdatePadList(hWnd); } break; case WM_COMMAND: - if (HIWORD(wParam)==BN_CLICKED && (LOWORD(wParam) == ID_LOAD || LOWORD(wParam) == ID_SAVE)) { + if (LOWORD(wParam) == IDC_PAD_TYPE) { + if (HIWORD(wParam) == CBN_SELCHANGE) { + HWND hWndCombo = GetDlgItem(hWnd, IDC_PAD_TYPE); + int index = ListView_GetNextItem(hWndList, -1, LVNI_SELECTED); + int sel = SendMessage(hWndCombo, CB_GETCURSEL, 0, 0); + int port, slot; + if (sel < 0 || !ListIndexToPortAndSlot(index, &port, &slot)) break; + if (sel != config.padConfigs[port][slot].type) { + config.padConfigs[port][slot].type = (PadType)sel; + UpdatePadList(hWnd); + UpdatePadPages(); + RefreshEnabledDevicesAndDisplay(0, hWnd, 1); + PropSheet_Changed(hWndProp, hWnd); + } + } + } + else if (HIWORD(wParam)==BN_CLICKED && (LOWORD(wParam) == ID_LOAD || LOWORD(wParam) == ID_SAVE)) { OPENFILENAMEW ofn; memset (&ofn, 0, sizeof(ofn)); ofn.lStructSize = sizeof(ofn); @@ -1563,6 +1740,7 @@ INT_PTR CALLBACK GeneralDialogProc(HWND hWnd, unsigned int msg, WPARAM wParam, L if (GetOpenFileNameW(&ofn)) { LoadSettings(1, ofn.lpstrFile); GeneralDialogProc(hWnd, WM_INITDIALOG, 0, 0); + PropSheet_Changed(hWndProp, hWnd); } } else { @@ -1583,6 +1761,14 @@ INT_PTR CALLBACK GeneralDialogProc(HWND hWnd, unsigned int msg, WPARAM wParam, L } else if (HIWORD(wParam)==BN_CLICKED && LOWORD(wParam) == ID_REFRESH) { RefreshEnabledDevicesAndDisplay(1, hWnd, 1); + UpdatePadList(hWnd); + } + else if (HIWORD(wParam)==BN_CLICKED && LOWORD(wParam) == IDC_ANALOG_START1) { + int index = ListView_GetNextItem(hWndList, -1, LVNI_SELECTED); + int port, slot; + if (!ListIndexToPortAndSlot(index, &port, &slot)) break; + config.padConfigs[port][slot].autoAnalog = (IsDlgButtonChecked(hWnd, IDC_ANALOG_START1) == BST_CHECKED); + PropSheet_Changed(hWndProp, hWnd); } else { int t = IDC_CLOSE_HACK1; @@ -1594,60 +1780,19 @@ INT_PTR CALLBACK GeneralDialogProc(HWND hWnd, unsigned int msg, WPARAM wParam, L CheckDlgButton(hWnd, IDC_CLOSE_HACK1, BST_UNCHECKED); } - config.forceHide = (IsDlgButtonChecked(hWnd, IDC_FORCE_HIDE) == BST_CHECKED); + int mtap = config.multitap[0] + 2*config.multitap[1]; + + for (int j=0; jhdr.idFrom == IDC_LIST && n->hdr.code == NM_DBLCLK) { - Diagnostics(hWnd); + else if (n->hdr.idFrom == IDC_LIST && n->hdr.code == NM_DBLCLK) { + Diagnostics(hWnd); + } + else if (n->hdr.idFrom == IDC_PAD_LIST) { + if (n->hdr.code == NM_CLICK) { + UpdatePadList(hWnd); } } } @@ -1748,7 +1890,7 @@ void CALLBACK PADconfigure() { psh.pszCaption = title; PropertySheet(&psh); LoadSettings(1); - hWnds[0] = hWnds[1] = 0; + memset(hWnds, 0, sizeof(hWnds)); } void UnloadConfigs() { diff --git a/plugins/LilyPad/Config.h b/plugins/LilyPad/Config.h index 24ded457f7..368d53d699 100644 --- a/plugins/LilyPad/Config.h +++ b/plugins/LilyPad/Config.h @@ -6,37 +6,60 @@ extern u8 ps2e; +enum PadType { + DisabledPad, + Dualshock2Pad, + GuitarPad +}; + +struct PadConfig { + PadType type; + u8 autoAnalog; +}; + struct GeneralConfig { public: - u8 disablePad[2]; + PadConfig padConfigs[2][4]; - u8 mouseUnfocus; - u8 disableScreenSaver; u8 closeHacks; - u8 axisButtons; DeviceAPI keyboardApi; DeviceAPI mouseApi; - struct { - u8 directInput; - u8 xInput; - } gameApis; - u8 debug; - u8 background; - u8 multipleBinding; - u8 forceHide; - u8 GH2; // Derived value, calculated by GetInput(). u8 ignoreKeys; - u8 GSThreadUpdates; - u8 escapeFullscreenHack; + union { + struct { + u8 forceHide; + u8 mouseUnfocus; + u8 background; + u8 multipleBinding; - u8 guitar[2]; - u8 AutoAnalog[2]; + struct { + u8 directInput; + u8 xInput; + } gameApis; - u8 saveStateTitle; + u8 multitap[2]; + + u8 GSThreadUpdates; + u8 escapeFullscreenHack; + u8 disableScreenSaver; + u8 debug; + + u8 saveStateTitle; + u8 GH2; + + u8 vistaVolume; + }; + u8 bools[1]; + }; + + int volume; + + // Unlike the others, not a changeable value. + DWORD osVersion; wchar_t lastSaveConfigPath[MAX_PATH+1]; wchar_t lastSaveConfigFileName[MAX_PATH+1]; @@ -48,6 +71,8 @@ void UnloadConfigs(); void AddIgnore(LPARAM k); +void SetVolume(int volume); + int LoadSettings(int force = 0, wchar_t *file = 0); void CALLBACK PADconfigure(); diff --git a/plugins/LilyPad/Diagnostics.cpp b/plugins/LilyPad/Diagnostics.cpp index 9efab71a60..07c2f3812a 100644 --- a/plugins/LilyPad/Diagnostics.cpp +++ b/plugins/LilyPad/Diagnostics.cpp @@ -8,12 +8,12 @@ Device *dev; -INT_PTR CALLBACK DiagDialog(HWND hWnd, unsigned int msg, WPARAM wParam, LPARAM lParam) { +INT_PTR CALLBACK DiagDialog(HWND hWnd, unsigned int uMsg, WPARAM wParam, LPARAM lParam) { int i; HWND hWndList = GetDlgItem(hWnd, IDC_LIST); static int fullRefresh; if (dev) { - switch (msg) { + switch (uMsg) { case WM_INITDIALOG: { fullRefresh = 1; @@ -91,16 +91,15 @@ INT_PTR CALLBACK DiagDialog(HWND hWnd, unsigned int msg, WPARAM wParam, LPARAM l } break; case WM_NOTIFY: - if (1) { - PSHNOTIFY* n = (PSHNOTIFY*) lParam; - if (n->hdr.idFrom != IDC_LIST || n->hdr.code != LVN_KEYDOWN) break; - NMLVKEYDOWN *key = (NMLVKEYDOWN *) n; - if (key->wVKey != VK_ESCAPE) break; + { + NMLVKEYDOWN *n = (NMLVKEYDOWN *) lParam; + // Don't always get the notification when testing DirectInput non-keyboard devices. + // Don't get it (Or want it) when testing keyboards. + if (n->hdr.idFrom != IDC_LIST || n->hdr.code != LVN_KEYDOWN || n->wVKey != VK_ESCAPE) break; } - else { case WM_ACTIVATE: - if (wParam != WA_INACTIVE) break; - } + if (uMsg == WM_ACTIVATE && wParam != WA_INACTIVE) break; + break; case WM_CLOSE: KillTimer(hWnd, 1); dm->ReleaseInput(); diff --git a/plugins/LilyPad/DirectInput.cpp b/plugins/LilyPad/DirectInput.cpp index 108205606c..5f0f388154 100644 --- a/plugins/LilyPad/DirectInput.cpp +++ b/plugins/LilyPad/DirectInput.cpp @@ -9,10 +9,12 @@ #include "PS2Etypes.h" #include +// Aka htons, without the winsock dependency. inline static u16 flipShort(u16 s) { return (s>>8) | (s<<8); } +// Aka htonl, without the winsock dependency. inline static u32 flipLong(u32 l) { return (((u32)flipShort((u16)l))<<16) | flipShort((u16)(l>>16)); } @@ -48,6 +50,9 @@ void ReleaseDirectInput() { di8d.lpDI8 = 0; } } + else { + di8d.refCount=di8d.refCount; + } } static int StringToGUID(GUID *pg, wchar_t *dataw) { @@ -95,9 +100,17 @@ public: } void SetEffect(ForceFeedbackBinding *binding, unsigned char force) { - unsigned int index = binding - pads[0].ffBindings; - if (index >= (unsigned int)pads[0].numFFBindings) { - index = pads[0].numFFBindings + (binding - pads[1].ffBindings); + int index = 0; + for (int port=0; port<2; port++) { + for (int slot=0; slot<4; slot++) { + unsigned int diff = binding - pads[port][slot].ffBindings; + if (diff < (unsigned int)pads[port][slot].numFFBindings) { + index += diff; + port = 2; + break; + } + index += pads[port][slot].numFFBindings; + } } IDirectInputEffect *die = diEffects[index].die; if (die) { @@ -136,7 +149,7 @@ public: } int Activate(void *d) { - int i, j; + int i; IDirectInput8 *di8 = GetDirectInput(); Deactivate(); if (!di8) return 0; @@ -147,12 +160,10 @@ public: } { - DIOBJECTDATAFORMAT *formats = (DIOBJECTDATAFORMAT*)malloc(sizeof(DIOBJECTDATAFORMAT) * numPhysicalControls); + DIOBJECTDATAFORMAT *formats = (DIOBJECTDATAFORMAT*)calloc(numPhysicalControls, sizeof(DIOBJECTDATAFORMAT)); for (i=0; i= pads[0].numFFBindings) { - b = &pads[1].ffBindings[i-pads[0].numFFBindings]; - } - else - b = &pads[0].ffBindings[i]; - ForceFeedbackEffectType *eff = ffEffectTypes + b->effectIndex; - GUID guid; - if (!StringToGUID(&guid, eff->effectID)) continue; + int count = GetFFBindingCount(); + diEffects = (DI8Effect*) calloc(count, sizeof(DI8Effect)); + i = 0; + for (int port=0; port<2; port++) { + for (int slot=0; slot<4; slot++) { + int subIndex = i; + for (int j=0; jeffectIndex; + GUID guid; + if (!StringToGUID(&guid, eff->effectID)) continue; - DIEFFECT dieffect; - memset(&dieffect, 0, sizeof(dieffect)); - dieffect.dwSize = sizeof(dieffect); - dieffect.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTIDS; - dieffect.dwDuration = 2000000; - dieffect.dwGain = 10000; - dieffect.dwTriggerButton = DIEB_NOTRIGGER; - union { - DIPERIODIC pediodic; - DIRAMPFORCE ramp; - DICONSTANTFORCE constant; - } stuff = {0,0,0,0}; + DIEFFECT dieffect; + memset(&dieffect, 0, sizeof(dieffect)); + dieffect.dwSize = sizeof(dieffect); + dieffect.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTIDS; + dieffect.dwDuration = 2000000; + dieffect.dwGain = 10000; + dieffect.dwTriggerButton = DIEB_NOTRIGGER; + union { + DIPERIODIC pediodic; + DIRAMPFORCE ramp; + DICONSTANTFORCE constant; + } stuff = {0,0,0,0}; - if (eff->type == EFFECT_CONSTANT) { - dieffect.cbTypeSpecificParams = sizeof(DICONSTANTFORCE); - } - else if (eff->type == EFFECT_PERIODIC) { - dieffect.cbTypeSpecificParams = sizeof(DIPERIODIC); - } - else if (eff->type == EFFECT_RAMP) { - dieffect.cbTypeSpecificParams = sizeof(DIRAMPFORCE); - } - dieffect.lpvTypeSpecificParams = &stuff; - - int maxForce = 0; - int numAxes = 0; - int *axes = (int*) malloc(sizeof(int) * 3 * numFFAxes); - DWORD *axisIDs = (DWORD*)(axes + numFFAxes); - LONG *dirList = (LONG*)(axisIDs + numFFAxes); - dieffect.rgdwAxes = axisIDs; - dieffect.rglDirection = dirList; - for (j=0; jaxes[j].force) { - int force = abs(b->axes[j].force); - if (force > maxForce) { - maxForce = force; + if (eff->type == EFFECT_CONSTANT) { + dieffect.cbTypeSpecificParams = sizeof(DICONSTANTFORCE); } - axes[numAxes] = j; - axisIDs[numAxes] = ffAxes[j].id; - dirList[numAxes] = b->axes[j].force; - numAxes++; + else if (eff->type == EFFECT_PERIODIC) { + dieffect.cbTypeSpecificParams = sizeof(DIPERIODIC); + } + else if (eff->type == EFFECT_RAMP) { + dieffect.cbTypeSpecificParams = sizeof(DIRAMPFORCE); + } + dieffect.lpvTypeSpecificParams = &stuff; + + int maxForce = 0; + int numAxes = 0; + int *axes = (int*) malloc(sizeof(int) * 3 * numFFAxes); + DWORD *axisIDs = (DWORD*)(axes + numFFAxes); + LONG *dirList = (LONG*)(axisIDs + numFFAxes); + dieffect.rgdwAxes = axisIDs; + dieffect.rglDirection = dirList; + for (int k=0; kaxes[k].force) { + int force = abs(b->axes[k].force); + if (force > maxForce) { + maxForce = force; + } + axes[numAxes] = k; + axisIDs[numAxes] = ffAxes[k].id; + dirList[numAxes] = b->axes[k].force; + numAxes++; + } + } + if (!numAxes) { + free(axes); + continue; + } + dieffect.cAxes = numAxes; + diEffects[i].scale = maxForce; + if (!SUCCEEDED(did->CreateEffect(guid, &dieffect, &diEffects[i].die, 0))) { + diEffects[i].die = 0; + diEffects[i].scale = 0; + } + + free(axes); + axes = 0; + i++; } } - if (!numAxes) { - free(axes); - continue; - } - dieffect.cAxes = numAxes; - diEffects[i].scale = maxForce; - if (!SUCCEEDED(did->CreateEffect(guid, &dieffect, &diEffects[i].die, 0))) { - diEffects[i].die = 0; - diEffects[i].scale = 0; - } - - free(axes); - axes = 0; } active = 1; return 1; @@ -303,14 +318,24 @@ public: return 1; } + int GetFFBindingCount() { + int count = 0; + for (int port = 0; port<2; port++) { + for (int slot = 0; slot<4; slot++) { + count += pads[port][slot].numFFBindings; + } + } + return count; + } + void Deactivate() { FreeState(); if (diEffects) { - for (int i=0; iStop(); diEffects[i].die->Release(); - diEffects[i].die = 0; } } free(diEffects); @@ -320,6 +345,7 @@ public: did->Unacquire(); did->Release(); ReleaseDirectInput(); + did = 0; active = 0; } } diff --git a/plugins/LilyPad/Global.h b/plugins/LilyPad/Global.h index d6a3621b05..17e41b7013 100644 --- a/plugins/LilyPad/Global.h +++ b/plugins/LilyPad/Global.h @@ -62,6 +62,7 @@ EXPORT_C_(u32) PADreadPort2 (PadDataS* pads); EXPORT_C_(u32) PSEgetLibType(); EXPORT_C_(u32) PSEgetLibVersion(); EXPORT_C_(void) PADconfigure(); +EXPORT_C_(s32) PADfreeze(int mode, freezeData *data); #ifdef NO_CRT inline void * malloc(size_t size) { diff --git a/plugins/LilyPad/InputManager.cpp b/plugins/LilyPad/InputManager.cpp index bb3c5cacbf..2be1429dca 100644 --- a/plugins/LilyPad/InputManager.cpp +++ b/plugins/LilyPad/InputManager.cpp @@ -67,12 +67,14 @@ Device::~Device() { // Generally called by deactivate, but just in case... FreeState(); int i; - for (int pad=0; pad<2; pad++) { - free(pads[pad].bindings); - for (i=0; iaxes = (AxisEffectInfo*) realloc(b->axes, sizeof(AxisEffectInfo) * (numFFAxes)); - memset(b->axes + (numFFAxes-1), 0, sizeof(AxisEffectInfo)); + for (int port=0; port<2; port++) { + for (int slot=0; slot<4; slot++) { + for (int i=0; iaxes = (AxisEffectInfo*) realloc(b->axes, sizeof(AxisEffectInfo) * (numFFAxes)); + memset(b->axes + (numFFAxes-1), 0, sizeof(AxisEffectInfo)); + } } } } @@ -161,7 +165,7 @@ void Device::CalcVirtualState() { } } else if (c->type & ABSAXIS) { - virtualControlState[index] = val; + virtualControlState[index] = (val + FULLY_DOWN)/2; // Positive. Overkill. virtualControlState[index+1] = (val & ~(val>>31)); // Negative @@ -254,9 +258,9 @@ PhysicalControl *Device::AddPhysicalControl(ControlType type, unsigned short id, return control; } -void Device::SetEffects(unsigned char pad, unsigned char motor, unsigned char force) { - for (int i=0; imotor == motor) { SetEffect(binding, force); } @@ -350,7 +354,7 @@ void InputDeviceManager::PostRead() { } } -Device *InputDeviceManager::GetActiveDevice(void *info, int axisHint, unsigned int *uid, int *index, int *value) { +Device *InputDeviceManager::GetActiveDevice(void *info, unsigned int *uid, int *index, int *value) { int i, j; Update(info); int bestDiff = FULLY_DOWN/2; @@ -359,31 +363,30 @@ Device *InputDeviceManager::GetActiveDevice(void *info, int axisHint, unsigned i if (devices[i]->active) { for (j=0; jnumVirtualControls; j++) { if (devices[i]->virtualControlState[j] == devices[i]->oldVirtualControlState[j]) continue; + if (devices[i]->virtualControls[j].uid & UID_POV) continue; // Fix for two things: // Releasing button used to click on bind button, and // DirectInput not updating control state. //Note: Handling latter not great for pressure sensitive button handling, but should still work... // with some effort. - if (!((devices[i]->virtualControls[j].uid >> 16) & (POV|RELAXIS))) { + if (!(devices[i]->virtualControls[j].uid & (POV|RELAXIS))) { if (abs(devices[i]->oldVirtualControlState[j]) > abs(devices[i]->virtualControlState[j])) { devices[i]->oldVirtualControlState[j] = 0; } } int diff = abs(devices[i]->virtualControlState[j] - devices[i]->oldVirtualControlState[j]); - if ((devices[i]->virtualControls[j].uid & UID_POV) && diff) { - if (devices[i]->virtualControlState[j] == -1) diff = 0; - else diff = 2*FULLY_DOWN; - } // Make it require a bit more work to bind relative axes. - else if (((devices[i]->virtualControls[j].uid>>16) & 0xFF) == RELAXIS) { + if (((devices[i]->virtualControls[j].uid>>16) & 0xFF) == RELAXIS) { diff = diff/4+1; } if (diff > bestDiff) { - if (axisHint != 2) { - if (devices[i]->virtualControls[j].uid & UID_POV) continue; - if (devices[i]->virtualControls[j].uid & UID_AXIS) { - if (!axisHint || (((devices[i]->virtualControls[j].uid>>16)&0xFF) != ABSAXIS)) continue; - } + if (devices[i]->virtualControls[j].uid & UID_AXIS) { + if ((((devices[i]->virtualControls[j].uid>>16)&0xFF) != ABSAXIS)) continue; + // Very picky when binding entire axes. Prefer binding half-axes. + if (!((devices[i]->oldVirtualControlState[j] < FULLY_DOWN/16 && devices[i]->virtualControlState[j] > FULLY_DOWN/8) || + (devices[i]->oldVirtualControlState[j] > 15*FULLY_DOWN/16 && devices[i]->virtualControlState[j] < 7*FULLY_DOWN/8))) + continue; + devices[i]->virtualControls[j].uid = devices[i]->virtualControls[j].uid; } bestDiff = diff; *uid = devices[i]->virtualControls[j].uid; @@ -428,7 +431,9 @@ void InputDeviceManager::DisableAllDevices() { void InputDeviceManager::DisableDevice(int index) { devices[index]->enabled = 0; - if (devices[index]->active) devices[index]->Deactivate(); + if (devices[index]->active) { + devices[index]->Deactivate(); + } } ForceFeedbackEffectType *Device::GetForcefeedbackEffect(wchar_t *id) { @@ -450,7 +455,7 @@ ForceFeedbackAxis *Device::GetForceFeedbackAxis(int id) { void InputDeviceManager::CopyBindings(int numOldDevices, Device **oldDevices) { int *oldMatches = (int*) malloc(sizeof(int) * numOldDevices); int *matches = (int*) malloc(sizeof(int) * numDevices); - int i, j, pad; + int i, j, port, slot; Device *old, *dev; for (i=0; ipads[pad].numBindings + old->pads[pad].numFFBindings) { - // Means that there are bindings. - oldMatches[i] = -1; + for (port=0; port<2; port++) { + for (slot=0; slot<4; slot++) { + if (old->pads[port][slot].numBindings + old->pads[port][slot].numFFBindings) { + // Means that there are bindings. + oldMatches[i] = -1; + } } } } @@ -513,37 +520,39 @@ void InputDeviceManager::CopyBindings(int numOldDevices, Device **oldDevices) { } else { dev = devices[oldMatches[i]]; - for (pad=0; pad<2; pad++) { - if (old->pads[pad].numBindings) { - dev->pads[pad].bindings = (Binding*) malloc(old->pads[pad].numBindings * sizeof(Binding)); - for (int j=0; jpads[pad].numBindings; j++) { - Binding *bo = old->pads[pad].bindings + j; - Binding *bn = dev->pads[pad].bindings + dev->pads[pad].numBindings; - VirtualControl *cn = dev->GetVirtualControl(old->virtualControls[bo->controlIndex].uid); - if (cn) { - *bn = *bo; - bn->controlIndex = cn - dev->virtualControls; - dev->pads[pad].numBindings++; + for (port=0; port<2; port++) { + for (slot=0; slot<4; slot++) { + if (old->pads[port][slot].numBindings) { + dev->pads[port][slot].bindings = (Binding*) malloc(old->pads[port][slot].numBindings * sizeof(Binding)); + for (int j=0; jpads[port][slot].numBindings; j++) { + Binding *bo = old->pads[port][slot].bindings + j; + Binding *bn = dev->pads[port][slot].bindings + dev->pads[port][slot].numBindings; + VirtualControl *cn = dev->GetVirtualControl(old->virtualControls[bo->controlIndex].uid); + if (cn) { + *bn = *bo; + bn->controlIndex = cn - dev->virtualControls; + dev->pads[port][slot].numBindings++; + } } } - } - if (old->pads[pad].numFFBindings) { - dev->pads[pad].ffBindings = (ForceFeedbackBinding*) malloc(old->pads[pad].numFFBindings * sizeof(ForceFeedbackBinding)); - for (int j=0; jpads[pad].numFFBindings; j++) { - ForceFeedbackBinding *bo = old->pads[pad].ffBindings + j; - ForceFeedbackBinding *bn = dev->pads[pad].ffBindings + dev->pads[pad].numFFBindings; - ForceFeedbackEffectType *en = dev->GetForcefeedbackEffect(old->ffEffectTypes[bo->effectIndex].effectID); - if (en) { - *bn = *bo; - bn->effectIndex = en - dev->ffEffectTypes; - bn->axes = (AxisEffectInfo*)calloc(dev->numFFAxes, sizeof(AxisEffectInfo)); - for (int k=0; knumFFAxes; k++) { - ForceFeedbackAxis *newAxis = dev->GetForceFeedbackAxis(old->ffAxes[k].id); - if (newAxis) { - bn->axes[newAxis - dev->ffAxes] = bo->axes[k]; + if (old->pads[port][slot].numFFBindings) { + dev->pads[port][slot].ffBindings = (ForceFeedbackBinding*) malloc(old->pads[port][slot].numFFBindings * sizeof(ForceFeedbackBinding)); + for (int j=0; jpads[port][slot].numFFBindings; j++) { + ForceFeedbackBinding *bo = old->pads[port][slot].ffBindings + j; + ForceFeedbackBinding *bn = dev->pads[port][slot].ffBindings + dev->pads[port][slot].numFFBindings; + ForceFeedbackEffectType *en = dev->GetForcefeedbackEffect(old->ffEffectTypes[bo->effectIndex].effectID); + if (en) { + *bn = *bo; + bn->effectIndex = en - dev->ffEffectTypes; + bn->axes = (AxisEffectInfo*)calloc(dev->numFFAxes, sizeof(AxisEffectInfo)); + for (int k=0; knumFFAxes; k++) { + ForceFeedbackAxis *newAxis = dev->GetForceFeedbackAxis(old->ffAxes[k].id); + if (newAxis) { + bn->axes[newAxis - dev->ffAxes] = bo->axes[k]; + } } + dev->pads[port][slot].numFFBindings++; } - dev->pads[pad].numFFBindings++; } } } @@ -554,11 +563,11 @@ void InputDeviceManager::CopyBindings(int numOldDevices, Device **oldDevices) { free(matches); } -void InputDeviceManager::SetEffect(unsigned char pad, unsigned char motor, unsigned char force) { +void InputDeviceManager::SetEffect(unsigned char port, unsigned int slot, unsigned char motor, unsigned char force) { for (int i=0; ienabled && dev->numFFEffectTypes) { - dev->SetEffects(pad, motor, force); + dev->SetEffects(port, slot, motor, force); } } } diff --git a/plugins/LilyPad/InputManager.h b/plugins/LilyPad/InputManager.h index a53969865d..a5f0587e11 100644 --- a/plugins/LilyPad/InputManager.h +++ b/plugins/LilyPad/InputManager.h @@ -194,7 +194,7 @@ public: }; }; - PadBindings pads[2]; + PadBindings pads[2][4]; // Virtual controls. All basically act like pressure sensitivity buttons, with // values between 0 and 2^16. 2^16 is fully down, 0 is up. Larger values @@ -267,7 +267,7 @@ public: // Note: Only used externally for binding, so if override the other one, can assume // all other forces are currently 0. inline virtual void SetEffect(ForceFeedbackBinding *binding, unsigned char force) {} - inline virtual void SetEffects(unsigned char pad, unsigned char motor, unsigned char force); + inline virtual void SetEffects(unsigned char port, unsigned int slot, unsigned char motor, unsigned char force); // Called after reading. Basically calls FlipState(). // Some device types (Those that don't incrementally update) @@ -276,7 +276,6 @@ public: virtual void PostRead(); }; -// Don't need objects for devices with no bound controls. class InputDeviceManager { public: Device **devices; @@ -289,8 +288,8 @@ public: // All old bindings are copied to matching devices. // When old devices are missing, I do a slightly more careful search - // using id2s and create new dummy devices if no matches. - + // using productIDs and then (in desperation) displayName. + // Finally create new dummy devices if no matches found. void CopyBindings(int numDevices, Device **devices); @@ -298,13 +297,13 @@ public: ~InputDeviceManager(); void AddDevice(Device *d); - // If axisHint is 1, prefer axes. - Device *GetActiveDevice(void *info, int axisHint, unsigned int *uid, int *index, int *value); + Device *GetActiveDevice(void *info, unsigned int *uid, int *index, int *value); void Update(void *attachInfo); + // Called after reading state, after Update(). void PostRead(); - void SetEffect(unsigned char pad, unsigned char motor, unsigned char force); + void SetEffect(unsigned char port, unsigned int slot, unsigned char motor, unsigned char force); // Update does this as needed. // void GetInput(void *v); diff --git a/plugins/LilyPad/KeyboardHook.cpp b/plugins/LilyPad/KeyboardHook.cpp index 28599fa96c..0c7a146b98 100644 --- a/plugins/LilyPad/KeyboardHook.cpp +++ b/plugins/LilyPad/KeyboardHook.cpp @@ -87,8 +87,8 @@ LRESULT CALLBACK IgnoreKeyboardHook(int code, WPARAM wParam, LPARAM lParam) { if (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN) { KBDLLHOOKSTRUCT* key = (KBDLLHOOKSTRUCT*) lParam; if (key->vkCode < 256) { - for (int i=0; ipads[0].numBindings; i++) { - if (ikhd->pads[0].bindings[i].controlIndex == key->vkCode) { + for (int i=0; ipads[0][0].numBindings; i++) { + if (ikhd->pads[0][0].bindings[i].controlIndex == key->vkCode) { return 1; } } @@ -97,6 +97,16 @@ LRESULT CALLBACK IgnoreKeyboardHook(int code, WPARAM wParam, LPARAM lParam) { return 1; } } + if (config.vistaVolume) { + if (key->vkCode == VK_VOLUME_DOWN) { + SetVolume(config.volume-3); + return 1; + } + if (key->vkCode == VK_VOLUME_UP) { + SetVolume(config.volume+3); + return 1; + } + } } else if (wParam == WM_KEYUP || wParam == WM_SYSKEYUP) { KBDLLHOOKSTRUCT* key = (KBDLLHOOKSTRUCT*) lParam; diff --git a/plugins/LilyPad/LilyPad.cpp b/plugins/LilyPad/LilyPad.cpp index 7d45affd31..913621c59f 100644 --- a/plugins/LilyPad/LilyPad.cpp +++ b/plugins/LilyPad/LilyPad.cpp @@ -3,6 +3,9 @@ #include #include +// For escape timer, so as not to break GSDX+DX9. +#include + #define PADdefs #include "PS2Etypes.h" #include "PS2Edefs.h" @@ -15,6 +18,10 @@ #include "svnrev.h" #include "resource.h" +#ifdef _DEBUG +#include "crtdbg.h" +#endif + // Used to prevent reading input and cleaning up input devices at the same time. // Only an issue when not reading input in GS thread and disabling devices due to // lost focus. @@ -23,7 +30,7 @@ CRITICAL_SECTION readInputCriticalSection; HINSTANCE hInst; HWND hWnd; -// Used to toggle mouse binding. +// Used to toggle mouse listening. u8 miceEnabled; // 2 when both pads are initialized, 1 for one pad, etc. @@ -32,14 +39,13 @@ int openCount = 0; int activeWindow = 0; int bufSize = 0; -static unsigned char outBuf[50]; -static unsigned char inBuf[50]; +unsigned char outBuf[50]; +unsigned char inBuf[50]; #define MODE_DIGITAL 0x41 #define MODE_ANALOG 0x73 #define MODE_DS2_NATIVE 0x79 - int IsWindowMaximized (HWND hWnd) { RECT rect; if (GetWindowRect(hWnd, &rect)) { @@ -79,10 +85,10 @@ void DEBUG_NEW_SET() { end++[0] = '\n'; DWORD junk; WriteFile(hFile, temp, end-temp, &junk, 0); - bufSize = 0; CloseHandle(hFile);; } } + bufSize = 0; } inline void DEBUG_IN(unsigned char c) { @@ -102,28 +108,44 @@ struct ButtonSum { Stick sticks[3]; }; -class Pad { + +struct PadFreezeData { + // Digital / Analog / DS2 Native + u8 mode; + + u8 modeLock; + + // In config mode + u8 config; + + u8 vibrate[8]; + u8 umask[2]; +}; + +class Pad : public PadFreezeData { public: ButtonSum sum, lockedSum; int lockedState; - u8 vibrate[8]; - - u8 umask[2]; + // Vibration indices. u8 vibrateI[2]; + + // Last vibration value. Only used so as not to call vibration + // functions when old and new values are both 0. u8 vibrateVal[2]; - // Digital / Analog / Full Analog (aka DS2 Native) - u8 mode; - u8 modeLock; - // In config mode - u8 config; + // Used to keep track of which pads I'm running. // Note that initialized pads *can* be disabled. // I keep track of state of non-disabled non-initialized // pads, but should never be asked for their state. u8 initialized; -} pads[2]; +} pads[2][4]; + +// Active slots for each port. +int slots[2]; +// Which ports we're running on. +int portInitialized[2]; // Force value to be from 0 to 255. u8 Cap (int i) { @@ -132,19 +154,25 @@ u8 Cap (int i) { return (u8) i; } - -// Just like RefreshEnabledDevices(), but takes into account -// mouse and focus state and which devices have bindings for -// enabled pads. Also releases keyboards if window is not focused. +// RefreshEnabledDevices() enables everything that can potentially +// be bound to, as well as the "Ignore keyboard" device. +// +// This enables everything that input should be read from while the +// emulator is running. Takes into account mouse and focus state +// and which devices have bindings for enabled pads. Releases +// keyboards if window is not focused. Releases game devices if +// background monitoring is not checked. // And releases games if not focused and config.background is not set. void UpdateEnabledDevices(int updateList = 0) { // Enable all devices I might want. Can ignore the rest. RefreshEnabledDevices(updateList); // Figure out which pads I'm getting input for. - int padsEnabled[2] = { - pads[0].initialized && !config.disablePad[0], - pads[1].initialized && !config.disablePad[1] - }; + int padsEnabled[2][4]; + for (int port = 0; port<2; port++) { + for (int slot = 0; slot<4; slot++) { + padsEnabled[port][slot] = pads[port][slot].initialized && config.padConfigs[port][slot].type != DisabledPad; + } + } for (int i=0; inumDevices; i++) { Device *dev = dm->devices[i]; @@ -156,7 +184,7 @@ void UpdateEnabledDevices(int updateList = 0) { // Disable ignore keyboard if don't have focus or there are no keys to ignore. if (dev->api == IGNORE_KEYBOARD) { - if (config.keyboardApi == NO_API || !activeWindow || !dev->pads[0].numBindings) { + if ((!config.vistaVolume && (config.keyboardApi == NO_API || !dev->pads[0][0].numBindings)) || !activeWindow) { dm->DisableDevice(i); } continue; @@ -173,9 +201,11 @@ void UpdateEnabledDevices(int updateList = 0) { else if (!activeWindow && !config.background) dm->DisableDevice(i); else { int numActiveBindings = 0; - for (int pad=0; pad<2; pad++) { - if (padsEnabled[pad]) { - numActiveBindings += dev->pads[pad].numBindings + dev->pads[pad].numFFBindings; + for (int port=0; port<2; port++) { + for (int slot=0; slot<4; slot++) { + if (padsEnabled[port][slot]) { + numActiveBindings += dev->pads[port][slot].numBindings + dev->pads[port][slot].numFFBindings; + } } } if (!numActiveBindings) @@ -199,10 +229,6 @@ BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD fdwReason, void* lpvReserved) { return 1; } -BOOL WINAPI MyDllMainCRTStartup(HANDLE hDllHandle, DWORD dwReason, LPVOID lpReserved) { - return DllMain((HINSTANCE) hDllHandle, dwReason, lpReserved); -} - void AddForce(ButtonSum *sum, u8 cmd, int delta = 255) { if (!delta) return; if (cmd<0x14) { @@ -293,12 +319,10 @@ void CapSum(ButtonSum *sum) { // key press info requests. int summed[3] = {0, 0, 0}; -int lockStateChanged[2] = {0,0}; #define LOCK_DIRECTION 2 #define LOCK_BUTTONS 4 #define LOCK_BOTH 1 -extern HWND hWndStealing; void Update(int pad) { if ((unsigned int)pad > 2) return; @@ -307,9 +331,13 @@ void Update(int pad) { return; } int i; - ButtonSum s[2]; - s[0] = pads[0].lockedSum; - s[1] = pads[1].lockedSum; + ButtonSum s[2][4]; + u8 lockStateChanged[2][4]; + memset(lockStateChanged, 0, sizeof(lockStateChanged)); + + for (i=0; i<8; i++) { + s[i&1][i>>1] = pads[i&1][i>>1].lockedSum; + } InitInfo info = { 0, hWnd, hWnd, 0 }; @@ -325,36 +353,38 @@ void Update(int pad) { // Skip both disabled devices and inactive enabled devices. // Shouldn't be any of the latter, in general, but just in case... if (!dev->virtualControlState) continue; - for (int pad=0; pad<2; pad++) { - if (config.disablePad[pad]) continue; - for (int j=0; jpads[pad].numBindings; j++) { - Binding *b = dev->pads[pad].bindings+j; - int cmd = b->command; - int state = dev->virtualControlState[b->controlIndex]; - if (!(turbo & b->turbo)) { - if (cmd > 0x0F && cmd != 0x28) { - ProcessButtonBinding(b, s+pad, state); - } - else if ((state>>15) && !(dev->oldVirtualControlState[b->controlIndex]>>15)) { - if (cmd == 0x0F) { - miceEnabled = !miceEnabled; - UpdateEnabledDevices(); + for (int port=0; port<2; port++) { + for (int slot=0; slot<4; slot++) { + if (config.padConfigs[port][slot].type == DisabledPad || !pads[port][slot].initialized) continue; + for (int j=0; jpads[port][slot].numBindings; j++) { + Binding *b = dev->pads[port][slot].bindings+j; + int cmd = b->command; + int state = dev->virtualControlState[b->controlIndex]; + if (!(turbo & b->turbo)) { + if (cmd > 0x0F && cmd != 0x28) { + ProcessButtonBinding(b, &s[port][slot], state); } - else if (cmd == 0x0C) { - lockStateChanged[pad] |= LOCK_BUTTONS; - } - else if (cmd == 0x0E) { - lockStateChanged[pad] |= LOCK_DIRECTION; - } - else if (cmd == 0x0D) { - lockStateChanged[pad] |= LOCK_BOTH; - } - else if (cmd == 0x28) { - if (!pads[pad].modeLock) { - if (pads[pad].mode != MODE_DIGITAL) - pads[pad].mode = MODE_DIGITAL; - else - pads[pad].mode = MODE_ANALOG; + else if ((state>>15) && !(dev->oldVirtualControlState[b->controlIndex]>>15)) { + if (cmd == 0x0F) { + miceEnabled = !miceEnabled; + UpdateEnabledDevices(); + } + else if (cmd == 0x0C) { + lockStateChanged[port][slot] |= LOCK_BUTTONS; + } + else if (cmd == 0x0E) { + lockStateChanged[port][slot] |= LOCK_DIRECTION; + } + else if (cmd == 0x0D) { + lockStateChanged[port][slot] |= LOCK_BOTH; + } + else if (cmd == 0x28) { + if (!pads[port][slot].modeLock) { + if (pads[port][slot].mode != MODE_DIGITAL) + pads[port][slot].mode = MODE_DIGITAL; + else + pads[port][slot].mode = MODE_ANALOG; + } } } } @@ -368,101 +398,98 @@ void Update(int pad) { LeaveCriticalSection(&readInputCriticalSection); } - for (int currentPad = 0; currentPad<2; currentPad++) { - if (config.guitar[currentPad]) { - if (!config.GH2) { - s[currentPad].sticks[1].vert = -s[currentPad].sticks[1].vert; - } - // GH2 hack. - else if (config.GH2) { - const unsigned int oldIdList[5] = {ID_R2, ID_CIRCLE, ID_TRIANGLE, ID_CROSS, ID_SQUARE}; - const unsigned int idList[5] = {ID_L2, ID_L1, ID_R1, ID_R2, ID_CROSS}; - int values[5]; - int i; - for (i=0; i<5; i++) { - int id = oldIdList[i] - 0x1104; - values[i] = s[currentPad].buttons[id]; - s[currentPad].buttons[id] = 0; + for (int port=0; port<2; port++) { + for (int slot=0; slot<4; slot++) { + if (config.padConfigs[port][slot].type == DisabledPad || !pads[port][slot].initialized) continue; + if (config.padConfigs[port][slot].type == GuitarPad) { + if (!config.GH2) { + s[port][slot].sticks[1].vert = -s[port][slot].sticks[1].vert; } - s[currentPad].buttons[ID_TRIANGLE-0x1104] = values[1]; - for (i=0; i<5; i++) { - int id = idList[i] - 0x1104; - s[currentPad].buttons[id] = values[i]; - } - if (abs(s[currentPad].sticks[0].vert) <= 48) { - for (int i=0; i<5; i++) { - unsigned int id = idList[i] - 0x1104; - if (pads[currentPad].sum.buttons[id] < s[currentPad].buttons[id]) { - s[currentPad].buttons[id] = pads[currentPad].sum.buttons[id]; + // GH2 hack. + else if (config.GH2) { + const unsigned int oldIdList[5] = {ID_R2, ID_CIRCLE, ID_TRIANGLE, ID_CROSS, ID_SQUARE}; + const unsigned int idList[5] = {ID_L2, ID_L1, ID_R1, ID_R2, ID_CROSS}; + int values[5]; + int i; + for (i=0; i<5; i++) { + int id = oldIdList[i] - 0x1104; + values[i] = s[port][slot].buttons[id]; + s[port][slot].buttons[id] = 0; + } + s[port][slot].buttons[ID_TRIANGLE-0x1104] = values[1]; + for (i=0; i<5; i++) { + int id = idList[i] - 0x1104; + s[port][slot].buttons[id] = values[i]; + } + if (abs(s[port][slot].sticks[0].vert) <= 48) { + for (int i=0; i<5; i++) { + unsigned int id = idList[i] - 0x1104; + if (pads[port][slot].sum.buttons[id] < s[port][slot].buttons[id]) { + s[port][slot].buttons[id] = pads[port][slot].sum.buttons[id]; + } } } - } - else if (abs(pads[currentPad].sum.sticks[0].vert) <= 48) { - for (int i=0; i<5; i++) { - unsigned int id = idList[i] - 0x1104; - if (pads[currentPad].sum.buttons[id]) { - s[currentPad].buttons[id] = 0; + else if (abs(pads[port][slot].sum.sticks[0].vert) <= 48) { + for (int i=0; i<5; i++) { + unsigned int id = idList[i] - 0x1104; + if (pads[port][slot].sum.buttons[id]) { + s[port][slot].buttons[id] = 0; + } } } } } - } - if (pads[currentPad].mode == 0x41) { - s[currentPad].sticks[0].horiz += - s[currentPad].sticks[1].horiz + - s[currentPad].sticks[2].horiz; - s[currentPad].sticks[0].vert += - s[currentPad].sticks[1].vert + - s[currentPad].sticks[2].vert; - } + if (pads[port][slot].mode == 0x41) { + s[port][slot].sticks[0].horiz += + s[port][slot].sticks[1].horiz + + s[port][slot].sticks[2].horiz; + s[port][slot].sticks[0].vert += + s[port][slot].sticks[1].vert + + s[port][slot].sticks[2].vert; + } - CapSum(&s[currentPad]); - if (lockStateChanged[currentPad]) { - if (lockStateChanged[currentPad] & LOCK_BOTH) { - if (pads[currentPad].lockedState != (LOCK_DIRECTION | LOCK_BUTTONS)) { - // Enable the one that's not enabled. - lockStateChanged[currentPad] ^= pads[currentPad].lockedState^(LOCK_DIRECTION | LOCK_BUTTONS); + CapSum(&s[port][slot]); + if (lockStateChanged[port][slot]) { + if (lockStateChanged[port][slot] & LOCK_BOTH) { + if (pads[port][slot].lockedState != (LOCK_DIRECTION | LOCK_BUTTONS)) { + // Enable the one that's not enabled. + lockStateChanged[port][slot] ^= pads[port][slot].lockedState^(LOCK_DIRECTION | LOCK_BUTTONS); + } + else { + // Disable both + lockStateChanged[port][slot] ^= LOCK_DIRECTION | LOCK_BUTTONS; + } } - else { - // Disable both - lockStateChanged[currentPad] ^= LOCK_DIRECTION | LOCK_BUTTONS; + if (lockStateChanged[port][slot] & LOCK_DIRECTION) { + if (pads[port][slot].lockedState & LOCK_DIRECTION) { + memset(pads[port][slot].lockedSum.sticks, 0, sizeof(pads[port][slot].lockedSum.sticks)); + } + else { + memcpy(pads[port][slot].lockedSum.sticks, s[port][slot].sticks, sizeof(pads[port][slot].lockedSum.sticks)); + } + pads[port][slot].lockedState ^= LOCK_DIRECTION; } - } - if (lockStateChanged[currentPad] & LOCK_DIRECTION) { - if (pads[currentPad].lockedState & LOCK_DIRECTION) { - memset(pads[currentPad].lockedSum.sticks, 0, sizeof(pads[currentPad].lockedSum.sticks)); + if (lockStateChanged[port][slot] & LOCK_BUTTONS) { + if (pads[port][slot].lockedState & LOCK_BUTTONS) { + memset(pads[port][slot].lockedSum.buttons, 0, sizeof(pads[port][slot].lockedSum.buttons)); + } + else { + memcpy(pads[port][slot].lockedSum.buttons, s[port][slot].buttons, sizeof(pads[port][slot].lockedSum.buttons)); + } + pads[port][slot].lockedState ^= LOCK_BUTTONS; } - else { - memcpy(pads[currentPad].lockedSum.sticks, s[currentPad].sticks, sizeof(pads[currentPad].lockedSum.sticks)); + for (i=0; i>1].sum = s[i&1][i>>1]; } summed[0] = 1; summed[1] = 1; @@ -474,10 +501,10 @@ void CALLBACK PADupdate(int pad) { if (config.GSThreadUpdates) Update(pad); } -inline void SetVibrate(Pad *pad, int motor, u8 val) { - if (val | pad->vibrateVal[motor]) { - dm->SetEffect(pad - pads, motor, val); - pad->vibrateVal[motor] = val; +inline void SetVibrate(int port, int slot, int motor, u8 val) { + if (val || pads[port][slot].vibrateVal[motor]) { + dm->SetEffect(port,slot, motor, val); + pads[port][slot].vibrateVal[motor] = val; } } @@ -486,7 +513,7 @@ u32 CALLBACK PS2EgetLibType(void) { return PS2E_LT_PAD; } -#define VERSION ((0<<8) | 9 | (10<<24)) +#define VERSION ((0<<8) | 9 | (11<<24)) u32 CALLBACK PS2EgetLibVersion2(u32 type) { ps2e = 1; @@ -499,6 +526,8 @@ u32 CALLBACK PS2EgetLibVersion2(u32 type) { void GetNameAndVersionString(wchar_t *out) { #ifdef _DEBUG wsprintfW(out, L"LilyPad Debug %i.%i.%i (r%i)", (VERSION>>8)&0xFF, VERSION&0xFF, (VERSION>>24)&0xFF, SVN_REV); +#elif (_MSC_VER != 1400) + wsprintfW(out, L"LilyPad svn %i.%i.%i (r%i)", (VERSION>>8)&0xFF, VERSION&0xFF, (VERSION>>24)&0xFF, SVN_REV); #else wsprintfW(out, L"LilyPad %i.%i.%i", (VERSION>>8)&0xFF, VERSION&0xFF, (VERSION>>24)&0xFF, SVN_REV); #endif @@ -510,6 +539,11 @@ char* CALLBACK PSEgetLibName() { sprintf(version, "LilyPad Debug (r%i)", SVN_REV); return version; #else + #if (_MSC_VER != 1400) + static char version[50]; + sprintf(version, "LilyPad svn (r%i)", SVN_REV); + return version; + #endif return "LilyPad"; #endif } @@ -524,30 +558,47 @@ char* CALLBACK PS2EgetLibName(void) { //} void CALLBACK PADshutdown() { - pads[0].initialized = 0; - pads[1].initialized = 0; + for (int i=0; i<8; i++) + pads[i&1][i>>1].initialized = 0; UnloadConfigs(); } -#ifdef _DEBUG -#include "crtdbg.h" -#endif - - inline void StopVibrate() { - for (int i=0; i<4; i++) { - SetVibrate(&pads[i/2], i&1, 0); + for (int i=0; i<8; i++) { + SetVibrate(i&1, i>>1, 0, 0); + SetVibrate(i&1, i>>1, 1, 0); } } -inline void ResetVibrate(Pad *pad) { - SetVibrate(pad, 0, 0); - SetVibrate(pad, 1, 0); - ((int*)(pad->vibrate))[0] = 0xFFFFFF5A; - ((int*)(pad->vibrate))[1] = 0xFFFFFFFF; +inline void ResetVibrate(int port, int slot) { + SetVibrate(port, slot, 0, 0); + SetVibrate(port, slot, 1, 0); + ((int*)(pads[port][slot].vibrate))[0] = 0xFFFFFF5A; + ((int*)(pads[port][slot].vibrate))[1] = 0xFFFFFFFF; +} + +void ResetPad(int port, int slot) { + memset(&pads[port][slot], 0, sizeof(pads[0][0])); + pads[port][slot].mode = MODE_DIGITAL; + pads[port][slot].umask[0] = pads[port][slot].umask[1] = 0xFF; + ResetVibrate(port, slot); + if (config.padConfigs[port][slot].autoAnalog) { + pads[port][slot].mode = MODE_ANALOG; + } } +struct QueryInfo { + u8 port; + u8 slot; + u8 lastByte; + u8 currentCommand; + u8 numBytes; + u8 queryDone; + u8 response[42]; +} query = {0,0,0,0, 0,0xFF, 0xF3}; + +int saveStateIndex = 0; s32 CALLBACK PADinit(u32 flags) { // Note: Won't load settings if already loaded. @@ -566,16 +617,18 @@ s32 CALLBACK PADinit(u32 flags) { #endif pad --; - memset(&pads[pad], 0, sizeof(pads[0])); - pads[pad].mode = MODE_DIGITAL; - pads[pad].umask[0] = pads[pad].umask[1] = 0xFF; - ResetVibrate(pads+pad); - if (config.AutoAnalog[pad]) { - pads[pad].mode = MODE_ANALOG; - } + ResetPad(pad, 0); - pads[pad].initialized = 1; + pads[pad][0].initialized = 1; + memset(slots, 0, sizeof(slots)); + query.lastByte = 1; + query.numBytes = 0; + ClearKeyQueue(); + // Just in case, when resuming emulation. + QueueKeyEvent(VK_SHIFT, KEYRELEASE); + QueueKeyEvent(VK_MENU, KEYRELEASE); + QueueKeyEvent(VK_CONTROL, KEYRELEASE); return 0; } @@ -618,17 +671,8 @@ static const u8 queryMode[7] = {0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; static const u8 setNativeMode[7] = {0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5A}; -struct QueryInfo { - u8 pad; - u8 lastByte; - u8 currentCommand; - u8 numBytes; - u8 queryDone; - u8 response[22]; -} query = {0,0,0,0, 0,0xFF, 0xF3}; - -int saveStateIndex = 0; - +// Implements a couple of the hacks, also responsible for monitoring device addition/removal and focus +// changes. ExtraWndProcResult HackWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *output) { switch (uMsg) { case WM_SETTEXT: @@ -659,6 +703,12 @@ ExtraWndProcResult HackWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPara } break; case WM_ACTIVATEAPP: + // Release any buttons PCSX2 may think are down when + // losing/gaining focus. + QueueKeyEvent(VK_SHIFT, KEYRELEASE); + QueueKeyEvent(VK_MENU, KEYRELEASE); + QueueKeyEvent(VK_CONTROL, KEYRELEASE); + // Need to do this when not reading input from gs thread. // Checking for that case not worth the effort. EnterCriticalSection(&readInputCriticalSection); @@ -751,15 +801,14 @@ s32 CALLBACK PADopen(void *pDsp) { } restoreFullScreen = 0; } - memset(&pads[0].sum, 0, sizeof(pads[0].sum)); - memset(&pads[0].lockedSum, 0, sizeof(pads[0].lockedSum)); - pads[0].lockedState = 0; - memset(&pads[1].sum, 0, sizeof(pads[0].sum)); - memset(&pads[1].lockedSum, 0, sizeof(pads[0].lockedSum)); - pads[1].lockedState = 0; + for (int port=0; port<2; port++) { + for (int slot=0; slot<4; slot++) { + memset(&pads[port][slot].sum, 0, sizeof(pads[port][slot].sum)); + memset(&pads[port][slot].lockedSum, 0, sizeof(pads[port][slot].lockedSum)); + pads[port][slot].lockedState = 0; + } + } - query.lastByte = 1; - query.numBytes = 0; // I'd really rather use this line, but GetActiveWindow() does not have complete specs. // It *seems* to return null when no window from this thread has focus, but the // Microsoft specs seem to imply it returns the window from this thread that would have focus, @@ -786,7 +835,8 @@ u8 CALLBACK PADstartPoll(int pad) { pad--; if ((unsigned int)pad <= 1) { query.queryDone = 0; - query.pad = pad; + query.port = pad; + query.slot = slots[query.port]; query.numBytes = 2; query.lastByte = 0; DEBUG_IN(pad); @@ -813,8 +863,21 @@ u8 CALLBACK PADpoll(u8 value) { DEBUG_OUT(query.response[1+query.lastByte]); return query.response[++query.lastByte]; } + /* + { + query.numBytes = 35; + u8 test[35] = {0xFF, 0x80, 0x5A, + 0x73, 0x5A, 0xFF, 0xFF, 0x80, 0x80, 0x80, 0x80, + 0x73, 0x5A, 0xFF, 0xFF, 0x80, 0x80, 0x80, 0x80, + 0x73, 0x5A, 0xFF, 0xFF, 0x80, 0x80, 0x80, 0x80, + 0x73, 0x5A, 0xFF, 0xFF, 0x80, 0x80, 0x80, 0x80 + }; + memcpy(query.response, test, sizeof(test)); + DEBUG_OUT(query.response[1+query.lastByte]); + return query.response[++query.lastByte]; + }//*/ int i; - Pad *pad = &pads[query.pad]; + Pad *pad = &pads[query.port][query.slot]; if (query.lastByte == 0) { query.lastByte++; query.currentCommand = value; @@ -832,7 +895,7 @@ u8 CALLBACK PADpoll(u8 value) { query.response[2] = 0x5A; { if (!config.GSThreadUpdates) { - Update(pad != pads); + Update(query.port); } ButtonSum *sum = &pad->sum; @@ -843,7 +906,7 @@ u8 CALLBACK PADpoll(u8 value) { for (i = 0; i<8; i++) { b2 -= (sum->buttons[i+4]>=128) << i; } - if (config.guitar[query.pad] && !config.GH2) { + if (config.padConfigs[query.port][query.slot].type == GuitarPad && !config.GH2) { sum->sticks[0].horiz = -255; // Not sure about this. Forces wammy to be from 0 to 0x7F. // if (sum->sticks[2].vert > 0) sum->sticks[2].vert = 0; @@ -915,11 +978,11 @@ u8 CALLBACK PADpoll(u8 value) { // SET_MODE_AND_LOCK case 0x44: SET_RESULT(setMode); - ResetVibrate(pad); + ResetVibrate(query.port, query.slot); break; // QUERY_MODEL_AND_MODE case 0x45: - if (!config.guitar[query.pad] || config.GH2) SET_FINAL_RESULT(queryModelDS2) + if (config.padConfigs[query.port][query.slot].type != GuitarPad || config.GH2) SET_FINAL_RESULT(queryModelDS2) else SET_FINAL_RESULT(queryModelDS1); query.response[5] = pad->mode != MODE_DIGITAL; break; @@ -939,7 +1002,7 @@ u8 CALLBACK PADpoll(u8 value) { case 0x4D: memcpy(query.response+2, pad->vibrate, 7); query.numBytes = 9; - ResetVibrate(pad); + ResetVibrate(query.port, query.slot); break; // SET_DS2_NATIVE_MODE case 0x4F: @@ -959,10 +1022,10 @@ u8 CALLBACK PADpoll(u8 value) { // READ_DATA_AND_VIBRATE case 0x42: if (query.lastByte == pad->vibrateI[0]) { - SetVibrate(pad, 1, 255*(0!=value)); + SetVibrate(query.port, query.slot, 1, 255*(0!=value)); } else if (query.lastByte == pad->vibrateI[1]) { - SetVibrate(pad, 0, value); + SetVibrate(query.port, query.slot, 0, value); } break; // CONFIG_MODE @@ -984,7 +1047,7 @@ u8 CALLBACK PADpoll(u8 value) { } else { pad->modeLock = 0; - if (pad->mode == MODE_DIGITAL && config.AutoAnalog[query.pad]) { + if (pad->mode == MODE_DIGITAL && config.padConfigs[query.port][query.slot].autoAnalog) { pad->mode = MODE_ANALOG; } } @@ -1077,7 +1140,6 @@ void CALLBACK PADabout() { s32 CALLBACK PADtest() { return 0; } -#include DWORD WINAPI RenameWindowThreadProc(void *lpParameter) { wchar_t newTitle[200]; @@ -1092,26 +1154,12 @@ DWORD WINAPI RenameWindowThreadProc(void *lpParameter) { return 0; } -// For escape fullscreen hack. This doesn't work when called from another thread, for some reason. -// That includes a new thread, independent of GS and PCSX2 thread, so use this to make sure it's -// called from the right spot. -ExtraWndProcResult KillFullScreenProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *output) { - // Prevent infinite recursion. Could also just remove this function from the list, - // but CONTINUE_BLISSFULLY_AND_RELEASE_PROC is a safer way to do that. - static int inFunction = 0; - if (!inFunction) { - inFunction = 1; - ShowWindow(hWnd, SW_MINIMIZE); - inFunction = 0; - } - return CONTINUE_BLISSFULLY_AND_RELEASE_PROC; -} - keyEvent* CALLBACK PADkeyEvent() { if (!config.GSThreadUpdates) { Update(2); } static char shiftDown = 0; + static char altDown = 0; static keyEvent ev; if (!GetQueuedKeyEvent(&ev)) return 0; if ((ev.key == VK_ESCAPE || (int)ev.key == -2) && ev.evt == KEYPRESS && config.escapeFullscreenHack) { @@ -1121,7 +1169,6 @@ keyEvent* CALLBACK PADkeyEvent() { QueueKeyEvent(-2, KEYPRESS); HANDLE hThread = CreateThread(0, 0, MaximizeWindowThreadProc, 0, 0, 0); if (hThread) CloseHandle(hThread); - //ShowWindowAsync(hWnd, SW_HIDE); restoreFullScreen = 1; return 0; } @@ -1139,28 +1186,104 @@ keyEvent* CALLBACK PADkeyEvent() { saveStateIndex = (saveStateIndex+10)%10; if (config.saveStateTitle) { // GSDX only checks its window's message queue at certain points or something, so - // have to do this in another thread to prevent lockup. + // have to do this in another thread to prevent deadlock. HANDLE hThread = CreateThread(0, 0, RenameWindowThreadProc, 0, 0, 0); if (hThread) CloseHandle(hThread); } } + // So don't change skip mode on alt-F4. + if (ev.key == VK_F4 && altDown) { + return 0; + } + if (ev.key == VK_LSHIFT || ev.key == VK_RSHIFT || ev.key == VK_SHIFT) { ev.key = VK_SHIFT; - if (ev.evt == KEYPRESS) - shiftDown = 1; - else - shiftDown = 0; + shiftDown = (ev.evt == KEYPRESS); } else if (ev.key == VK_LCONTROL || ev.key == VK_RCONTROL) { ev.key = VK_CONTROL; } - else if (ev.key == VK_LMENU || ev.key == VK_RMENU) { + else if (ev.key == VK_LMENU || ev.key == VK_RMENU || ev.key == VK_SHIFT) { ev.key = VK_MENU; + altDown = (ev.evt == KEYPRESS); } return &ev; } +#define PAD_SAVE_STATE_VERSION 0 + +struct PadPluginFreezeData { + char format[8]; + // Currently all different versions are incompatible. + // May split into major/minor with some compatibility rules. + u32 version; + // So when loading, know which plugin's settings I'm loading. + // Not a big deal. Use a static variable when saving to figure it out. + u8 port; + // active slot for port + u8 slot; + // Currently only use padData[0]. Save room for all 4 slots for simplicity. + PadFreezeData padData[4]; +}; + +s32 CALLBACK PADfreeze(int mode, freezeData *data) { + if (mode == FREEZE_SIZE) { + data->size = sizeof(PadPluginFreezeData); + } + else if (mode == FREEZE_LOAD) { + if (data->size < sizeof(PadPluginFreezeData)) return 0; + PadPluginFreezeData &pdata = *(PadPluginFreezeData*)(data->data); + if (pdata.version != PAD_SAVE_STATE_VERSION || strcmp(pdata.format, "PadMode")) { + return 0; + } + StopVibrate(); + int port = pdata.port; + for (int slot=0; slot<4; slot++) { + u8 mode = pads[port][slot].mode = pdata.padData[slot].mode; + if (mode != MODE_DIGITAL && mode != MODE_ANALOG && mode != MODE_DS2_NATIVE) { + ResetPad(port, slot); + continue; + } + pads[port][slot].config = pdata.padData[slot].config; + pads[port][slot].modeLock = pdata.padData[slot].modeLock; + memcpy(pads[port][slot].umask, pdata.padData[slot].umask, sizeof(pads[port][slot].umask)); + + slots[port] = slot; + // Means I only have to have one chunk of code to parse vibrate info. + // Other plugins don't store it exactly, but think it's technically correct + // to do so, though I could be wrong. + PADstartPoll(port+1); + PADpoll(0x4D); + for (int j=0; j<7; j++) { + PADpoll(pdata.padData[slot].vibrate[j]); + } + } + slots[port] = pdata.slot; + } + else if (mode == FREEZE_SAVE) { + if (data->size != sizeof(PadPluginFreezeData)) return 0; + PadPluginFreezeData &pdata = *(PadPluginFreezeData*)(data->data); + static int nextPort = 0; + if (!portInitialized[nextPort]) nextPort ^= 1; + int port = nextPort; + if (!portInitialized[nextPort^1]) nextPort = 0; + else nextPort ^= 1; + + + memset(&pdata, 0, sizeof(pdata)); + strcpy(pdata.format, "PadMode"); + pdata.version = PAD_SAVE_STATE_VERSION; + pdata.port = port; + pdata.slot = slots[port]; + for (int slot=0; slot<4; slot++) { + pdata.padData[slot] = pads[port][slot]; + } + } + else return -1; + return 0; + } + u32 CALLBACK PADreadPort1 (PadDataS* pads) { PADstartPoll(1); PADpoll(0x42); diff --git a/plugins/LilyPad/LilyPad.def b/plugins/LilyPad/LilyPad.def index c26aba711c..9754805d5a 100644 --- a/plugins/LilyPad/LilyPad.def +++ b/plugins/LilyPad/LilyPad.def @@ -19,4 +19,4 @@ EXPORTS PADtest PADabout PADupdate - + PADfreeze diff --git a/plugins/LilyPad/LilyPad.rc b/plugins/LilyPad/LilyPad.rc index 7056ddda7d..9fd6224740 100644 --- a/plugins/LilyPad/LilyPad.rc +++ b/plugins/LilyPad/LilyPad.rc @@ -74,39 +74,22 @@ BEGIN PUSHBUTTON "R2",ID_R2,372,73,45,15 PUSHBUTTON "L3",ID_L3,195,93,45,15 PUSHBUTTON "R3",ID_R3,371,93,46,15 - GROUPBOX "D-Pad",ID_DPAD,251,44,110,68 - PUSHBUTTON "Up",ID_DPAD_UP,275,54,35,15 - PUSHBUTTON "Left",ID_DPAD_LEFT,257,73,35,15 - PUSHBUTTON "Right",ID_DPAD_RIGHT,297,73,35,15 - PUSHBUTTON "Down",ID_DPAD_DOWN,275,92,35,15 - PUSHBUTTON "Vert Axis",ID_DPAD_UDAXIS,314,54,40,15 - PUSHBUTTON "Horiz Axis",ID_DPAD_LRAXIS,314,92,40,15 - PUSHBUTTON "L1/R1 Axis",ID_L1R1,231,117,45,15 - PUSHBUTTON "L2/R2 Axis",ID_L2R2,281,117,45,15 - PUSHBUTTON "L3/R3 Axis",ID_L3R3,331,117,45,15 - GROUPBOX "Left Analog Stick",ID_LSTICK,195,135,108,70 - PUSHBUTTON "Up",ID_LSTICK_UP,218,145,35,15 - PUSHBUTTON "Left",ID_LSTICK_LEFT,200,164,35,15 - PUSHBUTTON "Right",ID_LSTICK_RIGHT,240,164,35,15 - PUSHBUTTON "Down",ID_LSTICK_DOWN,218,184,35,15 - PUSHBUTTON "Vert Axis",ID_LSTICK_UDAXIS,257,145,40,15 - PUSHBUTTON "Horiz Axis",ID_LSTICK_LRAXIS,257,184,40,15 - GROUPBOX "Right Analog Stick",ID_RSTICK,309,135,108,70 - PUSHBUTTON "Up",ID_RSTICK_UP,332,145,35,15 - PUSHBUTTON "Left",ID_RSTICK_LEFT,314,164,35,15 - PUSHBUTTON "Right",ID_RSTICK_RIGHT,354,164,35,15 - PUSHBUTTON "Down",ID_RSTICK_DOWN,332,184,35,15 - PUSHBUTTON "Vert Axis",ID_RSTICK_UDAXIS,371,145,40,15 - PUSHBUTTON "Horiz Axis",ID_RSTICK_LRAXIS,371,184,40,15 - GROUPBOX "Sensitivity",ID_SENSITIVITY,195,207,222,49 - EDITTEXT IDC_AXIS_DEVICE1,201,218,74,12,ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP - EDITTEXT IDC_AXIS1,201,230,74,12,ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP - EDITTEXT IDC_AXIS_CONTROL1,201,242,74,12,ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP - CONTROL "",IDC_SLIDER1,"msctls_trackbar32",WS_TABSTOP,276,217,138,17 - CONTROL "Flip",IDC_FLIP1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,280,240,27,10 - CONTROL "Turbo",IDC_TURBO,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,309,240,34,10 - EDITTEXT IDC_AXIS_SENSITIVITY1,375,240,33,12,ES_RIGHT | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP,WS_EX_RTLREADING - GROUPBOX "",ID_FF,195,6,222,250 + GROUPBOX "D-Pad",IDC_DPAD,251,44,110,70 + PUSHBUTTON "Up",ID_DPAD_UP,285,55,35,15 + PUSHBUTTON "Left",ID_DPAD_LEFT,267,74,35,15 + PUSHBUTTON "Right",ID_DPAD_RIGHT,307,74,35,15 + PUSHBUTTON "Down",ID_DPAD_DOWN,285,93,35,15 + GROUPBOX "Left Analog Stick",IDC_LSTICK,195,115,108,70 + PUSHBUTTON "Up",ID_LSTICK_UP,228,126,35,15 + PUSHBUTTON "Left",ID_LSTICK_LEFT,210,145,35,15 + PUSHBUTTON "Right",ID_LSTICK_RIGHT,250,145,35,15 + PUSHBUTTON "Down",ID_LSTICK_DOWN,228,165,35,15 + GROUPBOX "Right Analog Stick",IDC_RSTICK,309,115,108,70 + PUSHBUTTON "Up",ID_RSTICK_UP,342,126,35,15 + PUSHBUTTON "Left",ID_RSTICK_LEFT,324,145,35,15 + PUSHBUTTON "Right",ID_RSTICK_RIGHT,364,145,35,15 + PUSHBUTTON "Down",ID_RSTICK_DOWN,342,165,35,15 + GROUPBOX "",ID_FF,195,6,222,248 COMBOBOX IDC_FF_EFFECT,203,20,206,106,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP CONTROL "",IDC_FF_AXIS1,"msctls_trackbar32",WS_TABSTOP,199,40,214,17 CONTROL "Axis 1",IDC_FF_AXIS1_ENABLED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,205,60,91,10 @@ -132,12 +115,20 @@ BEGIN CONTROL "Axis 6",IDC_FF_AXIS6_ENABLED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,205,240,91,10 CONTROL "Flip",IDC_FF_AXIS6_FLIP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,302,240,35,10 EDITTEXT IDC_FF_AXIS6_SCALE,375,240,33,12,ES_RIGHT | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP,WS_EX_RTLREADING - PUSHBUTTON "Test",ID_TEST,196,260,62,15 - PUSHBUTTON "Back to Controls",ID_CONTROLS,196,296,62,15 - PUSHBUTTON "Lock Input",ID_LOCK,196,260,62,15 - PUSHBUTTON "Lock Direction",ID_LOCK_DIRECTION,196,278,62,15 - PUSHBUTTON "Lock Buttons",ID_LOCK_BUTTONS,196,296,62,15 - GROUPBOX "New Force Feedback Effect",IDC_STATIC,262,260,155,51 + PUSHBUTTON "Test",ID_TEST,196,260,59,15 + PUSHBUTTON "Back to Controls",ID_CONTROLS,196,296,59,15 + GROUPBOX "Sensitivity",ID_SENSITIVITY,195,188,222,66 + EDITTEXT IDC_AXIS_DEVICE1,203,202,208,12,ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP + COMBOBOX IDC_AXIS_DIRECTION,202,218,70,47,CBS_DROPDOWNLIST | WS_TABSTOP + EDITTEXT IDC_AXIS_CONTROL1,203,240,74,12,ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP + CONTROL "",IDC_SLIDER1,"msctls_trackbar32",WS_TABSTOP,276,217,138,17 + CONTROL "Flip",IDC_FLIP1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,280,240,27,10 + CONTROL "Turbo",IDC_TURBO,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,309,240,34,10 + EDITTEXT IDC_AXIS_SENSITIVITY1,375,240,33,12,ES_RIGHT | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP,WS_EX_RTLREADING + PUSHBUTTON "Lock Input",ID_LOCK,196,260,59,15 + PUSHBUTTON "Lock Direction",ID_LOCK_DIRECTION,196,278,59,15 + PUSHBUTTON "Lock Buttons",ID_LOCK_BUTTONS,196,296,59,15 + GROUPBOX "Add Force Feedback Effect",IDC_STATIC,262,260,155,51 COMBOBOX IDC_FORCEFEEDBACK,269,273,142,106,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP PUSHBUTTON "Big Motor",ID_BIG_MOTOR,269,291,64,14 PUSHBUTTON "Small Motor",ID_SMALL_MOTOR,347,291,64,14 @@ -159,32 +150,10 @@ BEGIN PUSHBUTTON "Start",ID_START,256,122,45,15 PUSHBUTTON "Select/Tilt",ID_SELECT,307,122,45,15 PUSHBUTTON "Whammy Bar Up",ID_LSTICK_UP,219,146,69,15 - PUSHBUTTON "Whammy Bar Axis",ID_LSTICK_UDAXIS,212,165,84,15 - PUSHBUTTON "Whammy Bar Down",ID_LSTICK_DOWN,219,184,69,15 - PUSHBUTTON "Analog",ID_ANALOG,372,7,45,12,NOT WS_VISIBLE - PUSHBUTTON "Mouse",ID_MOUSE,372,51,45,12,NOT WS_VISIBLE - PUSHBUTTON "L3",ID_L3,203,7,45,15,NOT WS_VISIBLE - PUSHBUTTON "R3",ID_R3,203,23,46,15,NOT WS_VISIBLE + PUSHBUTTON "Whammy Bar Down",ID_LSTICK_DOWN,219,164,69,15 PUSHBUTTON "Strum Bar Up",ID_DPAD_UP,336,146,58,15 - PUSHBUTTON "Strum Bar Axis",ID_DPAD_UDAXIS,328,165,74,15 - PUSHBUTTON "Strum Bar Down",ID_DPAD_DOWN,336,184,58,15 - PUSHBUTTON "Left",ID_DPAD_LEFT,342,28,35,15,NOT WS_VISIBLE - PUSHBUTTON "Right",ID_DPAD_RIGHT,382,28,35,15,NOT WS_VISIBLE - PUSHBUTTON "L1",ID_L1,372,85,45,15,NOT WS_VISIBLE - PUSHBUTTON "R1",ID_R1,372,67,45,15,NOT WS_VISIBLE - PUSHBUTTON "L2",ID_L2,372,103,45,15,NOT WS_VISIBLE - PUSHBUTTON "L1/R1 Axis",ID_L1R1,203,74,45,15,NOT WS_VISIBLE - PUSHBUTTON "L2/R2 Axis",ID_L2R2,203,58,45,15,NOT WS_VISIBLE - PUSHBUTTON "L3/R3 Axis",ID_L3R3,203,42,45,15,NOT WS_VISIBLE - GROUPBOX "Sensitivity",ID_SENSITIVITY,195,207,222,49 - EDITTEXT IDC_AXIS_DEVICE1,201,218,74,12,ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP - EDITTEXT IDC_AXIS1,201,230,74,12,ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP - EDITTEXT IDC_AXIS_CONTROL1,201,242,74,12,ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP - CONTROL "",IDC_SLIDER1,"msctls_trackbar32",WS_TABSTOP,276,217,138,17 - CONTROL "Flip",IDC_FLIP1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,280,240,27,10 - CONTROL "Turbo",IDC_TURBO,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,309,240,34,10 - EDITTEXT IDC_AXIS_SENSITIVITY1,375,240,33,12,ES_RIGHT | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP,WS_EX_RTLREADING - GROUPBOX "",ID_FF,195,6,222,250 + PUSHBUTTON "Strum Bar Down",ID_DPAD_DOWN,336,164,58,15 + GROUPBOX "",ID_FF,195,6,222,248 COMBOBOX IDC_FF_EFFECT,203,20,206,106,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP CONTROL "",IDC_FF_AXIS1,"msctls_trackbar32",WS_TABSTOP,199,40,214,17 CONTROL "Axis 1",IDC_FF_AXIS1_ENABLED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,205,60,91,10 @@ -210,11 +179,19 @@ BEGIN CONTROL "Axis 6",IDC_FF_AXIS6_ENABLED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,205,240,91,10 CONTROL "Flip",IDC_FF_AXIS6_FLIP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,302,240,35,10 EDITTEXT IDC_FF_AXIS6_SCALE,375,240,33,12,ES_RIGHT | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP,WS_EX_RTLREADING - PUSHBUTTON "Test",ID_TEST,196,260,62,15 - PUSHBUTTON "Back to Controls",ID_CONTROLS,196,296,62,15 - PUSHBUTTON "Lock Input",ID_LOCK,196,260,62,15 - PUSHBUTTON "Lock Direction",ID_LOCK_DIRECTION,196,278,62,15 - PUSHBUTTON "Lock Buttons",ID_LOCK_BUTTONS,196,296,62,15 + PUSHBUTTON "Test",ID_TEST,196,260,59,15 + PUSHBUTTON "Back to Controls",ID_CONTROLS,196,296,59,15 + GROUPBOX "Binding Details",ID_SENSITIVITY,195,188,222,66 + EDITTEXT IDC_AXIS_DEVICE1,203,202,208,12,ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP + COMBOBOX IDC_AXIS_DIRECTION,202,218,70,47,CBS_DROPDOWNLIST | WS_TABSTOP + EDITTEXT IDC_AXIS_CONTROL1,203,240,74,12,ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP + CONTROL "",IDC_SLIDER1,"msctls_trackbar32",WS_TABSTOP,276,217,138,17 + CONTROL "Flip",IDC_FLIP1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,280,240,27,10 + CONTROL "Turbo",IDC_TURBO,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,309,240,34,10 + EDITTEXT IDC_AXIS_SENSITIVITY1,375,240,33,12,ES_RIGHT | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP,WS_EX_RTLREADING + PUSHBUTTON "Lock Input",ID_LOCK,196,260,59,15 + PUSHBUTTON "Lock Direction",ID_LOCK_DIRECTION,196,278,59,15 + PUSHBUTTON "Lock Buttons",ID_LOCK_BUTTONS,196,296,59,15 GROUPBOX "New Force Feedback Effect",IDC_STATIC,262,260,155,51 COMBOBOX IDC_FORCEFEEDBACK,269,273,142,106,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP PUSHBUTTON "Big Motor",ID_BIG_MOTOR,269,291,64,14 @@ -227,54 +204,50 @@ FONT 8, "MS Shell Dlg", 0, 0, 0x1 BEGIN GROUPBOX "Input APIs",IDC_STATIC,7,6,410,131 GROUPBOX "Keyboard API",IDC_STATIC,16,16,192,61 - CONTROL "Windows messaging (Recommended)",IDC_KB_WM,"Button",BS_AUTORADIOBUTTON | WS_GROUP,23,28,134,10 - CONTROL "Raw input (XP and later only)",IDC_KB_RAW,"Button",BS_AUTORADIOBUTTON,23,40,112,10 - CONTROL "DirectInput",IDC_KB_DI,"Button",BS_AUTORADIOBUTTON,23,52,112,10 + CONTROL "Windows messaging (Recommended)",IDC_KB_WM,"Button",BS_AUTORADIOBUTTON | WS_GROUP,22,28,134,10 + CONTROL "Raw input (XP and later only)",IDC_KB_RAW,"Button",BS_AUTORADIOBUTTON,22,40,112,10 + CONTROL "DirectInput",IDC_KB_DI,"Button",BS_AUTORADIOBUTTON,22,52,112,10 CONTROL "Disable (Intended for use with other pad plugins)",IDC_KB_DISABLE, - "Button",BS_AUTORADIOBUTTON,23,64,175,10 + "Button",BS_AUTORADIOBUTTON,22,64,175,10 GROUPBOX "Game Device APIs",IDC_STATIC,16,81,191,49 - CONTROL "DirectInput",IDC_G_DI,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,23,92,65,10 - CONTROL "XInput",IDC_G_XI,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,23,104,39,10 - CONTROL "Monitor when in background",IDC_BACKGROUND,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,23,116,106,10 - GROUPBOX "Mouse API",IDC_STATIC,216,16,192,73 - CONTROL "Windows messaging",IDC_M_WM,"Button",BS_AUTORADIOBUTTON | WS_GROUP,224,27,112,10 - CONTROL "Raw input (XP and later only)",IDC_M_RAW,"Button",BS_AUTORADIOBUTTON,224,39,112,10 - CONTROL "DirectInput",IDC_M_DI,"Button",BS_AUTORADIOBUTTON,224,51,112,10 - CONTROL "Disable",IDC_M_DISABLE,"Button",BS_AUTORADIOBUTTON,224,63,39,10 - CONTROL "Start without mouse focus",IDC_MOUSE_UNFOCUS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,224,75,97,10 - GROUPBOX "Advanced",IDC_STATIC,216,92,192,38 - CONTROL "Allow binding entire axes to single buttons",IDC_AXIS_BUTTONS, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,224,104,177,10 - CONTROL "Allow multiple binding",IDC_MULTIPLE_BINDING,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,224,116,83,10 - GROUPBOX "Pad Options",IDC_STATIC,7,140,410,67 - GROUPBOX "Pad 1",IDC_STATIC,16,150,192,49 - CONTROL "Disable pad",IDC_DISABLE_PAD1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,24,162,53,10 + CONTROL "DirectInput",IDC_G_DI,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,22,92,65,10 + CONTROL "XInput (Xbox 360 controllers only)",IDC_G_XI,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,22,104,125,10 + CONTROL "Monitor when in background",IDC_BACKGROUND,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,22,116,106,10 + GROUPBOX "Mouse API",IDC_STATIC,216,16,192,85 + CONTROL "Windows messaging (Recommended)",IDC_M_WM,"Button",BS_AUTORADIOBUTTON | WS_GROUP,223,27,134,10 + CONTROL "Raw input (XP and later only)",IDC_M_RAW,"Button",BS_AUTORADIOBUTTON,223,39,112,10 + CONTROL "DirectInput",IDC_M_DI,"Button",BS_AUTORADIOBUTTON,223,51,112,10 + CONTROL "Disable",IDC_M_DISABLE,"Button",BS_AUTORADIOBUTTON,223,63,39,10 + CONTROL "Start without mouse focus",IDC_MOUSE_UNFOCUS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,223,75,97,10 + CONTROL "Always hide cursor",IDC_FORCE_HIDE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,223,87,71,10 + GROUPBOX "Advanced",IDC_STATIC,216,105,192,25 + CONTROL "Allow binding multiple PS2 controls to one PC control",IDC_MULTIPLE_BINDING, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,223,116,182,10 + GROUPBOX "Pads",IDC_STATIC,7,140,410,67 + CONTROL "Port 1 Multitap",IDC_MULTITAP1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,152,63,10 + CONTROL "Port 2 Multitap",IDC_MULTITAP2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,164,63,10 + CONTROL "",IDC_PAD_LIST,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | WS_TABSTOP,81,152,183,48,WS_EX_CLIENTEDGE + COMBOBOX IDC_PAD_TYPE,270,153,140,41,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP CONTROL "Use analog mode whenever possible",IDC_ANALOG_START1, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,24,174,132,10 - CONTROL "Guitar",IDC_GUITAR1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,24,186,35,10 - GROUPBOX "Pad 2",IDC_STATIC,216,150,192,49 - CONTROL "Disable pad",IDC_DISABLE_PAD2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,224,162,53,10 - CONTROL "Use analog mode whenever possible",IDC_ANALOG_START2, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,224,174,132,10 - CONTROL "Guitar",IDC_GUITAR2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,224,186,35,10 + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,270,170,132,10 GROUPBOX "Device Diagnostics",IDC_STATIC,7,211,201,99 CONTROL "",IDC_LIST,"SysListView32",LVS_LIST | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_NOSORTHEADER | WS_BORDER | WS_VSCROLL | WS_TABSTOP,15,224,185,61,WS_EX_CLIENTEDGE PUSHBUTTON "Test Device",ID_TEST,86,289,57,15 PUSHBUTTON "Refresh",ID_REFRESH,152,289,48,15 - GROUPBOX "Hacks",IDC_STATIC,216,211,201,73 - CONTROL "Send escape on window close",IDC_CLOSE_HACK1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,224,223,113,10 - CONTROL "Exit emulator on window close",IDC_CLOSE_HACK2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,224,235,112,10 - CONTROL "Disable screensaver",IDC_DISABLE_SCREENSAVER,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,224,247,80,10 - CONTROL "Safe fullscreen exit on escape (For GSDX+DX10)",IDC_ESCAPE_FULLSCREEN_HACK, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,224,259,171,10 - CONTROL "Use GS thread (Recommended)",IDC_GS_THREAD_INPUT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,224,271,116,10 - CONTROL "Always hide cursor",IDC_FORCE_HIDE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,336,223,71,10 - CONTROL "Save state # in title",IDC_SAVE_STATE_TITLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,336,235,79,10 - CONTROL "Guitar Hero 2 Hack",IDC_GH2_HACK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,336,247,76,10 - GROUPBOX "Debugging",IDC_STATIC,216,285,79,25 - CONTROL "Enable logging",IDC_DEBUG_FILE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,223,296,63,10 - PUSHBUTTON "Load",ID_LOAD,313,295,48,15 - PUSHBUTTON "Save",ID_SAVE,369,295,48,15 + GROUPBOX "Miscellaneous",IDC_STATIC,216,211,201,35 + CONTROL "Use GS thread (Recommended)",IDC_GS_THREAD_INPUT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,221,221,116,10 + CONTROL "Disable screensaver",IDC_DISABLE_SCREENSAVER,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,221,232,80,10 + CONTROL "Local volume control",IDC_VISTA_VOLUME,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,336,221,77,10 + CONTROL "Enable logging",IDC_DEBUG_FILE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,336,232,62,10 + GROUPBOX "Hacks",IDC_STATIC,216,247,201,45 + CONTROL "Send escape on window close",IDC_CLOSE_HACK1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,223,257,113,10 + CONTROL "Exit emulator on window close",IDC_CLOSE_HACK2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,223,268,112,10 + CONTROL "Safe fullscreen exit on escape",IDC_ESCAPE_FULLSCREEN_HACK, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,223,279,112,10 + CONTROL "Save state # in title",IDC_SAVE_STATE_TITLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,336,257,79,10 + CONTROL "Guitar Hero 2 Hack",IDC_GH2_HACK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,336,268,76,10 + PUSHBUTTON "Load Bindings",ID_LOAD,283,295,62,15 + PUSHBUTTON "Save Bindings",ID_SAVE,355,295,62,15 END IDD_ABOUT DIALOGEX 0, 0, 108, 66 diff --git a/plugins/LilyPad/LilyPad_VC2005.vcproj b/plugins/LilyPad/LilyPad_VC2005.vcproj index 6c38229e45..c7ac387621 100644 --- a/plugins/LilyPad/LilyPad_VC2005.vcproj +++ b/plugins/LilyPad/LilyPad_VC2005.vcproj @@ -51,6 +51,7 @@ diff --git a/plugins/LilyPad/XInput.cpp b/plugins/LilyPad/XInput.cpp index f20141312d..12b1d5656f 100644 --- a/plugins/LilyPad/XInput.cpp +++ b/plugins/LilyPad/XInput.cpp @@ -27,7 +27,7 @@ __forceinline int ShortToAxis(int v) { class XInputDevice : public Device { // Cached last vibration values by pad and motor. // Need this, as only one value is changed at a time. - int ps2Vibration[2][2]; + int ps2Vibration[2][4][2]; // Minor optimization - cache last set vibration values // When there's no change, no need to do anything. XINPUT_VIBRATION xInputVibration; @@ -112,15 +112,17 @@ public: return 1; } - void SetEffects(unsigned char pad, unsigned char motor, unsigned char force) { - ps2Vibration[pad][motor] = force; + void SetEffects(unsigned char port, unsigned int slot, unsigned char motor, unsigned char force) { + ps2Vibration[port][slot][motor] = force; int newVibration[2] = {0,0}; for (int p=0; p<2; p++) { - for (int i=0; iaxes[0].force * (__int64)ps2Vibration[p][ffb->motor]) / 255); - newVibration[1] += (int)((ffb->axes[1].force * (__int64)ps2Vibration[p][ffb->motor]) / 255); + for (int s=0; s<4; s++) { + for (int i=0; iaxes[0].force * (__int64)ps2Vibration[p][s][ffb->motor]) / 255); + newVibration[1] += (int)((ffb->axes[1].force * (__int64)ps2Vibration[p][s][ffb->motor]) / 255); + } } } newVibration[0] = abs(newVibration[0]); @@ -140,11 +142,11 @@ public: } void SetEffect(ForceFeedbackBinding *binding, unsigned char force) { - PadBindings pBackup = pads[0]; - pads[0].ffBindings = binding; - pads[0].numFFBindings = 1; - SetEffects(0, binding->motor, 255); - pads[0] = pBackup; + PadBindings pBackup = pads[0][0]; + pads[0][0].ffBindings = binding; + pads[0][0].numFFBindings = 1; + SetEffects(0, 0, binding->motor, 255); + pads[0][0] = pBackup; } void Deactivate() { diff --git a/plugins/LilyPad/resource.h b/plugins/LilyPad/resource.h index c539c96b96..de3c4b4913 100644 --- a/plugins/LilyPad/resource.h +++ b/plugins/LilyPad/resource.h @@ -17,7 +17,6 @@ #define IDC_KB_WM 1102 #define IDC_KB_RAW 1103 #define IDC_DISABLE_PAD1 1104 -#define IDC_DISABLE_PAD2 1105 #define IDC_M_DISABLE 1106 #define IDC_M_DI 1107 #define IDC_M_WM 1108 @@ -25,39 +24,37 @@ #define IDC_G_XI 1110 #define IDC_G_DI 1111 #define IDC_CLOSE_HACK2 1112 -#define IDC_CLOSE_HACK3 1113 #define IDC_DEBUG_FILE 1114 #define IDC_GUITAR1 1115 -#define IDC_GUITAR2 1116 #define IDC_ANALOG_START1 1117 -#define IDC_ANALOG_START2 1118 +#define IDC_MULTITAP1 1118 #define IDC_DISABLE_SCREENSAVER 1119 #define IDC_MOUSE_UNFOCUS 1120 -#define IDC_MOUSE_UNFOCUS2 1121 #define IDC_AXIS_BUTTONS 1121 +#define IDC_MULTITAP2 1121 #define IDC_BACKGROUND 1122 #define IDC_MULTIPLE_BINDING 1123 #define IDC_DISABLE_SCREENSAVER2 1124 #define IDC_FORCE_HIDE 1124 -#define IDC_FORCE_HIDE2 1125 #define IDC_GH2_HACK 1125 #define IDC_FORCEFEEDBACK_HACK1 1126 -#define IDC_DISABLE_SCREENSAVER4 1127 -#define IDC_FORCEFEEDBACK_HACK2 1127 +#define IDC_VISTA_VOLUME 1126 #define IDC_GS_THREAD_INPUT 1128 -#define IDC_GS_THREAD_INPUT2 1129 #define IDC_SAVE_STATE_TITLE 1129 +#define IDC_PAD_LIST 1133 +#define IDC_COMBO1 1134 +#define IDC_PAD_TYPE 1134 #define IDC_SLIDER1 0x1000 #define IDC_FLIP1 0x1001 -#define IDC_AXIS1 0x1002 +#define IDC_AXIS_DIRECTION 0x1002 #define IDC_AXIS_CONTROL1 0x1003 #define IDC_AXIS_SENSITIVITY1 0x1004 #define IDC_TURBO 0x1005 #define IDC_AXIS_DEVICE1 0x1006 #define ID_SENSITIVITY 0x1007 -#define ID_DPAD 0x1008 -#define ID_LSTICK 0x1009 -#define ID_RSTICK 0x100A +#define IDC_DPAD 0x1008 +#define IDC_LSTICK 0x1009 +#define IDC_RSTICK 0x100A #define ID_GUITAR_HERO 0x10FB #define ID_LOCK_BUTTONS 0x10FC #define ID_LOCK 0x10FD @@ -88,15 +85,6 @@ #define ID_RSTICK_DOWN 0x1116 #define ID_RSTICK_LEFT 0x1117 #define ID_ANALOG 0x1118 -#define ID_DPAD_LRAXIS 0x1120 -#define ID_DPAD_UDAXIS 0x1121 -#define ID_LSTICK_LRAXIS 0x1122 -#define ID_LSTICK_UDAXIS 0x1123 -#define ID_RSTICK_LRAXIS 0x1124 -#define ID_RSTICK_UDAXIS 0x1125 -#define ID_L1R1 0x1126 -#define ID_L2R2 0x1127 -#define ID_L3R3 0x1128 #define ID_DELETE 0x11FF #define ID_DEBUG 0x1200 #define ID_IGNORE 0x1201 @@ -115,7 +103,7 @@ #define IDC_FF_MOTOR 0x1303 #define ID_FF 0x1304 #define IDC_FF_EFFECT 0x1305 -#define IDC_VERSION 0x1306 +#define IDC_VERSION 0x1306 #define IDC_FF_AXIS1_ENABLED 0x1310 #define IDC_FF_AXIS1 0x1311 #define IDC_FF_AXIS1_FLIP 0x1312 @@ -150,12 +138,12 @@ #define IDC_FF_AXIS8_SCALE 0x1383 // Next default values for new objects -// +// #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 112 #define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1127 +#define _APS_NEXT_CONTROL_VALUE 1135 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif diff --git a/plugins/USBnull/Win32/Config.c b/plugins/USBnull/Windows/Config.c similarity index 100% rename from plugins/USBnull/Win32/Config.c rename to plugins/USBnull/Windows/Config.c diff --git a/plugins/USBnull/Win32/Makefile b/plugins/USBnull/Windows/Makefile similarity index 100% rename from plugins/USBnull/Win32/Makefile rename to plugins/USBnull/Windows/Makefile diff --git a/plugins/USBnull/Win32/ProjectRootDir.vsprops b/plugins/USBnull/Windows/ProjectRootDir.vsprops similarity index 100% rename from plugins/USBnull/Win32/ProjectRootDir.vsprops rename to plugins/USBnull/Windows/ProjectRootDir.vsprops diff --git a/plugins/USBnull/Win32/USBnull.def b/plugins/USBnull/Windows/USBnull.def similarity index 100% rename from plugins/USBnull/Win32/USBnull.def rename to plugins/USBnull/Windows/USBnull.def diff --git a/plugins/USBnull/Win32/USBnull.rc b/plugins/USBnull/Windows/USBnull.rc similarity index 100% rename from plugins/USBnull/Win32/USBnull.rc rename to plugins/USBnull/Windows/USBnull.rc diff --git a/plugins/USBnull/Win32/USBnull_vc2008.vcproj b/plugins/USBnull/Windows/USBnull_vc2008.vcproj similarity index 100% rename from plugins/USBnull/Win32/USBnull_vc2008.vcproj rename to plugins/USBnull/Windows/USBnull_vc2008.vcproj diff --git a/plugins/USBnull/Win32/Win32.c b/plugins/USBnull/Windows/Win32.c similarity index 100% rename from plugins/USBnull/Win32/Win32.c rename to plugins/USBnull/Windows/Win32.c diff --git a/plugins/USBnull/Win32/resource.h b/plugins/USBnull/Windows/resource.h similarity index 100% rename from plugins/USBnull/Win32/resource.h rename to plugins/USBnull/Windows/resource.h diff --git a/plugins/spu2-x/src/Win32/AboutBox.cpp b/plugins/spu2-x/src/Windows/AboutBox.cpp similarity index 100% rename from plugins/spu2-x/src/Win32/AboutBox.cpp rename to plugins/spu2-x/src/Windows/AboutBox.cpp diff --git a/plugins/spu2-x/src/Win32/CfgHelpers.cpp b/plugins/spu2-x/src/Windows/CfgHelpers.cpp similarity index 100% rename from plugins/spu2-x/src/Win32/CfgHelpers.cpp rename to plugins/spu2-x/src/Windows/CfgHelpers.cpp diff --git a/plugins/spu2-x/src/Win32/Config.cpp b/plugins/spu2-x/src/Windows/Config.cpp similarity index 100% rename from plugins/spu2-x/src/Win32/Config.cpp rename to plugins/spu2-x/src/Windows/Config.cpp diff --git a/plugins/spu2-x/src/Win32/Config.h b/plugins/spu2-x/src/Windows/Config.h similarity index 100% rename from plugins/spu2-x/src/Win32/Config.h rename to plugins/spu2-x/src/Windows/Config.h diff --git a/plugins/spu2-x/src/Win32/ConfigDebug.cpp b/plugins/spu2-x/src/Windows/ConfigDebug.cpp similarity index 100% rename from plugins/spu2-x/src/Win32/ConfigDebug.cpp rename to plugins/spu2-x/src/Windows/ConfigDebug.cpp diff --git a/plugins/spu2-x/src/Win32/ConfigSoundtouch.cpp b/plugins/spu2-x/src/Windows/ConfigSoundtouch.cpp similarity index 100% rename from plugins/spu2-x/src/Win32/ConfigSoundtouch.cpp rename to plugins/spu2-x/src/Windows/ConfigSoundtouch.cpp diff --git a/plugins/spu2-x/src/Win32/Dialogs.h b/plugins/spu2-x/src/Windows/Dialogs.h similarity index 100% rename from plugins/spu2-x/src/Win32/Dialogs.h rename to plugins/spu2-x/src/Windows/Dialogs.h diff --git a/plugins/spu2-x/src/Win32/Dsound51.cpp b/plugins/spu2-x/src/Windows/Dsound51.cpp similarity index 100% rename from plugins/spu2-x/src/Win32/Dsound51.cpp rename to plugins/spu2-x/src/Windows/Dsound51.cpp diff --git a/plugins/spu2-x/src/Win32/Hyperlinks.cpp b/plugins/spu2-x/src/Windows/Hyperlinks.cpp similarity index 100% rename from plugins/spu2-x/src/Win32/Hyperlinks.cpp rename to plugins/spu2-x/src/Windows/Hyperlinks.cpp diff --git a/plugins/spu2-x/src/Win32/Hyperlinks.h b/plugins/spu2-x/src/Windows/Hyperlinks.h similarity index 100% rename from plugins/spu2-x/src/Win32/Hyperlinks.h rename to plugins/spu2-x/src/Windows/Hyperlinks.h diff --git a/plugins/spu2-x/src/Win32/RealtimeDebugger.cpp b/plugins/spu2-x/src/Windows/RealtimeDebugger.cpp similarity index 100% rename from plugins/spu2-x/src/Win32/RealtimeDebugger.cpp rename to plugins/spu2-x/src/Windows/RealtimeDebugger.cpp diff --git a/plugins/spu2-x/src/Win32/SndOut_DSound.cpp b/plugins/spu2-x/src/Windows/SndOut_DSound.cpp similarity index 100% rename from plugins/spu2-x/src/Win32/SndOut_DSound.cpp rename to plugins/spu2-x/src/Windows/SndOut_DSound.cpp diff --git a/plugins/spu2-x/src/Win32/SndOut_XAudio2.cpp b/plugins/spu2-x/src/Windows/SndOut_XAudio2.cpp similarity index 100% rename from plugins/spu2-x/src/Win32/SndOut_XAudio2.cpp rename to plugins/spu2-x/src/Windows/SndOut_XAudio2.cpp diff --git a/plugins/spu2-x/src/Win32/SndOut_waveOut.cpp b/plugins/spu2-x/src/Windows/SndOut_waveOut.cpp similarity index 100% rename from plugins/spu2-x/src/Win32/SndOut_waveOut.cpp rename to plugins/spu2-x/src/Windows/SndOut_waveOut.cpp diff --git a/plugins/spu2-x/src/Win32/Spu2-X.def b/plugins/spu2-x/src/Windows/Spu2-X.def similarity index 100% rename from plugins/spu2-x/src/Win32/Spu2-X.def rename to plugins/spu2-x/src/Windows/Spu2-X.def diff --git a/plugins/spu2-x/src/Win32/Spu2-X.rc b/plugins/spu2-x/src/Windows/Spu2-X.rc similarity index 100% rename from plugins/spu2-x/src/Win32/Spu2-X.rc rename to plugins/spu2-x/src/Windows/Spu2-X.rc diff --git a/plugins/spu2-x/src/Win32/Spu2-X_vs2008.vcproj b/plugins/spu2-x/src/Windows/Spu2-X_vs2008.vcproj similarity index 100% rename from plugins/spu2-x/src/Win32/Spu2-X_vs2008.vcproj rename to plugins/spu2-x/src/Windows/Spu2-X_vs2008.vcproj diff --git a/plugins/spu2-x/src/Win32/UIHelpers.cpp b/plugins/spu2-x/src/Windows/UIHelpers.cpp similarity index 100% rename from plugins/spu2-x/src/Win32/UIHelpers.cpp rename to plugins/spu2-x/src/Windows/UIHelpers.cpp diff --git a/plugins/spu2-x/src/Win32/dsp.cpp b/plugins/spu2-x/src/Windows/dsp.cpp similarity index 100% rename from plugins/spu2-x/src/Win32/dsp.cpp rename to plugins/spu2-x/src/Windows/dsp.cpp diff --git a/plugins/spu2-x/src/Win32/dsp.h b/plugins/spu2-x/src/Windows/dsp.h similarity index 100% rename from plugins/spu2-x/src/Win32/dsp.h rename to plugins/spu2-x/src/Windows/dsp.h diff --git a/plugins/spu2-x/src/Win32/resource.h b/plugins/spu2-x/src/Windows/resource.h similarity index 100% rename from plugins/spu2-x/src/Win32/resource.h rename to plugins/spu2-x/src/Windows/resource.h diff --git a/plugins/xpad/xpad.cpp b/plugins/xpad/xpad.cpp index 0ae8d20f2b..1551c3dd0f 100644 --- a/plugins/xpad/xpad.cpp +++ b/plugins/xpad/xpad.cpp @@ -99,8 +99,6 @@ EXPORT_C_(UINT32) PSEgetLibVersion() EXPORT_C_(UINT32) PS2EgetLibType() { - s_ps2 = true; - return PS2E_LT_PAD; } @@ -111,6 +109,8 @@ EXPORT_C_(char*) PS2EgetLibName() EXPORT_C_(UINT32) PS2EgetLibVersion2(UINT32 type) { + s_ps2 = true; + return (s_ver.build << 0) | (s_ver.revision << 8) | (PS2E_PAD_VERSION << 16) | (s_ver.minor << 24); } @@ -553,7 +553,34 @@ public: static int s_nRefs = 0; static HWND s_hWnd = NULL; static WNDPROC s_GSWndProc = NULL; -static KeyEvent s_event = {0, 0}; + +static class CKeyEventList : protected CAtlList, protected CCritSec +{ +public: + void Push(UINT32 event, UINT32 key) + { + CAutoLock cAutoLock(this); + + KeyEvent e; + + e.event = event; + e.key = key; + + AddTail(e); + } + + bool Pop(KeyEvent& e) + { + CAutoLock cAutoLock(this); + + if(IsEmpty()) return false; + + e = RemoveHead(); + + return true; + } + +} s_event; LRESULT WINAPI PADwndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { @@ -561,17 +588,14 @@ LRESULT WINAPI PADwndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { case WM_KEYDOWN: if(lParam & 0x40000000) return TRUE; - s_event.event = KEYPRESS; - s_event.key = wParam; + s_event.Push(KEYPRESS, wParam); return TRUE; case WM_KEYUP: - s_event.event = KEYRELEASE; - s_event.key = wParam; + s_event.Push(KEYRELEASE, wParam); return TRUE; case WM_DESTROY: case WM_QUIT: - s_event.event = KEYPRESS; - s_event.key = VK_ESCAPE; + s_event.Push(KEYPRESS, VK_ESCAPE); break; } @@ -666,10 +690,9 @@ EXPORT_C_(UINT32) PADreadPort2(PadDataS* ppds) EXPORT_C_(KeyEvent*) PADkeyEvent() { - static KeyEvent event; - event = s_event; - s_event.event = 0; - return &event; + static KeyEvent e; + + return s_event.Pop(e) ? &e : NULL; } EXPORT_C PADconfigure() diff --git a/plugins/xpad/xpad.h b/plugins/xpad/xpad.h index 3d63676fcd..9afa410498 100644 --- a/plugins/xpad/xpad.h +++ b/plugins/xpad/xpad.h @@ -87,3 +87,34 @@ struct KeyEvent #define KEYPRESS 1 #define KEYRELEASE 2 + +// + +class CCritSec +{ + CCritSec(const CCritSec &refCritSec); + CCritSec &operator=(const CCritSec &refCritSec); + + CRITICAL_SECTION m_CritSec; + +public: + CCritSec() {InitializeCriticalSection(&m_CritSec);}; + ~CCritSec() {DeleteCriticalSection(&m_CritSec);}; + + void Lock() {EnterCriticalSection(&m_CritSec);}; + void Unlock() {LeaveCriticalSection(&m_CritSec);}; +}; + +class CAutoLock +{ + CAutoLock(const CAutoLock &refAutoLock); + CAutoLock &operator=(const CAutoLock &refAutoLock); + +protected: + CCritSec * m_pLock; + +public: + CAutoLock(CCritSec * plock) {m_pLock = plock; m_pLock->Lock();}; + ~CAutoLock() {m_pLock->Unlock();}; +}; + diff --git a/plugins/zerogs/dx/Win32/Conf.cpp b/plugins/zerogs/dx/Windows/Conf.cpp similarity index 100% rename from plugins/zerogs/dx/Win32/Conf.cpp rename to plugins/zerogs/dx/Windows/Conf.cpp diff --git a/plugins/zerogs/dx/Win32/GSsoftdx.def b/plugins/zerogs/dx/Windows/GSsoftdx.def similarity index 100% rename from plugins/zerogs/dx/Win32/GSsoftdx.def rename to plugins/zerogs/dx/Windows/GSsoftdx.def diff --git a/plugins/zerogs/dx/Win32/Win32.cpp b/plugins/zerogs/dx/Windows/Win32.cpp similarity index 100% rename from plugins/zerogs/dx/Win32/Win32.cpp rename to plugins/zerogs/dx/Windows/Win32.cpp diff --git a/plugins/zerogs/dx/Win32/Win32.h b/plugins/zerogs/dx/Windows/Win32.h similarity index 100% rename from plugins/zerogs/dx/Win32/Win32.h rename to plugins/zerogs/dx/Windows/Win32.h diff --git a/plugins/zerogs/dx/Win32/aviUtil.h b/plugins/zerogs/dx/Windows/aviUtil.h similarity index 100% rename from plugins/zerogs/dx/Win32/aviUtil.h rename to plugins/zerogs/dx/Windows/aviUtil.h diff --git a/plugins/zerogs/dx/Win32/pcsxrootdir.vsprops b/plugins/zerogs/dx/Windows/pcsxrootdir.vsprops similarity index 100% rename from plugins/zerogs/dx/Win32/pcsxrootdir.vsprops rename to plugins/zerogs/dx/Windows/pcsxrootdir.vsprops diff --git a/plugins/zerogs/dx/Win32/plugin.def b/plugins/zerogs/dx/Windows/plugin.def similarity index 100% rename from plugins/zerogs/dx/Win32/plugin.def rename to plugins/zerogs/dx/Windows/plugin.def diff --git a/plugins/zerogs/dx/Win32/ps2fx.dat b/plugins/zerogs/dx/Windows/ps2fx.dat similarity index 100% rename from plugins/zerogs/dx/Win32/ps2fx.dat rename to plugins/zerogs/dx/Windows/ps2fx.dat diff --git a/plugins/zerogs/dx/Win32/resource.h b/plugins/zerogs/dx/Windows/resource.h similarity index 100% rename from plugins/zerogs/dx/Win32/resource.h rename to plugins/zerogs/dx/Windows/resource.h diff --git a/plugins/zerogs/dx/Win32/resrc1.h b/plugins/zerogs/dx/Windows/resrc1.h similarity index 100% rename from plugins/zerogs/dx/Win32/resrc1.h rename to plugins/zerogs/dx/Windows/resrc1.h diff --git a/plugins/zerogs/dx/Win32/zerogs.bmp b/plugins/zerogs/dx/Windows/zerogs.bmp similarity index 100% rename from plugins/zerogs/dx/Win32/zerogs.bmp rename to plugins/zerogs/dx/Windows/zerogs.bmp diff --git a/plugins/zerogs/dx/Win32/zerogs.rc b/plugins/zerogs/dx/Windows/zerogs.rc similarity index 100% rename from plugins/zerogs/dx/Win32/zerogs.rc rename to plugins/zerogs/dx/Windows/zerogs.rc diff --git a/plugins/zerogs/dx/Win32/zerogs_2008.vcproj b/plugins/zerogs/dx/Windows/zerogs_2008.vcproj similarity index 95% rename from plugins/zerogs/dx/Win32/zerogs_2008.vcproj rename to plugins/zerogs/dx/Windows/zerogs_2008.vcproj index f50ed49821..586f9aa94e 100644 --- a/plugins/zerogs/dx/Win32/zerogs_2008.vcproj +++ b/plugins/zerogs/dx/Windows/zerogs_2008.vcproj @@ -141,7 +141,7 @@ RuntimeLibrary="1" RuntimeTypeInfo="true" WarningLevel="3" - DebugInformationFormat="3" + DebugInformationFormat="4" />