diff --git a/pcsx2/CDVD/CDVD.cpp b/pcsx2/CDVD/CDVD.cpp index 750fe42a14..952655c8e6 100644 --- a/pcsx2/CDVD/CDVD.cpp +++ b/pcsx2/CDVD/CDVD.cpp @@ -556,7 +556,7 @@ void cdvdReset() cdvd.RTC.month = (u8)curtime.GetMonth(wxDateTime::GMT9) + 1; // WX returns Jan as "0" cdvd.RTC.year = (u8)(curtime.GetYear(wxDateTime::GMT9) - 2000); - GameDB = new DataBase_Loader("GameIndex.dbf"); + if( !GameDB ) GameDB = new DataBase_Loader("GameIndex.dbf"); } struct Freeze_v10Compat diff --git a/pcsx2/Hw.cpp b/pcsx2/Hw.cpp index fddc395ad9..1e13ed661e 100644 --- a/pcsx2/Hw.cpp +++ b/pcsx2/Hw.cpp @@ -17,6 +17,7 @@ #include "Common.h" #include "Hardware.h" +#include "newVif.h" using namespace R5900; @@ -25,14 +26,22 @@ u8 *psH; // hw mem const int rdram_devices = 2; // put 8 for TOOL and 2 for PS2 and PSX int rdram_sdevid = 0; +static bool hwInitialized = false; + void hwInit() { - gsInit(); + if( hwInitialized ) return; + + VifUnpackSSE_Init(); vif0Init(); vif1Init(); + + gsInit(); sifInit(); sprInit(); ipuInit(); + + hwInitialized = true; } /*void hwShutdown() @@ -52,8 +61,13 @@ void hwReset() psHu32(DMAC_ENABLEW) = 0x1201; psHu32(DMAC_ENABLER) = 0x1201; + sifInit(); + sprInit(); + gsReset(); ipuReset(); + vif0Reset(); + vif1Reset(); } __forceinline void intcInterrupt() diff --git a/pcsx2/IPU/IPU.cpp b/pcsx2/IPU/IPU.cpp index 7178ac1860..7f43a854a0 100644 --- a/pcsx2/IPU/IPU.cpp +++ b/pcsx2/IPU/IPU.cpp @@ -142,11 +142,7 @@ int ipuInit() void ipuReset() { - memzero(*ipuRegs); - g_nDMATransfer.reset(); - IPU1Status.InProgress = false; - IPU1Status.DMAMode = DMA_MODE_NORMAL; - IPU1Status.DMAFinished = true; + ipuInit(); } void ipuShutdown() diff --git a/pcsx2/R5900.cpp b/pcsx2/R5900.cpp index ada985d4d8..eb7e6cdb0e 100644 --- a/pcsx2/R5900.cpp +++ b/pcsx2/R5900.cpp @@ -78,8 +78,6 @@ void cpuReset() EEoCycle = cpuRegs.cycle; hwReset(); - vif0Reset(); - vif1Reset(); rcntInit(); psxReset(); diff --git a/pcsx2/System.cpp b/pcsx2/System.cpp index 0b40073c1a..0146c09b2f 100644 --- a/pcsx2/System.cpp +++ b/pcsx2/System.cpp @@ -17,11 +17,14 @@ #include "Common.h" #include "HostGui.h" -#include "sVU_zerorec.h" // for SuperVUDestroy - #include "System/PageFaultSource.h" #include "Utilities/EventSource.inl" +// Includes needed for cleanup, since we don't have a good system (yet) for +// cleaning up these things. +#include "sVU_zerorec.h" +#include "DataBase_Loader.h" + extern void closeNewVif(int idx); extern void resetNewVif(int idx); @@ -323,6 +326,10 @@ void SysCoreAllocations::CleanupMess() throw() { try { + GameDB.Delete(); + closeNewVif(0); + closeNewVif(1); + // Special SuperVU "complete" terminator (stupid hacky recompiler) SuperVUDestroy( -1 ); @@ -330,8 +337,6 @@ void SysCoreAllocations::CleanupMess() throw() recCpu.Shutdown(); vuMicroMemShutdown(); - closeNewVif(0); - closeNewVif(1); psxMemShutdown(); memShutdown(); vtlb_Core_Shutdown(); @@ -389,12 +394,11 @@ void SysClearExecutionCache() Cpu->Reset(); psxCpu->Reset(); + CpuVU0->Reset(); + CpuVU1->Reset(); resetNewVif(0); resetNewVif(1); - - CpuVU0->Reset(); - CpuVU1->Reset(); } // Maps a block of memory for use as a recompiled code buffer, and ensures that the diff --git a/pcsx2/gui/AppCoreThread.cpp b/pcsx2/gui/AppCoreThread.cpp index f083079b0f..db2d76c4f3 100644 --- a/pcsx2/gui/AppCoreThread.cpp +++ b/pcsx2/gui/AppCoreThread.cpp @@ -355,12 +355,13 @@ void BaseScopedCoreThread::DoResume() // handle the code directly). bool BaseScopedCoreThread::PostToSysExec( BaseSysExecEvent_ScopedCore* msg ) { - if( !msg || GetSysExecutorThread().IsSelf()) return false; + ScopedPtr smsg( msg ); + if( !smsg || GetSysExecutorThread().IsSelf()) return false; msg->SetSyncState(m_sync); msg->SetResumeStates(m_sync_resume, m_mtx_resume); - GetSysExecutorThread().PostEvent( msg ); + GetSysExecutorThread().PostEvent( smsg.DetachPtr() ); m_sync.WaitForResult(); m_sync.RethrowException(); diff --git a/pcsx2/gui/AppInit.cpp b/pcsx2/gui/AppInit.cpp index 2d9dffd643..6727843d95 100644 --- a/pcsx2/gui/AppInit.cpp +++ b/pcsx2/gui/AppInit.cpp @@ -657,6 +657,6 @@ struct CrtDebugBreak } }; -//CrtDebugBreak breakAt( 1175 ); +//CrtDebugBreak breakAt( 8564 ); #endif diff --git a/pcsx2/gui/ExecutorThread.cpp b/pcsx2/gui/ExecutorThread.cpp index 41f578ca62..cef9c963ed 100644 --- a/pcsx2/gui/ExecutorThread.cpp +++ b/pcsx2/gui/ExecutorThread.cpp @@ -227,11 +227,12 @@ void pxEvtHandler::AddPendingEvent( SysExecEvent& evt ) // void pxEvtHandler::PostEvent( SysExecEvent* evt ) { - if( !evt ) return; - + ScopedPtr sevt( evt ); + if( !sevt ) return; + if( m_Quitting ) { - evt->PostResult(); + sevt->PostResult(); return; } @@ -239,7 +240,7 @@ void pxEvtHandler::PostEvent( SysExecEvent* evt ) //DbgCon.WriteLn( L"(%s) Posting event: %s (queue count=%d)", GetEventHandlerName().c_str(), evt->GetEventName().c_str(), m_pendingEvents.size() ); - m_pendingEvents.push_back( evt ); + m_pendingEvents.push_back( sevt.DetachPtr() ); if( m_pendingEvents.size() == 1) m_wakeup.Post(); } @@ -421,7 +422,7 @@ void ExecutorThread::ShutdownQueue() // Exposes the internal pxEvtHandler::PostEvent API. See pxEvtHandler for details. void ExecutorThread::PostEvent( SysExecEvent* evt ) { - if( !pxAssert( m_EvtHandler ) ) return; + if( !pxAssert( m_EvtHandler ) ) { delete evt; return; } m_EvtHandler->PostEvent( evt ); } diff --git a/pcsx2/gui/FrameForGS.cpp b/pcsx2/gui/FrameForGS.cpp index 3d08be4c8e..b3153f93b2 100644 --- a/pcsx2/gui/FrameForGS.cpp +++ b/pcsx2/gui/FrameForGS.cpp @@ -251,7 +251,7 @@ GSFrame::GSFrame(wxWindow* parent, const wxString& title) wxStaticText* label = new wxStaticText( this, wxID_ANY, _("GS Output is Disabled!") ); m_id_OutputDisabled = label->GetId(); - label->SetFont( *new wxFont( 20, wxDEFAULT, wxNORMAL, wxBOLD ) ); + label->SetFont( wxFont( 20, wxDEFAULT, wxNORMAL, wxBOLD ) ); label->SetForegroundColour( *wxWHITE ); label->Show( EmuConfig.GS.DisableOutput ); diff --git a/pcsx2/gui/MainFrame.cpp b/pcsx2/gui/MainFrame.cpp index d78f0b0f61..fb95a11219 100644 --- a/pcsx2/gui/MainFrame.cpp +++ b/pcsx2/gui/MainFrame.cpp @@ -278,7 +278,6 @@ MainEmuFrame::MainEmuFrame(wxWindow* parent, const wxString& title) , m_menubar( *new wxMenuBar() ) - , m_menuBoot ( *new wxMenu() ) , m_menuCDVD ( *new wxMenu() ) , m_menuSys ( *new wxMenu() ) , m_menuConfig ( *new wxMenu() ) diff --git a/pcsx2/gui/MainFrame.h b/pcsx2/gui/MainFrame.h index eaf8031274..6a7aeb12aa 100644 --- a/pcsx2/gui/MainFrame.h +++ b/pcsx2/gui/MainFrame.h @@ -116,7 +116,6 @@ protected: wxMenuBar& m_menubar; - wxMenu& m_menuBoot; wxMenu& m_menuCDVD; wxMenu& m_menuSys; wxMenu& m_menuConfig; diff --git a/pcsx2/gui/MemoryCardFile.cpp b/pcsx2/gui/MemoryCardFile.cpp index 4ce1fd040a..dc082c8efd 100644 --- a/pcsx2/gui/MemoryCardFile.cpp +++ b/pcsx2/gui/MemoryCardFile.cpp @@ -95,6 +95,8 @@ uint FileMcd_GetMtapPort(uint slot) return 0; // technically unreachable. } +// Returns the multitap slot number, range 1 to 3 (slot 0 refers to the standard +// 1st and 2nd player slots). uint FileMcd_GetMtapSlot(uint slot) { switch( slot ) @@ -103,8 +105,8 @@ uint FileMcd_GetMtapSlot(uint slot) pxFailDev( "Invalid parameter in call to GetMtapSlot -- specified slot is one of the base slots, not a Multitap slot." ); break; - case 2: case 3: case 4: return slot-2; - case 5: case 6: case 7: return slot-5; + case 2: case 3: case 4: return slot-1; + case 5: case 6: case 7: return slot-4; jNO_DEFAULT } diff --git a/pcsx2/gui/Panels/MemoryCardListPanel.cpp b/pcsx2/gui/Panels/MemoryCardListPanel.cpp index bcd43c4a2b..dbf7a82f19 100644 --- a/pcsx2/gui/Panels/MemoryCardListPanel.cpp +++ b/pcsx2/gui/Panels/MemoryCardListPanel.cpp @@ -532,13 +532,11 @@ void Panels::MemoryCardListPanel_Simple::DoRefresh() { for( uint slot=0; slot<8; ++slot ) { + if( FileMcd_IsMultitapSlot(slot) && !m_MultitapEnabled[FileMcd_GetMtapPort(slot)] ) continue; + wxFileName fullpath( m_FolderPicker->GetPath() + g_Conf->Mcd[slot].Filename.GetFullName() ); EnumerateMemoryCard( m_Cards[slot], fullpath ); - m_Cards[slot].Slot = slot; - - if( FileMcd_IsMultitapSlot(slot) && !m_MultitapEnabled[FileMcd_GetMtapPort(slot)] ) - m_Cards[slot].IsEnabled = false; } if( m_listview ) m_listview->SetMcdProvider( this ); diff --git a/pcsx2/x86/newVif.h b/pcsx2/x86/newVif.h index fa3dbe547e..737791b64b 100644 --- a/pcsx2/x86/newVif.h +++ b/pcsx2/x86/newVif.h @@ -21,7 +21,12 @@ #include "x86emitter/x86emitter.h" using namespace x86Emitter; -// newVif_HashBucket.h uses this typedef, so it has to be decared first. +static const s64 _1mb = 0x100000; +#define aMax(x, y) std::max(x,y) +#define aMin(x, y) std::min(x,y) +#define _f __forceinline + +// newVif_HashBucket.h uses this typedef, so it has to be declared first. typedef u32 (__fastcall *nVifCall)(void*, void*); typedef void (__fastcall *nVifrecCall)(uptr dest, uptr src); @@ -32,18 +37,15 @@ extern void mVUmergeRegs(int dest, int src, int xyzw, bool modXYZW = 0); extern void _nVifUnpack (int idx, u8 *data, u32 size, bool isFill); extern void dVifUnpack (int idx, u8 *data, u32 size, bool isFill); extern void dVifInit (int idx); +extern void dVifReset (int idx); extern void dVifClose (int idx); extern void VifUnpackSSE_Init(); #define VUFT VIFUnpackFuncTable -#define _1mb (0x100000) #define _v0 0 #define _v1 0x55 #define _v2 0xaa #define _v3 0xff -#define aMax(x, y) std::max(x,y) -#define aMin(x, y) std::min(x,y) -#define _f __forceinline #define xmmCol0 xmm2 #define xmmCol1 xmm3 #define xmmCol2 xmm4 @@ -88,7 +90,7 @@ struct nVifStruct { u32 bSize; // Size of 'buffer' u8 buffer[_1mb]; // Buffer for partial transfers u8* recPtr; // Cur Pos to recompile to - u8* recEnd; // End of Rec Cache + u8* recEnd; // 'Safe' End of Rec Cache BlockBuffer* vifCache; // Block Buffer HashBucket<_tParams>* vifBlocks; // Vif Blocks int numBlocks; // # of Blocks Recompiled diff --git a/pcsx2/x86/newVif_BlockBuffer.h b/pcsx2/x86/newVif_BlockBuffer.h index 9acb5c40dd..03c3515c17 100644 --- a/pcsx2/x86/newVif_BlockBuffer.h +++ b/pcsx2/x86/newVif_BlockBuffer.h @@ -26,34 +26,61 @@ // deletion/cleanup respectfully... class BlockBuffer { protected: - u32 mSize; // Cur Size - u32 mSizeT; // Total Size - u8* mData; // Data Ptr + u32 mSize; // Cur Size (in bytes) + u32 mSizeT; // Total Size (in bytes) + u32 mGrowBy; // amount to grow by when buffer fills (in bytes) + u8* mData; // Data Ptr (allocated via SysMmap) + void alloc(int size) { mData = SysMmapEx(NULL, size, 0, "nVif_BlockBuffer"); if (!mData) throw Exception::OutOfMemory("nVif Error: Failed to allocate recompiler memory!"); - memset(mData, 0xcc, size); + clear(); } void dealloc(u8* &dPtr, int size) { - if (dPtr) { HostSys::Munmap(dPtr, size); dPtr = NULL; } + SafeSysMunmap( dPtr, size ); } + public: - BlockBuffer(u32 tSize) { mSizeT = tSize; mSize = 0; alloc(mSizeT); } - ~BlockBuffer() { dealloc(mData, mSizeT); } + virtual ~BlockBuffer() throw() { + dealloc(mData, mSizeT); + } + + BlockBuffer(u32 tSize, u32 growby=_1mb*2) { + mSizeT = tSize; + mGrowBy = growby; + mSize = 0; + alloc(mSizeT); + } + void append(void *addr, u32 size) { - if (mSize + size > mSizeT) grow(mSize*2 + size); - memcpy(&mData[mSize], addr, size); + if ((mSize + size) > mSizeT) grow(mSizeT + mGrowBy); + memcpy_fast(&mData[mSize], addr, size); mSize += size; } + + // Increases the allocation size. Warning: Unlike 'realloc' this function will + // CLEAR all contents of the buffer. This is because copying contents of recompiled + // caches is mostly useless since it invalidates any pointers into the block. + // (code relocation techniques are possible, but are difficult, potentially slow, + // and easily bug prone. Not recommended at this time). --air void grow(u32 newSize) { + pxAssume( newSize > mSizeT ); u8* temp = mData; - alloc (newSize); - memcpy (mData, temp, mSize); + alloc(newSize); dealloc(temp, mSizeT); + clear(); mSizeT = newSize; } - void clear() { mSize = 0; } - u32 getCurSize() { return mSize; } - u32 getSize() { return mSizeT; } - u8* getBlock() { return mData; } + + // clears the entire buffer to recompiler fill (0xcc), and sets mSize to 0. + // (indicating none of the buffer is allocated). + void clear() { + if( mSize == 0 ) return; // no clears needed if nothing's been written/modified + mSize = 0; + memset(mData, 0xcc, mSizeT); + } + + u32 getCurSize() { return mSize; } + u32 getAllocSize() { return mSizeT; } + u8* getBlock() { return mData; } }; diff --git a/pcsx2/x86/newVif_Dynarec.cpp b/pcsx2/x86/newVif_Dynarec.cpp index 052d054f56..23f52a19cf 100644 --- a/pcsx2/x86/newVif_Dynarec.cpp +++ b/pcsx2/x86/newVif_Dynarec.cpp @@ -21,13 +21,40 @@ #include "newVif_UnpackSSE.h" static __aligned16 nVifBlock _vBlock = {0}; +static bool dVifIsInitialized[2] = { false, false }; void dVifInit(int idx) { + nVif[idx].vifCache = NULL; + nVif[idx].vifBlocks = NULL; nVif[idx].numBlocks = 0; - nVif[idx].vifCache = new BlockBuffer(_1mb*4); // 4mb Rec Cache - nVif[idx].vifBlocks = new HashBucket<_tParams>(); + nVif[idx].recPtr = NULL; + nVif[idx].recEnd = NULL; + + dVifIsInitialized[idx] = true; +} + +void dVifReset(int idx) { + if( !dVifIsInitialized[idx] ) return; + + // If the VIF cache is greater than 12mb, then it's due for a complete reset back + // down to a reasonable starting point of 4mb. + if( nVif[idx].vifCache && (nVif[idx].vifCache->getAllocSize() > _1mb*12) ) + safe_delete(nVif[idx].vifCache); + + if( !nVif[idx].vifCache ) + nVif[idx].vifCache = new BlockBuffer(_1mb*4); + else + nVif[idx].vifCache->clear(); + + if( !nVif[idx].vifBlocks ) + nVif[idx].vifBlocks = new HashBucket<_tParams>(); + else + nVif[idx].vifBlocks->clear(); + + nVif[idx].numBlocks = 0; + nVif[idx].recPtr = nVif[idx].vifCache->getBlock(); - nVif[idx].recEnd = &nVif[idx].recPtr[nVif[idx].vifCache->getSize()-(_1mb/4)]; // .25mb Safe Zone + nVif[idx].recEnd = &nVif[idx].recPtr[nVif[idx].vifCache->getAllocSize()-(_1mb/4)]; // .25mb Safe Zone } void dVifClose(int idx) { @@ -201,11 +228,14 @@ static _f u8* dVifsetVUptr(const nVifStruct& v, int cl, int wl, bool isFill) { return ptr; } +// [TODO] : Finish implementing support for VIF's growable recBlocks buffer. Currently +// it clears the buffer only. static _f void dVifRecLimit(int idx) { if (nVif[idx].recPtr > nVif[idx].recEnd) { DevCon.WriteLn("nVif Rec - Out of Rec Cache! [%x > %x]", nVif[idx].recPtr, nVif[idx].recEnd); nVif[idx].vifBlocks->clear(); nVif[idx].recPtr = nVif[idx].vifCache->getBlock(); + nVif[idx].recEnd = &nVif[idx].recPtr[nVif[idx].vifCache->getAllocSize()-(_1mb/4)]; // .25mb Safe Zone } } @@ -255,6 +285,8 @@ void dVifUnpack(int idx, u8 *data, u32 size, bool isFill) { VifUnpackSSE_Dynarec( v, _vBlock ).CompileRoutine(); nVif[idx].recPtr = xGetPtr(); + // [TODO] : Ideally we should test recompile buffer limits prior to each instruction, + // which would be safer and more memory efficient than using an 0.25 meg recEnd marker. dVifRecLimit(idx); // Run the block we just compiled. Various conditions may force us to still use diff --git a/pcsx2/x86/newVif_HashBucket.h b/pcsx2/x86/newVif_HashBucket.h index ed9e1eedf7..0fac9e23e8 100644 --- a/pcsx2/x86/newVif_HashBucket.h +++ b/pcsx2/x86/newVif_HashBucket.h @@ -57,7 +57,7 @@ public: mBucket[i].Size = 0; } } - ~HashBucket() { clear(); } + virtual ~HashBucket() throw() { clear(); } int quickFind(u32 data) { return mBucket[data % hSize].Size; } diff --git a/pcsx2/x86/newVif_Unpack.cpp b/pcsx2/x86/newVif_Unpack.cpp index e05abc338f..d9911564f9 100644 --- a/pcsx2/x86/newVif_Unpack.cpp +++ b/pcsx2/x86/newVif_Unpack.cpp @@ -69,7 +69,11 @@ static const __aligned16 Fnptr_VifUnpackLoop UnpackSingleTable[2][2][2] = { }; // ---------------------------------------------------------------------------- -void initNewVif(int idx) { +void resetNewVif(int idx) +{ + // Safety Reset : Reassign all VIF structure info, just in case the VU1 pointers have + // changed for some reason. + nVif[idx].idx = idx; nVif[idx].VU = idx ? &VU1 : &VU0; nVif[idx].vif = idx ? &vif1 : &vif0; @@ -80,12 +84,17 @@ void initNewVif(int idx) { nVif[idx].bSize = 0; memzero(nVif[idx].buffer); - VifUnpackSSE_Init(); + if (newVifDynaRec) dVifReset(idx); +} + +void initNewVif(int idx) { + resetNewVif(idx); if (newVifDynaRec) dVifInit(idx); } -void closeNewVif(int idx) { if (newVifDynaRec) dVifClose(idx); } -void resetNewVif(int idx) { closeNewVif(idx); initNewVif(idx); } +void closeNewVif(int idx) { + if (newVifDynaRec) dVifClose(idx); +} static _f u8* setVUptr(int vuidx, const u8* vuMemBase, int offset) { return (u8*)(vuMemBase + ( offset & (vuidx ? 0x3ff0 : 0xff0) )); diff --git a/plugins/FWnull/FW.cpp b/plugins/FWnull/FW.cpp index ed2698f7a6..1788937970 100644 --- a/plugins/FWnull/FW.cpp +++ b/plugins/FWnull/FW.cpp @@ -60,13 +60,12 @@ EXPORT_C_(s32) FWinit() FWLog.WriteLn("Initializing FWnull"); // Initializing our registers. - fwregs = (s8*)malloc(0x10000); + fwregs = (s8*)calloc(0x10000,1); if (fwregs == NULL) { FWLog.Message("Error allocating Memory"); return -1; } - memset(fwregs, 0, 0x10000); return 0; } @@ -74,6 +73,8 @@ EXPORT_C_(void) FWshutdown() { // Freeing the registers. free(fwregs); + fwregs = NULL; + FWLog.Close(); } diff --git a/plugins/USBnull/USB.cpp b/plugins/USBnull/USB.cpp index cc17fa3188..952a8b22ad 100644 --- a/plugins/USBnull/USB.cpp +++ b/plugins/USBnull/USB.cpp @@ -56,7 +56,7 @@ EXPORT_C_(s32) USBinit() USBLog.WriteLn("Initializing USBnull"); // Initialize memory structures here. - usbregs = (s8*)malloc(0x10000); + usbregs = (s8*)calloc(0x10000, 1); if (usbregs == NULL) { @@ -64,7 +64,6 @@ EXPORT_C_(s32) USBinit() return -1; } - memset(usbregs, 0, 0x10000); return 0; } @@ -73,6 +72,9 @@ EXPORT_C_(void) USBshutdown() // Yes, we close things in the Shutdown routine, and // don't do anything in the close routine. USBLog.Close(); + + free(usbregs); + usbregs = NULL; } EXPORT_C_(s32) USBopen(void *pDsp)