mirror of https://github.com/PCSX2/pcsx2.git
Many small memoryleak fixes in PCSX2 (mostly related to newVIF's recompiler) and one memoryleak fixed in USBnull. Had to juggle around the initialization/reset code for VIF a bit to get it happy. This also removes quite a bit of redundant memory allocations and clears when starting/resetting the emulator; expect a small speedup on slower machines.
git-svn-id: http://pcsx2.googlecode.com/svn/trunk@3103 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
9e7394afff
commit
81c35c9fcc
|
@ -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
|
||||
|
|
16
pcsx2/Hw.cpp
16
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()
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -78,8 +78,6 @@ void cpuReset()
|
|||
EEoCycle = cpuRegs.cycle;
|
||||
|
||||
hwReset();
|
||||
vif0Reset();
|
||||
vif1Reset();
|
||||
rcntInit();
|
||||
psxReset();
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -355,12 +355,13 @@ void BaseScopedCoreThread::DoResume()
|
|||
// handle the code directly).
|
||||
bool BaseScopedCoreThread::PostToSysExec( BaseSysExecEvent_ScopedCore* msg )
|
||||
{
|
||||
if( !msg || GetSysExecutorThread().IsSelf()) return false;
|
||||
ScopedPtr<BaseSysExecEvent_ScopedCore> 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();
|
||||
|
||||
|
|
|
@ -657,6 +657,6 @@ struct CrtDebugBreak
|
|||
}
|
||||
};
|
||||
|
||||
//CrtDebugBreak breakAt( 1175 );
|
||||
//CrtDebugBreak breakAt( 8564 );
|
||||
|
||||
#endif
|
||||
|
|
|
@ -227,11 +227,12 @@ void pxEvtHandler::AddPendingEvent( SysExecEvent& evt )
|
|||
//
|
||||
void pxEvtHandler::PostEvent( SysExecEvent* evt )
|
||||
{
|
||||
if( !evt ) return;
|
||||
|
||||
ScopedPtr<SysExecEvent> 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 );
|
||||
}
|
||||
|
||||
|
|
|
@ -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 );
|
||||
|
||||
|
|
|
@ -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() )
|
||||
|
|
|
@ -116,7 +116,6 @@ protected:
|
|||
|
||||
wxMenuBar& m_menubar;
|
||||
|
||||
wxMenu& m_menuBoot;
|
||||
wxMenu& m_menuCDVD;
|
||||
wxMenu& m_menuSys;
|
||||
wxMenu& m_menuConfig;
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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; }
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -57,7 +57,7 @@ public:
|
|||
mBucket[i].Size = 0;
|
||||
}
|
||||
}
|
||||
~HashBucket() { clear(); }
|
||||
virtual ~HashBucket() throw() { clear(); }
|
||||
int quickFind(u32 data) {
|
||||
return mBucket[data % hSize].Size;
|
||||
}
|
||||
|
|
|
@ -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) ));
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue