Fixed a bug that caused old pre1.8 versions of Gsdx to crash at startup, and fixed some instability problems when loading savestates.

Cleaned up some MTGS code, and improved performance a bit, especially for games that tend to stress the GPU (when Gsdx registers 70%+ cpu).

Programmer notes: Several code cleanups to header files.  Added MemcpyFast.h and SafeArray.h, and removed a couple more ugly #include inter-dependencies. :)

git-svn-id: http://pcsx2-playground.googlecode.com/svn/trunk@656 a6443dda-0b58-4228-96e9-037be469359c
This commit is contained in:
Jake.Stine 2009-01-29 22:54:06 +00:00 committed by Gregory Hainaut
parent b32d84516a
commit b5f952fc5e
17 changed files with 653 additions and 541 deletions

View File

@ -63,14 +63,15 @@ extern TESTRUNARGS g_TestRun;
#define PSXSOUNDCLK ((int)(48000))
#include "Plugins.h"
#include "System.h"
#include "Misc.h"
#include "SaveState.h"
#include "DebugTools/Debug.h"
#include "R5900.h"
#include "Memory.h"
#include "Elfheader.h"
#include "Hw.h"
// Moving this before one of the other includes causes compilation issues.
#include "Misc.h"
//#include "Misc.h"
#include "Patch.h"
#define PCSX2_VERSION "Playground (beta)"

View File

@ -537,12 +537,20 @@ u32 loadElfCRC( const char* filename )
int loadElfFile(const char *filename)
{
// Reset all recompilers prior to initiating a BIOS or new ELF. The cleaner the
// slate, the happier the recompiler!
SysResetExecutionState();
if( filename == NULL || filename[0] == 0 )
{
Console::Notice( "Running the PS2 BIOS..." );
return -1;
}
// We still need to run the BIOS stub, so that all the EE hardware gets initialized correctly.
cpuExecuteBios();
int elfsize;
Console::Status("loadElfFile: %s", params filename);

View File

@ -290,7 +290,7 @@ static bool _gsGIFSoftReset( int mask )
if( !warned )
{
Console::Notice( "GIF Warning > Soft reset requested, but the GS plugin doesn't support it!" );
warned = true;
//warned = true;
}
return false;
}
@ -307,7 +307,7 @@ void gsGIFReset()
{
#ifndef PCSX2_VIRTUAL_MEM
// fixme - should this be here? (air)
memzero_obj(g_RealGSMem);
//memzero_obj(g_RealGSMem);
#endif
// perform a soft reset (but do not do a full reset if the soft reset API is unavailable)

View File

@ -230,10 +230,14 @@ public:
#endif
//return (uptr)&SendSimplePacket;
}
protected:
// Sets the gsEvent flag and releases a timeslice.
// For use in loops that wait on the GS thread to do certain things.
void SetEventWait();
// Saves MMX/XMM regs, posts an event to the mtgsThread flag and releases a timeslice.
// For use in surrounding loops that wait on the mtgs.
void PrepEventWait();
// Restores MMX/XMM regs. For use in surrounding loops that wait on the mtgs.
void PostEventWait() const;
// Processes a GIFtag & packet, and throws out some gsIRQs as needed.
// Used to keep interrupts in sync with the EE, while the GS itself

View File

@ -206,6 +206,8 @@ mtgsThreadObject::mtgsThreadObject() :
, m_RingBuffer( m_RingBufferSize + (Ps2MemSize::GSregs/sizeof(u128)) )
, m_gsMem( (u8*)m_RingBuffer.GetPtr( m_RingBufferSize ) )
{
memzero_obj( m_path );
// Wait for the thread to finish initialization (it runs GSinit, which can take
// some time since it's creating a new window and all), and then check for errors.
@ -641,7 +643,7 @@ void mtgsThreadObject::SetEvent()
m_CopyDataTally = 0;
}
void mtgsThreadObject::SetEventWait()
void mtgsThreadObject::PrepEventWait()
{
// Freeze registers because some kernel code likes to destroy them
FreezeXMMRegs(1);
@ -649,6 +651,10 @@ void mtgsThreadObject::SetEventWait()
//Console::Notice( "MTGS Stall! EE waits for nothing! ... except your GPU sometimes." );
SetEvent();
Timeslice();
}
void mtgsThreadObject::PostEventWait() const
{
FreezeXMMRegs(0);
FreezeMMXRegs(0);
}
@ -825,20 +831,21 @@ int mtgsThreadObject::PrepDataPacket( GIF_PATH pathidx, const u8* srcdata, u32 s
{
// generic gs wait/stall.
// Waits until the readpos is outside the scope of the write area.
while( true )
// if the writepos is past the readpos then we're safe.
// But if not then we need to make sure the readpos is outside the scope of
// the block about to be written (writepos + size)
if( writepos < volatize(m_RingPos) )
{
// two conditionals in the following while() loop, so precache
// the readpos for more efficient behavior:
uint readpos = volatize(m_RingPos);
// if the writepos is past the readpos then we're safe:
if( writepos >= readpos ) break;
// writepos is behind the readpos, so do a second check to see if the
// writepos is behind the readpos, so we need to wait until
// readpos is out past the end of the future write pos:
if( writepos+size < readpos ) break;
SetEventWait();
PrepEventWait();
while( writepos+size < volatize(m_RingPos) )
{
SpinWait();
}
PostEventWait();
}
}
else if( writepos + size > m_RingBufferSize )
@ -851,6 +858,7 @@ int mtgsThreadObject::PrepDataPacket( GIF_PATH pathidx, const u8* srcdata, u32 s
// greater than the current write position then we need to stall
// until it loops around to the beginning of the buffer
PrepEventWait();
while( true )
{
uint readpos = volatize(m_RingPos);
@ -863,7 +871,7 @@ int mtgsThreadObject::PrepDataPacket( GIF_PATH pathidx, const u8* srcdata, u32 s
// position below (bad!)
if( readpos < writepos && readpos != 0 ) break;
SetEventWait();
SpinWait();
}
m_lock_RingRestart.Lock();
@ -871,6 +879,7 @@ int mtgsThreadObject::PrepDataPacket( GIF_PATH pathidx, const u8* srcdata, u32 s
writepos = 0;
AtomicExchange( m_WritePos, writepos );
m_lock_RingRestart.Unlock();
SetEvent();
// stall until the read position is past the end of our incoming block,
// or until it reaches the current write position (signals an empty buffer).
@ -881,27 +890,31 @@ int mtgsThreadObject::PrepDataPacket( GIF_PATH pathidx, const u8* srcdata, u32 s
if( readpos == m_WritePos ) break;
if( writepos+size < readpos ) break;
SetEventWait();
SpinWait();
}
PostEventWait();
}
else // always true - if( writepos + size == MTGS_RINGBUFFEREND )
{
// Yay. Perfect fit. What are the odds?
//SysPrintf( "MTGS > Perfect Fit!\n");
PrepEventWait();
while( true )
{
uint readpos = volatize(m_RingPos);
// is the buffer empty? Don't wait...
if( readpos == writepos ) break;
// stop waiting if the buffer is empty!
if( writepos == readpos ) break;
// Copy is ready so long as readpos is less than writepos and *not*
// equal to the base of the ringbuffer (otherwise the buffer will stop)
// equal to the base of the ringbuffer (otherwise the buffer will stop
// when the writepos is wrapped around to zero later-on in SendDataPacket)
if( readpos < writepos && readpos != 0 ) break;
SetEventWait();
SpinWait();
}
PostEventWait();
}
#ifdef RINGBUF_DEBUG_STACK
@ -934,8 +947,15 @@ __forceinline uint mtgsThreadObject::_PrepForSimplePacket()
future_writepos &= m_RingBufferMask;
while( future_writepos == volatize(m_RingPos) )
SetEventWait();
if( future_writepos == volatize(m_RingPos) )
{
PrepEventWait();
do
{
SpinWait();
} while( future_writepos == volatize(m_RingPos) );
PostEventWait();
}
return future_writepos;
}

57
pcsx2/MemcpyFast.h Normal file
View File

@ -0,0 +1,57 @@
/* Pcsx2 - Pc Ps2 Emulator
* Copyright (C) 2002-2008 Pcsx2 Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef __MEMCPY_FAST_H__
#define __MEMCPY_FAST_H__
void _memset16_unaligned( void* dest, u16 data, size_t size );
#if defined(_WIN32) && !defined(__x86_64__)
// The new simplified memcpy_amd_ is now faster than memcpy_raz_.
// memcpy_amd_ also does mmx register saving, negating the need for freezeregs (code cleanup!)
// Additionally, using one single memcpy implementation keeps the code cache cleaner.
//extern void __fastcall memcpy_raz_udst(void *dest, const void *src, size_t bytes);
//extern void __fastcall memcpy_raz_usrc(void *dest, const void *src, size_t bytes);
//extern void __fastcall memcpy_raz_(void *dest, const void *src, size_t bytes);
extern void __fastcall memcpy_amd_(void *dest, const void *src, size_t bytes);
# include "windows/memzero.h"
# define memcpy_fast memcpy_amd_
# define memcpy_aligned memcpy_amd_
#else
// for now linux uses the GCC memcpy/memset implementations.
#define memcpy_fast memcpy
#define memcpy_raz_ memcpy
#define memcpy_raz_u memcpy
#define memcpy_aligned memcpy
#define memcpy_raz_u memcpy
#include "Linux/memzero.h"
#endif
extern u8 memcmp_mmx(const void* src1, const void* src2, int cmpsize);
extern void memxor_mmx(void* dst, const void* src1, int cmpsize);
#endif

View File

@ -28,9 +28,10 @@
#include "Common.h"
#include "PsxCommon.h"
#include "SaveState.h"
#include "CDVDisodrv.h"
#include "VUmicro.h"
#include "VU.h"
#include "iCore.h"
#include "iVUzerorec.h"
@ -556,6 +557,7 @@ void ProcessFKeys(int fkey, int shift)
SaveState::GetFilename( Text, StatesC );
gzLoadingState joe( Text ); // throws exception on version mismatch
cpuReset();
SysResetExecutionState();
joe.FreezeAll();
}
catch( Exception::StateLoadError_Recoverable& )

View File

@ -19,11 +19,10 @@
#ifndef __MISC_H__
#define __MISC_H__
#include "PS2Etypes.h"
#include "System.h"
#include "SaveState.h"
// --->> GNU GetText / NLS
/////////////////////////////////////////////////////////////////////////
// GNU GetText / NLS
#ifdef ENABLE_NLS
@ -49,27 +48,6 @@
#endif // ENABLE_NLS
// <<--- End GNU GetText / NLS
// --->> Path Utilities [PathUtil.c]
#define g_MaxPath 255 // 255 is safer with antiquitated Win32 ASCII APIs.
namespace Path
{
void Combine( string& dest, const string& srcPath, const string& srcFile );
bool isRooted( const string& path );
bool isDirectory( const string& path );
bool isFile( const string& path );
bool Exists( const string& path );
int getFileSize( const string& path );
void ReplaceExtension( string& dest, const string& src, const string& ext );
}
// <<--- END Path Utilities [PathUtil.c]
// [TODO] : Move the config options mess from Misc.h into "config.h" or someting more sensible.
/////////////////////////////////////////////////////////////////////////
@ -227,41 +205,6 @@ extern u8 g_globalXMMSaved;
#define FreezeXMMRegs(save) if( g_EEFreezeRegs ) { FreezeXMMRegs_(save); }
#define FreezeMMXRegs(save) if( g_EEFreezeRegs ) { FreezeMMXRegs_(save); }
void _memset16_unaligned( void* dest, u16 data, size_t size );
#if defined(_WIN32) && !defined(__x86_64__)
// The new simplified memcpy_amd_ is now faster than memcpy_raz_.
// memcpy_amd_ also does mmx register saving, negating the need for freezeregs (code cleanup!)
// Additionally, using one single memcpy implementation keeps the code cache cleaner.
//extern void __fastcall memcpy_raz_udst(void *dest, const void *src, size_t bytes);
//extern void __fastcall memcpy_raz_usrc(void *dest, const void *src, size_t bytes);
//extern void __fastcall memcpy_raz_(void *dest, const void *src, size_t bytes);
extern void __fastcall memcpy_amd_(void *dest, const void *src, size_t bytes);
# include "windows/memzero.h"
# define memcpy_fast memcpy_amd_
# define memcpy_aligned memcpy_amd_
#else
// for now linux uses the GCC memcpy/memset implementations.
#define memcpy_fast memcpy
#define memcpy_raz_ memcpy
#define memcpy_raz_u memcpy
#define memcpy_aligned memcpy
#define memcpy_raz_u memcpy
#include "Linux/memzero.h"
#endif
u8 memcmp_mmx(const void* src1, const void* src2, int cmpsize);
void memxor_mmx(void* dst, const void* src1, int cmpsize);
#ifdef _MSC_VER
#pragma pack()
#endif

View File

@ -13,7 +13,21 @@
#define LANGS_DIR "Langs"
#define LOGS_DIR "logs"
#define DEFAULT_MEMCARD1 "Mcd001.ps2"
#define DEFAULT_MEMCARD2 "Mcd002.ps2"
#define g_MaxPath 255 // 255 is safer with antiquated Win32 ASCII APIs.
namespace Path
{
void Combine( string& dest, const string& srcPath, const string& srcFile );
bool isRooted( const string& path );
bool isDirectory( const string& path );
bool isFile( const string& path );
bool Exists( const string& path );
int getFileSize( const string& path );
void ReplaceExtension( string& dest, const string& src, const string& ext );
}
#endif

View File

@ -125,8 +125,6 @@ void cpuShutdown()
// biosShutdown();
psxShutdown();
disR5900FreeSyms();
//Cpu->Shutdown();
}
void cpuException(u32 code, u32 bd)
@ -630,6 +628,10 @@ void cpuTestHwInts() {
cpuTestTIMRInts();
}
// This function performs a "hackish" execution of the BIOS stub, which initializes EE
// memory and hardware. It forcefully breaks execution when the stub is finished, prior
// to the PS2 logos being displayed. This allows us to "shortcut" right into a game
// without having to wait through the logos or endure game/bios localization checks.
void cpuExecuteBios()
{
// Set the video mode to user's default request:
@ -660,7 +662,11 @@ void cpuExecuteBios()
// REC_CLEARM(0x00200008);
// REC_CLEARM(0x00100008);
// REC_CLEARM(cpuRegs.pc);
//if( CHECK_EEREC ) Cpu->Reset();
// Reset the EErecs here, because the bios generates "slow" blocks that have hacky
// bBiosEnd checks in them and stuff. This deletes them so that the recs replace them
// with new faster versions:
Cpu->Reset();
Console::Notice("* PCSX2 *: ExecuteBios Complete");
//GSprintf(5, "PCSX2 " PCSX2_VERSION "\nExecuteBios Complete\n");

244
pcsx2/SafeArray.h Normal file
View File

@ -0,0 +1,244 @@
/* Pcsx2 - Pc Ps2 Emulator
* Copyright (C) 2002-2008 Pcsx2 Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef __SAFEARRAY_H__
#define __SAFEARRAY_H__
#include "MemcpyFast.h"
//////////////////////////////////////////////////////////////
// Safe deallocation macros -- always check pointer validity (non-null)
// and set pointer to null on deallocation.
#define safe_delete( ptr ) \
if( ptr != NULL ) { \
delete ptr; \
ptr = NULL; \
}
#define safe_delete_array( ptr ) \
if( ptr != NULL ) { \
delete[] ptr; \
ptr = NULL; \
}
#define safe_free( ptr ) \
if( ptr != NULL ) { \
free( ptr ); \
ptr = NULL; \
}
#define safe_aligned_free( ptr ) \
if( ptr != NULL ) { \
_aligned_free( ptr ); \
ptr = NULL; \
}
#define SafeSysMunmap( ptr, size ) \
if( ptr != NULL ) { \
SysMunmap( (uptr)ptr, size ); \
ptr = NULL; \
}
//////////////////////////////////////////////////////////////////
// Handy little class for allocating a resizable memory block, complete with
// exception-based error handling and automatic cleanup.
template< typename T >
class MemoryAlloc : public NoncopyableObject
{
public:
static const int DefaultChunkSize = 0x1000 * sizeof(T);
public:
const std::string Name; // user-assigned block name
int ChunkSize;
protected:
T* m_ptr;
int m_size; // size of the allocation of memory
const static std::string m_str_Unnamed;
protected:
// Internal contructor for use by derrived classes. This allws a derrived class to
// use its own memory allocation (with an aligned memory, for example).
// Throws:
// Exception::OutOfMemory if the allocated_mem pointr is NULL.
explicit MemoryAlloc( const std::string& name, T* allocated_mem, int initSize ) :
Name( name )
, ChunkSize( DefaultChunkSize )
, m_ptr( allocated_mem )
, m_size( initSize )
{
if( m_ptr == NULL )
throw Exception::OutOfMemory();
}
virtual T* _virtual_realloc( int newsize )
{
return (T*)realloc( m_ptr, newsize * sizeof(T) );
}
public:
virtual ~MemoryAlloc()
{
safe_free( m_ptr );
}
explicit MemoryAlloc( const std::string& name="Unnamed" ) :
Name( name )
, ChunkSize( DefaultChunkSize )
, m_ptr( NULL )
, m_size( 0 )
{
}
explicit MemoryAlloc( int initialSize, const std::string& name="Unnamed" ) :
Name( name )
, ChunkSize( DefaultChunkSize )
, m_ptr( (T*)malloc( initialSize * sizeof(T) ) )
, m_size( initialSize )
{
if( m_ptr == NULL )
throw Exception::OutOfMemory();
}
// Returns the size of the memory allocation, as according to the array type.
int GetLength() const { return m_size; }
// Returns the size of the memory allocation in bytes.
int GetSizeInBytes() const { return m_size * sizeof(T); }
// Ensures that the allocation is large enough to fit data of the
// amount requested. The memory allocation is not resized smaller.
void MakeRoomFor( int blockSize )
{
std::string temp;
if( blockSize > m_size )
{
const uint newalloc = blockSize + ChunkSize;
m_ptr = _virtual_realloc( newalloc );
if( m_ptr == NULL )
{
throw Exception::OutOfMemory(
"Out-of-memory on block re-allocation. "
"Old size: " + to_string( m_size ) + " bytes, "
"New size: " + to_string( newalloc ) + " bytes"
);
}
m_size = newalloc;
}
}
// Gets a pointer to the requested allocation index.
// DevBuilds : Throws std::out_of_range() if the index is invalid.
T *GetPtr( uint idx=0 ) { return _getPtr( idx ); }
const T *GetPtr( uint idx=0 ) const { return _getPtr( idx ); }
// Gets an element of this memory allocation much as if it were an array.
// DevBuilds : Throws std::out_of_range() if the index is invalid.
T& operator[]( int idx ) { return *_getPtr( (uint)idx ); }
const T& operator[]( int idx ) const { return *_getPtr( (uint)idx ); }
virtual MemoryAlloc<T>* Clone() const
{
MemoryAlloc<T>* retval = new MemoryAlloc<T>( m_size );
memcpy_fast( retval->GetPtr(), m_ptr, sizeof(T) * m_size );
return retval;
}
protected:
// A safe array index fetcher. Throws an exception if the array index
// is outside the bounds of the array.
// Performance Considerations: This function adds quite a bit of overhead
// to array indexing and thus should be done infrequently if used in
// time-critical situations. Indead of using it from inside loops, cache
// the pointer into a local variable and use stad (unsafe) C indexes.
T* _getPtr( uint i ) const
{
#ifdef PCSX2_DEVBUILD
if( i >= (uint)m_size )
{
throw Exception::IndexBoundsFault(
"Index out of bounds on MemoryAlloc: " + Name +
" (index=" + to_string(i) +
", size=" + to_string(m_size) + ")"
);
}
#endif
return &m_ptr[i];
}
};
//////////////////////////////////////////////////////////////////
// Handy little class for allocating a resizable memory block, complete with
// exception-based error handling and automatic cleanup.
// This one supports aligned data allocations too!
template< typename T, uint Alignment >
class SafeAlignedArray : public MemoryAlloc<T>
{
protected:
T* _virtual_realloc( int newsize )
{
// TODO : aligned_realloc will need a linux implementation now. -_-
return (T*)_aligned_realloc( m_ptr, newsize * sizeof(T), Alignment );
}
// Appends "(align: xx)" to the name of the allocation in devel builds.
// Maybe useful,maybe not... no harm in atatching it. :D
string _getName( const string& src )
{
#ifdef PCSX2_DEVBUILD
return src + "(align:" + to_string(Alignment) + ")";
#endif
return src;
}
public:
virtual ~SafeAlignedArray()
{
safe_aligned_free( m_ptr );
// mptr is set to null, so the parent class's destructor won't re-free it.
}
explicit SafeAlignedArray( const std::string& name="Unnamed" ) :
MemoryAlloc( name )
{
}
explicit SafeAlignedArray( int initialSize, const std::string& name="Unnamed" ) :
MemoryAlloc(
_getName(name),
(T*)_aligned_malloc( initialSize * sizeof(T), Alignment ),
initialSize
)
{
}
virtual SafeAlignedArray<T,Alignment>* Clone() const
{
SafeAlignedArray<T,Alignment>* retval = new SafeAlignedArray<T,Alignment>( m_size );
memcpy_fast( retval->GetPtr(), m_ptr, sizeof(T) * m_size );
return retval;
}
};
#endif

View File

@ -20,9 +20,10 @@
#include "Common.h"
#include "PsxCommon.h"
#include "SaveState.h"
#include "CDVDisodrv.h"
#include "VUmicro.h"
#include "VU.h"
#include "iCore.h"
#include "iVUzerorec.h"
@ -31,7 +32,6 @@
#include "COP0.h"
#include "Cache.h"
#include "Paths.h"
using namespace R5900;
@ -43,8 +43,8 @@ extern void recResetIOP();
static void PreLoadPrep()
{
recResetEE();
recResetIOP();
SysResetExecutionState();
#ifdef PCSX2_VIRTUAL_MEM
DWORD OldProtect;
// make sure can write

View File

@ -22,6 +22,8 @@
#include "PS2Etypes.h"
#include "Exceptions.h"
#include "Paths.h"
#include "MemcpyFast.h"
#include "SafeArray.h"
void SysDetect(); // Detects cpu type and fills cpuInfo structs.
bool SysInit(); // Init logfiles, directories, critical memory resources, and other OS-specific one-time
@ -37,11 +39,11 @@ void SysResetExecutionState();
void *SysLoadLibrary(const char *lib); // Loads Library
void *SysLoadSym(void *lib, const char *sym); // Loads Symbol from Library
const char *SysLibError(); // Gets previous error loading sysbols
const char *SysLibError(); // Gets previous error loading symbols
void SysCloseLibrary(void *lib); // Closes Library
// Maps a block of memory for use as a recompiled code buffer.
// The allocated block has code execution privliges.
// The allocated block has code execution privileges.
// Returns NULL on allocation failure.
void *SysMmap(uptr base, u32 size);
@ -99,7 +101,7 @@ namespace Console
extern void ClearColor();
// The following Write functions return bool so that we can use macros to exclude
// them from different buildypes. The return values are always zero.
// them from different build types. The return values are always zero.
// Writes a newline to the console.
extern bool __fastcall Newline();
@ -171,44 +173,10 @@ using Console::Color_Cyan;
using Console::Color_Yellow;
using Console::Color_White;
//////////////////////////////////////////////////////////////
// Safe deallocation macros -- always check pointer validity (non-null)
// and set pointer to null on deallocation.
#define safe_delete( ptr ) \
if( ptr != NULL ) { \
delete ptr; \
ptr = NULL; \
}
#define safe_delete_array( ptr ) \
if( ptr != NULL ) { \
delete[] ptr; \
ptr = NULL; \
}
#define safe_free( ptr ) \
if( ptr != NULL ) { \
free( ptr ); \
ptr = NULL; \
}
#define safe_aligned_free( ptr ) \
if( ptr != NULL ) { \
_aligned_free( ptr ); \
ptr = NULL; \
}
#define SafeSysMunmap( ptr, size ) \
if( ptr != NULL ) { \
SysMunmap( (uptr)ptr, size ); \
ptr = NULL; \
}
//////////////////////////////////////////////////////////////
// Dev / Debug conditionals --
// Consts for using if() statements instead of uglier #ifdef macros.
// Abbrivated macros for dev/debug only consoles and mesgboxes.
// Abbreviated macros for dev/debug only consoles and msgboxes.
#ifdef PCSX2_DEVBUILD
@ -264,177 +232,5 @@ int SysMapUserPhysicalPages(void* Addr, uptr NumPages, uptr* pblock, int pageoff
#endif
//////////////////////////////////////////////////////////////////
// Handy little class for allocating a resizable memory block, complete with
// exception-based error handling and automatic cleanup.
template< typename T >
class MemoryAlloc : public NoncopyableObject
{
public:
static const int DefaultChunkSize = 0x1000 * sizeof(T);
public:
const std::string Name; // user-assigned block name
int ChunkSize;
protected:
T* m_ptr;
int m_size; // size of the allocation of memory
const static std::string m_str_Unnamed;
protected:
// Internal contructor for use by derrived classes. This allws a derrived class to
// use its own memory allocation (with an aligned memory, for example).
// Throws:
// Exception::OutOfMemory if the allocated_mem pointr is NULL.
explicit MemoryAlloc( const std::string& name, T* allocated_mem, int initSize ) :
Name( name )
, ChunkSize( DefaultChunkSize )
, m_ptr( allocated_mem )
, m_size( initSize )
{
if( m_ptr == NULL )
throw Exception::OutOfMemory();
}
virtual T* _virtual_realloc( int newsize )
{
return (T*)realloc( m_ptr, newsize * sizeof(T) );
}
public:
virtual ~MemoryAlloc()
{
safe_free( m_ptr );
}
explicit MemoryAlloc( const std::string& name="Unnamed" ) :
Name( name )
, ChunkSize( DefaultChunkSize )
, m_ptr( NULL )
, m_size( 0 )
{
}
explicit MemoryAlloc( int initialSize, const std::string& name="Unnamed" ) :
Name( name )
, ChunkSize( DefaultChunkSize )
, m_ptr( (T*)malloc( initialSize * sizeof(T) ) )
, m_size( initialSize )
{
if( m_ptr == NULL )
throw Exception::OutOfMemory();
}
// Returns the size of the memory allocation, as according to the array type.
int GetLength() const { return m_size; }
// Returns the size of the memory allocation in bytes.
int GetSizeInBytes() const { return m_size * sizeof(T); }
// Ensures that the allocation is large enough to fit data of the
// amount requested. The memory allocation is not resized smaller.
void MakeRoomFor( int blockSize )
{
std::string temp;
if( blockSize > m_size )
{
const uint newalloc = blockSize + ChunkSize;
m_ptr = _virtual_realloc( newalloc );
if( m_ptr == NULL )
{
throw Exception::OutOfMemory(
"Out-of-memory on block re-allocation. "
"Old size: " + to_string( m_size ) + " bytes, "
"New size: " + to_string( newalloc ) + " bytes"
);
}
m_size = newalloc;
}
}
// Gets a pointer to the requested allocation index.
// DevBuilds : Throws std::out_of_range() if the index is invalid.
T *GetPtr( uint idx=0 ) { return _getPtr( idx ); }
const T *GetPtr( uint idx=0 ) const { return _getPtr( idx ); }
// Gets an element of this memory allocation much as if it were an array.
// DevBuilds : Throws std::out_of_range() if the index is invalid.
T& operator[]( int idx ) { return *_getPtr( (uint)idx ); }
const T& operator[]( int idx ) const { return *_getPtr( (uint)idx ); }
virtual MemoryAlloc<T>& Clone() const
{
MemoryAlloc<T>* retval = new MemoryAlloc<T>( m_size );
memcpy( retval->GetPtr(), m_ptr, sizeof(T) * m_size );
return *retval;
}
protected:
// A safe array index fetcher. Throws an exception if the array index
// is outside the bounds of the array.
// Performance Considerations: This function adds quite a bit of overhead
// to array indexing and thus should be done infrequently if used in
// time-critical situations. Indead of using it from inside loops, cache
// the pointer into a local variable and use stad (unsafe) C indexes.
T* _getPtr( uint i ) const
{
#ifdef PCSX2_DEVBUILD
if( i >= (uint)m_size )
{
throw Exception::IndexBoundsFault(
"Index out of bounds on MemoryAlloc: " + Name +
" (index=" + to_string(i) +
", size=" + to_string(m_size) + ")"
);
}
#endif
return &m_ptr[i];
}
};
template< typename T, uint Alignment >
class SafeAlignedArray : public MemoryAlloc<T>
{
protected:
T* _virtual_realloc( int newsize )
{
// TODO : aligned_realloc will need a linux implementation now. -_-
return (T*)_aligned_realloc( m_ptr, newsize * sizeof(T), Alignment );
}
// Appends "(align: xx)" to the name of the allocation in devel builds.
// Maybe useful,maybe not... no harm in atatching it. :D
string _getName( const string& src )
{
#ifdef PCSX2_DEVBUILD
return src + "(align:" + to_string(Alignment) + ")";
#endif
return src;
}
public:
virtual ~SafeAlignedArray()
{
safe_aligned_free( m_ptr );
// mptr is set to null, so the parent class's destructor won't re-free it.
}
explicit SafeAlignedArray( const std::string& name="Unnamed" ) :
MemoryAlloc( name )
{
}
explicit SafeAlignedArray( int initialSize, const std::string& name="Unnamed" ) :
MemoryAlloc(
_getName(name),
(T*)_aligned_malloc( initialSize * sizeof(T), Alignment ),
initialSize
)
{
}
};
#endif /* __SYSTEM_H__ */

View File

@ -719,22 +719,6 @@
<Filter
Name="Misc"
>
<File
RelativePath="..\..\x86\fast_routines.cpp"
>
<FileConfiguration
Name="Devel vtlb|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\memzero.h"
>
</File>
<File
RelativePath="..\..\Misc.cpp"
>
@ -751,10 +735,6 @@
RelativePath="..\..\Patch.h"
>
</File>
<File
RelativePath="..\..\PathUtils.cpp"
>
</File>
<File
RelativePath="..\..\PrecompiledHeader.cpp"
>
@ -812,14 +792,6 @@
RelativePath="..\..\PrecompiledHeader.h"
>
</File>
<File
RelativePath="..\..\SaveState.cpp"
>
</File>
<File
RelativePath="..\..\SaveState.h"
>
</File>
<File
RelativePath="..\..\SourceLog.cpp"
>
@ -1120,202 +1092,6 @@
>
</File>
</Filter>
<Filter
Name="DynarecEmitter"
>
<File
RelativePath="..\..\x86\ix86\ix86.cpp"
>
<FileConfiguration
Name="Devel vm|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="2"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug vm|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="2"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug vtlb|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="2"
/>
</FileConfiguration>
<FileConfiguration
Name="Release vm|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="2"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\x86\ix86\ix86.h"
>
</File>
<File
RelativePath="..\..\x86\ix86\ix86_3dnow.cpp"
>
<FileConfiguration
Name="Devel vm|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug vm|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug vtlb|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
/>
</FileConfiguration>
<FileConfiguration
Name="Release vm|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\x86\ix86\ix86_cpudetect.cpp"
>
</File>
<File
RelativePath="..\..\x86\ix86\ix86_fpu.cpp"
>
<FileConfiguration
Name="Devel vm|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug vm|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug vtlb|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
/>
</FileConfiguration>
<FileConfiguration
Name="Release vm|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\x86\ix86\ix86_mmx.cpp"
>
<FileConfiguration
Name="Devel vm|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug vm|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug vtlb|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
/>
</FileConfiguration>
<FileConfiguration
Name="Release vm|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\x86\ix86\ix86_sse.cpp"
>
<FileConfiguration
Name="Devel vm|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug vm|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug vtlb|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
/>
</FileConfiguration>
<FileConfiguration
Name="Release vm|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\x86\ix86\ix86_tools.cpp"
>
</File>
</Filter>
<Filter
Name="zlib"
>
@ -2969,6 +2745,30 @@
RelativePath="..\..\Exceptions.h"
>
</File>
<File
RelativePath="..\..\x86\fast_routines.cpp"
>
<FileConfiguration
Name="Devel vtlb|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\MemcpyFast.h"
>
</File>
<File
RelativePath="..\memzero.h"
>
</File>
<File
RelativePath="..\..\PathUtils.cpp"
>
</File>
<File
RelativePath="..\..\Plugins.cpp"
>
@ -2977,6 +2777,10 @@
RelativePath="..\..\Plugins.h"
>
</File>
<File
RelativePath="..\..\SafeArray.h"
>
</File>
<File
RelativePath="..\SamplProf.cpp"
>
@ -2985,6 +2789,14 @@
RelativePath="..\..\SamplProf.h"
>
</File>
<File
RelativePath="..\..\SaveState.cpp"
>
</File>
<File
RelativePath="..\..\SaveState.h"
>
</File>
<File
RelativePath="..\..\System.cpp"
>
@ -3005,6 +2817,202 @@
RelativePath="..\WinThreads.cpp"
>
</File>
<Filter
Name="DynarecEmitter"
>
<File
RelativePath="..\..\x86\ix86\ix86.cpp"
>
<FileConfiguration
Name="Devel vm|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="2"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug vm|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="2"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug vtlb|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="2"
/>
</FileConfiguration>
<FileConfiguration
Name="Release vm|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="2"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\x86\ix86\ix86.h"
>
</File>
<File
RelativePath="..\..\x86\ix86\ix86_3dnow.cpp"
>
<FileConfiguration
Name="Devel vm|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug vm|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug vtlb|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
/>
</FileConfiguration>
<FileConfiguration
Name="Release vm|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\x86\ix86\ix86_cpudetect.cpp"
>
</File>
<File
RelativePath="..\..\x86\ix86\ix86_fpu.cpp"
>
<FileConfiguration
Name="Devel vm|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug vm|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug vtlb|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
/>
</FileConfiguration>
<FileConfiguration
Name="Release vm|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\x86\ix86\ix86_mmx.cpp"
>
<FileConfiguration
Name="Devel vm|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug vm|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug vtlb|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
/>
</FileConfiguration>
<FileConfiguration
Name="Release vm|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\x86\ix86\ix86_sse.cpp"
>
<FileConfiguration
Name="Devel vm|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug vm|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug vtlb|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
/>
</FileConfiguration>
<FileConfiguration
Name="Release vm|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\x86\ix86\ix86_tools.cpp"
>
</File>
</Filter>
</Filter>
<File
RelativePath="..\..\Common.h"

View File

@ -750,6 +750,7 @@ LRESULT WINAPI MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
if (remoteDebugBios)
{
cpuReset();
SysResetExecutionState();
cpuExecuteBios();
DialogBox(gApp.hInstance, MAKEINTRESOURCE(IDD_RDEBUG), NULL, (DLGPROC)RemoteDebuggerProc);

View File

@ -275,8 +275,6 @@ void RunExecute( const char* elf_file, bool use_bios )
if (OpenPlugins(g_TestRun.ptitle) == -1)
return;
SysResetExecutionState();
if( elf_file == NULL )
{
if(g_RecoveryState != NULL)
@ -305,11 +303,11 @@ void RunExecute( const char* elf_file, bool use_bios )
// if the elf_file is null we use the CDVD elf file.
// But if the elf_file is an empty string then we boot the bios instead.
cpuExecuteBios();
char ename[g_MaxPath];
ename[0] = 0;
if( !use_bios )
GetPS2ElfName( ename );
loadElfFile( ename );
}
}
@ -318,7 +316,6 @@ void RunExecute( const char* elf_file, bool use_bios )
// Custom ELF specified (not using CDVD).
// Run the BIOS and load the ELF.
cpuExecuteBios();
loadElfFile( elf_file );
}

View File

@ -197,6 +197,7 @@ static __forceinline void memzero_ptr( void *dest )
case 3:
__asm
{
cld;
mov edi, dest
xor eax, eax
stosd
@ -208,6 +209,7 @@ static __forceinline void memzero_ptr( void *dest )
case 4:
__asm
{
cld;
mov edi, dest
xor eax, eax
stosd
@ -220,6 +222,7 @@ static __forceinline void memzero_ptr( void *dest )
case 5:
__asm
{
cld;
mov edi, dest
xor eax, eax
stosd
@ -233,6 +236,7 @@ static __forceinline void memzero_ptr( void *dest )
default:
__asm
{
cld;
mov ecx, remdat
mov edi, dest
xor eax, eax
@ -332,6 +336,7 @@ static __forceinline void memset_8( void *dest )
case 3:
__asm
{
cld;
mov edi, dest;
mov eax, data32;
stosd;
@ -343,6 +348,7 @@ static __forceinline void memset_8( void *dest )
case 4:
__asm
{
cld;
mov edi, dest;
mov eax, data32;
stosd;
@ -355,6 +361,7 @@ static __forceinline void memset_8( void *dest )
case 5:
__asm
{
cld;
mov edi, dest;
mov eax, data32;
stosd;
@ -368,6 +375,7 @@ static __forceinline void memset_8( void *dest )
default:
__asm
{
cld;
mov ecx, remdat;
mov edi, dest;
mov eax, data32;
@ -420,6 +428,7 @@ static __forceinline void memset_16( void *dest )
case 3:
__asm
{
cld;
mov edi, dest;
mov eax, data32;
stosd;
@ -431,6 +440,7 @@ static __forceinline void memset_16( void *dest )
case 4:
__asm
{
cld;
mov edi, dest;
mov eax, data32;
stosd;
@ -443,6 +453,7 @@ static __forceinline void memset_16( void *dest )
case 5:
__asm
{
cld;
mov edi, dest;
mov eax, data32;
stosd;
@ -456,6 +467,7 @@ static __forceinline void memset_16( void *dest )
default:
__asm
{
cld;
mov ecx, remdat;
mov edi, dest;
mov eax, data32;
@ -496,18 +508,14 @@ static __forceinline void memset_32( void *dest )
return;
case 2:
__asm
{
mov edi, dest;
mov eax, data32;
stosd;
stosd;
}
((u32*)dest)[0] = data32;
((u32*)dest)[1] = data32;
return;
case 3:
__asm
{
cld;
mov edi, dest;
mov eax, data32;
stosd;
@ -519,6 +527,7 @@ static __forceinline void memset_32( void *dest )
case 4:
__asm
{
cld;
mov edi, dest;
mov eax, data32;
stosd;
@ -531,6 +540,7 @@ static __forceinline void memset_32( void *dest )
case 5:
__asm
{
cld;
mov edi, dest;
mov eax, data32;
stosd;
@ -544,6 +554,7 @@ static __forceinline void memset_32( void *dest )
default:
__asm
{
cld;
mov ecx, remdat;
mov edi, dest;
mov eax, data32;