wxGui branch: Holy crap! I converted it to unicode! This was an absolutely maddening experience. [also: Merged with /trunk]

git-svn-id: http://pcsx2.googlecode.com/svn/branches/wxgui@1069 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
Jake.Stine 2009-04-27 02:04:31 +00:00
commit 5d36fe3839
238 changed files with 17755 additions and 14481 deletions

View File

@ -26,6 +26,7 @@
InheritedPropertySheets="..\..\..\3rdparty.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
@ -52,7 +53,7 @@
OmitFramePointers="true"
WholeProgramOptimization="true"
AdditionalIncludeDirectories="..\..\Include;..\..\Include\msvc;..\..\..\zlib"
PreprocessorDefinitions="WIN32;_LIB;__WXMSW__;wxUSE_GUI=0;wxUSE_BASE=1;_CRT_SECURE_NO_WARNINGS"
PreprocessorDefinitions="WIN32;_LIB;__WXMSW__;wxUSE_UNICODE=1;wxUSE_GUI=0;wxUSE_BASE=1;_CRT_SECURE_NO_WARNINGS"
StringPooling="true"
RuntimeLibrary="0"
BufferSecurityCheck="false"
@ -107,6 +108,7 @@
InheritedPropertySheets="..\..\..\3rdparty.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
@ -128,7 +130,7 @@
AdditionalOptions="/EHsc "
Optimization="0"
AdditionalIncludeDirectories="..\..\Include;..\..\Include\msvc;..\..\..\zlib"
PreprocessorDefinitions="WIN32;_LIB;_DEBUG;__WXMSW__;__WXDEBUG__;wxUSE_GUI=0;wxUSE_BASE=1;_CRT_SECURE_NO_WARNINGS"
PreprocessorDefinitions="WIN32;_LIB;_DEBUG;__WXMSW__;__WXDEBUG__;wxUSE_GUI=0;wxUSE_BASE=1;wxUSE_UNICODE=1;_CRT_SECURE_NO_WARNINGS"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
@ -179,6 +181,7 @@
InheritedPropertySheets="..\..\..\3rdparty.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="1"
WholeProgramOptimization="0"
>
<Tool
@ -204,7 +207,7 @@
FavorSizeOrSpeed="2"
WholeProgramOptimization="false"
AdditionalIncludeDirectories="..\..\Include;..\..\Include\msvc;..\..\..\zlib"
PreprocessorDefinitions="WIN32;_LIB;__WXMSW__;wxUSE_GUI=0;wxUSE_BASE=1;_CRT_SECURE_NO_WARNINGS"
PreprocessorDefinitions="WIN32;_LIB;__WXMSW__;wxUSE_UNICODE=1;wxUSE_GUI=0;wxUSE_BASE=1;_CRT_SECURE_NO_WARNINGS"
StringPooling="true"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"

View File

@ -20,7 +20,7 @@
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="10"
CharacterSet="2"
CharacterSet="1"
WholeProgramOptimization="0"
>
<Tool
@ -41,7 +41,7 @@
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="10"
CharacterSet="2"
CharacterSet="1"
WholeProgramOptimization="0"
>
<Tool
@ -62,7 +62,7 @@
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="10"
CharacterSet="2"
CharacterSet="1"
WholeProgramOptimization="0"
>
<Tool
@ -102,7 +102,7 @@
<Tool
Name="VCCustomBuildTool"
Description="Creating ..\..\lib\vc_lib\mswd\wx\msw\rcdefs.h"
CommandLine="cl /EP /nologo &quot;$(InputPath)&quot; &gt; &quot;..\..\lib\vc_lib\mswd\wx\msw\rcdefs.h&quot;"
CommandLine="cl /EP /nologo &quot;$(InputPath)&quot; &gt; &quot;..\..\lib\vc_lib\mswd\wx\msw\rcdefs.h&quot;&#x0D;&#x0A;"
Outputs="..\..\lib\vc_lib\mswd\wx\msw\rcdefs.h"
/>
</FileConfiguration>
@ -112,7 +112,7 @@
<Tool
Name="VCCustomBuildTool"
Description="Creating ..\..\lib\vc_lib\mswd\wx\msw\rcdefs.h"
CommandLine="cl /EP /nologo &quot;$(InputPath)&quot; &gt; &quot;..\..\lib\vc_lib\mswd\wx\msw\rcdefs.h&quot;"
CommandLine="cl /EP /nologo &quot;$(InputPath)&quot; &gt; &quot;..\..\lib\vc_lib\mswd\wx\msw\rcdefs.h&quot;&#x0D;&#x0A;"
Outputs="..\..\lib\vc_lib\mswd\wx\msw\rcdefs.h"
/>
</FileConfiguration>
@ -122,7 +122,7 @@
<Tool
Name="VCCustomBuildTool"
Description="Creating ..\..\lib\vc_lib\mswd\wx\msw\rcdefs.h"
CommandLine="cl /EP /nologo &quot;$(InputPath)&quot; &gt; &quot;..\..\lib\vc_lib\mswd\wx\msw\rcdefs.h&quot;"
CommandLine="cl /EP /nologo &quot;$(InputPath)&quot; &gt; &quot;..\..\lib\vc_lib\mswd\wx\msw\rcdefs.h&quot;&#x0D;&#x0A;"
Outputs="..\..\lib\vc_lib\mswd\wx\msw\rcdefs.h"
/>
</FileConfiguration>
@ -136,7 +136,7 @@
<Tool
Name="VCCustomBuildTool"
Description="Creating ..\..\lib\vc_lib\mswd\wx\setup.h"
CommandLine="copy &quot;$(InputPath)&quot; ..\..\lib\vc_lib\mswd\wx\setup.h"
CommandLine="copy &quot;$(InputPath)&quot; ..\..\lib\vc_lib\mswd\wx\setup.h&#x0D;&#x0A;"
Outputs="..\..\lib\vc_lib\mswd\wx\setup.h"
/>
</FileConfiguration>
@ -146,7 +146,7 @@
<Tool
Name="VCCustomBuildTool"
Description="Creating ..\..\lib\vc_lib\msw\wx\setup.h"
CommandLine="copy &quot;$(InputPath)&quot; ..\..\lib\vc_lib\msw\wx\setup.h"
CommandLine="copy &quot;$(InputPath)&quot; ..\..\lib\vc_lib\msw\wx\setup.h&#x0D;&#x0A;"
Outputs="..\..\lib\vc_lib\msw\wx\setup.h"
/>
</FileConfiguration>
@ -156,7 +156,7 @@
<Tool
Name="VCCustomBuildTool"
Description="Creating ..\..\lib\vc_lib\msw\wx\setup.h"
CommandLine="copy &quot;$(InputPath)&quot; ..\..\lib\vc_lib\msw\wx\setup.h"
CommandLine="copy &quot;$(InputPath)&quot; ..\..\lib\vc_lib\msw\wx\setup.h&#x0D;&#x0A;"
Outputs="..\..\lib\vc_lib\msw\wx\setup.h"
/>
</FileConfiguration>

View File

@ -26,6 +26,7 @@
InheritedPropertySheets="..\..\..\3rdparty.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
@ -47,7 +48,7 @@
AdditionalOptions="/EHsc "
Optimization="0"
AdditionalIncludeDirectories="..\..\Include;..\..\Include\msvc;..\..\..\zlib;..\..\src\png"
PreprocessorDefinitions="WIN32;_LIB;_DEBUG;__WXMSW__;__WXDEBUG__;wxUSE_BASE=0;_CRT_SECURE_NO_WARNINGS"
PreprocessorDefinitions="WIN32;_LIB;_DEBUG;__WXMSW__;__WXDEBUG__;wxUSE_BASE=0;wxUSE_UNICODE=1;_CRT_SECURE_NO_WARNINGS"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
@ -98,6 +99,7 @@
InheritedPropertySheets="..\..\..\3rdparty.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
@ -124,7 +126,7 @@
OmitFramePointers="true"
WholeProgramOptimization="true"
AdditionalIncludeDirectories="..\..\Include;..\..\Include\msvc;..\..\..\zlib;..\..\src\png"
PreprocessorDefinitions="WIN32;_LIB;__WXMSW__;wxUSE_BASE=0;_CRT_SECURE_NO_WARNINGS"
PreprocessorDefinitions="WIN32;_LIB;__WXMSW__;wxUSE_BASE=0;wxUSE_UNICODE=1;_CRT_SECURE_NO_WARNINGS"
StringPooling="true"
RuntimeLibrary="0"
BufferSecurityCheck="false"
@ -178,6 +180,7 @@
InheritedPropertySheets="..\..\..\3rdparty.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="1"
WholeProgramOptimization="0"
>
<Tool
@ -203,7 +206,7 @@
FavorSizeOrSpeed="2"
WholeProgramOptimization="false"
AdditionalIncludeDirectories="..\..\Include;..\..\Include\msvc;..\..\..\zlib;..\..\src\png"
PreprocessorDefinitions="WIN32;_LIB;__WXMSW__;wxUSE_BASE=0;_CRT_SECURE_NO_WARNINGS"
PreprocessorDefinitions="WIN32;_LIB;__WXMSW__;wxUSE_BASE=0;wxUSE_UNICODE=1;_CRT_SECURE_NO_WARNINGS"
StringPooling="true"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"

View File

@ -55,8 +55,6 @@
// disable the default case in a switch
#define jNO_DEFAULT \
{ \
break; \
\
default: \
jASSUME(0); \
break; \
@ -88,6 +86,7 @@ typedef unsigned int uint;
#define __naked __declspec(naked)
#define __unused /*unused*/
#define __noinline __declspec(noinline)
#define CALLBACK __stdcall
#else // _MSC_VER
@ -136,6 +135,7 @@ typedef union _LARGE_INTEGER
#define __unused __attribute__((unused))
#define _inline __inline__ __attribute__((unused))
#define __forceinline __attribute__((always_inline,unused))
#define __noinline __attribute__((noinline))
#define __naked // GCC lacks the naked specifier
#define CALLBACK // CALLBACK is win32-specific mess

View File

@ -20,11 +20,11 @@
#define __PCSX2CONFIG_H__
// Hack so that you can still use this file from C (not C++), or from a plugin without access to Paths.h.
#ifdef PLUGIN_ONLY
// .. and removed in favor of a less hackish approach (air)
#ifndef g_MaxPath
#define g_MaxPath 255
#else
#include "Paths.h"
#endif
#endif
/////////////////////////////////////////////////////////////////////////
// Session Configuration Override Flags
@ -44,7 +44,8 @@ extern SessionOverrideFlags g_Session;
//////////////////////////////////////////////////////////////////////////
// Pcsx2 User Configuration Options!
//#define PCSX2_MICROVU // Use Micro VU recs instead of Zero VU Recs
//#define PCSX2_MICROVU // Use Micro VU recs instead of Zero VU Recs
//#define PCSX2_MICROVU_ // Fully enable Micro VU recs (temporary option for now)
#define PCSX2_GSMULTITHREAD 1 // uses multi-threaded gs
#define PCSX2_EEREC 0x10
#define PCSX2_VU0REC 0x20
@ -55,19 +56,20 @@ extern SessionOverrideFlags g_Session;
#define PCSX2_FRAMELIMIT_SKIP 0x800
#define PCSX2_FRAMELIMIT_VUSKIP 0xc00
#define CHECK_FRAMELIMIT (Config.Options&PCSX2_FRAMELIMIT_MASK)
//------------ CPU Options!!! ---------------
#define CHECK_MULTIGS (Config.Options&PCSX2_GSMULTITHREAD)
#define CHECK_EEREC (!g_Session.ForceDisableEErec && Config.Options&PCSX2_EEREC)
//------------ SPEED/MISC HACKS!!! ---------------
#define CHECK_EE_CYCLERATE (Config.Hacks & 0x03)
#define CHECK_IOP_CYCLERATE (Config.Hacks & 0x08)
#define CHECK_WAITCYCLE_HACK (Config.Hacks & 0x10)
#define CHECK_INTC_STAT_HACK (Config.Hacks & 0x20)
#define CHECK_ESCAPE_HACK (Config.Hacks & 0x400)
#define CHECK_VU0REC (!g_Session.ForceDisableVU0rec && Config.Options&PCSX2_VU0REC)
#define CHECK_VU1REC (!g_Session.ForceDisableVU1rec && (Config.Options&PCSX2_VU1REC))
//------------ SPECIAL GAME FIXES!!! ---------------
#define CHECK_VUADDSUBHACK (Config.GameFixes & 0x1) // Special Fix for Tri-ace games, they use an encryption algorithm that requires VU addi opcode to be bit-accurate.
#define CHECK_FPUCOMPAREHACK (Config.GameFixes & 0x4) // Special Fix for Digimon Rumble Arena 2, fixes spinning/hanging on intro-menu.
#define CHECK_VUCLIPFLAGHACK (Config.GameFixes & 0x2) // Special Fix for Persona games, maybe others. It's to do with the VU clip flag (again).
#define CHECK_FPUMULHACK (Config.GameFixes & 0x8) // Special Fix for Tales of Destiny hangs.
//------------ Advanced Options!!! ---------------
#define CHECK_VU_OVERFLOW (Config.vuOptions & 0x1)
#define CHECK_VU_EXTRA_OVERFLOW (Config.vuOptions & 0x2) // If enabled, Operands are clamped before being used in the VU recs
@ -80,14 +82,40 @@ extern SessionOverrideFlags g_Session;
#define CHECK_FPU_FULL (Config.eeOptions & 0x4)
#define DEFAULT_eeOptions 0x01
#define DEFAULT_vuOptions 0x01
//------------ DEFAULT sseMXCSR VALUES!!! ---------------
#define DEFAULT_sseMXCSR 0xffc0 //FPU rounding > DaZ, FtZ, "chop"
#define DEFAULT_sseVUMXCSR 0xffc0 //VU rounding > DaZ, FtZ, "chop"
#define CHECK_FRAMELIMIT (Config.Options&PCSX2_FRAMELIMIT_MASK)
//------------ Recompiler defines - Comment to disable a recompiler ---------------
// Yay! These work now! (air) ... almost (air)
#define CHECK_VU0REC (!g_Session.ForceDisableVU0rec && Config.Options&PCSX2_VU0REC)
#define CHECK_VU1REC (!g_Session.ForceDisableVU1rec && (Config.Options&PCSX2_VU1REC))
#define SHIFT_RECOMPILE // Speed majorly reduced if disabled
#define BRANCH_RECOMPILE // Speed extremely reduced if disabled - more then shift
// Disabling all the recompilers in this block is interesting, as it still runs at a reasonable rate.
// It also adds a few glitches. Really reminds me of the old Linux 64-bit version. --arcum42
#define ARITHMETICIMM_RECOMPILE
#define ARITHMETIC_RECOMPILE
#define MULTDIV_RECOMPILE
#define JUMP_RECOMPILE
#define LOADSTORE_RECOMPILE
#define MOVE_RECOMPILE
#define MMI_RECOMPILE
#define MMI0_RECOMPILE
#define MMI1_RECOMPILE
#define MMI2_RECOMPILE
#define MMI3_RECOMPILE
#define FPU_RECOMPILE
#define CP0_RECOMPILE
#define CP2_RECOMPILE
// You can't recompile ARITHMETICIMM without ARITHMETIC.
#ifndef ARITHMETIC_RECOMPILE
#undef ARITHMETICIMM_RECOMPILE
#endif
#define EE_CONST_PROP // rec2 - enables constant propagation (faster)
// Memory Card configuration, per slot.
struct McdConfig
@ -133,7 +161,15 @@ public:
int PsxType;
int Patch;
int CustomFps;
int Hacks;
struct Hacks_t {
int EECycleRate;
bool IOPCycleDouble;
bool WaitCycleExt;
bool INTCSTATSlow;
int VUCycleSteal;
bool IdleLoopFF;
bool ESCExits; // this is a hack!?
} Hacks;
int GameFixes;
int CustomFrameSkip;
int CustomConsecutiveFrames;

251
pcsx2/AsciiString.cpp Normal file
View File

@ -0,0 +1,251 @@
/* Pcsx2 - Pc Ps2 Emulator
* Copyright (C) 2002-2009 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
*/
#include "PrecompiledHeader.h"
#include "SafeArray.h"
#include "AsciiString.h"
using namespace Threading;
namespace AsciiStringAllocator
{
struct PrivateHandle
{
AsciiStringAllocatorHandle* PublicHandle;
};
static const uint UnitLength = 256;
static const uint UnitLengthMask = UnitLength-1;
static const uint AllocationCleanupThreshold = 256;
static const uint InitialBufferLength = 0x100000; // 1MB!
static const AsciiStringAllocatorHandle* PublicHandleAllocated = (AsciiStringAllocatorHandle*)1;
static uint m_release_counter( 0 );
static SafeArray<PrivateHandle> m_PrivateHandles( InitialBufferLength / UnitLength );
static SafeArray<char> m_StringBuffer( InitialBufferLength );
static int m_NextPrivateHandle;
static int m_NextBufferIndex;
static MutexLock m_Lock;
static char* GetPtr( const AsciiStringAllocatorHandle& handle )
{
return &m_StringBuffer[ m_PrivateHandles[ handle.Index ] ];
}
static void DoCompact()
{
if( m_release_counter < AllocationCleanupThreshold ) return;
ScopedLock locker( m_Lock );
int handlecount = m_PrivateHandles.GetLength();
int writepos = 0;
for( int readpos=0; readpos<handlecount; readpos++ )
{
PrivateHandle& curhandle = m_PrivateHandles[readpos];
if( curhandle.PublicHandle != NULL )
{
int cwpos = writepos;
writepos++;
if( cwpos == readpos ) continue;
if( curhandle.PublicHandle != PublicHandleAllocated )
curhandle.PublicHandle->Index = cwpos;
// todo: replace this with a hardcoded XMM inline copy of 256 bytes. :)
memcpy_fast(
m_StringBuffer.GetPtr(cwpos*UnitLength),
m_StringBuffer.GetPtr(readpos*UnitLength),
UnitLength
);
}
}
}
void New( AsciiStringAllocatorHandle& dest, int length )
{
int numblocks = (length / UnitLength)+1;
length = numblocks * UnitLength;
ScopedLock locker( m_Lock );
AsciiStringAllocatorHandle retval( m_NextPrivateHandle, length );
m_PrivateHandles[m_NextPrivateHandle++].PublicHandle = &dest;
for( int p=numblocks-1; p; --p, ++m_NextPrivateHandle )
m_PrivateHandles[m_NextPrivateHandle].PublicHandle = PublicHandleAllocated;
m_StringBuffer.MakeRoomFor( m_NextPrivateHandle * UnitLength );
return retval;
}
bool Grow( AsciiStringAllocatorHandle& dest )
{
ScopedLock locker( m_lock );
if( m_PrivateHandles[m_NextPrivateHandle].PublicHandle == NULL )
{
m_PrivateHandles[m_NextPrivateHandle].PublicHandle = PublicHandleAllocated;
return true;
}
return false;
}
// releases the block without clearing the handle structure information
// and without doing a block compact check.
static int _release( AsciiStringAllocatorHandle& handle )
{
const int numblocks = handle.Length / UnitLength;
const int endblock = handle.Index + numblocks;
ScopedLock locker( m_Lock );
for( int i=handle.Index; i<endblock; i++ )
m_PrivateHandles[i].PublicHandle = NULL;
// Rewind the NextPrivateHandle if we haven't allocated anything else
// since this allocation was made.
if( endblock == m_NextPrivateHandle )
m_NextPrivateHandle = handle.Index;
return numblocks;
}
void Release( AsciiStringAllocatorHandle& handle )
{
handle.Index = -1;
handle.Length = 0;
m_release_counter += _release( handle );
if( m_release_counter >= AllocationCleanupThreshold )
DoCleanup();
}
// Allocates a new handle and copies the old string contents to the new reserve.
void Reallocate( AsciiStringAllocatorHandle& handle, int newsize )
{
int newblocks = (newsize / UnitLength)+1;
newsize = newblocks * UnitLength;
ScopedLock locker( m_Lock );
_release( handle );
m_StringBuffer.MakeRoomFor( m_NextPrivateHandle + newblocks );
if( m_NextPrivateHandle != handle.Index )
{
memcpy_fast(
m_StringBuffer.GetPtr( m_NextPrivateHandle ),
m_StringBuffer(handle.Index),
handle.Length
);
handle.Index = m_NextPrivateHandle;
}
handle.Length = newsize;
}
};
AsciiStringAllocatorHandle::GetPtr() const
{
return AsciiStringAllocator::GetPtr( *this );
}
//////////////////////////////////////////////////////////////////////////////////////////
//
AsciiString::AsciiString( int length_reserve )
{
AsciiStringAllocator::New( m_MemoryHandle, len )
}
const wxCharBuffer AsciiString::mb_str() const
{
// use wxCharBuffer here for sake of safety, since parallel string operations could
// result in the pointer to this string becoming invalid.
ScopedLock locker( AsciiStringAllocator::m_Lock );
return wxCharBuffer( AsciiStringAllocator::GetPtr( m_MemoryHandle ) );
}
AsciiStringLock::operator char*()
{
return m_buffer;
}
char& AsciiStringLock::operator[]( int idx )
{
return m_buffer[idx];
}
char AsciiStringLock::GetCharAt( int idx ) const
{
return m_buffer[idx];
}
char* AsciiStringLock::GetPtr()
{
return m_buffer;
}
AsciiStringLock::AsciiStringLock( AsciiString& str ) :
m_string( str )
{
m_string.Lock();
}
AsciiStringLock::~AsciiStringLock()
{
m_string.Unlock();
}
AsciiStringLock::operator char*()
{
AsciiStringAllocator::GetPtr( m_handle );
}
AsciiString AsciiString::operator+( const AsciiString& right )
{
int len = GetLength() + right.GetLength();
AsciiString dest( len+1 );
char* lockptr = m_MemoryHandle.GetPtr();
memcpy_fast( lockptr, GetBufferPtr(), GetLength() );
memcpy_fast( lockptr+GetLength(), right.GetBufferPtr(), right.GetLength() );
lockptr[dest.GetLength()] = 0;
}
AsciiString& AsciiString::Append( const AsciiString& src )
{
int needlen = src.GetLength() + GetLength()+1;
if( needlen >= m_MemoryHandle.Length )
{
// The new string is too large -- looks like we're going to need to allocate
// a larger block. We try and use Grow first, if the appending string is very
// short (it sometimes saves the need to copy the block to a new location)
if( src.GetLength() >= AsciiStringAllocator::UnitLength || !AsciiStringAllocator::Grow( m_MemoryHandle ) )
AsciiStringAllocator::Reallocate( m_MemoryHandle, needlen );
}
char* lockptr = m_MemoryHandle.GetPtr();
memcpy_fast( lockptr+GetLength(), src.GetBufferPtr(), src.GetLength() );
lockptr[GetLength()] = 0;
}

84
pcsx2/AsciiString.h Normal file
View File

@ -0,0 +1,84 @@
/* Pcsx2 - Pc Ps2 Emulator
* Copyright (C) 2002-2009 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
*/
#pragma once
class AsciiStringAllocatorHandle
{
public:
const int Index;
const int Length;
public:
AsciiStringAllocatorHandle( int handle, int len ) :
Index( handle ),
Length( len )
{
}
char* GetPtr() const;
void Lock();
void Unlock();
};
class AsciiString
{
protected:
AsciiStringAllocatorHandle m_MemoryHandle;
int m_Length;
public:
AsciiString();
AsciiString( AsciiString& copycat );
AsciiString( const char* src );
AsciiString( const char* src, int length );
AsciiString( const char* src, int startpos, int length );
AsciiString( int length_reserve );
const char* mb_str() const;
char mb_str_unsafe();
int GetLength() const
{
return m_Length;
}
AsciiString operator+( const AsciiString& right );
AsciiString& Append( const AsciiString& src );
void Lock();
void Unlock();
};
class AsciiStringLock
{
protected:
AsciiString& m_string;
char* m_buffer;
public:
AsciiStringLock( const AsciiStringAllocatorHandle& handle );
~AsciiStringLock();
char* GetPtr();
char GetCharAt( int idx ) const;
operator char*();
char& operator[]( int idx );
const char& operator[]( int idx ) const { return GetCharAt( idx ); }
};

View File

@ -19,6 +19,7 @@
#include "PrecompiledHeader.h"
#include <ctype.h>
#include <wx/datetime.h>
#include "IopCommon.h"
#include "CDVDiso.h"
@ -240,12 +241,12 @@ FILE *_cdvdOpenMechaVer() {
FILE* fd;
// get the name of the bios file
string Bios( Path::Combine( Config.BiosDir, Config.Bios ) );
// use the bios filename to get the name of the mecha ver file
// [TODO] : Upgrade this to use std::string!
// [TODO] : Upgrade this to use wxString!
strcpy(file, Bios.c_str());
strcpy(file, g_Conf.Files.Bios().ToAscii().data() );
ptr = file; i = (int)strlen(file);
while (i > 0) { if (ptr[i] == '.') break; i--; }
ptr[i+1] = '\0';
@ -254,11 +255,14 @@ FILE *_cdvdOpenMechaVer() {
// if file doesnt exist, create empty one
fd = fopen(file, "r+b");
if (fd == NULL) {
Console::Notice("MEC File Not Found , Creating Blank File");
Console::Notice( "MEC File Not Found, Creating Blank File..." );
fd = fopen(file, "wb");
if (fd == NULL) {
Msgbox::Alert("_cdvdOpenMechaVer: Error creating %s", params file);
exit(1);
if (fd == NULL)
{
Console::Error( "\tMEC File Creation failed!" );
throw Exception::CreateStream( file );
//Msgbox::Alert( "_cdvdOpenMechaVer: Error creating %s", params file);
//exit(1);
}
fputc(0x03, fd);
fputc(0x06, fd);
@ -285,12 +289,11 @@ FILE *_cdvdOpenNVM() {
FILE* fd;
// get the name of the bios file
string Bios( Path::Combine( Config.BiosDir, Config.Bios ) );
// use the bios filename to get the name of the nvm file
// [TODO] : Upgrade this to use std::string!
strcpy( file, Bios.c_str() );
strcpy( file, g_Conf.Files.Bios().ToAscii().data() );
ptr = file; i = (int)strlen(file);
while (i > 0) { if (ptr[i] == '.') break; i--; }
ptr[i+1] = '\0';
@ -301,9 +304,11 @@ FILE *_cdvdOpenNVM() {
if (fd == NULL) {
Console::Notice("NVM File Not Found , Creating Blank File");
fd = fopen(file, "wb");
if (fd == NULL) {
Msgbox::Alert("_cdvdOpenNVM: Error creating %s", params file);
exit(1);
if (fd == NULL)
{
throw Exception::CreateStream( file );
//Msgbox::Alert("_cdvdOpenNVM: Error creating %s", params file);
//exit(1);
}
for (i=0; i<1024; i++) fputc(0, fd);
}
@ -470,7 +475,7 @@ s32 cdvdWriteConfig(const u8* config)
void cdvdReadKey(u8 arg0, u16 arg1, u32 arg2, u8* key) {
char str[g_MaxPath];
wxString fname;
int numbers;
int letters;
unsigned int key_0_3;
@ -479,7 +484,9 @@ void cdvdReadKey(u8 arg0, u16 arg1, u32 arg2, u8* key) {
char exeName[12];
// get main elf name
GetPS2ElfName(str);
GetPS2ElfName(fname);
const wxCharBuffer crap( fname.ToAscii() );
const char* str = crap.data();
sprintf(exeName, "%c%c%c%c%c%c%c%c%c%c%c",str[8],str[9],str[10],str[11],str[12],str[13],str[14],str[15],str[16],str[17],str[18]);
DevCon::Notice("exeName = %s", params &str[8]);
@ -693,7 +700,7 @@ __forceinline void cdvdGetDiskType()
cdvd.Type = CDVDgetDiskType();
if (cdvd.Type == CDVD_TYPE_PS2CD) // && needReset == 1)
{
char str[g_MaxPath];
wxString str;
if (GetPS2ElfName(str) == 1)
{
cdvd.Type = CDVD_TYPE_PSCD;
@ -768,12 +775,18 @@ void cdvdReset()
cdvd.ReadTime = cdvdBlockReadTime( MODE_DVDROM );
// any random valid date will do
cdvd.RTC.hour = 1;
cdvd.RTC.day = 25;
cdvd.RTC.month = 5;
cdvd.RTC.year = 7; //2007
cdvdSetSystemTime( cdvd );
//cdvd.RTC.hour = 1;
//cdvd.RTC.day = 25;
//cdvd.RTC.month = 5;
//cdvd.RTC.year = 7; //2007
wxDateTime curtime( wxDateTime::GetTimeNow() );
cdvd.RTC.second = (u8)curtime.GetSecond();
cdvd.RTC.minute = (u8)curtime.GetMinute();
cdvd.RTC.hour = (u8)(curtime.GetHour()+1) % 24;
cdvd.RTC.day = (u8)curtime.GetDay();
cdvd.RTC.month = (u8)curtime.GetMonth();
cdvd.RTC.year = (u8)(curtime.GetYear() - 2000);
}
struct Freeze_v10Compat
@ -805,7 +818,7 @@ void cdvdNewDiskCB()
{
cdvd.Type = CDVDgetDiskType();
if(cdvd.Type == CDVD_TYPE_PS2CD) {
char str[g_MaxPath];
wxString str;
if(GetPS2ElfName(str) == 1) {
cdvd.Type = CDVD_TYPE_PSCD;
} // ENDIF- Does the SYSTEM.CNF file only say "BOOT="? PS1 CD then.

View File

@ -141,7 +141,4 @@ void cdvdWrite17(u8 rt);
void cdvdWrite18(u8 rt);
void cdvdWrite3A(u8 rt);
// Platform dependent system time assignment (see WinMisc / LnxMisc)
extern void cdvdSetSystemTime( cdvdStruct& setme );
#endif /* __CDVD_H__ */

View File

@ -308,8 +308,8 @@ namespace COP0 {
void MFC0()
{
// Note on _Rd_ Condition 9: CP0.Count should be updated even if _Rt_ is 0.
if( (_Rd_ != 9) && !_Rt_ ) return;
if(_Rd_ != 9) { COP0_LOG("%s", disR5900Current.getCString() ); }
if ((_Rd_ != 9) && !_Rt_ ) return;
if (_Rd_ != 9) { COP0_LOG("%s", disR5900Current.getCString() ); }
//if(bExecBIOS == FALSE && _Rd_ == 25) Console::WriteLn("MFC0 _Rd_ %x = %x", params _Rd_, cpuRegs.CP0.r[_Rd_]);
switch (_Rd_)
@ -412,30 +412,37 @@ int CPCOND0() {
//#define CPCOND0 1
#define BC0(cond) \
/*#define BC0(cond) \
if (CPCOND0() cond) { \
intDoBranch(_BranchTarget_); \
}
}*/
void BC0F() {
BC0(== 0);
if (CPCOND0() == 0) intDoBranch(_BranchTarget_);
}
void BC0T() {
BC0(== 1);
if (CPCOND0() == 1) intDoBranch(_BranchTarget_);
}
#define BC0L(cond) \
/*#define BC0L(cond) \
if (CPCOND0() cond) { \
intDoBranch(_BranchTarget_); \
} else cpuRegs.pc+= 4;
} else cpuRegs.pc+= 4;*/
void BC0FL() {
BC0L(== 0);
if (CPCOND0() == 0)
intDoBranch(_BranchTarget_);
else
cpuRegs.pc+= 4;
}
void BC0TL() {
BC0L(== 1);
if (CPCOND0() == 1)
intDoBranch(_BranchTarget_);
else
cpuRegs.pc+= 4;
}
void TLBR() {
@ -482,8 +489,7 @@ void TLBWR() {
void TLBP() {
int i;
union {
struct {
u32 VPN2:19;
@ -494,13 +500,13 @@ void TLBP() {
u32 u;
} EntryHi32;
EntryHi32.u=cpuRegs.CP0.n.EntryHi;
EntryHi32.u = cpuRegs.CP0.n.EntryHi;
cpuRegs.CP0.n.Index=0xFFFFFFFF;
for(i=0;i<48;i++){
if(tlb[i].VPN2==((~tlb[i].Mask)&(EntryHi32.s.VPN2))
&&((tlb[i].G&1)||((tlb[i].ASID & 0xff) == EntryHi32.s.ASID))) {
cpuRegs.CP0.n.Index=i;
if (tlb[i].VPN2 == ((~tlb[i].Mask) & (EntryHi32.s.VPN2))
&& ((tlb[i].G&1) || ((tlb[i].ASID & 0xff) == EntryHi32.s.ASID))) {
cpuRegs.CP0.n.Index = i;
break;
}
}

View File

@ -25,10 +25,6 @@
#include "VUops.h"
#include "VUmicro.h"
//namespace R5900 {
//namespace Interpreter {
//namespace OpcodeImpl{
using namespace R5900;
using namespace R5900::Interpreter;
@ -85,5 +81,3 @@ void BC2TL()
cpuRegs.pc+= 4;
}
}
//}}}

View File

@ -937,6 +937,34 @@ void psxDma3(u32 madr, u32 bcr, u32 chcr) {
psxDmaInterrupt(3);
}
#ifdef ENABLE_NEW_IOPDMA
s32 cdvdDmaRead(s32 channel, u32* data, u32 wordsLeft, u32* wordsProcessed)
{
// hacked up from the code above
if (cdr.Readed == 0)
{
//CDR_LOG("*** DMA 3 *** NOT READY");
wordsProcessed = 0;
return 10000;
}
memcpy_fast(data, cdr.pTransfer, wordsLeft);
//psxCpu->Clear(madr, cdsize/4);
cdr.pTransfer+=wordsLeft;
*wordsProcessed = wordsLeft;
Console::Status("New IOP DMA handled CDVD DMA: channel %d, data %p, remaining %08x, processed %08x.", params channel,data,wordsLeft, *wordsProcessed);
return 0;
}
void cdvdDmaInterrupt(s32 channel)
{
cdrInterrupt();
}
#endif
void cdrReset() {
memzero_obj(cdr);
cdr.CurTrack=1;

View File

@ -29,6 +29,8 @@
#define PCSX2_VERSION "(beta)"
#include "System.h"
#include "Plugins.h"
#include "SaveState.h"
@ -40,7 +42,4 @@
#include "Elfheader.h"
#include "Patch.h"
#include "System.h"
#include "Pcsx2Config.h"
#endif /* __COMMON_H__ */

190
pcsx2/Config.h Normal file
View File

@ -0,0 +1,190 @@
/* Pcsx2 - Pc Ps2 Emulator
* Copyright (C) 2002-2009 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
*/
#pragma once
class IniInterface;
//////////////////////////////////////////////////////////////////////////////////////////
// Pcsx2 Application Configuration.
//
// [TODO] : Rename this once we get to the point where the old Pcsx2Config stuff isn't in
// the way anymore. :)
//
class AppConfig
{
public:
struct ConsoleLogOptions
{
bool Visible;
// if true, DisplayPos is ignored and the console is automatically docked to the main window.
bool AutoDock;
// Display position used if AutoDock is false (ignored otherwise)
wxPoint DisplayPosition;
wxSize DisplaySize;
void LoadSave( IniInterface& conf );
};
struct FolderOptions
{
wxDirName Plugins;
wxDirName Bios;
wxDirName Snapshots;
wxDirName Savestates;
wxDirName MemoryCards;
wxDirName Dumps;
};
struct FilenameOptions
{
wxFileName Bios;
wxFileName CDVD;
wxFileName GS;
wxFileName PAD1;
wxFileName PAD2;
wxFileName SPU2;
wxFileName USB;
wxFileName FW;
wxFileName DEV9;
};
// Options struct for each memory card.
struct McdOptions
{
wxFileName Filename; // user-configured location of this memory card
bool Enabled; // memory card enabled (if false, memcard will not show up in-game)
};
struct McdSysOptions
{
McdOptions Mcd[2];
bool EnableNTFS; // enables automatic ntfs compression of memory cards (Win32 only)
bool EnableEjection; // enables simulated ejection of memory cards when loading savestates
void LoadSave( IniInterface& conf );
};
struct CpuRecompilerOptions
{
struct
{
bool
Enabled:1, // universal toggle for the profiler.
RecBlocks_EE:1, // Enables per-block profiling for the EE recompiler [unimplemented]
RecBlocks_IOP:1, // Enables per-block profiling for the IOP recompiler [unimplemented]
RecBlocks_VU1:1; // Enables per-block profiling for the VU1 recompiler [unimplemented]
} Profiler;
struct
{
bool
EnableEE:1,
EnableIOP:1,
EnableVU0:1,
EnableVU1:1;
} Recompiler;
void LoadSave( IniInterface& conf );
};
struct VideoOptions
{
bool MultithreadGS; // Uses the multithreaded GS interface.
bool closeOnEsc; // Closes the GS/Video port on escape (good for fullscreen activity)
bool UseFramelimiter;
int RegionMode; // 0=NTSC and 1=PAL
int CustomFps;
int CustomFrameSkip;
int CustomConsecutiveFrames;
int CustomConsecutiveSkip;
void LoadSave( IniInterface& conf );
};
struct GamefixOptions
{
bool
VuAddSubHack:1, // Fix for Tri-ace games, they use an encryption algorithm that requires VU addi opcode to be bit-accurate.
VuClipFlagHack:1, // Fix for Digimon Rumble Arena 2, fixes spinning/hanging on intro-menu.
FpuCompareHack:1, // Fix for Persona games, maybe others. It's to do with the VU clip flag (again).
FpuMulHack:1; // Fix for Tales of Destiny hangs.
void LoadSave();
};
struct SpeedhackOptions
{
int
EECycleRate:3, // EE cyclerate selector (1.0, 1.5, 2.0, 3.0)
IopCycleRate_X2:1, // enables the x2 multiplier of the IOP cyclerate
ExtWaitcycles:1, // enables extended waitcycles duration
IntcStat:1; // tells Pcsx2 to fast-forward through intc_stat waits.
void LoadSave( IniInterface& conf );
};
// Helper functions for returning full pathnames of various Folders and files
struct FullpathHelpers
{
FullpathHelpers( const AppConfig& conf ) : m_conf( conf ) {}
const AppConfig& m_conf;
wxString Bios() const;
wxString CDVD() const;
wxString GS() const;
wxString PAD1() const;
wxString PAD2() const;
wxString SPU2() const;
wxString DEV9() const;
wxString USB() const;
wxString FW() const;
wxString Mcd( uint mcdidx ) const;
};
public:
AppConfig() : Files( *this )
{
}
FullpathHelpers Files;
wxPoint MainGuiPosition;
bool CdvdVerboseReads; // enables cdvd read activity verbosely dumped to the console
CpuRecompilerOptions Cpu;
SpeedhackOptions Speedhacks;
GamefixOptions Gamefixes;
VideoOptions Video;
ConsoleLogOptions ConLogBox;
FolderOptions Folders;
FilenameOptions BaseFilenames;
McdSysOptions MemoryCards;
public:
void LoadSave( IniInterface& ini );
};
extern AppConfig g_Conf;

View File

@ -36,6 +36,7 @@ namespace Console
MutexLock m_writelock;
std::string m_format_buffer;
// ------------------------------------------------------------------------
void __fastcall SetTitle( const wxString& title )
{
ConsoleLogFrame* FrameHandle = wxGetApp().GetConsoleFrame();
@ -43,6 +44,7 @@ namespace Console
FrameHandle->SetTitle( title );
}
// ------------------------------------------------------------------------
void __fastcall SetColor( Colors color )
{
ConsoleLogFrame* FrameHandle = wxGetApp().GetConsoleFrame();
@ -57,6 +59,7 @@ namespace Console
FrameHandle->ClearColor();
}
// ------------------------------------------------------------------------
bool Newline()
{
ConsoleLogFrame* FrameHandle = wxGetApp().GetConsoleFrame();
@ -67,6 +70,7 @@ namespace Console
return false;
}
// ------------------------------------------------------------------------
bool __fastcall Write( const char* fmt )
{
ConsoleLogFrame* FrameHandle = wxGetApp().GetConsoleFrame();
@ -91,8 +95,34 @@ namespace Console
return false;
}
// Writes an unformatted string of text to the console (fast!)
// A newline is automatically appended.
// ------------------------------------------------------------------------
bool __fastcall Write( const wxString& fmt )
{
ConsoleLogFrame* FrameHandle = wxGetApp().GetConsoleFrame();
if( FrameHandle != NULL )
FrameHandle->Write( fmt );
wxCharBuffer jones( fmt.ToAscii() );
fwrite( fmt, 1, strlen( jones.data() ), emuLog );
return false;
}
bool __fastcall Write( Colors color, const wxString& fmt )
{
ConsoleLogFrame* FrameHandle = wxGetApp().GetConsoleFrame();
if( FrameHandle != NULL )
{
FrameHandle->SetColor( color );
FrameHandle->Write( fmt );
FrameHandle->ClearColor();
}
wxCharBuffer jones( fmt.ToAscii() );
fwrite( fmt, 1, strlen( jones.data() ), emuLog );
return false;
}
// ------------------------------------------------------------------------
bool __fastcall WriteLn( const char* fmt )
{
ConsoleLogFrame* FrameHandle = wxGetApp().GetConsoleFrame();
@ -106,8 +136,6 @@ namespace Console
return false;
}
// Writes an unformatted string of text to the console (fast!)
// A newline is automatically appended.
bool __fastcall WriteLn( Colors color, const char* fmt )
{
ConsoleLogFrame* FrameHandle = wxGetApp().GetConsoleFrame();
@ -123,6 +151,38 @@ namespace Console
return false;
}
// ------------------------------------------------------------------------
bool __fastcall WriteLn( const wxString& fmt )
{
ConsoleLogFrame* FrameHandle = wxGetApp().GetConsoleFrame();
if( FrameHandle != NULL )
{
FrameHandle->Write( fmt.c_str() );
FrameHandle->Newline();
}
wxCharBuffer jones( fmt.ToAscii() );
fputs( jones.data(), emuLog );
return false;
}
bool __fastcall WriteLn( Colors color, const wxString& fmt )
{
ConsoleLogFrame* FrameHandle = wxGetApp().GetConsoleFrame();
if( FrameHandle != NULL )
{
FrameHandle->SetColor( color );
FrameHandle->Write( fmt );
FrameHandle->Newline();
FrameHandle->ClearColor();
}
wxCharBuffer jones( fmt.ToAscii() );
fputs( jones.data(), emuLog );
return false;
}
// ------------------------------------------------------------------------
__forceinline void __fastcall _WriteLn( Colors color, const char* fmt, va_list args )
{
ConsoleLogFrame* FrameHandle = wxGetApp().GetConsoleFrame();
@ -147,12 +207,13 @@ namespace Console
if( color == Color_Red || color == Color_Yellow )
fputs( cstr, stderr ); // log notices and errors to stderr
wxASSERT_MSG( 0, cstr );
wxASSERT_MSG_A( 0, cstr );
}
fputs( cstr, emuLog );
}
// ------------------------------------------------------------------------
bool Write( const char* fmt, VARG_PARAM dummy, ... )
{
varg_assert();
@ -184,6 +245,7 @@ namespace Console
return false;
}
// ------------------------------------------------------------------------
bool WriteLn( const char* fmt, VARG_PARAM dummy, ... )
{
varg_assert();
@ -198,7 +260,7 @@ namespace Console
return false;
}
// Writes a line of colored text to the console, with automatic newline appendage.
// ------------------------------------------------------------------------
bool WriteLn( Colors color, const char* fmt, VARG_PARAM dummy, ... )
{
varg_assert();
@ -210,8 +272,7 @@ namespace Console
return false;
}
// Displays a message in the console with red emphasis.
// Newline is automatically appended.
// ------------------------------------------------------------------------
bool Error( const char* fmt, VARG_PARAM dummy, ... )
{
varg_assert();
@ -223,8 +284,7 @@ namespace Console
return false;
}
// Displays a message in the console with yellow emphasis.
// Newline is automatically appended.
// ------------------------------------------------------------------------
bool Notice( const char* fmt, VARG_PARAM dummy, ... )
{
varg_assert();
@ -236,8 +296,7 @@ namespace Console
return false;
}
// Displays a message in the console with green emphasis.
// Newline is automatically appended.
// ------------------------------------------------------------------------
bool Status( const char* fmt, VARG_PARAM dummy, ... )
{
varg_assert();
@ -249,57 +308,57 @@ namespace Console
return false;
}
// Displays a message in the console with red emphasis.
// Newline is automatically appended.
// ------------------------------------------------------------------------
bool __fastcall Error( const char* fmt )
{
WriteLn( Color_Red, fmt );
return false;
}
// Displays a message in the console with yellow emphasis.
// Newline is automatically appended.
bool __fastcall Notice( const char* fmt )
{
WriteLn( Color_Yellow, fmt );
return false;
}
// Displays a message in the console with green emphasis.
// Newline is automatically appended.
bool __fastcall Status( const char* fmt )
{
WriteLn( Color_Green, fmt );
return false;
}
// ------------------------------------------------------------------------
bool __fastcall Error( const wxString& src )
{
WriteLn( Color_Red, src );
return false;
}
bool __fastcall Notice( const wxString& src )
{
WriteLn( Color_Yellow, src );
return false;
}
bool __fastcall Status( const wxString& src )
{
WriteLn( Color_Green, src );
return false;
}
}
namespace Msgbox
{
bool Alert(const char* text)
bool Alert( const wxString& text )
{
wxMessageBox( text, "Pcsx2 Message", wxOK, wxGetApp().GetTopWindow() );
wxMessageBox( text, wxT("Pcsx2 Message"), wxOK, wxGetApp().GetTopWindow() );
return false;
}
bool Alert(const char* fmt, VARG_PARAM dummy, ...)
bool OkCancel( const wxString& text )
{
va_list list;
va_start(list, dummy);
Alert( vfmt_string( fmt, list ).c_str() );
va_end(list);
return false;
}
bool OkCancel( const char* fmt, VARG_PARAM dummy, ... )
{
va_list list;
va_start(list, dummy);
int result = wxMessageBox( vfmt_string( fmt, list ), "Pcsx2 Message", wxOK | wxCANCEL, wxGetApp().GetTopWindow() );
va_end(list);
return result == wxOK;
int result = wxMessageBox( text, wxT("Pcsx2 Message"), wxOK | wxCANCEL, wxGetApp().GetTopWindow() );
return result == wxOK;
}
}

View File

@ -164,7 +164,7 @@ struct vSyncTimingInfo
static vSyncTimingInfo vSyncInfo;
static __forceinline void vSyncInfoCalc( vSyncTimingInfo* info, u32 framesPerSecond, u32 scansPerFrame )
static void vSyncInfoCalc( vSyncTimingInfo* info, u32 framesPerSecond, u32 scansPerFrame )
{
// Important: Cannot use floats or doubles here. The emulator changes rounding modes
// depending on user-set speedhack options, and it can break float/double code
@ -270,8 +270,6 @@ u32 UpdateVSyncRate()
return (u32)m_iTicks;
}
extern u32 vu0time;
void frameLimitReset()
{
m_iStart = GetCPUTicks();
@ -282,13 +280,13 @@ void frameLimitReset()
// See the GS FrameSkip function for details on why this is here and not in the GS.
static __forceinline void frameLimit()
{
if( CHECK_FRAMELIMIT == PCSX2_FRAMELIMIT_NORMAL ) return;
if( Config.CustomFps >= 999 ) return; // means the user would rather just have framelimiting turned off...
s64 sDeltaTime;
u64 uExpectedEnd;
u64 iEnd;
if( CHECK_FRAMELIMIT == PCSX2_FRAMELIMIT_NORMAL ) return;
if( Config.CustomFps >= 999 ) return; // means the user would rather just have framelimiting turned off...
uExpectedEnd = m_iStart + m_iTicks;
iEnd = GetCPUTicks();
@ -465,7 +463,7 @@ __forceinline bool rcntUpdate_vSync()
return false;
}
static __forceinline void __fastcall _cpuTestTarget( int i )
static __forceinline void _cpuTestTarget( int i )
{
if (counters[i].count < counters[i].target) return;
@ -538,7 +536,7 @@ __forceinline bool rcntUpdate()
return retval;
}
static void _rcntSetGate( int index )
static __forceinline void _rcntSetGate( int index )
{
if (counters[index].mode.EnableGate)
{
@ -563,7 +561,7 @@ static void _rcntSetGate( int index )
}
// mode - 0 means hblank source, 8 means vblank source.
void __fastcall rcntStartGate(bool isVblank, u32 sCycle)
__forceinline void rcntStartGate(bool isVblank, u32 sCycle)
{
int i;
@ -624,7 +622,7 @@ void __fastcall rcntStartGate(bool isVblank, u32 sCycle)
}
// mode - 0 means hblank signal, 8 means vblank signal.
void __fastcall rcntEndGate(bool isVblank , u32 sCycle)
__forceinline void rcntEndGate(bool isVblank , u32 sCycle)
{
int i;
@ -665,7 +663,7 @@ void __fastcall rcntEndGate(bool isVblank , u32 sCycle)
// rcntUpdate, since we're being called from there anyway.
}
void __fastcall rcntWmode(int index, u32 value)
__forceinline void rcntWmode(int index, u32 value)
{
if(counters[index].mode.IsCounting) {
if(counters[index].mode.ClockSource != 0x3) {
@ -696,7 +694,7 @@ void __fastcall rcntWmode(int index, u32 value)
_rcntSet( index );
}
void __fastcall rcntWcount(int index, u32 value)
__forceinline void rcntWcount(int index, u32 value)
{
EECNT_LOG("EE Counter[%d] writeCount = %x, oldcount=%x, target=%x", index, value, counters[index].count, counters[index].target );
@ -722,7 +720,7 @@ void __fastcall rcntWcount(int index, u32 value)
_rcntSet( index );
}
void __fastcall rcntWtarget(int index, u32 value)
__forceinline void rcntWtarget(int index, u32 value)
{
EECNT_LOG("EE Counter[%d] writeTarget = %x", index, value);
@ -738,13 +736,13 @@ void __fastcall rcntWtarget(int index, u32 value)
_rcntSet( index );
}
void __fastcall rcntWhold(int index, u32 value)
__forceinline void rcntWhold(int index, u32 value)
{
EECNT_LOG("EE Counter[%d] Hold Write = %x", index, value);
counters[index].hold = value;
}
u32 __fastcall rcntRcount(int index)
__forceinline u32 rcntRcount(int index)
{
u32 ret;
@ -759,7 +757,7 @@ u32 __fastcall rcntRcount(int index)
return ret;
}
u32 __fastcall rcntCycle(int index)
__forceinline u32 rcntCycle(int index)
{
if (counters[index].mode.IsCounting && (counters[index].mode.ClockSource != 0x3))
return counters[index].count + ((cpuRegs.cycle - counters[index].sCycleT) / counters[index].rate);

View File

@ -139,14 +139,14 @@ extern bool rcntUpdate_vSync();
extern bool rcntUpdate();
extern void rcntInit();
extern void __fastcall rcntStartGate(bool mode, u32 sCycle);
extern void __fastcall rcntEndGate(bool mode, u32 sCycle);
extern void __fastcall rcntWcount(int index, u32 value);
extern void __fastcall rcntWmode(int index, u32 value);
extern void __fastcall rcntWtarget(int index, u32 value);
extern void __fastcall rcntWhold(int index, u32 value);
extern u32 __fastcall rcntRcount(int index);
extern u32 __fastcall rcntCycle(int index);
extern void rcntStartGate(bool mode, u32 sCycle);
extern void rcntEndGate(bool mode, u32 sCycle);
extern void rcntWcount(int index, u32 value);
extern void rcntWmode(int index, u32 value);
extern void rcntWtarget(int index, u32 value);
extern void rcntWhold(int index, u32 value);
extern u32 rcntRcount(int index);
extern u32 rcntCycle(int index);
u32 UpdateVSyncRate();
void frameLimitReset();

View File

@ -216,6 +216,8 @@ extern bool SrcLog_GPU( const char* fmt, ... );
#define MEMCARDS_LOG 0&&
#endif
//#define VIFUNPACKDEBUG //enable unpack debugging output
#ifdef VIFUNPACKDEBUG
#define VIFUNPACK_LOG VIF_LOG
#else

View File

@ -606,7 +606,7 @@ void (*COP2SPECIAL2PrintTable[128])( string& output ) =
//**************************TABLES CALLS***********************
void disR5900Fasm(string& output, u32 code, u32 pc)
void disR5900Fasm( string& output, u32 code, u32 pc )
{
string dbuf;
char obuf[48];

303
pcsx2/Dump.cpp Normal file
View File

@ -0,0 +1,303 @@
/* Pcsx2 - Pc Ps2 Emulator
* Copyright (C) 2002-2009 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
*/
////////////////////////////////////////////////////
#include "PrecompiledHeader.h"
#include "IopCommon.h"
#include "Counters.h"
#include "iCore.h"
#include "iR5900.h"
#include "IPU/IPU.h"
using namespace R5900;
// fixme: currently should not be uncommented.
//#define TEST_BROKEN_DUMP_ROUTINES
#ifdef TEST_BROKEN_DUMP_ROUTINES
//extern u32 psxdump;
//extern int rdram_devices; // put 8 for TOOL and 2 for PS2 and PSX
//extern int rdram_sdevid;
extern tIPU_BP g_BP;
#define VF_VAL(x) ((x==0x80000000)?0:(x))
#endif
// iR5900-32.cpp
extern EEINST* s_pInstCache;
extern u32 s_nEndBlock; // what pc the current block ends
void iDumpPsxRegisters(u32 startpc, u32 temp)
{
// [TODO] fixme : thie code is broken and has no labels. Needs a rewrite to be useful.
#ifdef TEST_BROKEN_DUMP_ROUTINES
int i;
const char* pstr = temp ? "t" : "";
// fixme: PSXM doesn't exist any more.
//__Log("%spsxreg: %x %x ra:%x k0: %x %x", pstr, startpc, psxRegs.cycle, psxRegs.GPR.n.ra, psxRegs.GPR.n.k0, *(int*)PSXM(0x13c128));
for(i = 0; i < 34; i+=2) __Log("%spsx%s: %x %x", pstr, disRNameGPR[i], psxRegs.GPR.r[i], psxRegs.GPR.r[i+1]);
__Log("%scycle: %x %x %x; counters %x %x", pstr, psxRegs.cycle, g_psxNextBranchCycle, EEsCycle,
psxNextsCounter, psxNextCounter);
__Log("psxdma%d c%x b%x m%x t%x", 2, HW_DMA2_CHCR, HW_DMA2_BCR, HW_DMA2_MADR, HW_DMA2_TADR);
__Log("psxdma%d c%x b%x m%x", 3, HW_DMA3_CHCR, HW_DMA3_BCR, HW_DMA3_MADR);
__Log("psxdma%d c%x b%x m%x t%x", 4, HW_DMA4_CHCR, HW_DMA4_BCR, HW_DMA4_MADR, HW_DMA4_TADR);
__Log("psxdma%d c%x b%x m%x", 6, HW_DMA6_CHCR, HW_DMA6_BCR, HW_DMA6_MADR);
__Log("psxdma%d c%x b%x m%x", 7, HW_DMA7_CHCR, HW_DMA7_BCR, HW_DMA7_MADR);
__Log("psxdma%d c%x b%x m%x", 8, HW_DMA8_CHCR, HW_DMA8_BCR, HW_DMA8_MADR);
__Log("psxdma%d c%x b%x m%x t%x", 9, HW_DMA9_CHCR, HW_DMA9_BCR, HW_DMA9_MADR, HW_DMA9_TADR);
__Log("psxdma%d c%x b%x m%x", 10, HW_DMA10_CHCR, HW_DMA10_BCR, HW_DMA10_MADR);
__Log("psxdma%d c%x b%x m%x", 11, HW_DMA11_CHCR, HW_DMA11_BCR, HW_DMA11_MADR);
__Log("psxdma%d c%x b%x m%x", 12, HW_DMA12_CHCR, HW_DMA12_BCR, HW_DMA12_MADR);
for(i = 0; i < 7; ++i)
__Log("%scounter%d: mode %x count %I64x rate %x scycle %x target %I64x", pstr, i, psxCounters[i].mode, psxCounters[i].count, psxCounters[i].rate, psxCounters[i].sCycleT, psxCounters[i].target);
#endif
}
void iDumpRegisters(u32 startpc, u32 temp)
{
// [TODO] fixme : this code is broken and has no labels. Needs a rewrite to be useful.
#ifdef TEST_BROKEN_DUMP_ROUTINES
int i;
const char* pstr;// = temp ? "t" : "";
const u32 dmacs[] = {0x8000, 0x9000, 0xa000, 0xb000, 0xb400, 0xc000, 0xc400, 0xc800, 0xd000, 0xd400 };
const char* psymb;
if (temp)
pstr = "t";
else
pstr = "";
psymb = disR5900GetSym(startpc);
if( psymb != NULL )
__Log("%sreg(%s): %x %x c:%x", pstr, psymb, startpc, cpuRegs.interrupt, cpuRegs.cycle);
else
__Log("%sreg: %x %x c:%x", pstr, startpc, cpuRegs.interrupt, cpuRegs.cycle);
for(i = 1; i < 32; ++i) __Log("%s: %x_%x_%x_%x", disRNameGPR[i], cpuRegs.GPR.r[i].UL[3], cpuRegs.GPR.r[i].UL[2], cpuRegs.GPR.r[i].UL[1], cpuRegs.GPR.r[i].UL[0]);
//for(i = 0; i < 32; i+=4) __Log("cp%d: %x_%x_%x_%x", i, cpuRegs.CP0.r[i], cpuRegs.CP0.r[i+1], cpuRegs.CP0.r[i+2], cpuRegs.CP0.r[i+3]);
//for(i = 0; i < 32; ++i) __Log("%sf%d: %f %x", pstr, i, fpuRegs.fpr[i].f, fpuRegs.fprc[i]);
//for(i = 1; i < 32; ++i) __Log("%svf%d: %f %f %f %f, vi: %x", pstr, i, VU0.VF[i].F[3], VU0.VF[i].F[2], VU0.VF[i].F[1], VU0.VF[i].F[0], VU0.VI[i].UL);
for(i = 0; i < 32; ++i) __Log("%sf%d: %x %x", pstr, i, fpuRegs.fpr[i].UL, fpuRegs.fprc[i]);
for(i = 1; i < 32; ++i) __Log("%svf%d: %x %x %x %x, vi: %x", pstr, i, VU0.VF[i].UL[3], VU0.VF[i].UL[2], VU0.VF[i].UL[1], VU0.VF[i].UL[0], VU0.VI[i].UL);
__Log("%svfACC: %x %x %x %x", pstr, VU0.ACC.UL[3], VU0.ACC.UL[2], VU0.ACC.UL[1], VU0.ACC.UL[0]);
__Log("%sLO: %x_%x_%x_%x, HI: %x_%x_%x_%x", pstr, cpuRegs.LO.UL[3], cpuRegs.LO.UL[2], cpuRegs.LO.UL[1], cpuRegs.LO.UL[0],
cpuRegs.HI.UL[3], cpuRegs.HI.UL[2], cpuRegs.HI.UL[1], cpuRegs.HI.UL[0]);
__Log("%sCycle: %x %x, Count: %x", pstr, cpuRegs.cycle, g_nextBranchCycle, cpuRegs.CP0.n.Count);
iDumpPsxRegisters(psxRegs.pc, temp);
__Log("f410,30,40: %x %x %x, %d %d", psHu32(0xf410), psHu32(0xf430), psHu32(0xf440), rdram_sdevid, rdram_devices);
__Log("cyc11: %x %x; vu0: %x, vu1: %x", cpuRegs.sCycle[1], cpuRegs.eCycle[1], VU0.cycle, VU1.cycle);
__Log("%scounters: %x %x; psx: %x %x", pstr, nextsCounter, nextCounter, psxNextsCounter, psxNextCounter);
// fixme: The members of the counters[i] struct are wrong here.
/*for(i = 0; i < 4; ++i) {
__Log("eetimer%d: count: %x mode: %x target: %x %x; %x %x; %x %x %x %x", i,
counters[i].count, counters[i].mode, counters[i].target, counters[i].hold, counters[i].rate,
counters[i].interrupt, counters[i].Cycle, counters[i].sCycle, counters[i].CycleT, counters[i].sCycleT);
}*/
__Log("VIF0_STAT = %x, VIF1_STAT = %x", psHu32(0x3800), psHu32(0x3C00));
__Log("ipu %x %x %x %x; bp: %x %x %x %x", psHu32(0x2000), psHu32(0x2010), psHu32(0x2020), psHu32(0x2030), g_BP.BP, g_BP.bufferhasnew, g_BP.FP, g_BP.IFC);
__Log("gif: %x %x %x", psHu32(0x3000), psHu32(0x3010), psHu32(0x3020));
for(i = 0; i < ArraySize(dmacs); ++i) {
DMACh* p = (DMACh*)(PS2MEM_HW+dmacs[i]);
__Log("dma%d c%x m%x q%x t%x s%x", i, p->chcr, p->madr, p->qwc, p->tadr, p->sadr);
}
__Log("dmac %x %x %x %x", psHu32(DMAC_CTRL), psHu32(DMAC_STAT), psHu32(DMAC_RBSR), psHu32(DMAC_RBOR));
__Log("intc %x %x", psHu32(INTC_STAT), psHu32(INTC_MASK));
__Log("sif: %x %x %x %x %x", psHu32(0xf200), psHu32(0xf220), psHu32(0xf230), psHu32(0xf240), psHu32(0xf260));
#endif
}
void iDumpVU0Registers()
{
// fixme: This code is outdated, broken, and lacks printed labels.
// Needs heavy mods to be useful.
#ifdef TEST_BROKEN_DUMP_ROUTINES
int i;
for(i = 1; i < 32; ++i) {
__Log("v%d: %x %x %x %x, vi: ", i, VF_VAL(VU0.VF[i].UL[3]), VF_VAL(VU0.VF[i].UL[2]),
VF_VAL(VU0.VF[i].UL[1]), VF_VAL(VU0.VF[i].UL[0]));
if( i == REG_Q || i == REG_P )
__Log("%f\n", VU0.VI[i].F);
else if( i == REG_MAC_FLAG )
__Log("%x\n", 0);//VU0.VI[i].UL&0xff);
else if( i == REG_STATUS_FLAG )
__Log("%x\n", 0);//VU0.VI[i].UL&0x03);
else if( i == REG_CLIP_FLAG )
__Log("0\n");
else
__Log("%x\n", VU0.VI[i].UL);
}
__Log("vfACC: %f %f %f %f\n", VU0.ACC.F[3], VU0.ACC.F[2], VU0.ACC.F[1], VU0.ACC.F[0]);
#endif
}
void iDumpVU1Registers()
{
// fixme: This code is outdated, broken, and lacks printed labels.
// Needs heavy mods to be useful.
#ifdef TEST_BROKEN_DUMP_ROUTINES
int i;
// static int icount = 0;
// __Log("%x\n", icount);
for(i = 1; i < 32; ++i) {
// __Log("v%d: w%f(%x) z%f(%x) y%f(%x) x%f(%x), vi: ", i, VU1.VF[i].F[3], VU1.VF[i].UL[3], VU1.VF[i].F[2], VU1.VF[i].UL[2],
// VU1.VF[i].F[1], VU1.VF[i].UL[1], VU1.VF[i].F[0], VU1.VF[i].UL[0]);
//__Log("v%d: %f %f %f %f, vi: ", i, VU1.VF[i].F[3], VU1.VF[i].F[2], VU1.VF[i].F[1], VU1.VF[i].F[0]);
__Log("v%d: %x %x %x %x, vi: ", i, VF_VAL(VU1.VF[i].UL[3]), VF_VAL(VU1.VF[i].UL[2]), VF_VAL(VU1.VF[i].UL[1]), VF_VAL(VU1.VF[i].UL[0]));
if( i == REG_Q || i == REG_P ) __Log("%f\n", VU1.VI[i].F);
//else __Log("%x\n", VU1.VI[i].UL);
else __Log("%x\n", (i==REG_STATUS_FLAG||i==REG_MAC_FLAG||i==REG_CLIP_FLAG)?0:VU1.VI[i].UL);
}
__Log("vfACC: %f %f %f %f\n", VU1.ACC.F[3], VU1.ACC.F[2], VU1.ACC.F[1], VU1.ACC.F[0]);
#endif
}
#ifdef PCSX2_DEVBUILD
// and not sure what these might have once been used for... (air)
//static const char *txt0 = "EAX = %x : ECX = %x : EDX = %x\n";
//static const char *txt0RC = "EAX = %x : EBX = %x : ECX = %x : EDX = %x : ESI = %x : EDI = %x\n";
//static const char *txt1 = "REG[%d] = %x_%x\n";
//static const char *txt2 = "M32 = %x\n";
#endif
////////////////////////////////////////////////////
#include "Utilities/AsciiFile.h"
// Originally from iR5900-32.cpp
void iDumpBlock( int startpc, u8 * ptr )
{
u8 used[34];
u8 fpuused[33];
int numused, fpunumused;
Console::Status( "dump1 %x:%x, %x", params startpc, pc, cpuRegs.cycle );
g_Conf.Folders.Dumps.Mkdir();
AsciiFile eff(
Path::Combine( g_Conf.Folders.Dumps, wxsFormat(wxT("R5900dump%.8X.txt"), startpc) ),
wxFile::write
);
if( disR5900GetSym(startpc) != NULL )
{
eff.Printf( disR5900GetSym( startpc ) );
eff.Printf( "\n" );
}
for ( uint i = startpc; i < s_nEndBlock; i += 4 )
{
string output;
disR5900Fasm( output, memRead32( i ), i );
eff.Printf( output.c_str() );
}
// write the instruction info
eff.Printf( "\n\nlive0 - %x, live1 - %x, live2 - %x, lastuse - %x\nmmx - %x, xmm - %x, used - %x\n",
EEINST_LIVE0, EEINST_LIVE1, EEINST_LIVE2, EEINST_LASTUSE, EEINST_MMX, EEINST_XMM, EEINST_USED
);
memzero_obj(used);
numused = 0;
for(uint i = 0; i < ArraySize(s_pInstCache->regs); ++i) {
if( s_pInstCache->regs[i] & EEINST_USED ) {
used[i] = 1;
numused++;
}
}
memzero_obj(fpuused);
fpunumused = 0;
for(uint i = 0; i < ArraySize(s_pInstCache->fpuregs); ++i) {
if( s_pInstCache->fpuregs[i] & EEINST_USED ) {
fpuused[i] = 1;
fpunumused++;
}
}
eff.Printf( " " );
for(uint i = 0; i < ArraySize(s_pInstCache->regs); ++i) {
if( used[i] ) eff.Printf( "%2d ", i );
}
eff.Printf( "\n" );
for(uint i = 0; i < ArraySize(s_pInstCache->fpuregs); ++i) {
if( fpuused[i] ) eff.Printf( "%2d ", i );
}
eff.Printf( "\n" );
eff.Printf( " " );
// TODO : Finish converting this over to wxWidgers wxFile stuff...
/*
int count;
EEINST* pcur;
for(uint i = 0; i < ArraySize(s_pInstCache->regs); ++i) {
if( used[i] ) fprintf(f, "%s ", disRNameGPR[i]);
}
for(uint i = 0; i < ArraySize(s_pInstCache->fpuregs); ++i) {
if( fpuused[i] ) fprintf(f, "%s ", i<32?"FR":"FA");
}
fprintf(f, "\n");
pcur = s_pInstCache+1;
for( uint i = 0; i < (s_nEndBlock-startpc)/4; ++i, ++pcur) {
fprintf(f, "%2d: %2.2x ", i+1, pcur->info);
count = 1;
for(uint j = 0; j < ArraySize(s_pInstCache->regs); j++) {
if( used[j] ) {
fprintf(f, "%2.2x%s", pcur->regs[j], ((count%8)&&count<numused)?"_":" ");
++count;
}
}
count = 1;
for(uint j = 0; j < ArraySize(s_pInstCache->fpuregs); j++) {
if( fpuused[j] ) {
fprintf(f, "%2.2x%s", pcur->fpuregs[j], ((count%8)&&count<fpunumused)?"_":" ");
++count;
}
}
fprintf(f, "\n");
}
fclose( f );*/
}

26
pcsx2/Dump.h Normal file
View File

@ -0,0 +1,26 @@
/* Pcsx2 - Pc Ps2 Emulator
* Copyright (C) 2002-2009 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
*/
#pragma once
extern void iDumpRegisters(u32 startpc, u32 temp);
extern void iDumpPsxRegisters(u32 startpc, u32 temp);
extern void iDumpVU0Registers();
extern void iDumpVU1Registers();
extern void iDumpBlock( int startpc, u8 * ptr );
extern void iIopDumpBlock( int startpc, u8 * ptr );

View File

@ -127,6 +127,12 @@ struct Elf32_Rel {
u32 r_info;
};
#if 0
// fixme: ELF command line option system.
// It parses a command line and pastes it into PS2 memory, and then points the a0 register at it.
// A user-written ELF can then load the data and respond accordingly. Needs a rewrite using modern
// string parsing utils. :)
//2002-09-19 (Florin)
char args[256]="ez.m2v"; //to be accessed by other files
uptr args_ptr; //a big value; in fact, it is an address
@ -142,7 +148,7 @@ uptr args_ptr; //a big value; in fact, it is an address
//+08+4*argc the program name(first param) <--
//+08+4*argc+strlen(argv[0]+1) the rest of params; i.e. a copy of 'args'
// see above 'char args[256];'
static uint parseCommandLine( const char *filename )
static uint parseCommandLine( const wxString& filename )
{
if ( ( args_ptr != 0xFFFFFFFF ) && ( args_ptr > 264 ) )
{ // 4 + 4 + 256
@ -209,11 +215,12 @@ static uint parseCommandLine( const char *filename )
return 0;
}
#endif
//---------------
struct ElfObject
{
string filename;
wxString filename;
SafeArray<u8> data;
ELF_HEADER& header;
ELF_PHR* proghead;
@ -223,7 +230,7 @@ struct ElfObject
// C++ does all the cleanup automagically for us.
~ElfObject() { }
ElfObject( const string& srcfile, uint hdrsize ) :
ElfObject( const wxString& srcfile, uint hdrsize ) :
filename( srcfile )
, data( hdrsize, "ELF headers" )
, header( *(ELF_HEADER*)data.GetPtr() )
@ -296,10 +303,11 @@ struct ElfObject
void readFile()
{
int rsize = 0;
if ((strnicmp( filename.c_str(), "cdrom0:", strlen("cdromN:")) == 0) ||
(strnicmp( filename.c_str(), "cdrom1:", strlen("cdromN:")) == 0))
const wxCharBuffer work( filename.ToAscii() );
if ((strnicmp( work.data(), "cdrom0:", strlen("cdromN:")) == 0) ||
(strnicmp( work.data(), "cdrom1:", strlen("cdromN:")) == 0))
{
int fi = CDVDFS_open(filename.c_str() + strlen("cdromN:"), 1);//RDONLY
int fi = CDVDFS_open(work.data() + strlen("cdromN:"), 1);//RDONLY
if (fi < 0) throw Exception::FileNotFound( filename );
@ -311,7 +319,7 @@ struct ElfObject
{
FILE *f;
f = fopen( filename.c_str(), "rb" );
f = fopen( work.data(), "rb" );
if( f == NULL ) Exception::FileNotFound( filename );
fseek( f, 0, SEEK_SET );
@ -404,8 +412,9 @@ struct ElfObject
{
ELF_LOG( "Elf32 Section Header [%x] %s", i, &sections_names[ secthead[ i ].sh_name ] );
if ( secthead[i].sh_flags & 0x2 )
args_ptr = min( args_ptr, secthead[ i ].sh_addr & 0x1ffffff );
// used by parseCommandLine
//if ( secthead[i].sh_flags & 0x2 )
// args_ptr = min( args_ptr, secthead[ i ].sh_addr & 0x1ffffff );
#ifdef PCSX2_DEVBULD
ELF_LOG("\n");
@ -462,21 +471,20 @@ struct ElfObject
void ElfApplyPatches()
{
string filename;
ssprintf( filename, "%8.8x", ElfCRC );
wxString filename( wxsFormat( wxT("%8.8x"), ElfCRC ) );
// if patches found the following status msg will be overwritten
Console::SetTitle( fmt_string( "Game running [CRC=%hs]", &filename ) );
Console::SetTitle( wxsFormat( _("Game running [CRC=%s]"), filename.c_str() ) );
if( !Config.Patch ) return;
if(LoadPatch( filename ) != 0)
{
Console::WriteLn("XML Loader returned an error. Trying to load a pnach...");
inifile_read( filename.c_str() );
Console::WriteLn( "XML Loader returned an error. Trying to load a pnach..." );
inifile_read( filename.ToAscii().data() );
}
else
Console::WriteLn("XML Loading success. Will not load from pnach...");
Console::WriteLn( "XML Loading success. Will not load from pnach..." );
applypatch( 0 );
}
@ -491,20 +499,20 @@ u32 loadElfCRC( const char* filename )
return 0;
DevCon::Status( "loadElfFile: %d bytes", params toc.fileSize );
u32 crcval = ElfObject( filename, toc.fileSize ).GetCRC();
u32 crcval = ElfObject( wxString::FromAscii( filename ), toc.fileSize ).GetCRC();
Console::Status( "loadElfFile: %s; CRC = %8.8X", params filename, crcval );
return crcval;
}
int loadElfFile(const char *filename)
int loadElfFile(const wxString& filename)
{
// Reset all recompilers prior to initiating a BIOS or new ELF. The cleaner the
// slate, the happier the recompiler!
SysClearExecutionCache();
if( filename == NULL || filename[0] == 0 )
if( filename.IsEmpty() )
{
Console::Notice( "Running the PS2 BIOS..." );
return -1;
@ -514,35 +522,42 @@ int loadElfFile(const char *filename)
cpuExecuteBios();
int elfsize;
Console::Status( wxsFormat( L"loadElfFile: %s", filename.c_str() ) );
Console::Status("loadElfFile: %s", params filename);
if (strnicmp( filename, "cdrom0:", strlen( "cdromN:" ) ) &&
strnicmp( filename, "cdrom1:", strlen( "cdromN:" ) ) )
const wxCharBuffer buffer( filename.ToAscii() );
const char* fnptr = buffer.data();
if( !filename.StartsWith( L"cdrom0:" ) && !filename.StartsWith( L"cdrom1:" ) )
{
// Loading from a file (or non-cd image)
struct stat sbuf;
if ( stat( filename, &sbuf ) != 0 )
return -1;
elfsize = sbuf.st_size;
elfsize = Path::GetFileSize( filename );
}
else
{
// Loading from a CD rom or CD image.
TocEntry toc;
CDVDFS_init( );
if ( CDVD_findfile( filename + strlen( "cdromN:" ), &toc ) == -1 )
if ( CDVD_findfile( fnptr + strlen( "cdromN:" ), &toc ) == -1 )
return -1;
elfsize = toc.fileSize;
}
Console::Status( "loadElfFile: %d", params elfsize);
Console::Status( wxsFormat(L"loadElfFile: %d", elfsize) );
if( elfsize == 0 ) return -1;
ElfObject elfobj( filename, elfsize );
if( elfobj.proghead == NULL )
throw Exception::CpuStateShutdown( fmt_string( "%s > This ELF has no program headers; Pcsx2 can't run what doesn't exist...", filename ) );
{
throw Exception::CpuStateShutdown(
wxsFormat( wxT("Invalid ELF header encountered in file:\n\t%s"), elfobj.filename ),
wxsFormat(_("Invalid ELF header, file: %s"), elfobj.filename )
);
}
//2002-09-19 (Florin)
args_ptr = 0xFFFFFFFF; //big value, searching for minimum
//args_ptr = 0xFFFFFFFF; //big value, searching for minimum [used by parseCommandLine]
elfobj.loadProgramHeaders();
elfobj.loadSectionHeaders();
@ -552,17 +567,19 @@ int loadElfFile(const char *filename)
cpuRegs.GPR.n.sp.UL[0] = 0x81f00000;
cpuRegs.GPR.n.gp.UL[0] = 0x81f80000; // might not be 100% ok
cpuRegs.GPR.n.a0.UL[0] = parseCommandLine( filename );
//cpuRegs.GPR.n.a0.UL[0] = parseCommandLine( filename ); // see #ifdef'd out parseCommendLine for details.
for ( uint i = 0; i < 0x100000; i++ ) {
if ( strcmp( "rom0:OSDSYS", (char*)PSM( i ) ) == 0 ) {
strcpy( (char*)PSM( i ), filename );
DevCon::Status( "addr %x \"%s\" -> \"%s\"", params i, "rom0:OSDSYS", filename );
for( uint i = 0; i < 0x100000; i++ )
{
if( memcmp( "rom0:OSDSYS", (char*)PSM( i ), 11 ) == 0 )
{
strcpy( (char*)PSM( i ), fnptr );
DevCon::Status( "loadElfFile: addr %x \"%s\" -> \"%s\"", params i, "rom0:OSDSYS", fnptr );
}
}
ElfCRC = elfobj.GetCRC();
Console::Status( "loadElfFile: %s; CRC = %8.8X", params filename, ElfCRC);
Console::Status( wxsFormat( L"loadElfFile: %s; CRC = %8.8X", filename.c_str(), ElfCRC ) );
ElfApplyPatches();
LoadGameSpecificSettings();

View File

@ -24,7 +24,7 @@ extern char args[256]; //to be filled by GUI
extern unsigned int args_ptr;
//-------------------
int loadElfFile(const char *filename);
int loadElfFile(const wxString& filename);
u32 loadElfCRC(const char *filename);
void LoadGameSpecificSettings();
void ElfApplyPatches();

165
pcsx2/Exceptions.cpp Normal file
View File

@ -0,0 +1,165 @@
/* Pcsx2 - Pc Ps2 Emulator
* Copyright (C) 2002-2009 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
*/
#include "PrecompiledHeader.h"
wxLocale* g_EnglishLocale = NULL;
//g_EnglishLocale = new wxLocale( wxLANGUAGE_ENGLISH );
wxString GetEnglish( const char* msg )
{
if( g_EnglishLocale == NULL ) return wxString::FromAscii(msg);
return g_EnglishLocale->GetString( wxString::FromAscii(msg).c_str() );
}
wxString GetTranslation( const char* msg )
{
return wxGetTranslation( wxString::FromAscii(msg).c_str() );
}
//////////////////////////////////////////////////////////////////////////////////////////
//
namespace Exception
{
// ------------------------------------------------------------------------
BaseException::~BaseException() throw() {}
BaseException::BaseException( const wxString& msg_eng, const wxString& msg_xlt ) :
m_message_eng( msg_eng ),
m_message( msg_xlt ),
m_stacktrace( wxEmptyString ) // unsupported yet
{
// Major hack. After a couple of tries, I'm still not managing to get Linux to catch these exceptions, so that the user actually
// gets the messages. Since Console is unavailable at this level, I'm using a simple printf, which of course, means it doesn't get
// logged. But at least the user sees it.
//
// I'll rip this out once I get Linux to actually catch these exceptions. Say, in BeginExecution or StartGui, like I would expect.
// -- arcum42
#ifdef __LINUX__
printf(msg.c_str());
#endif
}
// given message is assumed to be a translation key, and will be stored in translated
// and untranslated forms.
BaseException::BaseException( const char* msg_eng ) :
m_message_eng( GetEnglish( msg_eng ) ),
m_message( GetTranslation( msg_eng ) ),
m_stacktrace( wxEmptyString ) // unsupported yet
{
}
wxString BaseException::LogMessage() const
{
return m_message_eng + wxT("\n\n") + m_stacktrace;
}
// ------------------------------------------------------------------------
wxString Stream::LogMessage() const
{
return wxsFormat(
wxT("Stream exception: %s\n\tObject name: %s"),
m_message_eng, StreamName.c_str()
) + m_stacktrace;
}
wxString Stream::DisplayMessage() const
{
return m_message + wxT("\n") + StreamName.c_str();
}
// ------------------------------------------------------------------------
wxString PluginFailure::LogMessage() const
{
return wxsFormat(
wxT("%s plugin has encountered an error.\n\n"),
plugin_name.c_str()
) + m_stacktrace;
}
wxString PluginFailure::DisplayMessage() const
{
return wxsFormat( m_message, plugin_name );
}
// ------------------------------------------------------------------------
wxString FreezePluginFailure::LogMessage() const
{
return wxsFormat(
wxT("%s plugin returned an error while %s the state.\n\n"),
plugin_name.c_str(),
freeze_action.c_str()
) + m_stacktrace;
}
wxString FreezePluginFailure::DisplayMessage() const
{
return m_message;
}
// ------------------------------------------------------------------------
wxString UnsupportedStateVersion::LogMessage() const
{
// Note: no stacktrace needed for this one...
return wxsFormat( wxT("Unknown or unsupported savestate version: 0x%x"), Version );
}
wxString UnsupportedStateVersion::DisplayMessage() const
{
// m_message contains a recoverable savestate error which is helpful to the user.
return wxsFormat(
m_message + wxT("\n\n") +
wxsFormat( _("Unknown savestate version: 0x%x"), Version )
);
}
// ------------------------------------------------------------------------
wxString StateCrcMismatch::LogMessage() const
{
// Note: no stacktrace needed for this one...
return wxsFormat(
wxT("Game/CDVD does not match the savestate CRC.\n")
wxT("\tCdvd CRC: 0x%X\n\tGame CRC: 0x%X\n"),
Crc_Savestate, Crc_Cdvd
);
}
wxString StateCrcMismatch::DisplayMessage() const
{
return wxsFormat(
m_message + wxT("\n\n") +
wxsFormat( _(
"Savestate game/crc mismatch. Cdvd CRC: 0x%X Game CRC: 0x%X\n"),
Crc_Savestate, Crc_Cdvd
)
);
}
// ------------------------------------------------------------------------
wxString IndexBoundsFault::LogMessage() const
{
return wxT("Index out of bounds on SafeArray: ") + ArrayName +
wxsFormat( wxT("(index=%d, size=%d)"), BadIndex, ArrayLength );
}
wxString IndexBoundsFault::DisplayMessage() const
{
return m_message;
}
}

View File

@ -16,12 +16,9 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef _PCSX2_EXCEPTIONS_H_
#define _PCSX2_EXCEPTIONS_H_
#include <stdexcept>
#include "StringUtils.h"
#pragma once
//////////////////////////////////////////////////////////////////////////////////////////
// This class provides an easy and clean method for ensuring objects are not copyable.
class NoncopyableObject
{
@ -39,12 +36,12 @@ private:
const NoncopyableObject& operator=( const NoncopyableObject& );
};
//////////////////////////////////////////////////////////////////////////////////////////
// Base class used to implement type-safe sealed classes.
// This class should never be used directly. Use the Sealed
// macro instead, which ensures all sealed classes derive from a unique BaseSealed
// (preventing them from accidentally cirumventing sealing by inheriting from
// multiple sealed classes.
// This class should never be used directly. Use the Sealed macro instead, which ensures
// all sealed classes derive from a unique BaseSealed (preventing them from accidentally
// circumventing sealing by inheriting from multiple sealed classes.
//
template < int T >
class __BaseSealed
{
@ -54,52 +51,70 @@ protected:
}
};
// Use this macro/class as a base to seal a class from being derrived from.
// Use this macro/class as a base to seal a class from being derived from.
// This macro works by providing a unique base class with a protected constructor
// for every class that derives from it.
#define Sealed private virtual __BaseSealed<__COUNTER__>
extern wxLocale* g_EnglishLocale;
extern wxString GetEnglish( const char* msg );
extern wxString GetTranslation( const char* msg );
namespace Exception
{
//////////////////////////////////////////////////////////////////////////////////
// std::exception sucks, so I made a replacement.
// std::exception sucks, and isn't entirely cross-platform reliable in its implementation,
// so I made a replacement.
//
// Note, this class is "abstract" which means you shouldn't use it directly like, ever.
// Use Exception::RuntimeError or Exception::LogicError instead.
// Use Exception::RuntimeError or Exception::LogicError instead for generic exceptions.
//
class BaseException
{
protected:
const wxString m_message; // a "detailed" message of what disasterous thing has occured!
const wxString m_message_eng; // (untranslated) a "detailed" message of what disastrous thing has occurred!
const wxString m_message; // (translated) a "detailed" message of what disastrous thing has occurred!
const wxString m_stacktrace; // contains the stack trace string dump (unimplemented)
public:
virtual ~BaseException() throw()=0; // the =0; syntax forces this class into "abstract" mode.
explicit BaseException( const wxString& msg="Unhandled exception." ) :
m_message( msg )
{
// Major hack. After a couple of tries, I'm still not managing to get Linux to catch these exceptions, so that the user actually
// gets the messages. Since Console is unavailable at this level, I'm using a simple printf, which of course, means it doesn't get
// logged. But at least the user sees it.
//
// I'll rip this out once I get Linux to actually catch these exceptions. Say, in BeginExecution or StartGui, like I would expect.
// -- arcum42
#ifdef __LINUX__
printf(msg.c_str());
#endif
}
// copy construct
BaseException( const BaseException& src ) :
m_message_eng( src.m_message_eng ),
m_message( src.m_message ),
m_stacktrace( src.m_stacktrace ) { }
// Contruction using two pre-formatted pre-translated messages
BaseException( const wxString& msg_eng, const wxString& msg_xlt );
const wxString& Message() const { return m_message; }
const char* cMessage() const { return m_message.c_str(); }
// Construction using one translation key.
explicit BaseException( const char* msg_eng );
// Returns a message suitable for diagnostic / logging purposes.
// This message is always in english, and includes a full stack trace.
virtual wxString LogMessage() const;
// Returns a message suitable for end-user display.
// This message is usually meant for display in a user popup or such.
virtual wxString DisplayMessage() const { return m_message; }
};
//////////////////////////////////////////////////////////////////////////////////////////
// This class is used as a base exception for things tossed by PS2 cpus (EE, IOP, etc).
// Translation Note: These exceptions are never translated, except to issue a general
// error message to the user (which is xspecified below).
//
class Ps2Generic : public BaseException
{
public:
virtual ~Ps2Generic() throw() {}
explicit Ps2Generic( const wxString& msg="The Ps2/MIPS state encountered a general exception." ) :
Exception::BaseException( msg )
{
}
explicit Ps2Generic( const char* msg="Ps2/MIPS cpu caused a general exception" ) :
BaseException( msg ) { }
explicit Ps2Generic( const wxString& msg_eng, const wxString& msg_xlt=_("Ps2/MIPS cpu caused a general exception") ) :
BaseException( msg_eng, msg_xlt ) { }
virtual u32 GetPc() const=0;
virtual bool IsDelaySlot() const=0;
@ -111,18 +126,29 @@ namespace Exception
{
public:
virtual ~RuntimeError() throw() {}
explicit RuntimeError( const wxString& msg="An unhandled runtime error has occurred, somewhere in the depths of Pcsx2's cluttered brain-matter." ) :
BaseException( msg )
{}
RuntimeError( const RuntimeError& src ) : BaseException( src ) {}
explicit RuntimeError( const char* msg="An unhandled runtime error has occurred, somewhere in the depths of Pcsx2's cluttered brain-matter." ) :
BaseException( msg ) { }
explicit RuntimeError( const wxString& msg_eng, const wxString& msg_xlt ) :
BaseException( msg_eng, msg_xlt ) { }
};
// ------------------------------------------------------------------------
class LogicError : public BaseException
{
public:
virtual ~LogicError() throw() {}
explicit LogicError( const wxString& msg="An unhandled logic error has occured." ) :
BaseException( msg )
{}
LogicError( const LogicError& src ) : BaseException( src ) {}
explicit LogicError( const char* msg="An unhandled logic error has occurred." ) :
BaseException( msg ) { }
explicit LogicError( const wxString& msg_eng, const wxString& msg_xlt ) :
BaseException( msg_eng, msg_xlt ) { }
};
//////////////////////////////////////////////////////////////////////////////////
@ -130,46 +156,75 @@ namespace Exception
class OutOfMemory : public RuntimeError
{
public:
explicit OutOfMemory( const wxString& msg="Out of memory!" ) :
RuntimeError( msg ) {}
virtual ~OutOfMemory() throw() {}
explicit OutOfMemory( const char* msg="Out of memory" ) :
RuntimeError( msg ) {}
explicit OutOfMemory( const wxString& msg_eng, const wxString& msg_xlt=_("Out of memory") ) :
RuntimeError( msg_eng, msg_xlt ) { }
};
// ------------------------------------------------------------------------
// This exception thrown any time an operation is attempted when an object
// is in an uninitialized state.
class InvalidOperation : public LogicError
{
public:
virtual ~InvalidOperation() throw() {}
explicit InvalidOperation( const wxString& msg="Attempted method call is invalid for the current object or program state." ) :
explicit InvalidOperation( const char* msg="Attempted method call is invalid for the current object or program state." ) :
LogicError( msg ) {}
explicit InvalidOperation( const wxString& msg_eng, const wxString& msg_xlt ) :
LogicError( msg_eng, msg_xlt ) { }
};
// ------------------------------------------------------------------------
// This exception thrown any time an operation is attempted when an object
// is in an uninitialized state.
class InvalidArgument : public LogicError
{
public:
virtual ~InvalidArgument() throw() {}
explicit InvalidArgument( const wxString& msg="Invalid argument passed to a function." ) :
LogicError( msg ) {}
explicit InvalidArgument( const char* msg="Invalid argument passed to a function." ) :
LogicError( msg )
{
// assertions make debugging easier sometimes. :)
wxASSERT( msg );
}
};
// ------------------------------------------------------------------------
// Keep those array indexers in bounds when using the SafeArray type, or you'll be
// seeing these.
class IndexBoundsFault : public LogicError
{
public:
const wxString ArrayName;
const int ArrayLength;
const int BadIndex;
public:
virtual ~IndexBoundsFault() throw() {}
explicit IndexBoundsFault( const wxString& msg="Array index is outsides the bounds of an array." ) :
LogicError( msg ) {}
explicit IndexBoundsFault( const wxString& objname, int index, int arrsize ) :
LogicError( "Index is outside the bounds of an array." ),
ArrayName( objname ),
ArrayLength( arrsize ),
BadIndex( index )
{
// assertions make debugging easier sometimes. :)
wxASSERT( wxT("Index is outside the bounds of an array") );
}
virtual wxString LogMessage() const;
virtual wxString DisplayMessage() const;
};
// ------------------------------------------------------------------------
class ParseError : public RuntimeError
{
public:
virtual ~ParseError() throw() {}
explicit ParseError( const wxString& msg="Parse error" ) :
explicit ParseError( const char* msg="Parse error" ) :
RuntimeError( msg ) {}
};
@ -178,11 +233,12 @@ namespace Exception
class HardwareDeficiency : public RuntimeError
{
public:
explicit HardwareDeficiency( const wxString& msg="Your machine's hardware is incapable of running Pcsx2. Sorry dood." ) :
explicit HardwareDeficiency( const char* msg="Your machine's hardware is incapable of running Pcsx2. Sorry dood." ) :
RuntimeError( msg ) {}
virtual ~HardwareDeficiency() throw() {}
};
// ------------------------------------------------------------------------
// This exception is thrown by the PS2 emulation (R5900, etc) when bad things happen
// that force the emulation state to terminate. The GUI should handle them by returning
// the user to the GUI.
@ -190,66 +246,72 @@ namespace Exception
{
public:
virtual ~CpuStateShutdown() throw() {}
explicit CpuStateShutdown( const wxString& msg="The PS2 emulated state was shut down unexpectedly." ) :
explicit CpuStateShutdown( const char* msg="Unexpected emulation shutdown" ) :
RuntimeError( msg ) {}
explicit CpuStateShutdown( const wxString& msg_eng, const wxString& msg_xlt=wxString() ) :
RuntimeError( msg_eng, msg_xlt.IsEmpty() ? _("Unexpected emulation shutdown") : msg_xlt ) { }
};
// ------------------------------------------------------------------------
class PluginFailure : public RuntimeError
{
public:
wxString plugin_name; // name of the plugin
virtual ~PluginFailure() throw() {}
explicit PluginFailure( const wxString& plugin, const wxString& msg = "A plugin encountered a critical error." ) :
explicit PluginFailure( const char* plugin, const char* msg="%s plugin encountered a critical error" ) :
RuntimeError( msg )
, plugin_name( plugin ) {}
, plugin_name( wxString::FromAscii(plugin) ) {}
virtual wxString LogMessage() const;
virtual wxString DisplayMessage() const;
};
// ------------------------------------------------------------------------
class ThreadCreationError : public RuntimeError
{
public:
virtual ~ThreadCreationError() throw() {}
explicit ThreadCreationError( const wxString& msg="Thread could not be created." ) :
RuntimeError( msg ) {}
};
// This is a "special" exception that's primarily included for safe functioning in the
// Win32's ASCII API (ie, the non-Unicode one). Many of the old Win32 APIs don't support
// paths over 256 characters.
class PathTooLong : public RuntimeError
{
public:
virtual ~PathTooLong() throw() {}
explicit PathTooLong( const wxString& msg=
"A Pcsx2 pathname was too long for the system. Please move or reinstall Pcsx2 to\n"
"a location on your hard drive that has a shorter path." ) :
explicit ThreadCreationError( const char* msg="Thread could not be created." ) :
RuntimeError( msg ) {}
};
//////////////////////////////////////////////////////////////////////////////////
// STREAMING EXCEPTIONS
// ------------------------------------------------------------------------
// Generic stream error. Contains the name of the stream and a message.
// This exception is usually thrown via derrived classes, except in the (rare) case of a generic / unknown error.
// This exception is usually thrown via derived classes, except in the (rare) case of a generic / unknown error.
class Stream : public RuntimeError
{
public:
wxString stream_name; // name of the stream (if applicable)
wxString StreamName; // name of the stream (if applicable)
virtual ~Stream() throw() {}
// copy construct!
Stream( const Stream& src ) :
RuntimeError( src.Message() )
, stream_name( src.stream_name ) {}
RuntimeError( src ),
StreamName( src.StreamName ) {}
explicit Stream(
const wxString& objname=wxString(),
const wxString& msg="Invalid stream object" ) :
RuntimeError( msg + "\n\tFilename: " + objname )
, stream_name( objname ) {}
const char* msg="General file operation error" // general error while accessing or operating on a file or stream
) :
RuntimeError( msg ),
StreamName( objname ) {}
explicit Stream( const wxString& objname, const wxString& msg_eng, const wxString& msg_xlt=_("General file operation error") ) :
RuntimeError( msg_eng, msg_xlt ),
StreamName( objname ) {}
virtual wxString LogMessage() const;
virtual wxString DisplayMessage() const;
};
// ------------------------------------------------------------------------
// A generic base error class for bad streams -- corrupted data, sudden closures, loss of
// connection, or anything else that would indicate a failure to read the data after the
// stream was successfully opened.
@ -259,50 +321,63 @@ namespace Exception
virtual ~BadStream() throw() {}
explicit BadStream(
const wxString& objname=wxString(),
const wxString& msg="Stream data is corrupted or incomplete, or the stream connection closed unexpectedly" ) :
Stream( objname, msg ) {}
const char* msg="File data is corrupted or incomplete, or the stream connection closed unexpectedly"
) :
Stream( objname, msg ) {}
};
// ------------------------------------------------------------------------
// A generic exception for odd-ball stream creation errors.
class CreateStream : public Stream
{
public:
virtual ~CreateStream() throw() {}
explicit CreateStream(
const char* objname,
const char* msg="File could not be created or opened" ) :
Stream( wxString::FromAscii( objname ), msg ) {}
explicit CreateStream(
const wxString& objname=wxString(),
const wxString& msg="Stream could not be created or opened" ) :
const char* msg="File could not be created or opened" ) :
Stream( objname, msg ) {}
};
// ------------------------------------------------------------------------
// Exception thrown when an attempt to open a non-existent file is made.
// (this exception can also mean file permissions are invalid)
class FileNotFound : public CreateStream
{
public:
virtual ~FileNotFound() throw() {}
explicit FileNotFound(
const wxString& objname=wxString(),
const wxString& msg="File not found" ) :
const char* msg="File not found" ) :
CreateStream( objname, msg ) {}
};
// ------------------------------------------------------------------------
class AccessDenied : public CreateStream
{
public:
virtual ~AccessDenied() throw() {}
explicit AccessDenied(
const wxString& objname=wxString(),
const wxString& msg="Permission denied to file or stream" ) :
const char* msg="Permission denied to file" ) :
CreateStream( objname, msg ) {}
};
// ------------------------------------------------------------------------
// Generic End of Stream exception (sometimes an error, and sometimes just used as a
// shortcut for manual feof checks).
class EndOfStream : public Stream
{
public:
virtual ~EndOfStream() throw() {}
explicit EndOfStream( const wxString& objname=wxString(), const wxString& msg="End of stream was encountered" ) :
explicit EndOfStream( const wxString& objname, const char* msg="End of file" ) :
Stream( objname, msg ) {}
};
@ -316,10 +391,11 @@ namespace Exception
virtual ~BadSavedState() throw() {}
explicit BadSavedState(
const wxString& objname=wxString(),
const wxString& msg="Savestate data is corrupted or incomplete" ) :
const char* msg="Savestate data is corrupted" ) : // or incomplete
BadStream( objname, msg ) {}
};
// ------------------------------------------------------------------------
// Exception thrown by SaveState class when a critical plugin or gzread
class FreezePluginFailure : public RuntimeError
{
@ -328,12 +404,18 @@ namespace Exception
wxString freeze_action;
virtual ~FreezePluginFailure() throw() {}
explicit FreezePluginFailure( const wxString& plugin, const wxString& action ) :
RuntimeError( plugin + " plugin returned an error while " + action + " the state." )
, plugin_name( plugin )
, freeze_action( action ){}
explicit FreezePluginFailure( const char* plugin, const char* action,
const wxString& msg_xlt=_("Plugin error occurred while loading/saving state") )
:
RuntimeError( wxString(), msg_xlt ) // LogMessage / DisplayMessage build their own messages
, plugin_name( wxString::FromAscii(plugin) )
, freeze_action( wxString::FromAscii(action) ){}
virtual wxString LogMessage() const;
virtual wxString DisplayMessage() const;
};
// ------------------------------------------------------------------------
// The savestate code throws Recoverable errors when it fails prior to actually modifying
// the current emulation state. Recoverable errors are always thrown from the SaveState
// object construction (and never from Freeze methods).
@ -341,10 +423,11 @@ namespace Exception
{
public:
virtual ~StateLoadError_Recoverable() throw() {}
explicit StateLoadError_Recoverable( const wxString& msg="Recoverable error while loading savestate (existing emulation state is still intact)." ) :
explicit StateLoadError_Recoverable( const char* msg="Recoverable savestate load error" ) :
RuntimeError( msg ) {}
};
// ------------------------------------------------------------------------
// A recoverable exception thrown when the savestate being loaded isn't supported.
class UnsupportedStateVersion : public StateLoadError_Recoverable
{
@ -354,13 +437,15 @@ namespace Exception
public:
virtual ~UnsupportedStateVersion() throw() {}
explicit UnsupportedStateVersion( int version ) :
StateLoadError_Recoverable( fmt_string( "Unknown or unsupported savestate version: 0x%x", version ) )
StateLoadError_Recoverable(),
Version( version )
{}
explicit UnsupportedStateVersion( __unused int version, const wxString& msg ) :
StateLoadError_Recoverable( msg ) {}
virtual wxString LogMessage() const;
virtual wxString DisplayMessage() const;
};
// ------------------------------------------------------------------------
// A recoverable exception thrown when the CRC of the savestate does not match the
// CRC returned by the Cdvd driver.
// [feature not implemented yet]
@ -373,20 +458,12 @@ namespace Exception
public:
virtual ~StateCrcMismatch() throw() {}
explicit StateCrcMismatch( u32 crc_save, u32 crc_cdvd )
: StateLoadError_Recoverable( fmt_string(
"Game/CDVD does not match the savestate CRC.\n"
"\tCdvd CRC: 0x%X\n\tGame CRC: 0x%X\n", params crc_save, crc_cdvd
) )
: StateLoadError_Recoverable()
, Crc_Savestate( crc_save )
, Crc_Cdvd( crc_cdvd )
{}
explicit StateCrcMismatch( u32 crc_save, u32 crc_cdvd, const wxString& msg )
: StateLoadError_Recoverable( msg )
, Crc_Savestate( crc_save )
, Crc_Cdvd( crc_cdvd )
{}
virtual wxString LogMessage() const;
virtual wxString DisplayMessage() const;
};
}
#endif

View File

@ -24,16 +24,27 @@
#include "GS.h"
#include "iR5900.h"
#include "Counters.h"
#include "VifDma.h"
using namespace Threading;
using namespace std;
using namespace R5900;
static bool m_gsOpened = false;
u32 CSRw;
PCSX2_ALIGNED16( u8 g_RealGSMem[0x2000] );
extern int m_nCounters[];
// FrameSkipping Stuff
// Yuck, iSlowStart is needed by the MTGS, so can't make it static yet.
u64 m_iSlowStart=0;
static s64 m_iSlowTicks=0;
static bool m_justSkipped = false;
static bool m_StrictSkipping = false;
#ifdef PCSX2_DEVBUILD
// GS Playback
@ -98,21 +109,6 @@ __forceinline void GSVSYNC(void) {
}
#endif
u32 CSRw;
PCSX2_ALIGNED16( u8 g_RealGSMem[0x2000] );
#define PS2GS_BASE(mem) (g_RealGSMem+(mem&0x13ff))
extern int m_nCounters[];
// FrameSkipping Stuff
// Yuck, iSlowStart is needed by the MTGS, so can't make it static yet.
u64 m_iSlowStart=0;
static s64 m_iSlowTicks=0;
static bool m_justSkipped = false;
static bool m_StrictSkipping = false;
void _gs_ChangeTimings( u32 framerate, u32 iTicks )
{
m_iSlowStart = GetCPUTicks();
@ -839,8 +835,6 @@ void RunGSState( gzLoadingState& f )
list<GSStatePacket>::iterator it = packets.begin();
g_SaveGSStream = 3;
//int skipfirst = 1;
// first extract the data
while(1) {
@ -877,4 +871,4 @@ void RunGSState( gzLoadingState& f )
#endif
#undef GIFchain
//#undef GIFchain

View File

@ -28,18 +28,17 @@
using std::min;
#define gif ((DMACh*)&psH[0xA000])
#define spr0 ((DMACh*)&PS2MEM_HW[0xD000])
#define gifsplit 64
enum gifstate_t
{
GIF_STATE_EMPTY = 0,
GIF_STATE_STALL,
GIF_STATE_DONE
GIF_STATE_READY = 0,
GIF_STATE_STALL = 1,
GIF_STATE_DONE = 2,
GIF_STATE_EMPTY = 0x10
};
// A three-way toggle used to determine if the GIF is stalling (transferring) or done (finished).
static gifstate_t gifstate = GIF_STATE_EMPTY;
static int gifstate = GIF_STATE_READY;
static u64 s_gstag = 0; // used for querying the last tag
@ -49,6 +48,7 @@ static int gspath3done = 0;
static u32 gscycles = 0, prevcycles = 0, mfifocycles = 0;
static u32 gifqwc = 0;
bool gifmfifoirq = FALSE;
__forceinline void gsInterrupt() {
GIF_LOG("gsInterrupt: %8.8x", cpuRegs.cycle);
@ -57,8 +57,8 @@ __forceinline void gsInterrupt() {
//Console::WriteLn("Eh? why are you still interrupting! chcr %x, qwc %x, done = %x", params gif->chcr, gif->qwc, done);
return;
}
if(gif->qwc > 0 || gspath3done == 0) {
if( !(psHu32(DMAC_CTRL) & 0x1) ) {
if (gif->qwc > 0 || gspath3done == 0) {
if (!(psHu32(DMAC_CTRL) & 0x1)) {
Console::Notice("gs dma masked, re-scheduling...");
// re-raise the int shortly in the future
CPU_INT( 2, 64 );
@ -73,7 +73,7 @@ __forceinline void gsInterrupt() {
/*if (!(vif1Regs->mskpath3 && (vif1ch->chcr & 0x100)) || (psHu32(GIF_MODE) & 0x1))
CPU_INT( 2, 64 );*/
#endif
if(gspath3done == 0) return;
if(gspath3done == 0 || gif->qwc > 0) return;
}
gspath3done = 0;
@ -85,6 +85,7 @@ __forceinline void gsInterrupt() {
psHu32(GIF_STAT)&= ~0xE00; // OPH=0 | APATH=0
psHu32(GIF_STAT)&= ~0x1F000000; // QFC=0
hwDmacIrq(DMAC_GIF);
GIF_LOG("GIF DMA end");
}
@ -127,7 +128,7 @@ static void WRITERING_DMA(u32 *pMem, u32 qwc)
int _GIFchain() {
#ifdef GSPATH3FIX
u32 qwc = ((psHu32(GIF_MODE) & 0x4) && (vif1Regs->mskpath3)) ? min(8, (int)gif->qwc) : gif->qwc;
u32 qwc = ((psHu32(GIF_MODE) & 0x4) && (vif1Regs->mskpath3)) ? min(8, (int)gif->qwc) : min( gifsplit, (int)gif->qwc );
#else
u32 qwc = gif->qwc;
#endif
@ -151,7 +152,7 @@ int _GIFchain() {
return (qwc)*2;
}
__forceinline void GIFchain()
static __forceinline void GIFchain()
{
FreezeRegs(1);
if (gif->qwc) gscycles+= _GIFchain(); /* guessing */
@ -163,7 +164,7 @@ static __forceinline void dmaGIFend()
if ((psHu32(GIF_MODE) & 0x4) && gif->qwc != 0)
CPU_INT(2, min( 8, (int)gif->qwc ) /** BIAS*/);
else
CPU_INT(2, gif->qwc /** BIAS*/);
CPU_INT(2, min( gifsplit, (int)gif->qwc ) /** BIAS*/);
}
// These could probably be consolidated into one function,
@ -174,7 +175,7 @@ static __forceinline void GIFdmaEnd()
if (psHu32(GIF_MODE) & 0x4)
CPU_INT(2, min( 8, (int)gif->qwc ) /** BIAS*/);
else
CPU_INT(2, gif->qwc /** BIAS*/);
CPU_INT(2, min( gifsplit, (int)gif->qwc ) /** BIAS*/);
}
void GIFdma()
@ -189,7 +190,7 @@ void GIFdma()
return;
}
GIF_LOG("dmaGIFstart chcr = %lx, madr = %lx, qwc = %lx\n tadr = %lx, asr0 = %lx, asr1 = %lx", gif->chcr, gif->madr, gif->qwc, gif->tadr, gif->asr0, gif->asr1);
#ifndef GSPATH3FIX
if ( !(psHu32(GIF_MODE) & 0x4) ) {
@ -225,7 +226,7 @@ void GIFdma()
ptag = (u32*)dmaGetAddr(gif->tadr); //Set memory pointer to TADR
if (ptag == NULL) { //Is ptag empty?
psHu32(DMAC_STAT)|= 1<<15; //If yes, set BEIS (BUSERR) in DMAC_STAT register
psHu32(DMAC_STAT) |= DMAC_STAT_BEIS; //If yes, set BEIS (BUSERR) in DMAC_STAT register
return;
}
gscycles += 2;
@ -243,14 +244,10 @@ void GIFdma()
}
}
}
// When MTGS is enabled, Gifchain calls WRITERING_DMA, which calls GSRINGBUF_DONECOPY, which freezes
// the registers inside of the FreezeXMMRegs calls here and in the other two below..
// I'm not really sure that is intentional. --arcum42
GIFchain();
// Theres a comment below that says not to unfreeze the xmm regs, so not sure about freezing and unfreezing in GIFchain.
if((gif->qwc == 0) && ((gspath3done == 1) || (gif->chcr & 0xc) == 0)){
//if(gif->qwc > 0) Console::WriteLn("Hurray!"); // We *know* it is 0!
gspath3done = 0;
gif->chcr &= ~0x100;
GSCSRr &= ~0xC000;
@ -272,17 +269,20 @@ void GIFdma()
if (((gif->qwc == 0) && (gif->chcr & 0xc) == 0))
gspath3done = 1;
else
else if(gif->qwc > 0)
{
GIFdmaEnd();
return;
}
else {
}
if ((gif->chcr & 0xc) == 0x4 && gspath3done == 0)
{
// Chain Mode
while ((gspath3done == 0) && (gif->qwc == 0)) { //Loop if the transfers aren't intermittent
//while ((gspath3done == 0) && (gif->qwc == 0)) { //Loop if the transfers aren't intermittent
ptag = (u32*)dmaGetAddr(gif->tadr); //Set memory pointer to TADR
if (ptag == NULL) { //Is ptag empty?
psHu32(DMAC_STAT)|= 1<<15; //If yes, set BEIS (BUSERR) in DMAC_STAT register
psHu32(DMAC_STAT)|= DMAC_STAT_BEIS; //If yes, set BEIS (BUSERR) in DMAC_STAT register
return;
}
gscycles+=2; // Add 1 cycles from the QW read for the tag
@ -300,7 +300,7 @@ void GIFdma()
if ((psHu32(DMAC_CTRL) & 0xC0) == 0x80) { // STD == GIF
// there are still bugs, need to also check if gif->madr +16*qwc >= stadr, if not, stall
if(!gspath3done && gif->madr + (gif->qwc * 16) > psHu32(DMAC_STADR) && id == 4) {
if(!gspath3done && ((gif->madr + (gif->qwc * 16)) > psHu32(DMAC_STADR)) && (id == 4)) {
// stalled
Console::WriteLn("GS Stall Control Source = %x, Drain = %x\n MADR = %x, STADR = %x", params (psHu32(0xe000) >> 4) & 0x3, (psHu32(0xe000) >> 6) & 0x3,gif->madr, psHu32(DMAC_STADR));
prevcycles = gscycles;
@ -313,20 +313,20 @@ void GIFdma()
}
GIFchain(); //Transfers the data set by the switch
if ((gif->chcr & 0x80) && ptag[0] >> 31) { //Check TIE bit of CHCR and IRQ bit of tag
if ((gif->chcr & 0x80) && (ptag[0] >> 31)) { //Check TIE bit of CHCR and IRQ bit of tag
GIF_LOG("dmaIrq Set");
gspath3done = 1;
}
}
//}
}
prevcycles = 0;
if (!(vif1Regs->mskpath3 || (psHu32(GIF_MODE) & 0x1))) {
if (gspath3done == 0)
if (gspath3done == 0 || gif->qwc > 0)
{
if ((psHu32(GIF_MODE) & 0x4) && gif->qwc != 0)
if (gif->qwc != 0)
{
CPU_INT(2, min( 8, (int)gif->qwc )/** BIAS*/);
GIFdmaEnd();
}
else
{
@ -346,9 +346,9 @@ void GIFdma()
void dmaGIF() {
//We used to addd wait time for the buffer to fill here, fixing some timing problems in path 3 masking
//It takes the time of 24 QW for the BUS to become ready - The Punisher, And1 Streetball
GIF_LOG("dmaGIFstart chcr = %lx, madr = %lx, qwc = %lx\n tadr = %lx, asr0 = %lx, asr1 = %lx", gif->chcr, gif->madr, gif->qwc, gif->tadr, gif->asr0, gif->asr1);
if ((psHu32(DMAC_CTRL) & 0xC) == 0xC ) { // GIF MFIFO
Console::WriteLn("GIF MFIFO");
//Console::WriteLn("GIF MFIFO");
gifMFIFOInterrupt();
return;
}
@ -365,7 +365,8 @@ void dmaGIF() {
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
dmaGIFend();
//gspath3done = hwDmacSrcChainWithStack(gif, (ptag[0] >> 28) & 0x7);
GIFdmaEnd();
gif->qwc = 0;
return;
}
@ -414,8 +415,8 @@ static __forceinline int mfifoGIFrbTransfer() {
gifqwc -= mfifoqwc;
gif->qwc -= mfifoqwc;
gif->madr+= mfifoqwc*16;
mfifocycles+= (mfifoqwc) * 2; /* guessing */
gif->madr += mfifoqwc*16;
//mfifocycles += (mfifoqwc) * 2; /* guessing */
return 0;
}
@ -438,14 +439,13 @@ static __forceinline int mfifoGIFchain() {
if (pMem == NULL) return -1;
WRITERING_DMA(pMem, mfifoqwc);
gif->madr+= mfifoqwc*16;
gif->madr += mfifoqwc*16;
gif->qwc -= mfifoqwc;
mfifocycles+= (mfifoqwc) * 2; /* guessing */
mfifocycles += (mfifoqwc) * 2; /* guessing */
}
return 0;
}
bool gifmfifoirq = FALSE;
void mfifoGIFtransfer(int qwc) {
u32 *ptag;
@ -457,14 +457,14 @@ void mfifoGIFtransfer(int qwc) {
if(qwc > 0 ) {
gifqwc += qwc;
if(!(gif->chcr & 0x100))return;
if(gifstate == GIF_STATE_STALL) return;
if (gifstate != GIF_STATE_EMPTY) return;
gifstate &= ~GIF_STATE_EMPTY;
}
SPR_LOG("mfifoGIFtransfer %x madr %x, tadr %x", gif->chcr, gif->madr, gif->tadr);
if(gif->qwc == 0){
if(gif->tadr == spr0->madr) {
if (gif->qwc == 0) {
if (gif->tadr == spr0->madr) {
//if( gifqwc > 1 ) DevCon::WriteLn("gif mfifo tadr==madr but qwc = %d", params gifqwc);
//hwDmacIrq(14);
@ -492,20 +492,20 @@ void mfifoGIFtransfer(int qwc) {
case 1: // CNT - Transfer QWC following the tag.
gif->madr = psHu32(DMAC_RBOR) + ((gif->tadr + 16) & psHu32(DMAC_RBSR)); //Set MADR to QW after Tag
gif->tadr = psHu32(DMAC_RBOR) + ((gif->madr + (gif->qwc << 4)) & psHu32(DMAC_RBSR)); //Set TADR to QW following the data
gifstate = GIF_STATE_EMPTY;
gifstate = GIF_STATE_READY;
break;
case 2: // Next - Transfer QWC following tag. TADR = ADDR
temp = gif->madr; //Temporarily Store ADDR
gif->madr = psHu32(DMAC_RBOR) + ((gif->tadr + 16) & psHu32(DMAC_RBSR)); //Set MADR to QW following the tag
gif->tadr = temp; //Copy temporarily stored ADDR to Tag
gifstate = GIF_STATE_EMPTY;
gifstate = GIF_STATE_READY;
break;
case 3: // Ref - Transfer QWC from ADDR field
case 4: // Refs - Transfer QWC from ADDR field (Stall Control)
gif->tadr = psHu32(DMAC_RBOR) + ((gif->tadr + 16) & psHu32(DMAC_RBSR)); //Set TADR to next tag
gifstate = GIF_STATE_EMPTY;
gifstate = GIF_STATE_READY;
break;
case 7: // End - Transfer QWC following the tag
@ -521,12 +521,15 @@ void mfifoGIFtransfer(int qwc) {
gifmfifoirq = TRUE;
}
}
FreezeRegs(1);
if (mfifoGIFchain() == -1) {
Console::WriteLn("GIF dmaChain error size=%d, madr=%lx, tadr=%lx", params
gif->qwc, gif->madr, gif->tadr);
gifstate = GIF_STATE_STALL;
}
FreezeRegs(0);
if(gif->qwc == 0 && gifstate == GIF_STATE_DONE) gifstate = GIF_STATE_STALL;
@ -542,10 +545,16 @@ void gifMFIFOInterrupt()
cpuRegs.interrupt &= ~(1 << 11);
return ;
}
if((spr0->chcr & 0x100) && spr0->qwc == 0)
{
spr0->chcr &= ~0x100;
hwDmacIrq(8);
}
if(gifstate != GIF_STATE_STALL) {
if(gifqwc <= 0) {
//Console::WriteLn("Empty");
gifstate |= GIF_STATE_EMPTY;
psHu32(GIF_STAT)&= ~0xE00; // OPH=0 | APATH=0
hwDmacIrq(14);
return;
@ -554,14 +563,14 @@ void gifMFIFOInterrupt()
return;
}
#ifdef PCSX2_DEVBUILD
if(gifstate == GIF_STATE_EMPTY || gif->qwc > 0) {
if(gifstate == GIF_STATE_READY || gif->qwc > 0) {
Console::Error("gifMFIFO Panic > Shouldn't go here!");
return;
}
#endif
//if(gifqwc > 0) Console::WriteLn("GIF MFIFO ending with stuff in it %x", params gifqwc);
if (!gifmfifoirq) gifqwc = 0;
gifstate = GIF_STATE_EMPTY;
gifstate = GIF_STATE_READY;
gif->chcr &= ~0x100;
hwDmacIrq(DMAC_GIF);
GSCSRr &= ~0xC000; //Clear FIFO stuff

View File

@ -93,8 +93,8 @@ namespace HostGui
// For issuing notices to both the status bar and the console at the same time.
// Single-line text only please! Multi-line msgs should be directed to the
// console directly, thanks.
extern void Notice( const std::string& text );
extern void Notice( const wxString& text );
// sets the contents of the pcsx2 window status bar.
extern void SetStatusMsg( const std::string& text );
extern void SetStatusMsg( const wxString& text );
};

View File

@ -148,31 +148,31 @@ int hwMFIFOWrite(u32 addr, u8 *data, u32 size) {
}
int hwDmacSrcChainWithStack(DMACh *dma, int id) {
u32 temp;
bool hwDmacSrcChainWithStack(DMACh *dma, int id) {
switch (id) {
case 0: // Refe - Transfer Packet According to ADDR field
return 1; //End Transfer
return true; //End Transfer
case 1: // CNT - Transfer QWC following the tag.
dma->madr = dma->tadr + 16; //Set MADR to QW after Tag
dma->tadr = dma->madr + (dma->qwc << 4); //Set TADR to QW following the data
return 0;
return false;
case 2: // Next - Transfer QWC following tag. TADR = ADDR
temp = dma->madr; //Temporarily Store ADDR
{
u32 temp = dma->madr; //Temporarily Store ADDR
dma->madr = dma->tadr + 16; //Set MADR to QW following the tag
dma->tadr = temp; //Copy temporarily stored ADDR to Tag
return 0;
return false;
}
case 3: // Ref - Transfer QWC from ADDR field
case 4: // Refs - Transfer QWC from ADDR field (Stall Control)
dma->tadr += 16; //Set TADR to next tag
return 0;
return false;
case 5: // Call - Transfer QWC following the tag, save succeeding tag
temp = dma->madr; //Temporarily Store ADDR
{
u32 temp = dma->madr; //Temporarily Store ADDR
dma->madr = dma->tadr + 16; //Set MADR to data following the tag
@ -185,12 +185,12 @@ int hwDmacSrcChainWithStack(DMACh *dma, int id) {
dma->asr1 = dma->madr + (dma->qwc << 4); //If no store Succeeding tag in ASR1
}else {
Console::Notice("Call Stack Overflow (report if it fixes/breaks anything)");
return 1; //Return done
return true; //Return done
}
dma->tadr = temp; //Set TADR to temporarily stored ADDR
return 0;
return false;
}
case 6: // Ret - Transfer QWC following the tag, load next tag
dma->madr = dma->tadr + 16; //Set MADR to data following the tag
@ -209,668 +209,45 @@ int hwDmacSrcChainWithStack(DMACh *dma, int id) {
return 1; //End Transfer
}
}
return 0;
return false;
case 7: // End - Transfer QWC following the tag
dma->madr = dma->tadr + 16; //Set MADR to data following the tag
//Dont Increment tadr, breaks Soul Calibur II and III
return 1; //End Transfer
return true; //End Transfer
}
return -1;
return false;
}
int hwDmacSrcChain(DMACh *dma, int id) {
bool hwDmacSrcChain(DMACh *dma, int id) {
u32 temp;
switch (id) {
case 0: // Refe - Transfer Packet According to ADDR field
return 1; //End Transfer
return true; //End Transfer
case 1: // CNT - Transfer QWC following the tag.
dma->madr = dma->tadr + 16; //Set MADR to QW after Tag
dma->tadr = dma->madr + (dma->qwc << 4); //Set TADR to QW following the data
return 0;
return false;
case 2: // Next - Transfer QWC following tag. TADR = ADDR
temp = dma->madr; //Temporarily Store ADDR
dma->madr = dma->tadr + 16; //Set MADR to QW following the tag
dma->tadr = temp; //Copy temporarily stored ADDR to Tag
return 0;
return false;
case 3: // Ref - Transfer QWC from ADDR field
case 4: // Refs - Transfer QWC from ADDR field (Stall Control)
dma->tadr += 16; //Set TADR to next tag
return 0;
return false;
case 7: // End - Transfer QWC following the tag
dma->madr = dma->tadr + 16; //Set MADR to data following the tag
//Dont Increment tadr, breaks Soul Calibur II and III
return 1; //End Transfer
return true; //End Transfer
}
return -1;
return false;
}
// Original hwRead/Write32 functions .. left in for now, for troubleshooting purposes.
#if 0
mem32_t __fastcall hwRead32(u32 mem)
{
// *Performance Warning* This function is called -A-LOT. Be weary when making changes. It
// could impact FPS significantly.
// Optimization Note:
// Shortcut for the INTC_STAT register, which is checked *very* frequently as part of the EE's
// vsynch timers. INTC_STAT has the disadvantage of being in the 0x1000f000 case, which has
// a lot of additional registers in it, and combined with it's call frequency is a bad thing.
if(mem == INTC_STAT)
{
// This one is checked alot, so leave it commented out unless you love 600 meg logfiles.
//HW_LOG("DMAC_STAT Read 32bit %x\n", psHu32(0xe010));
return psHu32(INTC_STAT);
}
const u16 masked_mem = mem & 0xffff;
// We optimize the hw register reads by breaking them into manageable 4k chunks (for a total of
// 16 cases spanning the 64k PS2 hw register memory map). It helps also that the EE is, for
// the most part, designed so that various classes of registers are sectioned off into these
// 4k segments.
// Notes: Breaks from the switch statement will return a standard hw memory read.
// Special case handling of reads should use "return" directly.
switch( masked_mem>>12 ) // switch out as according to the 4k page of the access.
{
// Counters Registers
// This code uses some optimized trickery to produce more compact output.
// See below for the "reference" block to get a better idea what this code does. :)
case 0x0: // counters 0 and 1
case 0x1: // counters 2 and 3
{
const uint cntidx = masked_mem >> 11; // neat trick to scale the counter HW address into 0-3 range.
switch( (masked_mem>>4) & 0xf )
{
case 0x0: return (u16)rcntRcount(cntidx);
case 0x1: return (u16)counters[cntidx].modeval;
case 0x2: return (u16)counters[cntidx].target;
case 0x3: return (u16)counters[cntidx].hold;
}
}
#if 0 // Counters Reference Block (original case setup)
case 0x10000000: return (u16)rcntRcount(0);
case 0x10000010: return (u16)counters[0].modeval;
case 0x10000020: return (u16)counters[0].target;
case 0x10000030: return (u16)counters[0].hold;
case 0x10000800: return (u16)rcntRcount(1);
case 0x10000810: return (u16)counters[1].modeval;
case 0x10000820: return (u16)counters[1].target;
case 0x10000830: return (u16)counters[1].hold;
case 0x10001000: return (u16)rcntRcount(2);
case 0x10001010: return (u16)counters[2].modeval;
case 0x10001020: return (u16)counters[2].target;
case 0x10001800: return (u16)rcntRcount(3);
case 0x10001810: return (u16)counters[3].modeval;
case 0x10001820: return (u16)counters[3].target;
#endif
break;
case 0x2: return ipuRead32( mem );
case 0xf:
switch( (masked_mem >> 4) & 0xff )
{
case 0x01:
HW_LOG("INTC_MASK Read32, value=0x%x", psHu32(INTC_MASK));
break;
case 0x13: // 0x1000f130
case 0x26: // 0x1000f260 SBUS?
case 0x41: // 0x1000f410
case 0x43: // MCH_RICM
return 0;
case 0x24: // 0x1000f240: SBUS
return psHu32(0xf240) | 0xF0000102;
case 0x44: // 0x1000f440: MCH_DRD
if( !((psHu32(0xf430) >> 6) & 0xF) )
{
switch ((psHu32(0xf430)>>16) & 0xFFF)
{
//MCH_RICM: x:4|SA:12|x:5|SDEV:1|SOP:4|SBC:1|SDEV:5
case 0x21://INIT
if(rdram_sdevid < rdram_devices)
{
rdram_sdevid++;
return 0x1F;
}
return 0;
case 0x23://CNFGA
return 0x0D0D; //PVER=3 | MVER=16 | DBL=1 | REFBIT=5
case 0x24://CNFGB
//0x0110 for PSX SVER=0 | CORG=8(5x9x7) | SPT=1 | DEVTYP=0 | BYTE=0
return 0x0090; //SVER=0 | CORG=4(5x9x6) | SPT=1 | DEVTYP=0 | BYTE=0
case 0x40://DEVID
return psHu32(0xf430) & 0x1F; // =SDEV
}
}
return 0;
}
break;
///////////////////////////////////////////////////////
// Most of the following case handlers are for developer builds only (logging).
// It'll all optimize to ziltch in public release builds.
case 0x03:
case 0x04:
case 0x05:
case 0x06:
case 0x07:
case 0x08:
case 0x09:
case 0x0a:
{
const char* regName = "Unknown";
switch( mem )
{
case D2_CHCR: regName = "DMA2_CHCR"; break;
case D2_MADR: regName = "DMA2_MADR"; break;
case D2_QWC: regName = "DMA2_QWC"; break;
case D2_TADR: regName = "DMA2_TADDR"; break;
case D2_ASR0: regName = "DMA2_ASR0"; break;
case D2_ASR1: regName = "DMA2_ASR1"; break;
case D2_SADR: regName = "DMA2_SADDR"; break;
}
HW_LOG( "Hardware Read32 at 0x%x (%s), value=0x%x", mem, regName, psHu32(mem) );
}
break;
case 0x0b:
if( mem == D4_CHCR )
HW_LOG("Hardware Read32 at 0x%x (IPU1:DMA4_CHCR), value=0x%x", mem, psHu32(mem));
break;
case 0x0c:
case 0x0d:
case 0x0e:
if( mem == DMAC_STAT )
HW_LOG("DMAC_STAT Read32, value=0x%x", psHu32(DMAC_STAT));
break;
jNO_DEFAULT;
}
// Optimization note: We masked 'mem' earlier, so it's safe to access PS2MEM_HW directly.
// (checked disasm, and MSVC 2008 fails to optimize it on its own)
//return psHu32(mem);
return *((u32*)&PS2MEM_HW[masked_mem]);
}
__forceinline void __fastcall hwWrite32(u32 mem, u32 value)
{
if ((mem>=0x10002000) && (mem<0x10003000)) { //IPU regs
ipuWrite32(mem,value);
return;
}
if ((mem>=0x10003800) && (mem<0x10003c00)) {
vif0Write32(mem, value);
return;
}
if ((mem>=0x10003c00) && (mem<0x10004000)) {
vif1Write32(mem, value);
return;
}
switch (mem) {
case 0x10000000: rcntWcount(0, value); break;
case 0x10000010: rcntWmode(0, value); break;
case 0x10000020: rcntWtarget(0, value); break;
case 0x10000030: rcntWhold(0, value); break;
case 0x10000800: rcntWcount(1, value); break;
case 0x10000810: rcntWmode(1, value); break;
case 0x10000820: rcntWtarget(1, value); break;
case 0x10000830: rcntWhold(1, value); break;
case 0x10001000: rcntWcount(2, value); break;
case 0x10001010: rcntWmode(2, value); break;
case 0x10001020: rcntWtarget(2, value); break;
case 0x10001800: rcntWcount(3, value); break;
case 0x10001810: rcntWmode(3, value); break;
case 0x10001820: rcntWtarget(3, value); break;
case GIF_CTRL:
//Console::WriteLn("GIF_CTRL write %x", params value);
psHu32(mem) = value & 0x8;
if (value & 0x1)
gsGIFReset();
else if( value & 8 )
psHu32(GIF_STAT) |= 8;
else
psHu32(GIF_STAT) &= ~8;
return;
case GIF_MODE:
// need to set GIF_MODE (hamster ball)
psHu32(GIF_MODE) = value;
if (value & 0x1)
psHu32(GIF_STAT)|= 0x1;
else
psHu32(GIF_STAT)&= ~0x1;
if (value & 0x4)
psHu32(GIF_STAT)|= 0x4;
else
psHu32(GIF_STAT)&= ~0x4;
break;
case GIF_STAT: // stat is readonly
Console::WriteLn("Gifstat write value = %x", params value);
return;
case 0x10008000: // dma0 - vif0
DMA_LOG("VIF0dma %lx", value);
DmaExec(dmaVIF0, mem, value);
break;
case 0x10009000: // dma1 - vif1 - chcr
DMA_LOG("VIF1dma CHCR %lx", value);
DmaExec(dmaVIF1, mem, value);
break;
#ifdef PCSX2_DEVBUILD
case 0x10009010: // dma1 - vif1 - madr
HW_LOG("VIF1dma Madr %lx", value);
psHu32(mem) = value;//dma1 madr
break;
case 0x10009020: // dma1 - vif1 - qwc
HW_LOG("VIF1dma QWC %lx", value);
psHu32(mem) = value;//dma1 qwc
break;
case 0x10009030: // dma1 - vif1 - tadr
HW_LOG("VIF1dma TADR %lx", value);
psHu32(mem) = value;//dma1 tadr
break;
case 0x10009040: // dma1 - vif1 - asr0
HW_LOG("VIF1dma ASR0 %lx", value);
psHu32(mem) = value;//dma1 asr0
break;
case 0x10009050: // dma1 - vif1 - asr1
HW_LOG("VIF1dma ASR1 %lx", value);
psHu32(mem) = value;//dma1 asr1
break;
case 0x10009080: // dma1 - vif1 - sadr
HW_LOG("VIF1dma SADR %lx", value);
psHu32(mem) = value;//dma1 sadr
break;
#endif
case 0x1000a000: // dma2 - gif
DMA_LOG("0x%8.8x hwWrite32: GSdma %lx", cpuRegs.cycle, value);
DmaExec(dmaGIF, mem, value);
break;
#ifdef PCSX2_DEVBUILD
case 0x1000a010:
psHu32(mem) = value;//dma2 madr
HW_LOG("Hardware write DMA2_MADR 32bit at %x with value %x",mem,value);
break;
case 0x1000a020:
psHu32(mem) = value;//dma2 qwc
HW_LOG("Hardware write DMA2_QWC 32bit at %x with value %x",mem,value);
break;
case 0x1000a030:
psHu32(mem) = value;//dma2 taddr
HW_LOG("Hardware write DMA2_TADDR 32bit at %x with value %x",mem,value);
break;
case 0x1000a040:
psHu32(mem) = value;//dma2 asr0
HW_LOG("Hardware write DMA2_ASR0 32bit at %x with value %x",mem,value);
break;
case 0x1000a050:
psHu32(mem) = value;//dma2 asr1
HW_LOG("Hardware write DMA2_ASR1 32bit at %x with value %x",mem,value);
break;
case 0x1000a080:
psHu32(mem) = value;//dma2 saddr
HW_LOG("Hardware write DMA2_SADDR 32bit at %x with value %x",mem,value);
break;
#endif
case 0x1000b000: // dma3 - fromIPU
DMA_LOG("IPU0dma %lx", value);
DmaExec(dmaIPU0, mem, value);
break;
#ifdef PCSX2_DEVBUILD
case 0x1000b010:
psHu32(mem) = value;//dma2 madr
HW_LOG("Hardware write IPU0DMA_MADR 32bit at %x with value %x",mem,value);
break;
case 0x1000b020:
psHu32(mem) = value;//dma2 madr
HW_LOG("Hardware write IPU0DMA_QWC 32bit at %x with value %x",mem,value);
break;
case 0x1000b030:
psHu32(mem) = value;//dma2 tadr
HW_LOG("Hardware write IPU0DMA_TADR 32bit at %x with value %x",mem,value);
break;
case 0x1000b080:
psHu32(mem) = value;//dma2 saddr
HW_LOG("Hardware write IPU0DMA_SADDR 32bit at %x with value %x",mem,value);
break;
#endif
case 0x1000b400: // dma4 - toIPU
DMA_LOG("IPU1dma %lx", value);
DmaExec(dmaIPU1, mem, value);
break;
#ifdef PCSX2_DEVBUILD
case 0x1000b410:
psHu32(mem) = value;//dma2 madr
HW_LOG("Hardware write IPU1DMA_MADR 32bit at %x with value %x",mem,value);
break;
case 0x1000b420:
psHu32(mem) = value;//dma2 madr
HW_LOG("Hardware write IPU1DMA_QWC 32bit at %x with value %x",mem,value);
break;
case 0x1000b430:
psHu32(mem) = value;//dma2 tadr
HW_LOG("Hardware write IPU1DMA_TADR 32bit at %x with value %x",mem,value);
break;
case 0x1000b480:
psHu32(mem) = value;//dma2 saddr
HW_LOG("Hardware write IPU1DMA_SADDR 32bit at %x with value %x",mem,value);
break;
#endif
case 0x1000c000: // dma5 - sif0
DMA_LOG("SIF0dma %lx", value);
DmaExec(dmaSIF0, mem, value);
break;
case 0x1000c400: // dma6 - sif1
DMA_LOG("SIF1dma %lx", value);
DmaExec(dmaSIF1, mem, value);
break;
#ifdef PCSX2_DEVBUILD
case 0x1000c420: // dma6 - sif1 - qwc
HW_LOG("SIF1dma QWC = %lx", value);
psHu32(mem) = value;
break;
case 0x1000c430: // dma6 - sif1 - tadr
HW_LOG("SIF1dma TADR = %lx", value);
psHu32(mem) = value;
break;
#endif
case 0x1000c800: // dma7 - sif2
DMA_LOG("SIF2dma %lx", value);
DmaExec(dmaSIF2, mem, value);
break;
case 0x1000d000: // dma8 - fromSPR
DMA_LOG("fromSPRdma %lx", value);
DmaExec(dmaSPR0, mem, value);
break;
case 0x1000d400: // dma9 - toSPR
DMA_LOG("toSPRdma %lx", value);
DmaExec(dmaSPR1, mem, value);
break;
case 0x1000e000: // DMAC_CTRL
HW_LOG("DMAC_CTRL Write 32bit %x", value);
psHu32(0xe000) = value;
break;
case 0x1000e010: // DMAC_STAT
HW_LOG("DMAC_STAT Write 32bit %x", value);
psHu16(0xe010)&= ~(value & 0xffff); // clear on 1
psHu16(0xe012) ^= (u16)(value >> 16);
cpuTestDMACInts();
break;
case 0x1000f000: // INTC_STAT
HW_LOG("INTC_STAT Write 32bit %x", value);
psHu32(0xf000)&=~value;
break;
case 0x1000f010: // INTC_MASK
HW_LOG("INTC_MASK Write 32bit %x", value);
psHu32(0xf010) ^= (u16)value;
cpuTestINTCInts();
break;
case 0x1000f430://MCH_RICM: x:4|SA:12|x:5|SDEV:1|SOP:4|SBC:1|SDEV:5
if ((((value >> 16) & 0xFFF) == 0x21) && (((value >> 6) & 0xF) == 1) && (((psHu32(0xf440) >> 7) & 1) == 0))//INIT & SRP=0
rdram_sdevid = 0; // if SIO repeater is cleared, reset sdevid
psHu32(mem) = value & ~0x80000000; //kill the busy bit
break;
case 0x1000f440://MCH_DRD:
psHu32(mem) = value;
break;
case 0x1000f590: // DMAC_ENABLEW
HW_LOG("DMAC_ENABLEW Write 32bit %lx", value);
psHu32(0xf590) = value;
psHu32(0xf520) = value;
return;
case 0x1000f200:
psHu32(mem) = value;
break;
case 0x1000f220:
psHu32(mem) |= value;
break;
case 0x1000f230:
psHu32(mem) &= ~value;
break;
case 0x1000f240:
if(!(value & 0x100))
psHu32(mem) &= ~0x100;
else
psHu32(mem) |= 0x100;
break;
case 0x1000f260:
psHu32(mem) = 0;
break;
case 0x1000f130:
case 0x1000f410:
HW_LOG("Unknown Hardware write 32 at %x with value %x (%x)", mem, value, cpuRegs.CP0.n.Status.val);
break;
default:
psHu32(mem) = value;
HW_LOG("Unknown Hardware write 32 at %x with value %x (%x)", mem, value, cpuRegs.CP0.n.Status.val);
break;
}
}
#endif
/*
__forceinline void hwWrite64(u32 mem, u64 value)
{
u32 val32;
int i;
if ((mem>=0x10002000) && (mem<=0x10002030)) {
ipuWrite64(mem, value);
return;
}
if ((mem>=0x10003800) && (mem<0x10003c00)) {
vif0Write32(mem, value); return;
}
if ((mem>=0x10003c00) && (mem<0x10004000)) {
vif1Write32(mem, value); return;
}
switch (mem) {
case GIF_CTRL:
DevCon::Status("GIF_CTRL write 64", params value);
psHu32(mem) = value & 0x8;
if(value & 0x1) {
gsGIFReset();
//gsReset();
}
else {
if( value & 8 ) psHu32(GIF_STAT) |= 8;
else psHu32(GIF_STAT) &= ~8;
}
return;
case GIF_MODE:
#ifdef GSPATH3FIX
Console::Status("GIFMODE64 %x", params value);
#endif
psHu64(GIF_MODE) = value;
if (value & 0x1) psHu32(GIF_STAT)|= 0x1;
else psHu32(GIF_STAT)&= ~0x1;
if (value & 0x4) psHu32(GIF_STAT)|= 0x4;
else psHu32(GIF_STAT)&= ~0x4;
break;
case GIF_STAT: // stat is readonly
return;
case 0x1000a000: // dma2 - gif
DMA_LOG("0x%8.8x hwWrite64: GSdma %lx", cpuRegs.cycle, value);
DmaExec(dmaGIF, mem, value);
break;
case 0x1000e000: // DMAC_CTRL
HW_LOG("DMAC_CTRL Write 64bit %x", value);
psHu64(mem) = value;
break;
case 0x1000e010: // DMAC_STAT
HW_LOG("DMAC_STAT Write 64bit %x", value);
val32 = (u32)value;
psHu16(0xe010)&= ~(val32 & 0xffff); // clear on 1
val32 = val32 >> 16;
for (i=0; i<16; i++) { // reverse on 1
if (val32 & (1<<i)) {
if (psHu16(0xe012) & (1<<i))
psHu16(0xe012)&= ~(1<<i);
else
psHu16(0xe012)|= 1<<i;
}
}
cpuTestDMACInts();
break;
case 0x1000f590: // DMAC_ENABLEW
psHu32(0xf590) = value;
psHu32(0xf520) = value;
break;
case 0x1000f000: // INTC_STAT
HW_LOG("INTC_STAT Write 64bit %x", value);
psHu32(INTC_STAT)&=~value;
cpuTestINTCInts();
break;
case 0x1000f010: // INTC_MASK
HW_LOG("INTC_MASK Write 32bit %x", value);
for (i=0; i<16; i++) { // reverse on 1
const int s = (1<<i);
if (value & s) {
if (psHu32(INTC_MASK) & s)
psHu32(INTC_MASK)&= ~s;
else
psHu32(INTC_MASK)|= s;
}
}
cpuTestINTCInts();
break;
case 0x1000f130:
case 0x1000f410:
case 0x1000f430:
break;
default:
psHu64(mem) = value;
HW_LOG("Unknown Hardware write 64 at %x with value %x (status=%x)",mem,value, cpuRegs.CP0.n.Status.val);
break;
}
}
__forceinline void hwWrite128(u32 mem, const u64 *value)
{
if (mem >= 0x10004000 && mem < 0x10008000) {
WriteFIFO(mem, value); return;
}
switch (mem) {
case 0x1000f590: // DMAC_ENABLEW
psHu32(0xf590) = *(u32*)value;
psHu32(0xf520) = *(u32*)value;
break;
case 0x1000f130:
case 0x1000f410:
case 0x1000f430:
break;
default:
psHu64(mem ) = value[0];
psHu64(mem+8) = value[1];
HW_LOG("Unknown Hardware write 128 at %x with value %x_%x (status=%x)", mem, value[1], value[0], cpuRegs.CP0.n.Status.val);
break;
}
}
*/

View File

@ -21,25 +21,16 @@
extern u8 *psH; // hw mem
#define psHs8(mem) (*(s8 *)&PS2MEM_HW[(mem) & 0xffff])
#define psHs16(mem) (*(s16*)&PS2MEM_HW[(mem) & 0xffff])
#define psHs32(mem) (*(s32*)&PS2MEM_HW[(mem) & 0xffff])
#define psHs64(mem) (*(s64*)&PS2MEM_HW[(mem) & 0xffff])
#define psHu8(mem) (*(u8 *)&PS2MEM_HW[(mem) & 0xffff])
#define psHu16(mem) (*(u16*)&PS2MEM_HW[(mem) & 0xffff])
#define psHu32(mem) (*(u32*)&PS2MEM_HW[(mem) & 0xffff])
#define psHu64(mem) (*(u64*)&PS2MEM_HW[(mem) & 0xffff])
extern void CPU_INT( u32 n, s32 ecycle );
//////////////////////////////////////////////////////////////////////////
// Hardware FIFOs (128 bit access only!)
//
// VIF0 -- 0x10004000 -- psH[0x4000]
// VIF1 -- 0x10005000 -- psH[0x5000]
// GIF -- 0x10006000 -- psH[0x6000]
// IPUout -- 0x10007000 -- psH[0x7000]
// IPUin -- 0x10007010 -- psH[0x7010]
// VIF0 -- 0x10004000 -- PS2MEM_HW[0x4000]
// VIF1 -- 0x10005000 -- PS2MEM_HW[0x5000]
// GIF -- 0x10006000 -- PS2MEM_HW[0x6000]
// IPUout -- 0x10007000 -- PS2MEM_HW[0x7000]
// IPUin -- 0x10007010 -- PS2MEM_HW[0x7010]
void __fastcall ReadFIFO_page_4(u32 mem, mem128_t *out);
void __fastcall ReadFIFO_page_5(u32 mem, mem128_t *out);
@ -73,177 +64,183 @@ struct DMACh {
};
// HW defines
enum HWaddress
{
RCNT0_COUNT = 0x10000000,
RCNT0_MODE = 0x10000010,
RCNT0_TARGET = 0x10000020,
RCNT0_HOLD = 0x10000030,
#define RCNT0_COUNT 0x10000000
#define RCNT0_MODE 0x10000010
#define RCNT0_TARGET 0x10000020
#define RCNT0_HOLD 0x10000030
RCNT1_COUNT = 0x10000800,
RCNT1_MODE = 0x10000810,
RCNT1_TARGET = 0x10000820,
RCNT1_HOLD = 0x10000830,
#define RCNT1_COUNT 0x10000800
#define RCNT1_MODE 0x10000810
#define RCNT1_TARGET 0x10000820
#define RCNT1_HOLD 0x10000830
RCNT2_COUNT = 0x10001000,
RCNT2_MODE = 0x10001010,
RCNT2_TARGET = 0x10001020,
#define RCNT2_COUNT 0x10001000
#define RCNT2_MODE 0x10001010
#define RCNT2_TARGET 0x10001020
RCNT3_COUNT = 0x10001800,
RCNT3_MODE = 0x10001810,
RCNT3_TARGET = 0x10001820,
#define RCNT3_COUNT 0x10001800
#define RCNT3_MODE 0x10001810
#define RCNT3_TARGET 0x10001820
IPU_CMD = 0x10002000,
IPU_CTRL = 0x10002010,
IPU_BP = 0x10002020,
IPU_TOP = 0x10002030,
#define IPU_CMD 0x10002000
#define IPU_CTRL 0x10002010
#define IPU_BP 0x10002020
#define IPU_TOP 0x10002030
GIF_CTRL = 0x10003000,
GIF_MODE = 0x10003010,
GIF_STAT = 0x10003020,
GIF_TAG0 = 0x10003040,
GIF_TAG1 = 0x10003050,
GIF_TAG2 = 0x10003060,
GIF_TAG3 = 0x10003070,
GIF_CNT = 0x10003080,
GIF_P3CNT = 0x10003090,
GIF_P3TAG = 0x100030A0,
GIF_FIFO = 0x10006000,
#define GIF_CTRL 0x10003000
#define GIF_MODE 0x10003010
#define GIF_STAT 0x10003020
#define GIF_TAG0 0x10003040
#define GIF_TAG1 0x10003050
#define GIF_TAG2 0x10003060
#define GIF_TAG3 0x10003070
#define GIF_CNT 0x10003080
#define GIF_P3CNT 0x10003090
#define GIF_P3TAG 0x100030A0
#define GIF_FIFO 0x10006000
#define IPUout_FIFO 0x10007000
#define IPUin_FIFO 0x10007010
IPUout_FIFO = 0x10007000,
IPUin_FIFO = 0x10007010,
//VIF0
#define D0_CHCR 0x10008000
#define D0_MADR 0x10008010
#define D0_QWC 0x10008020
D0_CHCR = 0x10008000,
D0_MADR = 0x10008010,
D0_QWC = 0x10008020,
//VIF1
#define D1_CHCR 0x10009000
#define D1_MADR 0x10009010
#define D1_QWC 0x10009020
#define D1_TADR 0x10009030
#define D1_ASR0 0x10009040
#define D1_ASR1 0x10009050
#define D1_SADR 0x10009080
D1_CHCR = 0x10009000,
D1_MADR = 0x10009010,
D1_QWC = 0x10009020,
D1_TADR = 0x10009030,
D1_ASR0 = 0x10009040,
D1_ASR1 = 0x10009050,
D1_SADR = 0x10009080,
//GS
#define D2_CHCR 0x1000A000
#define D2_MADR 0x1000A010
#define D2_QWC 0x1000A020
#define D2_TADR 0x1000A030
#define D2_ASR0 0x1000A040
#define D2_ASR1 0x1000A050
#define D2_SADR 0x1000A080
D2_CHCR = 0x1000A000,
D2_MADR = 0x1000A010,
D2_QWC = 0x1000A020,
D2_TADR = 0x1000A030,
D2_ASR0 = 0x1000A040,
D2_ASR1 = 0x1000A050,
D2_SADR = 0x1000A080,
//fromIPU
#define D3_CHCR 0x1000B000
#define D3_MADR 0x1000B010
#define D3_QWC 0x1000B020
#define D3_TADR 0x1000B030
#define D3_SADR 0x1000B080
D3_CHCR = 0x1000B000,
D3_MADR = 0x1000B010,
D3_QWC = 0x1000B020,
D3_TADR = 0x1000B030,
D3_SADR = 0x1000B080,
//toIPU
#define D4_CHCR 0x1000B400
#define D4_MADR 0x1000B410
#define D4_QWC 0x1000B420
#define D4_TADR 0x1000B430
#define D4_SADR 0x1000B480
D4_CHCR = 0x1000B400,
D4_MADR = 0x1000B410,
D4_QWC = 0x1000B420,
D4_TADR = 0x1000B430,
D4_SADR = 0x1000B480,
//SIF0
#define D5_CHCR 0x1000C000
#define D5_MADR 0x1000C010
#define D5_QWC 0x1000C020
D5_CHCR = 0x1000C000,
D5_MADR = 0x1000C010,
D5_QWC = 0x1000C020,
//SIF1
#define D6_CHCR 0x1000C400
#define D6_MADR 0x1000C410
#define D6_QWC 0x1000C420
D6_CHCR = 0x1000C400,
D6_MADR = 0x1000C410,
D6_QWC = 0x1000C420,
//SIF2
#define D7_CHCR 0x1000C800
#define D7_MADR 0x1000C810
#define D7_QWC 0x1000C820
D7_CHCR = 0x1000C800,
D7_MADR = 0x1000C810,
D7_QWC = 0x1000C820,
//fromSPR
#define D8_CHCR 0x1000D000
#define D8_MADR 0x1000D010
#define D8_QWC 0x1000D020
#define D8_SADR 0x1000D080
D8_CHCR = 0x1000D000,
D8_MADR = 0x1000D010,
D8_QWC = 0x1000D020,
D8_SADR = 0x1000D080,
DMAC_CTRL = 0x1000E000,
DMAC_STAT = 0x1000E010,
DMAC_PCR = 0x1000E020,
DMAC_SQWC = 0x1000E030,
DMAC_RBSR = 0x1000E040,
DMAC_RBOR = 0x1000E050,
DMAC_STADR = 0x1000E060,
#define DMAC_CTRL 0x1000E000
#define DMAC_STAT 0x1000E010
#define DMAC_PCR 0x1000E020
#define DMAC_SQWC 0x1000E030
#define DMAC_RBSR 0x1000E040
#define DMAC_RBOR 0x1000E050
#define DMAC_STADR 0x1000E060
INTC_STAT = 0x1000F000,
INTC_MASK = 0x1000F010,
#define INTC_STAT 0x1000F000
#define INTC_MASK 0x1000F010
SBUS_F220 = 0x1000F220,
SBUS_SMFLG = 0x1000F230,
SBUS_F240 = 0x1000F240,
#define SBUS_F220 0x1000F220
#define SBUS_SMFLG 0x1000F230
#define SBUS_F240 0x1000F240
DMAC_ENABLER = 0x1000F520,
DMAC_ENABLEW = 0x1000F590,
#define DMAC_ENABLER 0x1000F520
#define DMAC_ENABLEW 0x1000F590
GS_PMODE = 0x12000000,
GS_SMODE1 = 0x12000010,
GS_SMODE2 = 0x12000020,
GS_SRFSH = 0x12000030,
GS_SYNCH1 = 0x12000040,
GS_SYNCH2 = 0x12000050,
GS_SYNCV = 0x12000060,
GS_DISPFB1 = 0x12000070,
GS_DISPLAY1 = 0x12000080,
GS_DISPFB2 = 0x12000090,
GS_DISPLAY2 = 0x120000A0,
GS_EXTBUF = 0x120000B0,
GS_EXTDATA = 0x120000C0,
GS_EXTWRITE = 0x120000D0,
GS_BGCOLOR = 0x120000E0,
GS_CSR = 0x12001000,
GS_IMR = 0x12001010,
GS_BUSDIR = 0x12001040,
GS_SIGLBLID = 0x12001080
};
#define SBFLG_IOPALIVE 0x10000
#define SBFLG_IOPSYNC 0x40000
#define GS_PMODE 0x12000000
#define GS_SMODE1 0x12000010
#define GS_SMODE2 0x12000020
#define GS_SRFSH 0x12000030
#define GS_SYNCH1 0x12000040
#define GS_SYNCH2 0x12000050
#define GS_SYNCV 0x12000060
#define GS_DISPFB1 0x12000070
#define GS_DISPLAY1 0x12000080
#define GS_DISPFB2 0x12000090
#define GS_DISPLAY2 0x120000A0
#define GS_EXTBUF 0x120000B0
#define GS_EXTDATA 0x120000C0
#define GS_EXTWRITE 0x120000D0
#define GS_BGCOLOR 0x120000E0
#define GS_CSR 0x12001000
#define GS_IMR 0x12001010
#define GS_BUSDIR 0x12001040
#define GS_SIGLBLID 0x12001080
#define INTC_GS 0
#define INTC_SBUS 1
#define INTC_VBLANK_S 2
#define INTC_VBLANK_E 3
#define INTC_VIF0 4
#define INTC_VIF1 5
#define INTC_VU0 6
#define INTC_VU1 7
#define INTC_IPU 8
#define INTC_TIM0 9
#define INTC_TIM1 10
#define INTC_TIM2 11
#define INTC_TIM3 12
#define SBFLG_IOPALIVE 0x10000
#define SBFLG_IOPSYNC 0x40000
enum INTCIrqs
{
INTC_GS = 0,
INTC_SBUS,
INTC_VBLANK_S,
INTC_VBLANK_E,
INTC_VIF0,
INTC_VIF1,
INTC_VU0,
INTC_VU1,
INTC_IPU,
INTC_TIM0,
INTC_TIM1,
INTC_TIM2,
INTC_TIM3,
};
#define DMAC_STAT_SIS (1<<13) // stall condition
#define DMAC_STAT_MEIS (1<<14) // mfifo empty
#define DMAC_STAT_BEIS (1<<15) // bus error
#define DMAC_STAT_SIM (1<<29) // stall mask
#define DMAC_STAT_MEIM (1<<30) // mfifo mask
#define DMAC_VIF0 0
#define DMAC_VIF1 1
#define DMAC_GIF 2
#define DMAC_FROM_IPU 3
#define DMAC_TO_IPU 4
#define DMAC_SIF0 5
#define DMAC_SIF1 6
#define DMAC_SIF2 7
#define DMAC_FROM_SPR 8
#define DMAC_TO_SPR 9
#define DMAC_ERROR 15
enum DMACIrqs
{
DMAC_VIF0 = 0,
DMAC_VIF1,
DMAC_GIF,
DMAC_FROM_IPU,
DMAC_TO_IPU,
DMAC_SIF0,
DMAC_SIF1,
DMAC_SIF2,
DMAC_FROM_SPR,
DMAC_TO_SPR,
DMAC_ERROR = 15,
};
#define VIF0_STAT_VPS_W (1)
#define VIF0_STAT_VPS_D (2)
@ -275,35 +272,39 @@ struct DMACh {
#define VIF1_STAT_ER1 (1<<13)
#define VIF1_STAT_FDR (1<<23)
#define VIF_STAT_VPS_W (1)
#define VIF_STAT_VPS_D (2)
#define VIF_STAT_VPS_T (3)
#define VIF_STAT_VPS (3)
#define VIF_STAT_VEW (1<<2)
#define VIF_STAT_VGW (1<<3)
#define VIF_STAT_MRK (1<<6)
#define VIF_STAT_DBF (1<<7)
#define VIF_STAT_VSS (1<<8)
#define VIF_STAT_VFS (1<<9)
#define VIF_STAT_VIS (1<<10)
#define VIF_STAT_INT (1<<11)
#define VIF_STAT_ER0 (1<<12)
#define VIF_STAT_ER1 (1<<13)
#define VIF_STAT_FDR (1<<23)
//DMA interrupts & masks
#define BEISintr (0x8000)
#define VIF0intr (0x10001)
#define VIF1intr (0x20002)
#define GIFintr (0x40004)
#define IPU0intr (0x80008)
#define IPU1intr (0x100010)
#define SIF0intr (0x200020)
#define SIF1intr (0x400040)
#define SIF2intr (0x800080)
#define SPR0intr (0x1000100)
#define SPR1intr (0x2000200)
#define SISintr (0x20002000)
#define MEISintr (0x40004000)
#define DMAend(dma, num) { \
dma->chcr &= ~0x100; \
psHu32(DMAC_STAT)|= 1<<num; \
return; \
}
#define DMAerror(dma, num) { \
psHu32(DMAC_STAT)|= 1<<15; /* BUS error */ \
DMAend(dma, num); \
}
#define _dmaGetAddr(dma, ptr, addr, num) \
ptr = (u32*)dmaGetAddr(addr); \
if (ptr == NULL) DMAerror(dma, num);
enum DMAInter
{
BEISintr = 0x8000,
VIF0intr = 0x10001,
VIF1intr = 0x20002,
GIFintr = 0x40004,
IPU0intr = 0x80008,
IPU1intr = 0x100010,
SIF0intr = 0x200020,
SIF1intr =0x400040,
SIF2intr = 0x800080,
SPR0intr = 0x1000100,
SPR1intr = 0x2000200,
SISintr = 0x20002000,
MEISintr = 0x40004000
};
#ifdef PCSX2_VIRTUAL_MEM
@ -348,20 +349,35 @@ static __forceinline void *dmaGetAddr(u32 addr) {
u8 *ptr;
// if (addr & 0xf) { DMA_LOG("*PCSX2*: DMA address not 128bit aligned: %8.8x", addr); }
if (addr & 0x80000000) { // teh sux why the f00k 0xE0000000
return (void*)&psS[addr & 0x3ff0];
}
// teh sux why the f00k 0xE0000000
if (addr & 0x80000000) return (void*)&psS[addr & 0x3ff0];
ptr = (u8*)vtlb_GetPhyPtr(addr&0x1FFFFFF0);
if (ptr == NULL) {
Console::Error("*PCSX2*: DMA error: %8.8x", params addr);
Console::Error( "*PCSX2*: DMA error: %8.8x", params addr);
return NULL;
}
return ptr;
}
#endif
#endif
static __forceinline u32 *_dmaGetAddr(DMACh *dma, u32 addr, u32 num)
{
u32 *ptr = (u32*)dmaGetAddr(addr);
if (ptr == NULL)
{
// DMA Error
psHu32(DMAC_STAT) |= DMAC_STAT_BEIS; /* BUS error */
// DMA End
psHu32(DMAC_STAT) |= 1<<num;
dma->chcr &= ~0x100;
}
return ptr;
}
void hwInit();
void hwReset();
@ -422,8 +438,8 @@ void hwDmacIrq(int n);
int hwMFIFORead(u32 addr, u8 *data, u32 size);
int hwMFIFOWrite(u32 addr, u8 *data, u32 size);
int hwDmacSrcChainWithStack(DMACh *dma, int id);
int hwDmacSrcChain(DMACh *dma, int id);
bool hwDmacSrcChainWithStack(DMACh *dma, int id);
bool hwDmacSrcChain(DMACh *dma, int id);
int hwConstRead8 (u32 x86reg, u32 mem, u32 sign);
int hwConstRead16(u32 x86reg, u32 mem, u32 sign);

View File

@ -61,34 +61,35 @@ __forceinline u8 hwRead8(u32 mem)
switch (mem)
{
case 0x10000000: ret = (u8)rcntRcount(0); break;
case 0x10000010: ret = (u8)counters[0].modeval; break;
case 0x10000020: ret = (u8)counters[0].target; break;
case 0x10000030: ret = (u8)counters[0].hold; break;
// Note: the values without defines = the defines + 1.
case RCNT0_COUNT: ret = (u8)rcntRcount(0); break;
case RCNT0_MODE: ret = (u8)counters[0].modeval; break;
case RCNT0_TARGET: ret = (u8)counters[0].target; break;
case RCNT0_HOLD: ret = (u8)counters[0].hold; break;
case 0x10000001: ret = (u8)(rcntRcount(0)>>8); break;
case 0x10000011: ret = (u8)(counters[0].modeval>>8); break;
case 0x10000021: ret = (u8)(counters[0].target>>8); break;
case 0x10000031: ret = (u8)(counters[0].hold>>8); break;
case 0x10000800: ret = (u8)rcntRcount(1); break;
case 0x10000810: ret = (u8)counters[1].modeval; break;
case 0x10000820: ret = (u8)counters[1].target; break;
case 0x10000830: ret = (u8)counters[1].hold; break;
case RCNT1_COUNT: ret = (u8)rcntRcount(1); break;
case RCNT1_MODE: ret = (u8)counters[1].modeval; break;
case RCNT1_TARGET: ret = (u8)counters[1].target; break;
case RCNT1_HOLD: ret = (u8)counters[1].hold; break;
case 0x10000801: ret = (u8)(rcntRcount(1)>>8); break;
case 0x10000811: ret = (u8)(counters[1].modeval>>8); break;
case 0x10000821: ret = (u8)(counters[1].target>>8); break;
case 0x10000831: ret = (u8)(counters[1].hold>>8); break;
case 0x10001000: ret = (u8)rcntRcount(2); break;
case 0x10001010: ret = (u8)counters[2].modeval; break;
case 0x10001020: ret = (u8)counters[2].target; break;
case RCNT2_COUNT: ret = (u8)rcntRcount(2); break;
case RCNT2_MODE: ret = (u8)counters[2].modeval; break;
case RCNT2_TARGET: ret = (u8)counters[2].target; break;
case 0x10001001: ret = (u8)(rcntRcount(2)>>8); break;
case 0x10001011: ret = (u8)(counters[2].modeval>>8); break;
case 0x10001021: ret = (u8)(counters[2].target>>8); break;
case 0x10001800: ret = (u8)rcntRcount(3); break;
case 0x10001810: ret = (u8)counters[3].modeval; break;
case 0x10001820: ret = (u8)counters[3].target; break;
case RCNT3_COUNT: ret = (u8)rcntRcount(3); break;
case RCNT3_MODE: ret = (u8)counters[3].modeval; break;
case RCNT3_TARGET: ret = (u8)counters[3].target; break;
case 0x10001801: ret = (u8)(rcntRcount(3)>>8); break;
case 0x10001811: ret = (u8)(counters[3].modeval>>8); break;
case 0x10001821: ret = (u8)(counters[3].target>>8); break;
@ -97,7 +98,7 @@ __forceinline u8 hwRead8(u32 mem)
if ((mem & 0xffffff0f) == 0x1000f200)
{
if(mem == 0x1000f260) ret = 0;
else if(mem == 0x1000F240) {
else if(mem == SBUS_F240) {
ret = psHu32(mem);
//psHu32(mem) &= ~0x4000;
}
@ -120,34 +121,34 @@ __forceinline u16 hwRead16(u32 mem)
{
u16 ret;
if( mem >= 0x10002000 && mem < 0x10008000 )
if( mem >= IPU_CMD && mem < D0_CHCR )
Console::Notice("Unexpected hwRead16 from 0x%x", params mem);
switch (mem)
{
case 0x10000000: ret = (u16)rcntRcount(0); break;
case 0x10000010: ret = (u16)counters[0].modeval; break;
case 0x10000020: ret = (u16)counters[0].target; break;
case 0x10000030: ret = (u16)counters[0].hold; break;
case RCNT0_COUNT: ret = (u16)rcntRcount(0); break;
case RCNT0_MODE: ret = (u16)counters[0].modeval; break;
case RCNT0_TARGET: ret = (u16)counters[0].target; break;
case RCNT0_HOLD: ret = (u16)counters[0].hold; break;
case 0x10000800: ret = (u16)rcntRcount(1); break;
case 0x10000810: ret = (u16)counters[1].modeval; break;
case 0x10000820: ret = (u16)counters[1].target; break;
case 0x10000830: ret = (u16)counters[1].hold; break;
case RCNT1_COUNT: ret = (u16)rcntRcount(1); break;
case RCNT1_MODE: ret = (u16)counters[1].modeval; break;
case RCNT1_TARGET: ret = (u16)counters[1].target; break;
case RCNT1_HOLD: ret = (u16)counters[1].hold; break;
case 0x10001000: ret = (u16)rcntRcount(2); break;
case 0x10001010: ret = (u16)counters[2].modeval; break;
case 0x10001020: ret = (u16)counters[2].target; break;
case RCNT2_COUNT: ret = (u16)rcntRcount(2); break;
case RCNT2_MODE: ret = (u16)counters[2].modeval; break;
case RCNT2_TARGET: ret = (u16)counters[2].target; break;
case 0x10001800: ret = (u16)rcntRcount(3); break;
case 0x10001810: ret = (u16)counters[3].modeval; break;
case 0x10001820: ret = (u16)counters[3].target; break;
case RCNT3_COUNT: ret = (u16)rcntRcount(3); break;
case RCNT3_MODE: ret = (u16)counters[3].modeval; break;
case RCNT3_TARGET: ret = (u16)counters[3].target; break;
default:
if ((mem & 0xffffff0f) == 0x1000f200)
{
if(mem == 0x1000f260) ret = 0;
else if(mem == 0x1000F240) {
else if(mem == SBUS_F240) {
ret = psHu16(mem) | 0x0102;
psHu32(mem) &= ~0x4000;
}

View File

@ -40,11 +40,22 @@ using namespace R5900;
// dark cloud2 uses 8 bit DMAs register writes
static __forceinline void DmaExec8( void (*func)(), u32 mem, u8 value )
{
u32 qwcRegister = (mem | 0x20) & ~0x1; //Need to remove the lower bit else we end up clearing TADR
//Its invalid for the hardware to write a DMA while it is active, not without Suspending the DMAC
if((value & 0x1) && (psHu8(mem) & 0x1) == 0x1 && (psHu32(DMAC_CTRL) & 0x1) == 1) {
DMA_LOG( "DMAExec8 Attempt to run DMA while one is already active mem = %x", mem );
return;
}
// Upper 16bits of QWC should not be written since QWC is 16bits in size.
if ((psHu32(qwcRegister) >> 16) != 0)
{
DMA_LOG("DMA QWC (%x) upper 16bits set to %x\n",
qwcRegister,
psHu32(qwcRegister) >> 16);
psHu32(qwcRegister) = 0;
}
psHu8(mem) = (u8)value;
if ((psHu8(mem) & 0x1) && (psHu32(DMAC_CTRL) & 0x1))
{
@ -55,11 +66,22 @@ static __forceinline void DmaExec8( void (*func)(), u32 mem, u8 value )
static __forceinline void DmaExec16( void (*func)(), u32 mem, u16 value )
{
u32 qwcRegister = mem | 0x20;
//Its invalid for the hardware to write a DMA while it is active, not without Suspending the DMAC
if((value & 0x100) && (psHu32(mem) & 0x100) == 0x100 && (psHu32(DMAC_CTRL) & 0x1) == 1) {
DMA_LOG( "DMAExec16 Attempt to run DMA while one is already active mem = %x", mem);
return;
}
// Upper 16bits of QWC should not be written since QWC is 16bits in size.
if ((psHu32(qwcRegister) >> 16) != 0)
{
DMA_LOG("DMA QWC (%x) upper 16bits set to %x\n",
qwcRegister,
psHu32(qwcRegister) >> 16);
psHu32(qwcRegister) = 0;
}
psHu16(mem) = (u16)value;
if ((psHu16(mem) & 0x100) && (psHu32(DMAC_CTRL) & 0x1))
{
@ -70,11 +92,22 @@ static __forceinline void DmaExec16( void (*func)(), u32 mem, u16 value )
static void DmaExec( void (*func)(), u32 mem, u32 value )
{
u32 qwcRegister = mem | 0x20;
//Its invalid for the hardware to write a DMA while it is active, not without Suspending the DMAC
if((value & 0x100) && (psHu32(mem) & 0x100) == 0x100 && (psHu32(DMAC_CTRL) & 0x1) == 1) {
DMA_LOG( "DMAExec32 Attempt to run DMA while one is already active mem = %x", mem );
return;
}
// Upper 16bits of QWC should not be written since QWC is 16bits in size.
if ((psHu32(qwcRegister) >> 16) != 0)
{
DMA_LOG("DMA QWC (%x) upper 16bits set to %x\n",
qwcRegister,
psHu32(qwcRegister) >> 16);
psHu32(qwcRegister) = 0;
}
/* Keep the old tag if in chain mode and hw doesnt set it*/
if( (value & 0xc) == 0x4 && (value & 0xffff0000) == 0)
psHu32(mem) = (psHu32(mem) & 0xFFFF0000) | (u16)value;
@ -112,27 +145,27 @@ void hwWrite8(u32 mem, u8 value) {
DevCon::Notice( "hwWrite8 to 0x%x = 0x%x", params mem, value );
switch (mem) {
case 0x10000000: rcntWcount(0, value); break;
case 0x10000010: rcntWmode(0, (counters[0].modeval & 0xff00) | value); break;
case RCNT0_COUNT: rcntWcount(0, value); break;
case RCNT0_MODE: rcntWmode(0, (counters[0].modeval & 0xff00) | value); break;
case 0x10000011: rcntWmode(0, (counters[0].modeval & 0xff) | value << 8); break;
case 0x10000020: rcntWtarget(0, value); break;
case 0x10000030: rcntWhold(0, value); break;
case RCNT0_TARGET: rcntWtarget(0, value); break;
case RCNT0_HOLD: rcntWhold(0, value); break;
case 0x10000800: rcntWcount(1, value); break;
case 0x10000810: rcntWmode(1, (counters[1].modeval & 0xff00) | value); break;
case RCNT1_COUNT: rcntWcount(1, value); break;
case RCNT1_MODE: rcntWmode(1, (counters[1].modeval & 0xff00) | value); break;
case 0x10000811: rcntWmode(1, (counters[1].modeval & 0xff) | value << 8); break;
case 0x10000820: rcntWtarget(1, value); break;
case 0x10000830: rcntWhold(1, value); break;
case RCNT1_TARGET: rcntWtarget(1, value); break;
case RCNT1_HOLD: rcntWhold(1, value); break;
case 0x10001000: rcntWcount(2, value); break;
case 0x10001010: rcntWmode(2, (counters[2].modeval & 0xff00) | value); break;
case RCNT2_COUNT: rcntWcount(2, value); break;
case RCNT2_MODE: rcntWmode(2, (counters[2].modeval & 0xff00) | value); break;
case 0x10001011: rcntWmode(2, (counters[2].modeval & 0xff) | value << 8); break;
case 0x10001020: rcntWtarget(2, value); break;
case RCNT2_TARGET: rcntWtarget(2, value); break;
case 0x10001800: rcntWcount(3, value); break;
case 0x10001810: rcntWmode(3, (counters[3].modeval & 0xff00) | value); break;
case RCNT3_COUNT: rcntWcount(3, value); break;
case RCNT3_MODE: rcntWmode(3, (counters[3].modeval & 0xff00) | value); break;
case 0x10001811: rcntWmode(3, (counters[3].modeval & 0xff) | value << 8); break;
case 0x10001820: rcntWtarget(3, value); break;
case RCNT3_TARGET: rcntWtarget(3, value); break;
case 0x1000f180:
if (value == '\n') {
@ -166,7 +199,7 @@ void hwWrite8(u32 mem, u8 value) {
DevCon::Notice("8 bit VIF1 DMA Start while DMAC Disabled\n");
QueuedDMA |= 0x2;
}
if(value & 0x1) vif1.done = 0; //This must be done here! some games (ala Crash of the Titans) pause the dma to start MFIFO
if(value & 0x1) vif1.done = false; //This must be done here! some games (ala Crash of the Titans) pause the dma to start MFIFO
DmaExec8(dmaVIF1, mem, value);
break;
@ -288,25 +321,25 @@ __forceinline void hwWrite16(u32 mem, u16 value)
switch(mem)
{
case 0x10000000: rcntWcount(0, value); break;
case 0x10000010: rcntWmode(0, value); break;
case 0x10000020: rcntWtarget(0, value); break;
case 0x10000030: rcntWhold(0, value); break;
case RCNT0_COUNT: rcntWcount(0, value); break;
case RCNT0_MODE: rcntWmode(0, value); break;
case RCNT0_TARGET: rcntWtarget(0, value); break;
case RCNT0_HOLD: rcntWhold(0, value); break;
case 0x10000800: rcntWcount(1, value); break;
case 0x10000810: rcntWmode(1, value); break;
case 0x10000820: rcntWtarget(1, value); break;
case 0x10000830: rcntWhold(1, value); break;
case RCNT1_COUNT: rcntWcount(1, value); break;
case RCNT1_MODE: rcntWmode(1, value); break;
case RCNT1_TARGET: rcntWtarget(1, value); break;
case RCNT1_HOLD: rcntWhold(1, value); break;
case 0x10001000: rcntWcount(2, value); break;
case 0x10001010: rcntWmode(2, value); break;
case 0x10001020: rcntWtarget(2, value); break;
case RCNT2_COUNT: rcntWcount(2, value); break;
case RCNT2_MODE: rcntWmode(2, value); break;
case RCNT2_TARGET: rcntWtarget(2, value); break;
case 0x10001800: rcntWcount(3, value); break;
case 0x10001810: rcntWmode(3, value); break;
case 0x10001820: rcntWtarget(3, value); break;
case RCNT3_COUNT: rcntWcount(3, value); break;
case RCNT3_MODE: rcntWmode(3, value); break;
case RCNT3_TARGET: rcntWtarget(3, value); break;
case 0x10008000: // dma0 - vif0
case D0_CHCR: // dma0 - vif0
DMA_LOG("VIF0dma %lx", value);
if ((value & 0x100) && !(psHu32(DMAC_CTRL) & 0x1))
{
@ -316,46 +349,46 @@ __forceinline void hwWrite16(u32 mem, u16 value)
DmaExec16(dmaVIF0, mem, value);
break;
case 0x10009000: // dma1 - vif1 - chcr
case D1_CHCR: // dma1 - vif1 - chcr
DMA_LOG("VIF1dma CHCR %lx", value);
if ((value & 0x100) && !(psHu32(DMAC_CTRL) & 0x1))
{
DevCon::Notice("16 bit VIF1 DMA Start while DMAC Disabled\n");
QueuedDMA |= 0x2;
}
if(value & 0x100) vif1.done = 0; //This must be done here! some games (ala Crash of the Titans) pause the dma to start MFIFO
if(value & 0x100) vif1.done = false; //This must be done here! some games (ala Crash of the Titans) pause the dma to start MFIFO
DmaExec16(dmaVIF1, mem, value);
break;
#ifdef PCSX2_DEVBUILD
case 0x10009010: // dma1 - vif1 - madr
case D1_MADR: // dma1 - vif1 - madr
HW_LOG("VIF1dma Madr %lx", value);
psHu16(mem) = value;//dma1 madr
break;
case 0x10009020: // dma1 - vif1 - qwc
case D1_QWC: // dma1 - vif1 - qwc
HW_LOG("VIF1dma QWC %lx", value);
psHu16(mem) = value;//dma1 qwc
break;
case 0x10009030: // dma1 - vif1 - tadr
case D1_TADR: // dma1 - vif1 - tadr
HW_LOG("VIF1dma TADR %lx", value);
psHu16(mem) = value;//dma1 tadr
break;
case 0x10009040: // dma1 - vif1 - asr0
case D1_ASR0: // dma1 - vif1 - asr0
HW_LOG("VIF1dma ASR0 %lx", value);
psHu16(mem) = value;//dma1 asr0
break;
case 0x10009050: // dma1 - vif1 - asr1
case D1_ASR1: // dma1 - vif1 - asr1
HW_LOG("VIF1dma ASR1 %lx", value);
psHu16(mem) = value;//dma1 asr1
break;
case 0x10009080: // dma1 - vif1 - sadr
case D1_SADR: // dma1 - vif1 - sadr
HW_LOG("VIF1dma SADR %lx", value);
psHu16(mem) = value;//dma1 sadr
break;
#endif
// ---------------------------------------------------
case 0x1000a000: // dma2 - gif
case D2_CHCR: // dma2 - gif
DMA_LOG("0x%8.8x hwWrite32: GSdma %lx", cpuRegs.cycle, value);
if ((value & 0x100) && !(psHu32(DMAC_CTRL) & 0x1))
{
@ -366,33 +399,33 @@ __forceinline void hwWrite16(u32 mem, u16 value)
break;
#ifdef PCSX2_DEVBUILD
case 0x1000a010:
case D2_MADR:
psHu16(mem) = value;//dma2 madr
HW_LOG("Hardware write DMA2_MADR 32bit at %x with value %x",mem,value);
break;
case 0x1000a020:
psHu16(mem) = value;//dma2 qwc
HW_LOG("Hardware write DMA2_QWC 32bit at %x with value %x",mem,value);
break;
case 0x1000a030:
psHu16(mem) = value;//dma2 taddr
HW_LOG("Hardware write DMA2_TADDR 32bit at %x with value %x",mem,value);
break;
case 0x1000a040:
psHu16(mem) = value;//dma2 asr0
HW_LOG("Hardware write DMA2_ASR0 32bit at %x with value %x",mem,value);
break;
case 0x1000a050:
psHu16(mem) = value;//dma2 asr1
HW_LOG("Hardware write DMA2_ASR1 32bit at %x with value %x",mem,value);
break;
case 0x1000a080:
psHu16(mem) = value;//dma2 saddr
HW_LOG("Hardware write DMA2_SADDR 32bit at %x with value %x",mem,value);
break;
case D2_QWC:
psHu16(mem) = value;//dma2 qwc
HW_LOG("Hardware write DMA2_QWC 32bit at %x with value %x",mem,value);
break;
case D2_TADR:
psHu16(mem) = value;//dma2 taddr
HW_LOG("Hardware write DMA2_TADDR 32bit at %x with value %x",mem,value);
break;
case D2_ASR0:
psHu16(mem) = value;//dma2 asr0
HW_LOG("Hardware write DMA2_ASR0 32bit at %x with value %x",mem,value);
break;
case D2_ASR1:
psHu16(mem) = value;//dma2 asr1
HW_LOG("Hardware write DMA2_ASR1 32bit at %x with value %x",mem,value);
break;
case D2_SADR:
psHu16(mem) = value;//dma2 saddr
HW_LOG("Hardware write DMA2_SADDR 32bit at %x with value %x",mem,value);
break;
#endif
case 0x1000b000: // dma3 - fromIPU
case D3_CHCR: // dma3 - fromIPU
DMA_LOG("IPU0dma %lx", value);
if ((value & 0x100) && !(psHu32(DMAC_CTRL) & 0x1))
{
@ -403,25 +436,25 @@ __forceinline void hwWrite16(u32 mem, u16 value)
break;
#ifdef PCSX2_DEVBUILD
case 0x1000b010:
case D3_MADR:
psHu16(mem) = value;//dma2 madr
HW_LOG("Hardware write IPU0DMA_MADR 32bit at %x with value %x",mem,value);
break;
case 0x1000b020:
psHu16(mem) = value;//dma2 madr
case D3_QWC:
psHu16(mem) = value;//dma2 madr
HW_LOG("Hardware write IPU0DMA_QWC 32bit at %x with value %x",mem,value);
break;
case 0x1000b030:
case D3_TADR:
psHu16(mem) = value;//dma2 tadr
HW_LOG("Hardware write IPU0DMA_TADR 32bit at %x with value %x",mem,value);
break;
case 0x1000b080:
case D3_SADR:
psHu16(mem) = value;//dma2 saddr
HW_LOG("Hardware write IPU0DMA_SADDR 32bit at %x with value %x",mem,value);
break;
#endif
case 0x1000b400: // dma4 - toIPU
case D4_CHCR: // dma4 - toIPU
DMA_LOG("IPU1dma %lx", value);
if ((value & 0x100) && !(psHu32(DMAC_CTRL) & 0x1))
{
@ -432,24 +465,24 @@ __forceinline void hwWrite16(u32 mem, u16 value)
break;
#ifdef PCSX2_DEVBUILD
case 0x1000b410:
psHu16(mem) = value;//dma2 madr
case D4_MADR:
psHu16(mem) = value;//dma2 madr
HW_LOG("Hardware write IPU1DMA_MADR 32bit at %x with value %x",mem,value);
break;
case 0x1000b420:
psHu16(mem) = value;//dma2 madr
case D4_QWC:
psHu16(mem) = value;//dma2 madr
HW_LOG("Hardware write IPU1DMA_QWC 32bit at %x with value %x",mem,value);
break;
case 0x1000b430:
case D4_TADR:
psHu16(mem) = value;//dma2 tadr
HW_LOG("Hardware write IPU1DMA_TADR 32bit at %x with value %x",mem,value);
break;
case 0x1000b480:
case D4_SADR:
psHu16(mem) = value;//dma2 saddr
HW_LOG("Hardware write IPU1DMA_SADDR 32bit at %x with value %x",mem,value);
break;
#endif
case 0x1000c000: // dma5 - sif0
case D5_CHCR: // dma5 - sif0
DMA_LOG("SIF0dma %lx", value);
// if (value == 0) psxSu32(0x30) = 0x40000;
if ((value & 0x100) && !(psHu32(DMAC_CTRL) & 0x1))
@ -463,7 +496,7 @@ __forceinline void hwWrite16(u32 mem, u16 value)
case 0x1000c002:
//?
break;
case 0x1000c400: // dma6 - sif1
case D6_CHCR: // dma6 - sif1
DMA_LOG("SIF1dma %lx", value);
if ((value & 0x100) && !(psHu32(DMAC_CTRL) & 0x1))
{
@ -474,7 +507,8 @@ __forceinline void hwWrite16(u32 mem, u16 value)
break;
#ifdef PCSX2_DEVBUILD
case 0x1000c420: // dma6 - sif1 - qwc
// No D6_MADR, and a TADR address that's not in the defines?
case D6_QWC: // dma6 - sif1 - qwc
HW_LOG("SIF1dma QWC = %lx", value);
psHu16(mem) = value;
break;
@ -485,7 +519,7 @@ __forceinline void hwWrite16(u32 mem, u16 value)
break;
#endif
case 0x1000c800: // dma7 - sif2
case D7_CHCR: // dma7 - sif2
DMA_LOG("SIF2dma %lx", value);
if ((value & 0x100) && !(psHu32(DMAC_CTRL) & 0x1))
{
@ -497,7 +531,7 @@ __forceinline void hwWrite16(u32 mem, u16 value)
case 0x1000c802:
//?
break;
case 0x1000d000: // dma8 - fromSPR
case D8_CHCR: // dma8 - fromSPR
DMA_LOG("fromSPRdma %lx", value);
if ((value & 0x100) && !(psHu32(DMAC_CTRL) & 0x1))
{
@ -532,13 +566,13 @@ __forceinline void hwWrite16(u32 mem, u16 value)
psHu16(mem) = value;
break;
case 0x1000f220:
case SBUS_F220:
psHu16(mem) |= value;
break;
case 0x1000f230:
case SBUS_SMFLG:
psHu16(mem) &= ~value;
break;
case 0x1000f240:
case SBUS_F240:
if(!(value & 0x100))
psHu16(mem) &= ~0x100;
else
@ -762,13 +796,13 @@ void __fastcall hwWrite32_page_0F( u32 mem, u32 value )
case HELPSWITCH(0x1000f200):
psHu32(mem) = value;
break;
case HELPSWITCH(0x1000f220):
case HELPSWITCH(SBUS_F220):
psHu32(mem) |= value;
break;
case HELPSWITCH(0x1000f230):
case HELPSWITCH(SBUS_SMFLG):
psHu32(mem) &= ~value;
break;
case HELPSWITCH(0x1000f240):
case HELPSWITCH(SBUS_F240):
if(!(value & 0x100))
psHu32(mem) &= ~0x100;
else
@ -782,7 +816,7 @@ void __fastcall hwWrite32_page_0F( u32 mem, u32 value )
psHu32(mem) = value;
break;
case HELPSWITCH(0x1000f590): // DMAC_ENABLEW
case HELPSWITCH(DMAC_ENABLEW): // DMAC_ENABLEW
HW_LOG("DMAC_ENABLEW Write 32bit %lx", value);
psHu32(0xf590) = value;
psHu32(0xf520) = value;
@ -826,7 +860,7 @@ void __fastcall hwWrite32_generic( u32 mem, u32 value )
}
if(value & 0x100)
{
vif1.done = 0; //This must be done here! some games (ala Crash of the Titans) pause the dma to start MFIFO
vif1.done = false; //This must be done here! some games (ala Crash of the Titans) pause the dma to start MFIFO
}
DmaExec(dmaVIF1, mem, value);
return;
@ -850,14 +884,14 @@ void __fastcall hwWrite32_generic( u32 mem, u32 value )
return;
case D2_MADR: regName = "GIFdma MADR"; break;
case D2_QWC: regName = "GIFdma QWC"; break;
case D2_TADR: regName = "GIFdma TADDR"; break;
case D2_ASR0: regName = "GIFdma ASR0"; break;
case D2_ASR1: regName = "GIFdma ASR1"; break;
case D2_SADR: regName = "GIFdma SADDR"; break;
case D2_QWC: regName = "GIFdma QWC"; break;
case D2_TADR: regName = "GIFdma TADDR"; break;
case D2_ASR0: regName = "GIFdma ASR0"; break;
case D2_ASR1: regName = "GIFdma ASR1"; break;
case D2_SADR: regName = "GIFdma SADDR"; break;
//------------------------------------------------------------------
case 0x1000c000: // dma5 - sif0
case D5_CHCR: // dma5 - sif0
DMA_LOG("SIF0dma EXECUTE, value=0x%x", value);
//if (value == 0) psxSu32(0x30) = 0x40000;
if ((value & 0x100) && !(psHu32(DMAC_CTRL) & 0x1))
@ -868,7 +902,7 @@ void __fastcall hwWrite32_generic( u32 mem, u32 value )
DmaExec(dmaSIF0, mem, value);
return;
//------------------------------------------------------------------
case 0x1000c400: // dma6 - sif1
case D6_CHCR: // dma6 - sif1
DMA_LOG("SIF1dma EXECUTE, value=0x%x", value);
if ((value & 0x100) && !(psHu32(DMAC_CTRL) & 0x1))
{
@ -878,11 +912,12 @@ void __fastcall hwWrite32_generic( u32 mem, u32 value )
DmaExec(dmaSIF1, mem, value);
return;
case 0x1000c420: regName = "SIF1dma QWC"; break;
// Again, no MADR, and an undefined TADR.
case D6_QWC: regName = "SIF1dma QWC"; break;
case 0x1000c430: regName = "SIF1dma TADR"; break;
//------------------------------------------------------------------
case 0x1000c800: // dma7 - sif2
case D7_CHCR: // dma7 - sif2
DMA_LOG("SIF2dma EXECUTE, value=0x%x", value);
if ((value & 0x100) && !(psHu32(DMAC_CTRL) & 0x1))
{
@ -892,7 +927,7 @@ void __fastcall hwWrite32_generic( u32 mem, u32 value )
DmaExec(dmaSIF2, mem, value);
return;
//------------------------------------------------------------------
case 0x1000d000: // dma8 - fromSPR
case D8_CHCR: // dma8 - fromSPR
DMA_LOG("SPR0dma EXECUTE (fromSPR), value=0x%x", value);
if ((value & 0x100) && !(psHu32(DMAC_CTRL) & 0x1))
{
@ -1015,7 +1050,7 @@ void __fastcall hwWrite64_generic( u32 mem, const mem64_t* srcval )
switch (mem)
{
case 0x1000a000: // dma2 - gif
case D2_CHCR: // dma2 - gif
DMA_LOG("0x%8.8x hwWrite64: GSdma %x", cpuRegs.cycle, value);
DmaExec(dmaGIF, mem, value);
break;
@ -1037,7 +1072,7 @@ void __fastcall hwWrite64_generic( u32 mem, const mem64_t* srcval )
case 0x1000f430:
break;
case 0x1000f590: // DMAC_ENABLEW
case DMAC_ENABLEW: // DMAC_ENABLEW
psHu32(0xf590) = value;
psHu32(0xf520) = value;
break;
@ -1070,7 +1105,7 @@ void __fastcall hwWrite128_generic(u32 mem, const mem128_t *srcval)
cpuTestINTCInts();
break;
case 0x1000f590: // DMAC_ENABLEW
case DMAC_ENABLEW: // DMAC_ENABLEW
psHu32(0xf590) = srcval[0];
psHu32(0xf520) = srcval[0];
break;

View File

@ -48,11 +48,6 @@ using namespace std; // for min / max
# define IPU_FORCEINLINE __forceinline
#endif
//IPUregisters g_ipuRegsReal;
#define ipu0dma ((DMACh *)&PS2MEM_HW[0xb000])
#define ipu1dma ((DMACh *)&PS2MEM_HW[0xb400])
#define IPU_DMA_GIFSTALL 1
#define IPU_DMA_TIE0 2
#define IPU_DMA_TIE1 4
@ -369,7 +364,7 @@ __forceinline void ipuWrite64(u32 mem, u64 value)
switch (mem)
{
case 0x10:
case 0x00:
IPU_LOG("Ipu write64: IPU_CMD=0x%08X", value);
IPUCMD_WRITE((u32)value);
break;
@ -1372,9 +1367,11 @@ int FIFOto_write(u32* pMem, int size)
g_nDMATransfer |= IPU_DMA_ACTV1; \
return totalqwc; \
} \
} \
} \
}
extern void gsInterrupt();
int IPU1dma()
{
u32 *ptag, *pMem;
@ -1388,6 +1385,13 @@ int IPU1dma()
assert(!(g_nDMATransfer & IPU_DMA_TIE1));
//We need to make sure GIF has flushed before sending IPU data, it seems to REALLY screw FFX videos
while(gif->chcr & 0x100)
{
GIF_LOG("Flushing gif chcr %x tadr %x madr %x qwc %x", gif->chcr, gif->tadr, gif->madr, gif->qwc);
gsInterrupt();
}
// in kh, qwc == 0 when dma_actv1 is set
if ((g_nDMATransfer & IPU_DMA_ACTV1) && ipu1dma->qwc > 0)
{
@ -1404,8 +1408,6 @@ int IPU1dma()
return totalqwc;
}
g_nDMATransfer &= ~(IPU_DMA_ACTV1 | IPU_DMA_DOTIE1);
if ((ipu1dma->chcr&0xc) == 0)
{
IPU_INT_TO(totalqwc*BIAS);
@ -1449,6 +1451,8 @@ int IPU1dma()
return totalqwc;
}
}
g_nDMATransfer &= ~(IPU_DMA_ACTV1 | IPU_DMA_DOTIE1);
}
if ((ipu1dma->chcr & 0xc) == 0 && ipu1dma->qwc == 0) // Normal Mode

View File

@ -112,7 +112,8 @@ void __fastcall intDoBranch(u32 target)
}
}
void intSetBranch() {
void intSetBranch()
{
branch2 = /*cpuRegs.branch =*/ 1;
}
@ -133,90 +134,223 @@ namespace OpcodeImpl {
* Format: OP target *
*********************************************************/
void J() {
void J()
{
doBranch(_JumpTarget_);
}
void JAL() {
_SetLink(31); doBranch(_JumpTarget_);
void JAL()
{
_SetLink(31);
doBranch(_JumpTarget_);
}
/*********************************************************
* Register branch logic *
* Format: OP rs, rt, offset *
*********************************************************/
#define RepBranchi32(op) \
if (cpuRegs.GPR.r[_Rs_].SD[0] op cpuRegs.GPR.r[_Rt_].SD[0]) doBranch(_BranchTarget_); \
else intEventTest();
void BEQ() // Branch if Rs == Rt
{
if (cpuRegs.GPR.r[_Rs_].SD[0] == cpuRegs.GPR.r[_Rt_].SD[0])
doBranch(_BranchTarget_);
else
intEventTest();
}
void BEQ() { RepBranchi32(==) } // Branch if Rs == Rt
void BNE() { RepBranchi32(!=) } // Branch if Rs != Rt
void BNE() // Branch if Rs != Rt
{
if (cpuRegs.GPR.r[_Rs_].SD[0] != cpuRegs.GPR.r[_Rt_].SD[0])
doBranch(_BranchTarget_);
else
intEventTest();
}
/*********************************************************
* Register branch logic *
* Format: OP rs, offset *
*********************************************************/
#define RepZBranchi32(op) \
if(cpuRegs.GPR.r[_Rs_].SD[0] op 0) { \
doBranch(_BranchTarget_); \
}
#define RepZBranchLinki32(op) \
void BGEZ() // Branch if Rs >= 0
{
if(cpuRegs.GPR.r[_Rs_].SD[0] >= 0)
{
doBranch(_BranchTarget_);
}
}
void BGEZAL() // Branch if Rs >= 0 and link
{
_SetLink(31);
if (cpuRegs.GPR.r[_Rs_].SD[0] >= 0)
{
doBranch(_BranchTarget_);
}
}
void BGTZ() // Branch if Rs > 0
{
if (cpuRegs.GPR.r[_Rs_].SD[0] > 0)
{
doBranch(_BranchTarget_);
}
}
void BLEZ() // Branch if Rs <= 0
{
if (cpuRegs.GPR.r[_Rs_].SD[0] <= 0)
{
doBranch(_BranchTarget_);
}
}
void BLTZ() // Branch if Rs < 0
{
if (cpuRegs.GPR.r[_Rs_].SD[0] < 0)
{
doBranch(_BranchTarget_);
}
}
void BLTZAL() // Branch if Rs < 0 and link
{
_SetLink(31); \
if(cpuRegs.GPR.r[_Rs_].SD[0] op 0) { \
doBranch(_BranchTarget_); \
if (cpuRegs.GPR.r[_Rs_].SD[0] < 0)
{
doBranch(_BranchTarget_);
}
void BGEZ() { RepZBranchi32(>=) } // Branch if Rs >= 0
void BGEZAL() { RepZBranchLinki32(>=) } // Branch if Rs >= 0 and link
void BGTZ() { RepZBranchi32(>) } // Branch if Rs > 0
void BLEZ() { RepZBranchi32(<=) } // Branch if Rs <= 0
void BLTZ() { RepZBranchi32(<) } // Branch if Rs < 0
void BLTZAL() { RepZBranchLinki32(<) } // Branch if Rs < 0 and link
}
/*********************************************************
* Register branch logic Likely *
* Format: OP rs, offset *
*********************************************************/
#define RepZBranchi32Likely(op) \
if(cpuRegs.GPR.r[_Rs_].SD[0] op 0) { \
doBranch(_BranchTarget_); \
} else { cpuRegs.pc +=4; intEventTest(); }
#define RepZBranchLinki32Likely(op) \
_SetLink(31); \
if(cpuRegs.GPR.r[_Rs_].SD[0] op 0) { \
doBranch(_BranchTarget_); \
} else { cpuRegs.pc +=4; intEventTest(); }
#define RepBranchi32Likely(op) \
if(cpuRegs.GPR.r[_Rs_].SD[0] op cpuRegs.GPR.r[_Rt_].SD[0]) { \
doBranch(_BranchTarget_); \
} else { cpuRegs.pc +=4; intEventTest(); }
void BEQL() { RepBranchi32Likely(==) } // Branch if Rs == Rt
void BNEL() { RepBranchi32Likely(!=) } // Branch if Rs != Rt
void BLEZL() { RepZBranchi32Likely(<=) } // Branch if Rs <= 0
void BGTZL() { RepZBranchi32Likely(>) } // Branch if Rs > 0
void BLTZL() { RepZBranchi32Likely(<) } // Branch if Rs < 0
void BGEZL() { RepZBranchi32Likely(>=) } // Branch if Rs >= 0
void BLTZALL() { RepZBranchLinki32Likely(<) } // Branch if Rs < 0 and link
void BGEZALL() { RepZBranchLinki32Likely(>=) } // Branch if Rs >= 0 and link
void BEQL() // Branch if Rs == Rt
{
if(cpuRegs.GPR.r[_Rs_].SD[0] == cpuRegs.GPR.r[_Rt_].SD[0])
{
doBranch(_BranchTarget_);
}
else
{
cpuRegs.pc +=4;
intEventTest();
}
}
void BNEL() // Branch if Rs != Rt
{
if(cpuRegs.GPR.r[_Rs_].SD[0] != cpuRegs.GPR.r[_Rt_].SD[0])
{
doBranch(_BranchTarget_);
}
else
{
cpuRegs.pc +=4;
intEventTest();
}
}
void BLEZL() // Branch if Rs <= 0
{
if(cpuRegs.GPR.r[_Rs_].SD[0] <= 0)
{
doBranch(_BranchTarget_);
}
else
{
cpuRegs.pc +=4;
intEventTest();
}
}
void BGTZL() // Branch if Rs > 0
{
if(cpuRegs.GPR.r[_Rs_].SD[0] > 0)
{
doBranch(_BranchTarget_);
}
else
{
cpuRegs.pc +=4;
intEventTest();
}
}
void BLTZL() // Branch if Rs < 0
{
if(cpuRegs.GPR.r[_Rs_].SD[0] < 0)
{
doBranch(_BranchTarget_);
}
else
{
cpuRegs.pc +=4;
intEventTest();
}
}
void BGEZL() // Branch if Rs >= 0
{
if(cpuRegs.GPR.r[_Rs_].SD[0] >= 0)
{
doBranch(_BranchTarget_);
}
else
{
cpuRegs.pc +=4;
intEventTest();
}
}
void BLTZALL() // Branch if Rs < 0 and link
{
_SetLink(31);
if(cpuRegs.GPR.r[_Rs_].SD[0] < 0)
{
doBranch(_BranchTarget_);
}
else
{
cpuRegs.pc +=4;
intEventTest();
}
}
void BGEZALL() // Branch if Rs >= 0 and link
{
_SetLink(31);
if(cpuRegs.GPR.r[_Rs_].SD[0] >= 0)
{
doBranch(_BranchTarget_);
}
else
{
cpuRegs.pc +=4;
intEventTest();
}
}
/*********************************************************
* Register jump *
* Format: OP rs, rd *
*********************************************************/
void JR() {
void JR()
{
doBranch(cpuRegs.GPR.r[_Rs_].UL[0]);
}
void JALR() {
void JALR()
{
u32 temp = cpuRegs.GPR.r[_Rs_].UL[0];
if (_Rd_) { _SetLink(_Rd_); }
if (_Rd_) _SetLink(_Rd_);
doBranch(temp);
}
@ -235,7 +369,7 @@ void intReset()
branch2 = 0;
}
bool intEventTest()
bool intEventTest()
{
// Perform counters, ints, and IOP updates:
return _cpuBranchTest_Shared();

View File

@ -29,10 +29,10 @@
#include "Sio.h"
#include "Sif.h"
#include "IopDma.h"
#include "IopMem.h"
#include "IopHw.h"
#include "IopBios.h"
#include "IopDma.h"
#include "IopCounters.h"
#include "IopSio2.h"

View File

@ -38,8 +38,7 @@
#define PSXPIXEL ((int)(PSXCLK / 13500000))
#define PSXSOUNDCLK ((int)(48000))
psxCounter psxCounters[8];
psxCounter psxCounters[NUM_COUNTERS];
s32 psxNextCounter;
u32 psxNextsCounter;
u8 psxhblankgate = 0;
@ -141,6 +140,12 @@ void psxRcntInit() {
psxCounters[7].mode = 0x8;
}
#ifdef ENABLE_NEW_IOPDMA
psxCounters[8].rate = 2000;
psxCounters[8].CycleT = psxCounters[7].rate;
psxCounters[8].mode = 0x8;
#endif
for (i=0; i<8; i++)
psxCounters[i].sCycleT = psxRegs.cycle;
@ -453,6 +458,24 @@ void psxRcntUpdate()
if (c < psxNextCounter) psxNextCounter = c;
}
#ifdef ENABLE_NEW_IOPDMA
// New Iop DMA handler WIP
{
const s32 difference = psxRegs.cycle - psxCounters[8].sCycleT;
s32 c = psxCounters[8].CycleT;
if(difference >= psxCounters[8].CycleT)
{
psxCounters[8].sCycleT = psxRegs.cycle;
psxCounters[8].CycleT = psxCounters[8].rate;
IopDmaUpdate(difference);
}
else c -= difference;
if (c < psxNextCounter) psxNextCounter = c;
}
#endif
for (i=0; i<6; i++) _rcntSet( i );
}

View File

@ -27,7 +27,13 @@ struct psxCounter {
s32 CycleT;
};
extern psxCounter psxCounters[8];
#ifdef ENABLE_NEW_IOPDMA
# define NUM_COUNTERS 9
#else
# define NUM_COUNTERS 8
#endif
extern psxCounter psxCounters[NUM_COUNTERS];
extern s32 psxNextCounter;
extern u32 psxNextsCounter;

View File

@ -28,6 +28,7 @@ using namespace R3000A;
// Should be a bool, and will be next time I break savestate. --arcum42
int iopsifbusy[2] = { 0, 0 };
extern int eesifbusy[2];
static void __fastcall psxDmaGeneric(u32 madr, u32 bcr, u32 chcr, u32 spuCore, _SPU2writeDMA4Mem spu2WriteFunc, _SPU2readDMA4Mem spu2ReadFunc)
{
@ -74,6 +75,14 @@ static void __fastcall psxDmaGeneric(u32 madr, u32 bcr, u32 chcr, u32 spuCore, _
}
}
void psxDma2(u32 madr, u32 bcr, u32 chcr) // GPU
{
HW_DMA2_CHCR &= ~0x01000000;
psxDmaInterrupt(2);
}
/* psxDma3 is in CdRom.cpp */
void psxDma4(u32 madr, u32 bcr, u32 chcr) // SPU2's Core 0
{
psxDmaGeneric(madr, bcr, chcr, 0, SPU2writeDMA4Mem, SPU2readDMA4Mem);
@ -87,12 +96,6 @@ int psxDma4Interrupt()
return 1;
}
void psxDma2(u32 madr, u32 bcr, u32 chcr) // GPU
{
HW_DMA2_CHCR &= ~0x01000000;
psxDmaInterrupt(2);
}
void psxDma6(u32 madr, u32 bcr, u32 chcr)
{
u32 *mem = (u32 *)iopPhysMem(madr);
@ -130,7 +133,32 @@ int psxDma7Interrupt()
return 1;
}
extern int eesifbusy[2];
void psxDma8(u32 madr, u32 bcr, u32 chcr)
{
const int size = (bcr >> 16) * (bcr & 0xFFFF) * 8;
switch (chcr & 0x01000201)
{
case 0x01000201: //cpu to dev9 transfer
PSXDMA_LOG("*** DMA 8 - DEV9 mem2dev9 *** %lx addr = %lx size = %lx", chcr, madr, bcr);
DEV9writeDMA8Mem((u32*)iopPhysMem(madr), size);
break;
case 0x01000200: //dev9 to cpu transfer
PSXDMA_LOG("*** DMA 8 - DEV9 dev9mem *** %lx addr = %lx size = %lx", chcr, madr, bcr);
DEV9readDMA8Mem((u32*)iopPhysMem(madr), size);
break;
default:
PSXDMA_LOG("*** DMA 8 - DEV9 unknown *** %lx addr = %lx size = %lx", chcr, madr, bcr);
break;
}
HW_DMA8_CHCR &= ~0x01000000;
psxDmaInterrupt2(1);
}
void psxDma9(u32 madr, u32 bcr, u32 chcr)
{
SIF_LOG("IOP: dmaSIF0 chcr = %lx, madr = %lx, bcr = %lx, tadr = %lx", chcr, madr, bcr, HW_DMA9_TADR);
@ -164,32 +192,9 @@ void psxDma10(u32 madr, u32 bcr, u32 chcr)
}
}
void psxDma8(u32 madr, u32 bcr, u32 chcr)
{
/* psxDma11 & psxDma 12 are in IopSio2,cpp, along with the appropriate interrupt functions. */
const int size = (bcr >> 16) * (bcr & 0xFFFF) * 8;
switch (chcr & 0x01000201)
{
case 0x01000201: //cpu to dev9 transfer
PSXDMA_LOG("*** DMA 8 - DEV9 mem2dev9 *** %lx addr = %lx size = %lx", chcr, madr, bcr);
DEV9writeDMA8Mem((u32*)iopPhysMem(madr), size);
break;
case 0x01000200: //dev9 to cpu transfer
PSXDMA_LOG("*** DMA 8 - DEV9 dev9mem *** %lx addr = %lx size = %lx", chcr, madr, bcr);
DEV9readDMA8Mem((u32*)iopPhysMem(madr), size);
break;
default:
PSXDMA_LOG("*** DMA 8 - DEV9 unknown *** %lx addr = %lx size = %lx", chcr, madr, bcr);
break;
}
HW_DMA8_CHCR &= ~0x01000000;
psxDmaInterrupt2(1);
}
void dev9Interrupt()
void dev9Interrupt()
{
if ((dev9Handler != NULL) && (dev9Handler() != 1)) return;
@ -202,7 +207,7 @@ void dev9Irq(int cycles)
PSX_INT(IopEvt_DEV9, cycles);
}
void usbInterrupt()
void usbInterrupt()
{
if (usbHandler != NULL && (usbHandler() != 1)) return;
@ -253,35 +258,96 @@ void iopIntcIrq(uint irqType)
//
// fixme: Is this in progress?
#if FALSE
#ifdef ENABLE_NEW_IOPDMA
typedef s32(* DmaHandler)(s32 channel, u32* data, u32 wordsLeft, u32* wordsProcessed);
typedef void (* DmaIHandler)(s32 channel);
s32 errDmaWrite(s32 channel, u32* data, u32 wordsLeft, u32* wordsProcessed);
s32 errDmaRead(s32 channel, u32* data, u32 wordsLeft, u32* wordsProcessed);
struct DmaHandlerInfo
s32 spu2DmaRead(s32 channel, u32* data, u32 bytesLeft, u32* bytesProcessed)
{
DmaHandler Read;
DmaHandler Write;
DmaIHandler Interrupt;
};
// FIXME: change the plugin interfaces so that they are aware of this new dma handler
struct DmaStatusInfo
/*
u32 bytes = 1024;
if(bytesLeft<1024)
bytes=bytesLeft;
*/
u32 bytes=bytesLeft;
// Update the spu2 to the current cycle before initiating the DMA
if (SPU2async)
{
SPU2async(psxRegs.cycle - psxCounters[6].sCycleT);
//Console::Status("cycles sent to SPU2 %x\n", psxRegs.cycle - psxCounters[6].sCycleT);
psxCounters[6].sCycleT = psxRegs.cycle;
psxCounters[6].CycleT = bytes * 3;
psxNextCounter -= (psxRegs.cycle - psxNextsCounter);
psxNextsCounter = psxRegs.cycle;
if (psxCounters[6].CycleT < psxNextCounter)
psxNextCounter = psxCounters[6].CycleT;
}
if(channel==7)
SPU2readDMA7Mem((u16 *)data, bytes/2);
else
SPU2readDMA4Mem((u16 *)data, bytes/2);
*bytesProcessed = bytes;
return 0;
}
s32 spu2DmaWrite(s32 channel, u32* data, u32 bytesLeft, u32* bytesProcessed)
{
u32 Control;
u32 Width; // bytes/word, for timing purposes
u32 MemAddr;
u32 ByteCount;
u32 Target;
};
// FIXME: change the plugin interfaces so that they are aware of this new dma handler
// FIXME: Dummy constants, to be "filled in" with proper values later
#define DMA_CTRL_ACTIVE 0x80000000
#define DMA_CTRL_DIRECTION 0x00000001
#define DMA_CHANNEL_MAX 16 /* ? */
/*
u32 bytes = 1024;
if(bytesLeft<1024)
bytes=bytesLeft;
*/
u32 bytes=bytesLeft;
// Update the spu2 to the current cycle before initiating the DMA
if (SPU2async)
{
SPU2async(psxRegs.cycle - psxCounters[6].sCycleT);
//Console::Status("cycles sent to SPU2 %x\n", psxRegs.cycle - psxCounters[6].sCycleT);
psxCounters[6].sCycleT = psxRegs.cycle;
psxCounters[6].CycleT = bytes * 3;
psxNextCounter -= (psxRegs.cycle - psxNextsCounter);
psxNextsCounter = psxRegs.cycle;
if (psxCounters[6].CycleT < psxNextCounter)
psxNextCounter = psxCounters[6].CycleT;
}
if(channel==7)
SPU2writeDMA7Mem((u16 *)data, bytes/2);
else
SPU2writeDMA4Mem((u16 *)data, bytes/2);
*bytesProcessed = bytes;
return 0;
}
void spu2DmaInterrupt(s32 channel)
{
if(channel==7)
SPU2interruptDMA7();
else
SPU2interruptDMA4();
}
//typedef s32(* DmaHandler)(s32 channel, u32* data, u32 bytesLeft, u32* bytesProcessed);
//typedef void (* DmaIHandler)(s32 channel);
s32 errDmaWrite(s32 channel, u32* data, u32 bytesLeft, u32* bytesProcessed);
s32 errDmaRead(s32 channel, u32* data, u32 bytesLeft, u32* bytesProcessed);
DmaStatusInfo IopChannels[DMA_CHANNEL_MAX]; // I dont' knwo how many there are, 10?
@ -295,9 +361,9 @@ DmaHandlerInfo IopDmaHandlers[DMA_CHANNEL_MAX] =
{0}, //5
{0}, //6: OT?
{spu2DmaRead, spu2DmaWrite, spu2DmaInterrupt}, //7: Spu Core1
{dev9DmaRead, dev9DmaWrite, dev9DmaInterrupt}, //8: Dev9
{sif0DmaRead, sif0DmaWrite, sif0DmaInterrupt}, //9: SIF0
{sif1DmaRead, sif1DmaWrite, sif1DmaInterrupt}, //10: SIF1
{0},//{dev9DmaRead, dev9DmaWrite, dev9DmaInterrupt}, //8: Dev9
{0},//{sif0DmaRead, sif0DmaWrite, sif0DmaInterrupt}, //9: SIF0
{0},//{sif1DmaRead, sif1DmaWrite, sif1DmaInterrupt}, //10: SIF1
{0}, // Sio2
{0}, // Sio2
};
@ -319,26 +385,37 @@ const char* IopDmaNames[DMA_CHANNEL_MAX] =
"Sio2",
"?", "?", "?"
};
};
// Prototypes. To be implemented later (or in other parts of the emulator)
void SetDmaUpdateTarget(u32 delay);
void RaiseDmaIrq(u32 channel);
void SetDmaUpdateTarget(u32 delay)
{
psxCounters[8].CycleT = delay;
}
void RaiseDmaIrq(u32 channel)
{
if(channel<7)
psxDmaInterrupt(channel);
else
psxDmaInterrupt2(channel-7);
}
// WARNING: CALLER ****[MUST]**** CALL IopDmaUpdate RIGHT AFTER THIS!
void IopDmaStart(int channel, u32 chcr, u32 madr, u32 bcr)
{
// I dont' really understand this, but it's used above. Is this BYTES OR WHAT?
int size = (bcr >> 16) * (bcr & 0xFFFF);
int size = 4* (bcr >> 16) * (bcr & 0xFFFF);
IopChannels[channel].Control = chcr | DMA_CTRL_ACTIVE;
IopChannels[channel].MemAddr = madr;
IopChannels[channel].ByteCount = size;
SetDmaUpdateTarget(0);
}
void IopDmaUpdate(u32 elapsed)
{
u32 MinDelay = 0xFFFFFFFF;
s32 MinDelay = 0x7FFFFFFF;
for (int i = 0;i < DMA_CHANNEL_MAX;i++)
{
@ -358,12 +435,17 @@ void IopDmaUpdate(u32 elapsed)
else
{
// TODO: Make sure it's the right order
DmaHandler handler = (ch->Control & DMA_CTRL_DIRECTION) ? IopDmaHandlers[i].Read : IopDmaHandlers[i].Write;
DmaHandler handler = (ch->Control & DMA_CTRL_DIRECTION) ? IopDmaHandlers[i].Write : IopDmaHandlers[i].Read;
u32 BCount = 0;
s32 Target = (handler) ? handler(i, (u32*)PSXM(ch->MemAddr), ch->ByteCount, &BCount) : 0;
s32 Target = (handler) ? handler(i, (u32*)iopPhysMem(ch->MemAddr), ch->ByteCount, &BCount) : 0;
ch->Target = 100;
if(BCount>0)
{
psxCpu->Clear(ch->MemAddr, BCount/4);
}
int TTarget = 100;
if (Target < 0)
{
// TODO: ... What to do if the plugin errors? :P
@ -373,29 +455,38 @@ void IopDmaUpdate(u32 elapsed)
ch->MemAddr += BCount;
ch->ByteCount -= BCount;
ch->Target = BCount / ch->Width;
TTarget = BCount; // / ch->Width;
}
if (Target != 0) ch->Target = Target;
if (Target != 0) TTarget = Target;
if (ch->Target<MinDelay) MinDelay = TTarget;
ch->Target += TTarget;
}
}
}
}
if(MinDelay<0x7FFFFFFF)
SetDmaUpdateTarget(MinDelay);
else
SetDmaUpdateTarget(10000);
}
s32 errDmaRead(s32 channel, u32* data, u32 wordsLeft, u32* wordsProcessed)
s32 errDmaRead(s32 channel, u32* data, u32 bytesLeft, u32* bytesProcessed)
{
Console::Error("ERROR: Tried to read using DMA %d (%s). Ignoring.", 0, channel, IopDmaNames[channel]);
Console::Error("ERROR: Tried to read using DMA %d (%s). Ignoring.", params 0, channel, IopDmaNames[channel]);
*wordsProcessed = wordsLeft;
*bytesProcessed = bytesLeft;
return 0;
}
s32 errDmaWrite(s32 channel, u32* data, u32 wordsLeft, u32* wordsProcessed)
s32 errDmaWrite(s32 channel, u32* data, u32 bytesLeft, u32* bytesProcessed)
{
Console::Error("ERROR: Tried to write using DMA %d (%s). Ignoring.", 0, channel, IopDmaNames[channel]);
Console::Error("ERROR: Tried to write using DMA %d (%s). Ignoring.", params 0, channel, IopDmaNames[channel]);
*wordsProcessed = wordsLeft;
*bytesProcessed = bytesLeft;
return 0;
}

View File

@ -21,6 +21,46 @@
#include "PS2Edefs.h"
//#define ENABLE_NEW_IOPDMA
#ifdef ENABLE_NEW_IOPDMA
typedef s32(* DmaHandler)(s32 channel, u32* data, u32 bytesLeft, u32* bytesProcessed);
typedef void (* DmaIHandler)(s32 channel);
struct DmaHandlerInfo
{
DmaHandler Read;
DmaHandler Write;
DmaIHandler Interrupt;
};
struct DmaStatusInfo
{
u32 Control;
u32 Width; // bytes/word, for timing purposes
u32 MemAddr;
u32 ByteCount;
s32 Target;
};
// FIXME: Dummy constants, to be "filled in" with proper values later
#define DMA_CTRL_ACTIVE 0x01000000
#define DMA_CTRL_DIRECTION 0x00000001
#define DMA_CHANNEL_MAX 16 /* ? */
// WARNING: CALLER ****[MUST]**** CALL IopDmaUpdate RIGHT AFTER THIS!
void IopDmaStart(int channel, u32 chcr, u32 madr, u32 bcr);
void IopDmaUpdate(u32 elapsed);
// external dma handlers
extern s32 cdvdDmaRead(s32 channel, u32* data, u32 bytesLeft, u32* bytesProcessed);
extern void cdvdDmaInterrupt(s32 channel);
//#else
#endif
void psxDma2(u32 madr, u32 bcr, u32 chcr);
void psxDma3(u32 madr, u32 bcr, u32 chcr);
void psxDma4(u32 madr, u32 bcr, u32 chcr);

View File

@ -41,7 +41,7 @@ void psxHwReset() {
u8 psxHwRead8(u32 add) {
u8 hard;
if (add >= 0x1f801600 && add < 0x1f801700) {
if (add >= HW_USB_START && add < HW_USB_END) {
return USBread8(add);
}
@ -53,24 +53,24 @@ u8 psxHwRead8(u32 add) {
return DEV9read8(add);
#ifdef PCSX2_DEVBUILD
case 0x1f801100:
case 0x1f801104:
case 0x1f801108:
case 0x1f801110:
case 0x1f801114:
case 0x1f801118:
case 0x1f801120:
case 0x1f801124:
case 0x1f801128:
case 0x1f801480:
case 0x1f801484:
case 0x1f801488:
case 0x1f801490:
case 0x1f801494:
case 0x1f801498:
case 0x1f8014a0:
case 0x1f8014a4:
case 0x1f8014a8:
case IOP_T0_COUNT:
case IOP_T0_MODE:
case IOP_T0_TARGET:
case IOP_T1_COUNT:
case IOP_T1_MODE:
case IOP_T1_TARGET:
case IOP_T2_COUNT:
case IOP_T2_MODE:
case IOP_T2_TARGET:
case IOP_T3_COUNT:
case IOP_T3_MODE:
case IOP_T3_TARGET:
case IOP_T4_COUNT:
case IOP_T4_MODE:
case IOP_T4_TARGET:
case IOP_T5_COUNT:
case IOP_T5_MODE:
case IOP_T5_TARGET:
DevCon::Notice( "IOP Counter Read8 from addr0x%x = 0x%x", params add, psxHu8(add) );
return psxHu8(add);
#endif
@ -102,7 +102,7 @@ u8 psxHwRead8(u32 add) {
u16 psxHwRead16(u32 add) {
u16 hard;
if (add >= 0x1f801600 && add < 0x1f801700) {
if (add >= HW_USB_START && add < HW_USB_END) {
return USBread16(add);
}
@ -136,50 +136,50 @@ u16 psxHwRead16(u32 add) {
return hard;
//Serial port stuff not support now ;P
// case 0x1f801050: hard = serial_read16(); break;
// case 0x1f801054: hard = serial_status_read(); break;
// case 0x1f80105a: hard = serial_control_read(); break;
// case 0x1f80105e: hard = serial_baud_read(); break;
// case 0x1f801050: hard = serial_read16(); break;
// case 0x1f801054: hard = serial_status_read(); break;
// case 0x1f80105a: hard = serial_control_read(); break;
// case 0x1f80105e: hard = serial_baud_read(); break;
case 0x1f801100:
case IOP_T0_COUNT:
hard = (u16)psxRcntRcount16(0);
PSXCNT_LOG("T0 count read16: %x", hard);
return hard;
case 0x1f801104:
case IOP_T0_MODE:
hard = psxCounters[0].mode;
psxCounters[0].mode &= ~0x1800;
psxCounters[0].mode &= ~0x1800;
psxCounters[0].mode |= 0x400;
PSXCNT_LOG("T0 mode read16: %x", hard);
return hard;
case 0x1f801108:
case IOP_T0_TARGET:
hard = psxCounters[0].target;
PSXCNT_LOG("T0 target read16: %x", hard);
return hard;
case 0x1f801110:
case IOP_T1_COUNT:
hard = (u16)psxRcntRcount16(1);
PSXCNT_LOG("T1 count read16: %x", hard);
return hard;
case 0x1f801114:
case IOP_T1_MODE:
hard = psxCounters[1].mode;
psxCounters[1].mode &= ~0x1800;
psxCounters[1].mode |= 0x400;
PSXCNT_LOG("T1 mode read16: %x", hard);
return hard;
case 0x1f801118:
case IOP_T1_TARGET:
hard = psxCounters[1].target;
PSXCNT_LOG("T1 target read16: %x", hard);
return hard;
case 0x1f801120:
case IOP_T2_COUNT:
hard = (u16)psxRcntRcount16(2);
PSXCNT_LOG("T2 count read16: %x", hard);
return hard;
case 0x1f801124:
case IOP_T2_MODE:
hard = psxCounters[2].mode;
psxCounters[2].mode &= ~0x1800;
psxCounters[2].mode |= 0x400;
PSXCNT_LOG("T2 mode read16: %x", hard);
return hard;
case 0x1f801128:
case IOP_T2_TARGET:
hard = psxCounters[2].target;
PSXCNT_LOG("T2 target read16: %x", hard);
return hard;
@ -187,45 +187,45 @@ u16 psxHwRead16(u32 add) {
case 0x1f80146e: // DEV9_R_REV
return DEV9read16(add);
case 0x1f801480:
case IOP_T3_COUNT:
hard = (u16)psxRcntRcount32(3);
PSXCNT_LOG("T3 count read16: %lx", hard);
return hard;
case 0x1f801484:
case IOP_T3_MODE:
hard = psxCounters[3].mode;
psxCounters[3].mode &= ~0x1800;
psxCounters[3].mode |= 0x400;
PSXCNT_LOG("T3 mode read16: %lx", hard);
return hard;
case 0x1f801488:
case IOP_T3_TARGET:
hard = psxCounters[3].target;
PSXCNT_LOG("T3 target read16: %lx", hard);
return hard;
case 0x1f801490:
case IOP_T4_COUNT:
hard = (u16)psxRcntRcount32(4);
PSXCNT_LOG("T4 count read16: %lx", hard);
return hard;
case 0x1f801494:
case IOP_T4_MODE:
hard = psxCounters[4].mode;
psxCounters[4].mode &= ~0x1800;
psxCounters[4].mode |= 0x400;
PSXCNT_LOG("T4 mode read16: %lx", hard);
return hard;
case 0x1f801498:
case IOP_T4_TARGET:
hard = psxCounters[4].target;
PSXCNT_LOG("T4 target read16: %lx", hard);
return hard;
case 0x1f8014a0:
case IOP_T5_COUNT:
hard = (u16)psxRcntRcount32(5);
PSXCNT_LOG("T5 count read16: %lx", hard);
return hard;
case 0x1f8014a4:
case IOP_T5_MODE:
hard = psxCounters[5].mode;
psxCounters[5].mode &= ~0x1800;
psxCounters[5].mode |= 0x400;
PSXCNT_LOG("T5 mode read16: %lx", hard);
return hard;
case 0x1f8014a8:
case IOP_T5_TARGET:
hard = psxCounters[5].target;
PSXCNT_LOG("T5 target read16: %lx", hard);
return hard;
@ -238,11 +238,11 @@ u16 psxHwRead16(u32 add) {
hard = psxHu16(0x1506);
PSXHW_LOG("DMA7 BCR_count 16bit read %lx", hard);
return hard;
//case 0x1f802030: hard = //int_2000????
//case 0x1f802040: hard =//dip switches...??
// case 0x1f802030: hard = //int_2000????
// case 0x1f802040: hard =//dip switches...??
default:
if (add>=0x1f801c00 && add<0x1f801e00) {
if (add>=HW_SPU2_START && add<HW_SPU2_END) {
hard = SPU2read(add);
} else {
hard = psxHu16(add);
@ -259,10 +259,10 @@ u16 psxHwRead16(u32 add) {
u32 psxHwRead32(u32 add) {
u32 hard;
if (add >= 0x1f801600 && add < 0x1f801700) {
if (add >= HW_USB_START && add < HW_USB_END) {
return USBread32(add);
}
if (add >= 0x1f808400 && add <= 0x1f808550) {//the size is a complete guess..
if (add >= HW_FW_START && add <= HW_FW_END) {//the size is a complete guess..
return FWread32(add);
}
@ -275,7 +275,7 @@ u32 psxHwRead32(u32 add) {
PAD_LOG("sio read32 ;ret = %lx", hard);
return hard;
// case 0x1f801050: hard = serial_read32(); break;//serial port
// case 0x1f801050: hard = serial_read32(); break;//serial port
case 0x1f801060:
PSXHW_LOG("RAM size read %lx", psxHu32(0x1060));
return psxHu32(0x1060);
@ -289,18 +289,17 @@ u32 psxHwRead32(u32 add) {
psxHu32(0x1078) = 0;
return hard;
/* case 0x1f801810:
// case 0x1f801810:
// hard = GPU_readData();
PSXHW_LOG("GPU DATA 32bit read %lx", hard);
return hard;*/
/* case 0x1f801814:
hard = GPU_readStatus();
PSXHW_LOG("GPU STATUS 32bit read %lx", hard);
return hard;
*/
/* case 0x1f801820: hard = mdecRead0(); break;
case 0x1f801824: hard = mdecRead1(); break;
*/
// PSXHW_LOG("GPU DATA 32bit read %lx", hard);
// return hard;
// case 0x1f801814:
// hard = GPU_readStatus();
// PSXHW_LOG("GPU STATUS 32bit read %lx", hard);
// return hard;
//
// case 0x1f801820: hard = mdecRead0(); break;
// case 0x1f801824: hard = mdecRead1(); break;
case 0x1f8010a0:
PSXHW_LOG("DMA2 MADR 32bit read %lx", psxHu32(0x10a0));
@ -352,7 +351,7 @@ u32 psxHwRead32(u32 add) {
PSXHW_LOG("DMA ICR 32bit read %lx", HW_DMA_ICR);
return HW_DMA_ICR;
//SSBus registers
//SSBus registers
case 0x1f801000:
hard = psxHu32(0x1000);
PSXHW_LOG("SSBUS <spd_addr> 32bit read %lx", hard);
@ -432,79 +431,78 @@ u32 psxHwRead32(u32 add) {
case 0x1f8010c8:
PSXHW_LOG("DMA4 CHCR 32bit read %lx", HW_DMA4_CHCR);
return HW_DMA4_CHCR; // DMA4 chcr (SPU DMA)
return HW_DMA4_CHCR; // DMA4 chcr (SPU DMA)
// time for rootcounters :)
case 0x1f801100:
case IOP_T0_COUNT:
hard = (u16)psxRcntRcount16(0);
PSXCNT_LOG("T0 count read32: %lx", hard);
return hard;
case 0x1f801104:
case IOP_T0_MODE:
hard = (u16)psxCounters[0].mode;
PSXCNT_LOG("T0 mode read32: %lx", hard);
return hard;
case 0x1f801108:
case IOP_T0_TARGET:
hard = psxCounters[0].target;
PSXCNT_LOG("T0 target read32: %lx", hard);
return hard;
case 0x1f801110:
case IOP_T1_COUNT:
hard = (u16)psxRcntRcount16(1);
PSXCNT_LOG("T1 count read32: %lx", hard);
return hard;
case 0x1f801114:
case IOP_T1_MODE:
hard = (u16)psxCounters[1].mode;
PSXCNT_LOG("T1 mode read32: %lx", hard);
return hard;
case 0x1f801118:
case IOP_T1_TARGET:
hard = psxCounters[1].target;
PSXCNT_LOG("T1 target read32: %lx", hard);
return hard;
case 0x1f801120:
case IOP_T2_COUNT:
hard = (u16)psxRcntRcount16(2);
PSXCNT_LOG("T2 count read32: %lx", hard);
return hard;
case 0x1f801124:
case IOP_T2_MODE:
hard = (u16)psxCounters[2].mode;
PSXCNT_LOG("T2 mode read32: %lx", hard);
return hard;
case 0x1f801128:
case IOP_T2_TARGET:
hard = psxCounters[2].target;
PSXCNT_LOG("T2 target read32: %lx", hard);
return hard;
case 0x1f801480:
case IOP_T3_COUNT:
hard = (u32)psxRcntRcount32(3);
PSXCNT_LOG("T3 count read32: %lx", hard);
return hard;
case 0x1f801484:
case IOP_T3_MODE:
hard = (u16)psxCounters[3].mode;
PSXCNT_LOG("T3 mode read32: %lx", hard);
return hard;
case 0x1f801488:
case IOP_T3_TARGET:
hard = psxCounters[3].target;
PSXCNT_LOG("T3 target read32: %lx", hard);
return hard;
case 0x1f801490:
case IOP_T4_COUNT:
hard = (u32)psxRcntRcount32(4);
PSXCNT_LOG("T4 count read32: %lx", hard);
return hard;
case 0x1f801494:
case IOP_T4_MODE:
hard = (u16)psxCounters[4].mode;
PSXCNT_LOG("T4 mode read32: %lx", hard);
return hard;
case 0x1f801498:
case IOP_T4_TARGET:
hard = psxCounters[4].target;
PSXCNT_LOG("T4 target read32: %lx", hard);
return hard;
case 0x1f8014a0:
case IOP_T5_COUNT:
hard = (u32)psxRcntRcount32(5);
PSXCNT_LOG("T5 count read32: %lx", hard);
return hard;
case 0x1f8014a4:
case IOP_T5_MODE:
hard = (u16)psxCounters[5].mode;
PSXCNT_LOG("T5 mode read32: %lx", hard);
return hard;
case 0x1f8014a8:
case IOP_T5_TARGET:
hard = psxCounters[5].target;
PSXCNT_LOG("T5 target read32: %lx", hard);
return hard;
@ -619,18 +617,11 @@ u32 psxHwRead32(u32 add) {
return hard;
}
int g_pbufi;
// A buffer that stores messages until it gets a /n or the number of chars (g_pbufi) is more then 1023.
s8 g_pbuf[1024];
#define DmaExec(n) { \
if (HW_DMA##n##_CHCR & 0x01000000 && \
HW_DMA_PCR & (8 << (n * 4))) { \
psxDma##n(HW_DMA##n##_MADR, HW_DMA##n##_BCR, HW_DMA##n##_CHCR); \
} \
}
int g_pbufi;
void psxHwWrite8(u32 add, u8 value) {
if (add >= 0x1f801600 && add < 0x1f801700) {
if (add >= HW_USB_START && add < HW_USB_END) {
USBwrite8(add, value); return;
}
if((add & 0xf) == 0xa)
@ -638,28 +629,28 @@ void psxHwWrite8(u32 add, u8 value) {
switch (add) {
case 0x1f801040:
sioWrite8(value);
break;
// case 0x1f801050: serial_write8(value); break;//serial port
sioWrite8(value);
break;
// case 0x1f801050: serial_write8(value); break;//serial port
case 0x1f801100:
case 0x1f801104:
case 0x1f801108:
case 0x1f801110:
case 0x1f801114:
case 0x1f801118:
case 0x1f801120:
case 0x1f801124:
case 0x1f801128:
case 0x1f801480:
case 0x1f801484:
case 0x1f801488:
case 0x1f801490:
case 0x1f801494:
case 0x1f801498:
case 0x1f8014a0:
case 0x1f8014a4:
case 0x1f8014a8:
case IOP_T0_COUNT:
case IOP_T0_MODE:
case IOP_T0_TARGET:
case IOP_T1_COUNT:
case IOP_T1_MODE:
case IOP_T1_TARGET:
case IOP_T2_COUNT:
case IOP_T2_MODE:
case IOP_T2_TARGET:
case IOP_T3_COUNT:
case IOP_T3_MODE:
case IOP_T3_TARGET:
case IOP_T4_COUNT:
case IOP_T4_MODE:
case IOP_T4_TARGET:
case IOP_T5_COUNT:
case IOP_T5_MODE:
case IOP_T5_TARGET:
DevCon::Notice( "IOP Counter Write8 to addr 0x%x = 0x%x", params add, value );
psxHu8(add) = value;
return;
@ -676,17 +667,19 @@ void psxHwWrite8(u32 add, u8 value) {
case 0x1f80380c:
if (value == '\r') break;
if (value == '\n' || g_pbufi >= 1023) {
g_pbuf[g_pbufi++] = 0; g_pbufi = 0;
if (value == '\n' || g_pbufi >= 1023) { // A line break, or the buffer is about to overflow.
g_pbuf[g_pbufi++] = 0;
g_pbufi = 0;
DevCon::WriteLn( Color_Cyan, g_pbuf );
}
else g_pbuf[g_pbufi++] = value;
psxHu8(add) = value;
psxHu8(add) = value;
return;
case 0x1F808260:
PSXHW_LOG("SIO2 write8 DATAIN <- %08X", value);
sio2_serialIn(value);return;//serial data feed/fifo
sio2_serialIn(value);
return;//serial data feed/fifo
default:
psxHu8(add) = value;
@ -698,7 +691,7 @@ void psxHwWrite8(u32 add, u8 value) {
}
void psxHwWrite16(u32 add, u16 value) {
if (add >= 0x1f801600 && add < 0x1f801700) {
if (add >= HW_USB_START && add < HW_USB_END) {
USBwrite16(add, value); return;
}
@ -727,10 +720,10 @@ void psxHwWrite16(u32 add, u16 value) {
return;
//serial port ;P
// case 0x1f801050: serial_write16(value); break;
// case 0x1f80105a: serial_control_write(value);break;
// case 0x1f80105e: serial_baud_write(value); break;
// case 0x1f801054: serial_status_write(value); break;
// case 0x1f801050: serial_write16(value); break;
// case 0x1f80105a: serial_control_write(value);break;
// case 0x1f80105e: serial_baud_write(value); break;
// case 0x1f801054: serial_status_write(value); break;
case 0x1f801070:
PSXHW_LOG("IREG 16bit write %x", value);
@ -760,33 +753,33 @@ void psxHwWrite16(u32 add, u16 value) {
PSXHW_LOG("DMA4 BCR_count 16bit write %lx", value);
psxHu16(0x10c6) = value; return; // DMA4 bcr_count
case 0x1f801100:
case IOP_T0_COUNT:
PSXCNT_LOG("COUNTER 0 COUNT 16bit write %x", value);
psxRcntWcount16(0, value); return;
case 0x1f801104:
case IOP_T0_MODE:
PSXCNT_LOG("COUNTER 0 MODE 16bit write %x", value);
psxRcnt0Wmode(value); return;
case 0x1f801108:
case IOP_T0_TARGET:
PSXCNT_LOG("COUNTER 0 TARGET 16bit write %x", value);
psxRcntWtarget16(0, value); return;
case 0x1f801110:
case IOP_T1_COUNT:
PSXCNT_LOG("COUNTER 1 COUNT 16bit write %x", value);
psxRcntWcount16(1, value); return;
case 0x1f801114:
case IOP_T1_MODE:
PSXCNT_LOG("COUNTER 1 MODE 16bit write %x", value);
psxRcnt1Wmode(value); return;
case 0x1f801118:
case IOP_T1_TARGET:
PSXCNT_LOG("COUNTER 1 TARGET 16bit write %x", value);
psxRcntWtarget16(1, value); return;
case 0x1f801120:
case IOP_T2_COUNT:
PSXCNT_LOG("COUNTER 2 COUNT 16bit write %x", value);
psxRcntWcount16(2, value); return;
case 0x1f801124:
case IOP_T2_MODE:
PSXCNT_LOG("COUNTER 2 MODE 16bit write %x", value);
psxRcnt2Wmode(value); return;
case 0x1f801128:
case IOP_T2_TARGET:
PSXCNT_LOG("COUNTER 2 TARGET 16bit write %x", value);
psxRcntWtarget16(2, value); return;
@ -795,33 +788,33 @@ void psxHwWrite16(u32 add, u16 value) {
psxHu16(0x1450) = value/* & (~0x8)*/;
return;
case 0x1f801480:
case IOP_T3_COUNT:
PSXCNT_LOG("COUNTER 3 COUNT 16bit write %lx", value);
psxRcntWcount32(3, value); return;
case 0x1f801484:
case IOP_T3_MODE:
PSXCNT_LOG("COUNTER 3 MODE 16bit write %lx", value);
psxRcnt3Wmode(value); return;
case 0x1f801488:
case IOP_T3_TARGET:
PSXCNT_LOG("COUNTER 3 TARGET 16bit write %lx", value);
psxRcntWtarget32(3, value); return;
case 0x1f801490:
case IOP_T4_COUNT:
PSXCNT_LOG("COUNTER 4 COUNT 16bit write %lx", value);
psxRcntWcount32(4, value); return;
case 0x1f801494:
case IOP_T4_MODE:
PSXCNT_LOG("COUNTER 4 MODE 16bit write %lx", value);
psxRcnt4Wmode(value); return;
case 0x1f801498:
case IOP_T4_TARGET:
PSXCNT_LOG("COUNTER 4 TARGET 16bit write %lx", value);
psxRcntWtarget32(4, value); return;
case 0x1f8014a0:
case IOP_T5_COUNT:
PSXCNT_LOG("COUNTER 5 COUNT 16bit write %lx", value);
psxRcntWcount32(5, value); return;
case 0x1f8014a4:
case IOP_T5_MODE:
PSXCNT_LOG("COUNTER 5 MODE 16bit write %lx", value);
psxRcnt5Wmode(value); return;
case 0x1f8014a8:
case IOP_T5_TARGET:
PSXCNT_LOG("COUNTER 5 TARGET 16bit write %lx", value);
psxRcntWtarget32(5, value); return;
@ -834,7 +827,7 @@ void psxHwWrite16(u32 add, u16 value) {
PSXHW_LOG("DMA7 BCR_count 16bit write %lx", value);
return;
default:
if (add>=0x1f801c00 && add<0x1f801e00) {
if (add>=HW_SPU2_START && add<HW_SPU2_END) {
SPU2write(add, value);
return;
}
@ -847,18 +840,11 @@ void psxHwWrite16(u32 add, u16 value) {
PSXHW_LOG("*Known 16bit write at address %lx value %x", add, value);
}
#define DmaExec2(n) { \
if (HW_DMA##n##_CHCR & 0x01000000 && \
HW_DMA_PCR2 & (8 << ((n-7) * 4))) { \
psxDma##n(HW_DMA##n##_MADR, HW_DMA##n##_BCR, HW_DMA##n##_CHCR); \
} \
}
void psxHwWrite32(u32 add, u32 value) {
if (add >= 0x1f801600 && add < 0x1f801700) {
if (add >= HW_USB_START && add < HW_USB_END) {
USBwrite32(add, value); return;
}
if (add >= 0x1f808400 && add <= 0x1f808550) {
if (add >= HW_FW_START && add <= HW_FW_END) {
FWwrite32(add, value); return;
}
switch (add) {
@ -1034,7 +1020,7 @@ void psxHwWrite32(u32 add, u32 value) {
case 0x1f8010c8:
PSXHW_LOG("DMA4 CHCR 32bit write %lx", value);
HW_DMA4_CHCR = value; // DMA4 chcr (SPU DMA)
DmaExec(4);
DmaExecNew(4);
return;
//------------------------------------------------------------------
@ -1067,7 +1053,7 @@ void psxHwWrite32(u32 add, u32 value) {
case 0x1f801508:
PSXHW_LOG("DMA7 CHCR 32bit write %lx", value);
HW_DMA7_CHCR = value; // DMA7 chcr (SPU2)
DmaExec2(7);
DmaExecNew2(7);
return;
//------------------------------------------------------------------
@ -1179,63 +1165,63 @@ void psxHwWrite32(u32 add, u32 value) {
case 0x1f801824:
mdecWrite1(value); break;
*/
case 0x1f801100:
case IOP_T0_COUNT:
PSXCNT_LOG("COUNTER 0 COUNT 32bit write %lx", value);
psxRcntWcount16(0, value ); return;
case 0x1f801104:
case IOP_T0_MODE:
PSXCNT_LOG("COUNTER 0 MODE 32bit write %lx", value);
psxRcnt0Wmode(value); return;
case 0x1f801108:
case IOP_T0_TARGET:
PSXCNT_LOG("COUNTER 0 TARGET 32bit write %lx", value);
psxRcntWtarget16(0, value ); return;
case 0x1f801110:
case IOP_T1_COUNT:
PSXCNT_LOG("COUNTER 1 COUNT 32bit write %lx", value);
psxRcntWcount16(1, value ); return;
case 0x1f801114:
case IOP_T1_MODE:
PSXCNT_LOG("COUNTER 1 MODE 32bit write %lx", value);
psxRcnt1Wmode(value); return;
case 0x1f801118:
case IOP_T1_TARGET:
PSXCNT_LOG("COUNTER 1 TARGET 32bit write %lx", value);
psxRcntWtarget16(1, value ); return;
case 0x1f801120:
case IOP_T2_COUNT:
PSXCNT_LOG("COUNTER 2 COUNT 32bit write %lx", value);
psxRcntWcount16(2, value ); return;
case 0x1f801124:
case IOP_T2_MODE:
PSXCNT_LOG("COUNTER 2 MODE 32bit write %lx", value);
psxRcnt2Wmode(value); return;
case 0x1f801128:
case IOP_T2_TARGET:
PSXCNT_LOG("COUNTER 2 TARGET 32bit write %lx", value);
psxRcntWtarget16(2, value); return;
case 0x1f801480:
case IOP_T3_COUNT:
PSXCNT_LOG("COUNTER 3 COUNT 32bit write %lx", value);
psxRcntWcount32(3, value); return;
case 0x1f801484:
case IOP_T3_MODE:
PSXCNT_LOG("COUNTER 3 MODE 32bit write %lx", value);
psxRcnt3Wmode(value); return;
case 0x1f801488:
case IOP_T3_TARGET:
PSXCNT_LOG("COUNTER 3 TARGET 32bit write %lx", value);
psxRcntWtarget32(3, value); return;
case 0x1f801490:
case IOP_T4_COUNT:
PSXCNT_LOG("COUNTER 4 COUNT 32bit write %lx", value);
psxRcntWcount32(4, value); return;
case 0x1f801494:
case IOP_T4_MODE:
PSXCNT_LOG("COUNTER 4 MODE 32bit write %lx", value);
psxRcnt4Wmode(value); return;
case 0x1f801498:
case IOP_T4_TARGET:
PSXCNT_LOG("COUNTER 4 TARGET 32bit write %lx", value);
psxRcntWtarget32(4, value); return;
case 0x1f8014a0:
case IOP_T5_COUNT:
PSXCNT_LOG("COUNTER 5 COUNT 32bit write %lx", value);
psxRcntWcount32(5, value); return;
case 0x1f8014a4:
case IOP_T5_MODE:
PSXCNT_LOG("COUNTER 5 MODE 32bit write %lx", value);
psxRcnt5Wmode(value); return;
case 0x1f8014a8:
case IOP_T5_TARGET:
PSXCNT_LOG("COUNTER 5 TARGET 32bit write %lx", value);
psxRcntWtarget32(5, value); return;

View File

@ -22,6 +22,72 @@
#include "R3000A.h"
#include "IopMem.h"
#define HW_USB_START 0x1f801600
#define HW_USB_END 0x1f801700
#define HW_FW_START 0x1f808400
#define HW_FW_END 0x1f808550
#define HW_SPU2_START 0x1f801c00
#define HW_SPU2_END 0x1f801e00
/* Registers for the IOP Counters */
enum IOPCountRegs
{
IOP_T0_COUNT = 0x1f801100,
IOP_T1_COUNT = 0x1f801110,
IOP_T2_COUNT = 0x1f801120,
IOP_T3_COUNT = 0x1f801480,
IOP_T4_COUNT = 0x1f801490,
IOP_T5_COUNT = 0x1f8014a0,
IOP_T0_MODE = 0x1f801104,
IOP_T1_MODE = 0x1f801114,
IOP_T2_MODE = 0x1f801124,
IOP_T3_MODE = 0x1f801484,
IOP_T4_MODE = 0x1f801494,
IOP_T5_MODE = 0x1f8014a4,
IOP_T0_TARGET= 0x1f801108,
IOP_T1_TARGET = 0x1f801118,
IOP_T2_TARGET = 0x1f801128,
IOP_T3_TARGET = 0x1f801488,
IOP_T4_TARGET = 0x1f801498,
IOP_T5_TARGET = 0x1f8014a8
};
// fixme: I'm sure there's a better way to do this. --arcum42
#define DmaExec(n) { \
if (HW_DMA##n##_CHCR & 0x01000000 && \
HW_DMA_PCR & (8 << (n * 4))) { \
psxDma##n(HW_DMA##n##_MADR, HW_DMA##n##_BCR, HW_DMA##n##_CHCR); \
} \
}
#define DmaExec2(n) { \
if (HW_DMA##n##_CHCR & 0x01000000 && \
HW_DMA_PCR2 & (8 << ((n-7) * 4))) { \
psxDma##n(HW_DMA##n##_MADR, HW_DMA##n##_BCR, HW_DMA##n##_CHCR); \
} \
}
#ifdef ENABLE_NEW_IOPDMA
#define DmaExecNew(n) { \
if (HW_DMA##n##_CHCR & 0x01000000 && \
HW_DMA_PCR & (8 << (n * 4))) { \
IopDmaStart(n, HW_DMA##n##_CHCR, HW_DMA##n##_MADR, HW_DMA##n##_BCR); \
} \
}
#define DmaExecNew2(n) { \
if (HW_DMA##n##_CHCR & 0x01000000 && \
HW_DMA_PCR2 & (8 << ((n-7) * 4))) { \
IopDmaStart(n, HW_DMA##n##_CHCR, HW_DMA##n##_MADR, HW_DMA##n##_BCR); \
} \
}
#else
#define DmaExecNew(n) DmaExec(n)
#define DmaExecNew2(n) DmaExec2(n)
#endif
#define HW_DMA0_MADR (psxHu32(0x1080)) // MDEC in DMA
#define HW_DMA0_BCR (psxHu32(0x1084))
#define HW_DMA0_CHCR (psxHu32(0x1088))

View File

@ -53,59 +53,65 @@ void on_Game_Fix_OK(GtkButton *button, gpointer user_data)
gtk_main_quit();
}
void on_vu_slider_changed(GtkRange *range, gpointer user_data)
{
int i;
i = gtk_range_get_value(range);
gtk_label_set_text(GTK_LABEL(lookup_widget(SpeedHacksDlg,"vu_cycle_stealing_label")),vu_stealing_labels[i]);
}
void on_ee_slider_changed(GtkRange *range, gpointer user_data)
{
int i;
i = gtk_range_get_value(range);
gtk_label_set_text(GTK_LABEL(lookup_widget(SpeedHacksDlg,"ee_cycle_label")),ee_cycle_labels[i]);
}
void on_Speed_Hacks(GtkMenuItem *menuitem, gpointer user_data)
{
SpeedHacksDlg = create_SpeedHacksDlg();
GtkRange *vuScale = GTK_RANGE(lookup_widget(SpeedHacksDlg, "VUCycleHackScale"));
GtkRange *eeScale = GTK_RANGE(lookup_widget(SpeedHacksDlg, "EECycleHackScale"));
set_checked(SpeedHacksDlg, "check_iop_cycle_rate", Config.Hacks.IOPCycleDouble);
set_checked(SpeedHacksDlg, "check_wait_cycles_sync_hack", Config.Hacks.WaitCycleExt);
set_checked(SpeedHacksDlg, "check_intc_sync_hack", Config.Hacks.INTCSTATSlow);
set_checked(SpeedHacksDlg, "check_idle_loop_fastforward", Config.Hacks.IdleLoopFF);
switch (CHECK_EE_CYCLERATE)
{
case 0:
set_checked(SpeedHacksDlg, "check_default_cycle_rate", true);
break;
case 1:
set_checked(SpeedHacksDlg, "check_1_5_cycle_rate", true);
break;
case 2:
set_checked(SpeedHacksDlg, "check_2_cycle_rate", true);
break;
case 3:
set_checked(SpeedHacksDlg, "check_3_cycle_rate", true);
break;
default:
set_checked(SpeedHacksDlg, "check_default_cycle_rate", true);
break;
}
set_checked(SpeedHacksDlg, "check_iop_cycle_rate", CHECK_IOP_CYCLERATE);
set_checked(SpeedHacksDlg, "check_wait_cycles_sync_hack", CHECK_WAITCYCLE_HACK);
set_checked(SpeedHacksDlg, "check_intc_sync_hack", CHECK_INTC_STAT_HACK);
set_checked(SpeedHacksDlg, "check_ESC_hack", CHECK_ESCAPE_HACK);
gtk_range_set_value(vuScale, Config.Hacks.VUCycleSteal);
on_vu_slider_changed(vuScale, NULL);
gtk_range_set_value(eeScale, Config.Hacks.EECycleRate);
on_ee_slider_changed(eeScale, NULL);
gtk_widget_show_all(SpeedHacksDlg);
gtk_widget_set_sensitive(MainWindow, FALSE);
gtk_main();
}
void on_Speed_Hack_OK(GtkButton *button, gpointer user_data)
{
Config.Hacks = 0;
if is_checked(SpeedHacksDlg, "check_default_cycle_rate")
Config.Hacks = 0;
else if is_checked(SpeedHacksDlg, "check_1_5_cycle_rate")
Config.Hacks = 1;
else if is_checked(SpeedHacksDlg, "check_2_cycle_rate")
Config.Hacks = 2;
else if is_checked(SpeedHacksDlg, "check_3_cycle_rate")
Config.Hacks = 3;
Config.Hacks |= is_checked(SpeedHacksDlg, "check_iop_cycle_rate") << 3;
Config.Hacks |= is_checked(SpeedHacksDlg, "check_wait_cycles_sync_hack") << 4;
Config.Hacks |= is_checked(SpeedHacksDlg, "check_intc_sync_hack") << 5;
Config.Hacks |= is_checked(SpeedHacksDlg, "check_ESC_hack") << 10;
SaveConfig();
PcsxConfig::Hacks_t newhacks;
newhacks.EECycleRate = 0;
newhacks.IOPCycleDouble = is_checked(SpeedHacksDlg, "check_iop_cycle_rate");
newhacks.WaitCycleExt = is_checked(SpeedHacksDlg, "check_wait_cycles_sync_hack");
newhacks.INTCSTATSlow = is_checked(SpeedHacksDlg, "check_intc_sync_hack");
newhacks.IdleLoopFF = is_checked(SpeedHacksDlg, "check_idle_loop_fastforward");
newhacks.VUCycleSteal = gtk_range_get_value(GTK_RANGE(lookup_widget(SpeedHacksDlg, "VUCycleHackScale")));
newhacks.EECycleRate = gtk_range_get_value(GTK_RANGE(lookup_widget(SpeedHacksDlg, "EECycleHackScale")));
if (memcmp(&newhacks, &Config.Hacks, sizeof(newhacks)))
{
SysRestorableReset();
Config.Hacks = newhacks;
SaveConfig();
}
gtk_widget_destroy(SpeedHacksDlg);
gtk_widget_set_sensitive(MainWindow, TRUE);
gtk_main_quit();

View File

@ -101,6 +101,21 @@ char iop_log_names[9][32] =
"GPU Log"
};
char vu_stealing_labels[5][256] =
{
"0: No speedup.",
"1: Slight speedup, should work with most games.",
"2: Moderate speedup, should work with most games with minor problems.",
"3: Large speedup, may break many games and make others skip frames.",
"4: Very large speedup, will break games in interesting ways."
};
char ee_cycle_labels[3][256] =
{
"Default Cycle Rate: Most compatible option - recommended for everyone with high-end machines.",
"x1.5 Cycle Rate: Moderate speedup, and works well with most games.",
"x2 Cycle Rate: Big speedup! Works well with many games."
};
//Tri-Ace - IDC_GAMEFIX2
#define FLAG_VU_ADD_SUB 0x1
// Persona3/4 - IDC_GAMEFIX4

View File

@ -39,18 +39,3 @@ u64 GetCPUTicks()
gettimeofday(&t, NULL);
return ((u64)t.tv_sec*GetTickFrequency())+t.tv_usec;
}
void cdvdSetSystemTime( cdvdStruct& cdvd )
{
time_t traw;
struct tm* ptlocal;
time(&traw);
ptlocal = localtime(&traw);
cdvd.RTC.second = ptlocal->tm_sec;
cdvd.RTC.minute = ptlocal->tm_min;
cdvd.RTC.hour = ptlocal->tm_hour;
cdvd.RTC.day = ptlocal->tm_mday;
cdvd.RTC.month = ptlocal->tm_mon;
cdvd.RTC.year = ptlocal->tm_year;
}

View File

@ -100,7 +100,19 @@ int LoadConfig()
GetValuel("varLog", varLog);
#endif
GetValuel("Options", Config.Options);
GetValuel("Hacks", Config.Hacks);
GetValuel("EECycleRate", Config.Hacks.EECycleRate);
if (Config.Hacks.EECycleRate > 2)
Config.Hacks.EECycleRate = 2;
GetValuel("IOPCycleDouble", Config.Hacks.IOPCycleDouble);
GetValuel("WaitCycleExt", Config.Hacks.WaitCycleExt);
GetValuel("INTCSTATSlow", Config.Hacks.INTCSTATSlow);
GetValuel("VUCycleSteal", Config.Hacks.VUCycleSteal);
GetValuel("IdleLoopFF", Config.Hacks.IdleLoopFF);
GetValuel("ESCExits", Config.Hacks.ESCExits);
if (Config.Hacks.VUCycleSteal < 0 || Config.Hacks.VUCycleSteal > 4)
Config.Hacks.VUCycleSteal = 0;
GetValuel("Fixes", Config.GameFixes);
GetValuel("CustomFps", Config.CustomFps);
@ -162,7 +174,14 @@ void SaveConfig()
SetValuel("Options", Config.Options);
SetValuel("Hacks", Config.Hacks);
SetValuel("EECycleRate", Config.Hacks.EECycleRate);
SetValuel("IOPCycleDouble", Config.Hacks.IOPCycleDouble);
SetValuel("WaitCycleExt", Config.Hacks.WaitCycleExt);
SetValuel("INTCSTATSlow", Config.Hacks.INTCSTATSlow);
SetValuel("VUCycleSteal", Config.Hacks.VUCycleSteal);
SetValuel("IdleLoopFF", Config.Hacks.IdleLoopFF);
SetValuel("ESCExits", Config.Hacks.ESCExits);
SetValuel("Fixes", Config.GameFixes);
SetValuel("Patch", Config.Patch);

View File

@ -13,6 +13,14 @@ void
On_Dialog_Cancelled (GtkButton *button,
gpointer user_data);
void
on_ee_slider_changed (GtkRange *range,
gpointer user_data);
void
on_vu_slider_changed (GtkRange *range,
gpointer user_data);
void
on_Speed_Hack_OK (GtkButton *button,
gpointer user_data);

View File

@ -615,21 +615,21 @@ create_SpeedHacksDlg (void)
GtkWidget *vbox59;
GtkWidget *label88;
GtkWidget *hbox39;
GtkWidget *vbox72;
GtkWidget *frame37;
GtkWidget *alignment32;
GtkWidget *vbox61;
GtkWidget *check_default_cycle_rate;
GSList *check_default_cycle_rate_group = NULL;
GtkWidget *label98;
GtkWidget *check_1_5_cycle_rate;
GtkWidget *label93;
GtkWidget *check_2_cycle_rate;
GtkWidget *label94;
GtkWidget *check_3_cycle_rate;
GtkWidget *label95;
GtkWidget *hseparator1;
GtkWidget *EECycleHackScale;
GtkWidget *ee_cycle_label;
GtkWidget *hseparator2;
GtkWidget *label91;
GtkWidget *label105;
GtkWidget *frame39;
GtkWidget *alignment34;
GtkWidget *vbox73;
GtkWidget *VUCycleHackScale;
GtkWidget *vu_cycle_stealing_label;
GtkWidget *label111;
GtkWidget *vbox60;
GtkWidget *check_iop_cycle_rate;
GtkWidget *label96;
@ -637,10 +637,10 @@ create_SpeedHacksDlg (void)
GtkWidget *label97;
GtkWidget *check_intc_sync_hack;
GtkWidget *label101;
GtkWidget *frame36;
GtkWidget *alignment31;
GtkWidget *check_ESC_hack;
GtkWidget *label89;
GtkWidget *vbox71;
GtkWidget *check_idle_loop_fastforward;
GtkWidget *label110;
GtkWidget *hseparator1;
GtkWidget *dialog_action_area3;
GtkWidget *button99;
GtkWidget *button98;
@ -669,10 +669,15 @@ create_SpeedHacksDlg (void)
gtk_widget_show (hbox39);
gtk_box_pack_start (GTK_BOX (vbox59), hbox39, TRUE, TRUE, 0);
vbox72 = gtk_vbox_new (FALSE, 0);
gtk_widget_set_name (vbox72, "vbox72");
gtk_widget_show (vbox72);
gtk_box_pack_start (GTK_BOX (hbox39), vbox72, TRUE, TRUE, 0);
frame37 = gtk_frame_new (NULL);
gtk_widget_set_name (frame37, "frame37");
gtk_widget_show (frame37);
gtk_box_pack_start (GTK_BOX (hbox39), frame37, TRUE, TRUE, 0);
gtk_box_pack_start (GTK_BOX (vbox72), frame37, TRUE, TRUE, 0);
alignment32 = gtk_alignment_new (0.5, 0.5, 1, 1);
gtk_widget_set_name (alignment32, "alignment32");
@ -685,68 +690,25 @@ create_SpeedHacksDlg (void)
gtk_widget_show (vbox61);
gtk_container_add (GTK_CONTAINER (alignment32), vbox61);
check_default_cycle_rate = gtk_radio_button_new_with_mnemonic (NULL, _("Default Cycle Rate"));
gtk_widget_set_name (check_default_cycle_rate, "check_default_cycle_rate");
gtk_widget_show (check_default_cycle_rate);
gtk_box_pack_start (GTK_BOX (vbox61), check_default_cycle_rate, FALSE, FALSE, 0);
gtk_radio_button_set_group (GTK_RADIO_BUTTON (check_default_cycle_rate), check_default_cycle_rate_group);
check_default_cycle_rate_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (check_default_cycle_rate));
EECycleHackScale = gtk_hscale_new (GTK_ADJUSTMENT (gtk_adjustment_new (0, 0, 2, 1, 0, 0)));
gtk_widget_set_name (EECycleHackScale, "EECycleHackScale");
gtk_widget_show (EECycleHackScale);
gtk_box_pack_start (GTK_BOX (vbox61), EECycleHackScale, FALSE, FALSE, 0);
gtk_scale_set_draw_value (GTK_SCALE (EECycleHackScale), FALSE);
gtk_scale_set_digits (GTK_SCALE (EECycleHackScale), 0);
label98 = gtk_label_new (_("Most compatible option - recommended for everyone with high-end machines."));
gtk_widget_set_name (label98, "label98");
gtk_widget_show (label98);
gtk_box_pack_start (GTK_BOX (vbox61), label98, FALSE, FALSE, 0);
gtk_label_set_line_wrap (GTK_LABEL (label98), TRUE);
gtk_misc_set_alignment (GTK_MISC (label98), 0.29, 0.5);
ee_cycle_label = gtk_label_new (_("Most compatible option - recommended for everyone with high-end machines."));
gtk_widget_set_name (ee_cycle_label, "ee_cycle_label");
gtk_widget_show (ee_cycle_label);
gtk_box_pack_start (GTK_BOX (vbox61), ee_cycle_label, FALSE, FALSE, 0);
gtk_label_set_line_wrap (GTK_LABEL (ee_cycle_label), TRUE);
check_1_5_cycle_rate = gtk_radio_button_new_with_mnemonic (NULL, _("Use x1.5 Cycle Rate"));
gtk_widget_set_name (check_1_5_cycle_rate, "check_1_5_cycle_rate");
gtk_widget_show (check_1_5_cycle_rate);
gtk_box_pack_start (GTK_BOX (vbox61), check_1_5_cycle_rate, FALSE, FALSE, 0);
gtk_radio_button_set_group (GTK_RADIO_BUTTON (check_1_5_cycle_rate), check_default_cycle_rate_group);
check_default_cycle_rate_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (check_1_5_cycle_rate));
hseparator2 = gtk_hseparator_new ();
gtk_widget_set_name (hseparator2, "hseparator2");
gtk_widget_show (hseparator2);
gtk_box_pack_start (GTK_BOX (vbox61), hseparator2, FALSE, FALSE, 0);
label93 = gtk_label_new (_("Moderate speedup, and works well with most games."));
gtk_widget_set_name (label93, "label93");
gtk_widget_show (label93);
gtk_box_pack_start (GTK_BOX (vbox61), label93, FALSE, FALSE, 0);
gtk_label_set_line_wrap (GTK_LABEL (label93), TRUE);
gtk_misc_set_alignment (GTK_MISC (label93), 0.29, 0.5);
check_2_cycle_rate = gtk_radio_button_new_with_mnemonic (NULL, _("Use x2 Cycle Rate"));
gtk_widget_set_name (check_2_cycle_rate, "check_2_cycle_rate");
gtk_widget_show (check_2_cycle_rate);
gtk_box_pack_start (GTK_BOX (vbox61), check_2_cycle_rate, FALSE, FALSE, 0);
gtk_radio_button_set_group (GTK_RADIO_BUTTON (check_2_cycle_rate), check_default_cycle_rate_group);
check_default_cycle_rate_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (check_2_cycle_rate));
label94 = gtk_label_new (_("Big speedup! Works well with many games."));
gtk_widget_set_name (label94, "label94");
gtk_widget_show (label94);
gtk_box_pack_start (GTK_BOX (vbox61), label94, FALSE, FALSE, 0);
gtk_label_set_line_wrap (GTK_LABEL (label94), TRUE);
gtk_misc_set_alignment (GTK_MISC (label94), 0.36, 0.5);
check_3_cycle_rate = gtk_radio_button_new_with_mnemonic (NULL, _("Use x3 Cycle Rate"));
gtk_widget_set_name (check_3_cycle_rate, "check_3_cycle_rate");
gtk_widget_show (check_3_cycle_rate);
gtk_box_pack_start (GTK_BOX (vbox61), check_3_cycle_rate, FALSE, FALSE, 0);
gtk_radio_button_set_group (GTK_RADIO_BUTTON (check_3_cycle_rate), check_default_cycle_rate_group);
check_default_cycle_rate_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (check_3_cycle_rate));
label95 = gtk_label_new (_("Big speedup, but causes flickering or missing geometry on many games."));
gtk_widget_set_name (label95, "label95");
gtk_widget_show (label95);
gtk_box_pack_start (GTK_BOX (vbox61), label95, FALSE, FALSE, 0);
gtk_label_set_line_wrap (GTK_LABEL (label95), TRUE);
gtk_misc_set_alignment (GTK_MISC (label95), 0.24, 0.5);
hseparator1 = gtk_hseparator_new ();
gtk_widget_set_name (hseparator1, "hseparator1");
gtk_widget_show (hseparator1);
gtk_box_pack_start (GTK_BOX (vbox61), hseparator1, FALSE, FALSE, 0);
label91 = gtk_label_new (_("Important: X2 & X3 sync hacks *will* cause choppy/skippy audio on many FMV movies.\nKnown to work well with a couple games, namely Shadow of the Colossus (but breaks most other games)."));
label91 = gtk_label_new (_("Important: the X2 sync hack *will* cause choppy/skippy audio on many FMV movies."));
gtk_widget_set_name (label91, "label91");
gtk_widget_show (label91);
gtk_box_pack_start (GTK_BOX (vbox61), label91, FALSE, FALSE, 0);
@ -758,6 +720,41 @@ create_SpeedHacksDlg (void)
gtk_frame_set_label_widget (GTK_FRAME (frame37), label105);
gtk_label_set_use_markup (GTK_LABEL (label105), TRUE);
frame39 = gtk_frame_new (NULL);
gtk_widget_set_name (frame39, "frame39");
gtk_widget_show (frame39);
gtk_box_pack_start (GTK_BOX (vbox72), frame39, TRUE, TRUE, 0);
alignment34 = gtk_alignment_new (0.5, 0.5, 1, 1);
gtk_widget_set_name (alignment34, "alignment34");
gtk_widget_show (alignment34);
gtk_container_add (GTK_CONTAINER (frame39), alignment34);
gtk_alignment_set_padding (GTK_ALIGNMENT (alignment34), 0, 0, 12, 0);
vbox73 = gtk_vbox_new (FALSE, 0);
gtk_widget_set_name (vbox73, "vbox73");
gtk_widget_show (vbox73);
gtk_container_add (GTK_CONTAINER (alignment34), vbox73);
VUCycleHackScale = gtk_hscale_new (GTK_ADJUSTMENT (gtk_adjustment_new (0, 0, 4, 1, 0, 0)));
gtk_widget_set_name (VUCycleHackScale, "VUCycleHackScale");
gtk_widget_show (VUCycleHackScale);
gtk_box_pack_start (GTK_BOX (vbox73), VUCycleHackScale, TRUE, TRUE, 0);
gtk_scale_set_draw_value (GTK_SCALE (VUCycleHackScale), FALSE);
gtk_scale_set_digits (GTK_SCALE (VUCycleHackScale), 0);
vu_cycle_stealing_label = gtk_label_new (_("2: Moderate speedup, should work with most games with minor problems."));
gtk_widget_set_name (vu_cycle_stealing_label, "vu_cycle_stealing_label");
gtk_widget_show (vu_cycle_stealing_label);
gtk_box_pack_start (GTK_BOX (vbox73), vu_cycle_stealing_label, FALSE, FALSE, 0);
gtk_label_set_line_wrap (GTK_LABEL (vu_cycle_stealing_label), TRUE);
label111 = gtk_label_new (_("<b>VU Cycle Stealing (Speedup for 3d geometry)</b>"));
gtk_widget_set_name (label111, "label111");
gtk_widget_show (label111);
gtk_frame_set_label_widget (GTK_FRAME (frame39), label111);
gtk_label_set_use_markup (GTK_LABEL (label111), TRUE);
vbox60 = gtk_vbox_new (FALSE, 0);
gtk_widget_set_name (vbox60, "vbox60");
gtk_widget_show (vbox60);
@ -785,7 +782,7 @@ create_SpeedHacksDlg (void)
gtk_box_pack_start (GTK_BOX (vbox60), label97, FALSE, FALSE, 0);
gtk_label_set_line_wrap (GTK_LABEL (label97), TRUE);
check_intc_sync_hack = gtk_check_button_new_with_mnemonic (_("INTC Sync Hack (experimental)"));
check_intc_sync_hack = gtk_check_button_new_with_mnemonic (_("INTC Sync Hack"));
gtk_widget_set_name (check_intc_sync_hack, "check_intc_sync_hack");
gtk_widget_show (check_intc_sync_hack);
gtk_box_pack_start (GTK_BOX (vbox60), check_intc_sync_hack, FALSE, FALSE, 0);
@ -796,27 +793,26 @@ create_SpeedHacksDlg (void)
gtk_box_pack_start (GTK_BOX (vbox60), label101, FALSE, FALSE, 0);
gtk_label_set_line_wrap (GTK_LABEL (label101), TRUE);
frame36 = gtk_frame_new (NULL);
gtk_widget_set_name (frame36, "frame36");
gtk_widget_show (frame36);
gtk_box_pack_start (GTK_BOX (vbox59), frame36, FALSE, FALSE, 0);
vbox71 = gtk_vbox_new (FALSE, 0);
gtk_widget_set_name (vbox71, "vbox71");
gtk_widget_show (vbox71);
gtk_box_pack_start (GTK_BOX (vbox60), vbox71, TRUE, TRUE, 0);
alignment31 = gtk_alignment_new (0.5, 0.5, 1, 1);
gtk_widget_set_name (alignment31, "alignment31");
gtk_widget_show (alignment31);
gtk_container_add (GTK_CONTAINER (frame36), alignment31);
gtk_alignment_set_padding (GTK_ALIGNMENT (alignment31), 0, 0, 12, 0);
check_idle_loop_fastforward = gtk_check_button_new_with_mnemonic (_("Idle Loop Fast-Forward (experimental)"));
gtk_widget_set_name (check_idle_loop_fastforward, "check_idle_loop_fastforward");
gtk_widget_show (check_idle_loop_fastforward);
gtk_box_pack_start (GTK_BOX (vbox71), check_idle_loop_fastforward, FALSE, FALSE, 0);
check_ESC_hack = gtk_check_button_new_with_mnemonic (_("Escape Hack - Use Esc key to fully exit PCSX2."));
gtk_widget_set_name (check_ESC_hack, "check_ESC_hack");
gtk_widget_show (check_ESC_hack);
gtk_container_add (GTK_CONTAINER (alignment31), check_ESC_hack);
label110 = gtk_label_new (_("Speedup for a few games, including FFX with no known side effects. More later."));
gtk_widget_set_name (label110, "label110");
gtk_widget_show (label110);
gtk_box_pack_start (GTK_BOX (vbox71), label110, FALSE, FALSE, 0);
gtk_label_set_line_wrap (GTK_LABEL (label110), TRUE);
label89 = gtk_label_new (_("<b>Miscellaneous</b>"));
gtk_widget_set_name (label89, "label89");
gtk_widget_show (label89);
gtk_frame_set_label_widget (GTK_FRAME (frame36), label89);
gtk_label_set_use_markup (GTK_LABEL (label89), TRUE);
hseparator1 = gtk_hseparator_new ();
gtk_widget_set_name (hseparator1, "hseparator1");
gtk_widget_show (hseparator1);
gtk_box_pack_start (GTK_BOX (vbox60), hseparator1, FALSE, FALSE, 0);
dialog_action_area3 = GTK_DIALOG (SpeedHacksDlg)->action_area;
gtk_widget_set_name (dialog_action_area3, "dialog_action_area3");
@ -835,6 +831,12 @@ create_SpeedHacksDlg (void)
gtk_dialog_add_action_widget (GTK_DIALOG (SpeedHacksDlg), button98, GTK_RESPONSE_CANCEL);
GTK_WIDGET_SET_FLAGS (button98, GTK_CAN_DEFAULT);
g_signal_connect ((gpointer) EECycleHackScale, "value_changed",
G_CALLBACK (on_ee_slider_changed),
NULL);
g_signal_connect ((gpointer) VUCycleHackScale, "value_changed",
G_CALLBACK (on_vu_slider_changed),
NULL);
g_signal_connect ((gpointer) button99, "clicked",
G_CALLBACK (on_Speed_Hack_OK),
NULL);
@ -848,20 +850,21 @@ create_SpeedHacksDlg (void)
GLADE_HOOKUP_OBJECT (SpeedHacksDlg, vbox59, "vbox59");
GLADE_HOOKUP_OBJECT (SpeedHacksDlg, label88, "label88");
GLADE_HOOKUP_OBJECT (SpeedHacksDlg, hbox39, "hbox39");
GLADE_HOOKUP_OBJECT (SpeedHacksDlg, vbox72, "vbox72");
GLADE_HOOKUP_OBJECT (SpeedHacksDlg, frame37, "frame37");
GLADE_HOOKUP_OBJECT (SpeedHacksDlg, alignment32, "alignment32");
GLADE_HOOKUP_OBJECT (SpeedHacksDlg, vbox61, "vbox61");
GLADE_HOOKUP_OBJECT (SpeedHacksDlg, check_default_cycle_rate, "check_default_cycle_rate");
GLADE_HOOKUP_OBJECT (SpeedHacksDlg, label98, "label98");
GLADE_HOOKUP_OBJECT (SpeedHacksDlg, check_1_5_cycle_rate, "check_1_5_cycle_rate");
GLADE_HOOKUP_OBJECT (SpeedHacksDlg, label93, "label93");
GLADE_HOOKUP_OBJECT (SpeedHacksDlg, check_2_cycle_rate, "check_2_cycle_rate");
GLADE_HOOKUP_OBJECT (SpeedHacksDlg, label94, "label94");
GLADE_HOOKUP_OBJECT (SpeedHacksDlg, check_3_cycle_rate, "check_3_cycle_rate");
GLADE_HOOKUP_OBJECT (SpeedHacksDlg, label95, "label95");
GLADE_HOOKUP_OBJECT (SpeedHacksDlg, hseparator1, "hseparator1");
GLADE_HOOKUP_OBJECT (SpeedHacksDlg, EECycleHackScale, "EECycleHackScale");
GLADE_HOOKUP_OBJECT (SpeedHacksDlg, ee_cycle_label, "ee_cycle_label");
GLADE_HOOKUP_OBJECT (SpeedHacksDlg, hseparator2, "hseparator2");
GLADE_HOOKUP_OBJECT (SpeedHacksDlg, label91, "label91");
GLADE_HOOKUP_OBJECT (SpeedHacksDlg, label105, "label105");
GLADE_HOOKUP_OBJECT (SpeedHacksDlg, frame39, "frame39");
GLADE_HOOKUP_OBJECT (SpeedHacksDlg, alignment34, "alignment34");
GLADE_HOOKUP_OBJECT (SpeedHacksDlg, vbox73, "vbox73");
GLADE_HOOKUP_OBJECT (SpeedHacksDlg, VUCycleHackScale, "VUCycleHackScale");
GLADE_HOOKUP_OBJECT (SpeedHacksDlg, vu_cycle_stealing_label, "vu_cycle_stealing_label");
GLADE_HOOKUP_OBJECT (SpeedHacksDlg, label111, "label111");
GLADE_HOOKUP_OBJECT (SpeedHacksDlg, vbox60, "vbox60");
GLADE_HOOKUP_OBJECT (SpeedHacksDlg, check_iop_cycle_rate, "check_iop_cycle_rate");
GLADE_HOOKUP_OBJECT (SpeedHacksDlg, label96, "label96");
@ -869,10 +872,10 @@ create_SpeedHacksDlg (void)
GLADE_HOOKUP_OBJECT (SpeedHacksDlg, label97, "label97");
GLADE_HOOKUP_OBJECT (SpeedHacksDlg, check_intc_sync_hack, "check_intc_sync_hack");
GLADE_HOOKUP_OBJECT (SpeedHacksDlg, label101, "label101");
GLADE_HOOKUP_OBJECT (SpeedHacksDlg, frame36, "frame36");
GLADE_HOOKUP_OBJECT (SpeedHacksDlg, alignment31, "alignment31");
GLADE_HOOKUP_OBJECT (SpeedHacksDlg, check_ESC_hack, "check_ESC_hack");
GLADE_HOOKUP_OBJECT (SpeedHacksDlg, label89, "label89");
GLADE_HOOKUP_OBJECT (SpeedHacksDlg, vbox71, "vbox71");
GLADE_HOOKUP_OBJECT (SpeedHacksDlg, check_idle_loop_fastforward, "check_idle_loop_fastforward");
GLADE_HOOKUP_OBJECT (SpeedHacksDlg, label110, "label110");
GLADE_HOOKUP_OBJECT (SpeedHacksDlg, hseparator1, "hseparator1");
GLADE_HOOKUP_OBJECT_NO_REF (SpeedHacksDlg, dialog_action_area3, "dialog_action_area3");
GLADE_HOOKUP_OBJECT (SpeedHacksDlg, button99, "button99");
GLADE_HOOKUP_OBJECT (SpeedHacksDlg, button98, "button98");

View File

@ -1275,270 +1275,250 @@ If you have problems, Disable all of these and try again.</property>
<property name="spacing">0</property>
<child>
<widget class="GtkFrame" id="frame37">
<widget class="GtkVBox" id="vbox72">
<property name="visible">True</property>
<property name="label_xalign">0</property>
<property name="label_yalign">0.5</property>
<property name="shadow_type">GTK_SHADOW_ETCHED_IN</property>
<property name="homogeneous">False</property>
<property name="spacing">0</property>
<child>
<widget class="GtkAlignment" id="alignment32">
<widget class="GtkFrame" id="frame37">
<property name="visible">True</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xscale">1</property>
<property name="yscale">1</property>
<property name="top_padding">0</property>
<property name="bottom_padding">0</property>
<property name="left_padding">12</property>
<property name="right_padding">0</property>
<property name="label_xalign">0</property>
<property name="label_yalign">0.5</property>
<property name="shadow_type">GTK_SHADOW_ETCHED_IN</property>
<child>
<widget class="GtkVBox" id="vbox61">
<widget class="GtkAlignment" id="alignment32">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">2</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xscale">1</property>
<property name="yscale">1</property>
<property name="top_padding">0</property>
<property name="bottom_padding">0</property>
<property name="left_padding">12</property>
<property name="right_padding">0</property>
<child>
<widget class="GtkRadioButton" id="check_default_cycle_rate">
<widget class="GtkVBox" id="vbox61">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">Default Cycle Rate</property>
<property name="use_underline">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<property name="active">False</property>
<property name="inconsistent">False</property>
<property name="draw_indicator">True</property>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<property name="homogeneous">False</property>
<property name="spacing">2</property>
<child>
<widget class="GtkLabel" id="label98">
<property name="visible">True</property>
<property name="label" translatable="yes">Most compatible option - recommended for everyone with high-end machines.</property>
<property name="use_underline">False</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">True</property>
<property name="selectable">False</property>
<property name="xalign">0.289999991655</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkHScale" id="EECycleHackScale">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="draw_value">False</property>
<property name="value_pos">GTK_POS_TOP</property>
<property name="digits">0</property>
<property name="update_policy">GTK_UPDATE_CONTINUOUS</property>
<property name="inverted">False</property>
<property name="adjustment">0 0 2 1 0 0</property>
<signal name="value_changed" handler="on_ee_slider_changed" last_modification_time="Wed, 22 Apr 2009 03:03:42 GMT"/>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkRadioButton" id="check_1_5_cycle_rate">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">Use x1.5 Cycle Rate</property>
<property name="use_underline">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<property name="active">False</property>
<property name="inconsistent">False</property>
<property name="draw_indicator">True</property>
<property name="group">check_default_cycle_rate</property>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="ee_cycle_label">
<property name="visible">True</property>
<property name="label" translatable="yes">Most compatible option - recommended for everyone with high-end machines.</property>
<property name="use_underline">False</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">True</property>
<property name="selectable">False</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label93">
<property name="visible">True</property>
<property name="label" translatable="yes">Moderate speedup, and works well with most games.</property>
<property name="use_underline">False</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">True</property>
<property name="selectable">False</property>
<property name="xalign">0.289999991655</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkHSeparator" id="hseparator2">
<property name="visible">True</property>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkRadioButton" id="check_2_cycle_rate">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">Use x2 Cycle Rate</property>
<property name="use_underline">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<property name="active">False</property>
<property name="inconsistent">False</property>
<property name="draw_indicator">True</property>
<property name="group">check_default_cycle_rate</property>
<child>
<widget class="GtkLabel" id="label91">
<property name="visible">True</property>
<property name="label" translatable="yes">Important: the X2 sync hack *will* cause choppy/skippy audio on many FMV movies.</property>
<property name="use_underline">False</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">True</property>
<property name="selectable">False</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label94">
<property name="visible">True</property>
<property name="label" translatable="yes">Big speedup! Works well with many games.</property>
<property name="use_underline">False</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">True</property>
<property name="selectable">False</property>
<property name="xalign">0.360000014305</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkRadioButton" id="check_3_cycle_rate">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">Use x3 Cycle Rate</property>
<property name="use_underline">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<property name="active">False</property>
<property name="inconsistent">False</property>
<property name="draw_indicator">True</property>
<property name="group">check_default_cycle_rate</property>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label95">
<property name="visible">True</property>
<property name="label" translatable="yes">Big speedup, but causes flickering or missing geometry on many games.</property>
<property name="use_underline">False</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">True</property>
<property name="selectable">False</property>
<property name="xalign">0.239999994636</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkHSeparator" id="hseparator1">
<property name="visible">True</property>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label91">
<property name="visible">True</property>
<property name="label" translatable="yes">Important: X2 &amp; X3 sync hacks *will* cause choppy/skippy audio on many FMV movies.
Known to work well with a couple games, namely Shadow of the Colossus (but breaks most other games).</property>
<property name="use_underline">False</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">True</property>
<property name="selectable">False</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
</widget>
</child>
<child>
<widget class="GtkLabel" id="label105">
<property name="visible">True</property>
<property name="label" translatable="yes">&lt;b&gt;EmotionEngine (EE) Sync Hacks&lt;/b&gt;</property>
<property name="use_underline">False</property>
<property name="use_markup">True</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</widget>
<packing>
<property name="type">label_item</property>
</packing>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label105">
<widget class="GtkFrame" id="frame39">
<property name="visible">True</property>
<property name="label" translatable="yes">&lt;b&gt;EmotionEngine (EE) Sync Hacks&lt;/b&gt;</property>
<property name="use_underline">False</property>
<property name="use_markup">True</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
<property name="label_xalign">0</property>
<property name="label_yalign">0.5</property>
<property name="shadow_type">GTK_SHADOW_ETCHED_IN</property>
<child>
<widget class="GtkAlignment" id="alignment34">
<property name="visible">True</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xscale">1</property>
<property name="yscale">1</property>
<property name="top_padding">0</property>
<property name="bottom_padding">0</property>
<property name="left_padding">12</property>
<property name="right_padding">0</property>
<child>
<widget class="GtkVBox" id="vbox73">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">0</property>
<child>
<widget class="GtkHScale" id="VUCycleHackScale">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="draw_value">False</property>
<property name="value_pos">GTK_POS_TOP</property>
<property name="digits">0</property>
<property name="update_policy">GTK_UPDATE_CONTINUOUS</property>
<property name="inverted">False</property>
<property name="adjustment">0 0 4 1 0 0</property>
<signal name="value_changed" handler="on_vu_slider_changed" last_modification_time="Wed, 22 Apr 2009 02:51:47 GMT"/>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="vu_cycle_stealing_label">
<property name="visible">True</property>
<property name="label" translatable="yes">2: Moderate speedup, should work with most games with minor problems.</property>
<property name="use_underline">False</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">True</property>
<property name="selectable">False</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkLabel" id="label111">
<property name="visible">True</property>
<property name="label" translatable="yes">&lt;b&gt;VU Cycle Stealing (Speedup for 3d geometry)&lt;/b&gt;</property>
<property name="use_underline">False</property>
<property name="use_markup">True</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</widget>
<packing>
<property name="type">label_item</property>
</packing>
</child>
</widget>
<packing>
<property name="type">label_item</property>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
</widget>
@ -1649,7 +1629,7 @@ Known to work well with a couple games, namely Shadow of the Colossus (but break
<widget class="GtkCheckButton" id="check_intc_sync_hack">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">INTC Sync Hack (experimental)</property>
<property name="label" translatable="yes">INTC Sync Hack</property>
<property name="use_underline">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
@ -1688,6 +1668,74 @@ Known to work well with a couple games, namely Shadow of the Colossus (but break
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkVBox" id="vbox71">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">0</property>
<child>
<widget class="GtkCheckButton" id="check_idle_loop_fastforward">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">Idle Loop Fast-Forward (experimental)</property>
<property name="use_underline">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<property name="active">False</property>
<property name="inconsistent">False</property>
<property name="draw_indicator">True</property>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label110">
<property name="visible">True</property>
<property name="label" translatable="yes">Speedup for a few games, including FFX with no known side effects. More later.</property>
<property name="use_underline">False</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">True</property>
<property name="selectable">False</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
<child>
<widget class="GtkHSeparator" id="hseparator1">
<property name="visible">True</property>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
</widget>
<packing>
<property name="padding">0</property>
@ -1702,71 +1750,6 @@ Known to work well with a couple games, namely Shadow of the Colossus (but break
<property name="fill">True</property>
</packing>
</child>
<child>
<widget class="GtkFrame" id="frame36">
<property name="visible">True</property>
<property name="label_xalign">0</property>
<property name="label_yalign">0.5</property>
<property name="shadow_type">GTK_SHADOW_ETCHED_IN</property>
<child>
<widget class="GtkAlignment" id="alignment31">
<property name="visible">True</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xscale">1</property>
<property name="yscale">1</property>
<property name="top_padding">0</property>
<property name="bottom_padding">0</property>
<property name="left_padding">12</property>
<property name="right_padding">0</property>
<child>
<widget class="GtkCheckButton" id="check_ESC_hack">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">Escape Hack - Use Esc key to fully exit PCSX2.</property>
<property name="use_underline">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<property name="active">False</property>
<property name="inconsistent">False</property>
<property name="draw_indicator">True</property>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkLabel" id="label89">
<property name="visible">True</property>
<property name="label" translatable="yes">&lt;b&gt;Miscellaneous&lt;/b&gt;</property>
<property name="use_underline">False</property>
<property name="use_markup">True</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</widget>
<packing>
<property name="type">label_item</property>
</packing>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
</widget>
<packing>
<property name="padding">0</property>

View File

@ -177,11 +177,15 @@ void PLZCW() {
_PLZCW (1);
}
#define PMFHL_CLAMP(dst, src) \
if ((int)src > (int)0x00007fff) dst = 0x7fff; \
else \
if ((int)src < (int)0xffff8000) dst = 0x8000; \
else dst = (u16)src;
__forceinline void PMFHL_CLAMP(u16 dst, u16 src)
{
if ((int)src > (int)0x00007fff)
dst = 0x7fff;
else if ((int)src < (int)0xffff8000)
dst = 0x8000;
else
dst = (u16)src;
}
void PMFHL() {
if (!_Rd_) return;

View File

@ -224,7 +224,7 @@ void mtgsThreadObject::Start()
m_post_InitDone.Wait();
if( m_returncode != 0 ) // means the thread failed to init the GS plugin
throw Exception::PluginFailure( "GS", "The GS plugin failed to open/initialize." );
throw Exception::PluginFailure( "GS", wxLt("%s plugin initialization failed.") ); // plugin returned an error after having been asked very nicely to initialize itself." );
}
mtgsThreadObject::~mtgsThreadObject()

View File

@ -11,7 +11,7 @@ R3000AInterpreter.cpp R3000AOpcodeTables.cpp R5900.cpp R5900OpcodeImpl.cpp R5900
SPR.cpp SaveState.cpp Sif.cpp Sio.cpp SourceLog.cpp Stats.cpp System.cpp ThreadTools.cpp \
VU0.cpp VU0micro.cpp VU0microInterp.cpp VU1micro.cpp VU1microInterp.cpp VUflags.cpp VUmicroMem.cpp VUops.cpp \
Vif.cpp VifDma.cpp vssprintf.cpp vtlb.cpp xmlpatchloader.cpp AlignedMalloc.cpp \
RecoverySystem.cpp Saveslots.cpp
RecoverySystem.cpp Saveslots.cpp Dump.cpp
@ -20,7 +20,8 @@ CDVD.h CDVDiso.h CDVDisodrv.h CDVDlib.h COP0.h Cache.h CdRom.h Common.h Counters
Elfheader.h Exceptions.h GS.h Hw.h IopBios.h IopBios2.h IopCounters.h IopDma.h IopHw.h IopMem.h IopSio2.h Memcpyfast.h \
Memory.h MemoryCard.h Misc.h Patch.h Paths.h Plugins.h PrecompiledHeader.h IopCommon.h R3000A.h R5900.h R5900OpcodeTables.h \
SPR.h SamplProf.h SaveState.h Sif.h Sifcmd.h Sio.h SafeArray.h Stats.h StringUtils.h System.h Threading.h \
VU.h VUflags.h VUmicro.h VUops.h Vif.h VifDma.h cheatscpp.h vtlb.h NakedAsm.h R5900Exceptions.h HostGui.h Pcsx2Config.h
VU.h VUflags.h VUmicro.h VUops.h Vif.h VifDma.h cheatscpp.h vtlb.h NakedAsm.h R5900Exceptions.h HostGui.h Pcsx2Config.h \
Dump.h
SUBDIRS = x86 . DebugTools IPU RDebug tinyxml NewGUI
#Linux

View File

@ -42,6 +42,7 @@ BIOS
#pragma warning(disable:4799) // No EMMS at end of function
#include <vector>
#include <wx/file.h>
#include "IopCommon.h"
#include "iR5900.h"
@ -85,26 +86,26 @@ u16 ba0R16(u32 mem)
// Attempts to load a BIOS rom file, by trying multiple combinations of base filename
// and extension. The bios specified in Config.Bios is used as the base.
void loadBiosRom( const char *ext, u8 *dest, long maxSize )
void loadBiosRom( const wxChar *ext, u8 *dest, long maxSize )
{
string Bios1;
wxString Bios1;
long filesize;
string Bios( Path::Combine( Config.BiosDir, Config.Bios ) );
// Try first a basic extension concatenation (normally results in something like name.bin.rom1)
ssprintf(Bios1, "%hs.%s", &Bios, ext);
if( (filesize=Path::getFileSize( Bios1 ) ) <= 0 )
const wxString Bios( g_Conf.Files.Bios() );
Bios1.Printf( wxS("%s.%s"), Bios.c_str(), ext);
if( (filesize=Path::GetFileSize( Bios1 ) ) <= 0 )
{
// Try the name properly extensioned next (name.rom1)
Bios1 = Path::ReplaceExtension( Bios, ext );
if( (filesize=Path::getFileSize( Bios1 ) ) <= 0 )
if( (filesize=Path::GetFileSize( Bios1 ) ) <= 0 )
{
// Try for the old-style method (rom1.bin)
Bios1 = Path::Combine( Config.BiosDir, ext ) + ".bin";
if( (filesize=Path::getFileSize( Bios1 ) ) <= 0 )
Bios1 = Path::Combine( g_Conf.Folders.Bios, (wxString)ext ) + wxT(".bin");
if( (filesize=Path::GetFileSize( Bios1 ) ) <= 0 )
{
Console::Notice( "Bios Warning > %s not found.", params ext );
Console::Notice( "Load Bios Warning: %s not found (this is not an error!)", params wxString(ext).ToAscii().data() );
return;
}
}
@ -112,9 +113,8 @@ void loadBiosRom( const char *ext, u8 *dest, long maxSize )
// if we made it this far, we have a successful file found:
FILE *fp = fopen(Bios1.c_str(), "rb");
fread(dest, 1, min( maxSize, filesize ), fp);
fclose(fp);
wxFile fp( Bios1 );
fp.Read( dest, min( maxSize, filesize ) );
}
static u32 psMPWC[(Ps2MemSize::Base/32)>>12];
@ -517,8 +517,8 @@ void __fastcall vuMicroRead128(u32 addr,mem128_t* data)
data[1]=*(u64*)&vu->Micro[addr+8];
}
// [TODO] : Profile this code and see how often the VUs get written, and how
// often it changes the values being written (invoking a cpuClear).
// Profiled VU writes: Happen very infrequently, with exception of BIOS initialization (at most twice per
// frame in-game, and usually none at all after BIOS), so cpu clears aren't much of a big deal.
template<int vunum, bool dynrec>
void __fastcall vuMicroWrite8(u32 addr,mem8_t data)
@ -738,8 +738,8 @@ void memReset()
_ext_memWrite8<1>, _ext_memWrite16<1>, hwWrite32_page_0E, hwWrite64_page_0E, hwWrite128_generic
);
vtlbMemR32FP* page0F32( CHECK_INTC_STAT_HACK ? hwRead32_page_0F_INTC_HACK : hwRead32_page_0F );
vtlbMemR64FP* page0F64( CHECK_INTC_STAT_HACK ? hwRead64_generic_INTC_HACK : hwRead64_generic );
vtlbMemR32FP* page0F32( Config.Hacks.INTCSTATSlow ? hwRead32_page_0F_INTC_HACK : hwRead32_page_0F );
vtlbMemR64FP* page0F64( Config.Hacks.INTCSTATSlow ? hwRead64_generic_INTC_HACK : hwRead64_generic );
hw_by_page[0xf] = vtlb_RegisterHandler(
_ext_memRead8<1>, _ext_memRead16<1>, page0F32, page0F64, hwRead128_generic,
@ -780,29 +780,28 @@ void memReset()
vtlb_VMap(0x00000000,0x00000000,0x20000000);
vtlb_VMapUnmap(0x20000000,0x60000000);
FILE *fp;
string Bios( Path::Combine( Config.BiosDir, Config.Bios ) );
wxString Bios( g_Conf.Files.Bios() );
long filesize;
if( ( filesize = Path::getFileSize( Bios ) ) <= 0 )
long filesize = Path::GetFileSize( Bios );
if( filesize <= 0 )
{
//Console::Error("Unable to load bios: '%s', PCSX2 can't run without that", params Bios);
throw Exception::FileNotFound( Bios,
"The specified Bios file was not found. A bios is required for Pcsx2 to run.\n\nFile not found" );
wxFile fp( Bios.c_str() );
fp.Read( PS2MEM_ROM, min( (long)Ps2MemSize::Rom, filesize ) );
}
else
{
// Translated: Bios file not found or not specified ... A bios is required for Pcsx2 to run!
throw Exception::FileNotFound( Bios, wxLt("Bios not found") );
}
fp = fopen(Bios.c_str(), "rb");
fread(PS2MEM_ROM, 1, min( (long)Ps2MemSize::Rom, filesize ), fp);
fclose(fp);
BiosVersion = GetBiosVersion();
Console::Status("Bios Version %d.%d", params BiosVersion >> 8, BiosVersion & 0xff);
//injectIRX("host.irx"); //not fully tested; still buggy
loadBiosRom("rom1", PS2MEM_ROM1, Ps2MemSize::Rom1);
loadBiosRom("rom2", PS2MEM_ROM2, Ps2MemSize::Rom2);
loadBiosRom("erom", PS2MEM_EROM, Ps2MemSize::ERom);
loadBiosRom( wxT("rom1"), PS2MEM_ROM1, Ps2MemSize::Rom1 );
loadBiosRom( wxT("rom2"), PS2MEM_ROM2, Ps2MemSize::Rom2 );
loadBiosRom( wxT("erom"), PS2MEM_EROM, Ps2MemSize::ERom );
}
int mmap_GetRamPageInfo(void* ptr)
@ -820,6 +819,7 @@ void mmap_MarkCountedRamPage(void* ptr,u32 vaddr)
u32 offset=((u8*)ptr-psM);
offset>>=12;
psMPWC[(offset/32)] &= ~(1<<(offset&31));
for (u32 i=0;i<psMPWVA[offset].size();i++)
{

View File

@ -23,6 +23,7 @@
#endif
//#define ENABLECACHE
#include "vtlb.h"
namespace Ps2MemSize
{
@ -57,9 +58,40 @@ extern u8 *psS; //0.015 mb, scratch pad
extern u8 g_RealGSMem[Ps2MemSize::GSregs];
#define PS2MEM_GS g_RealGSMem
#define PS2GS_BASE(mem) (g_RealGSMem+(mem&0x13ff))
// Various useful locations
#define spr0 ((DMACh*)&PS2MEM_HW[0xD000])
#define spr1 ((DMACh*)&PS2MEM_HW[0xD400])
#define gif ((DMACh*)&PS2MEM_HW[0xA000])
#define vif0ch ((DMACh*)&PS2MEM_HW[0x8000])
#define vif1ch ((DMACh*)&PS2MEM_HW[0x9000])
#define sif0dma ((DMACh*)&PS2MEM_HW[0xc000])
#define sif1dma ((DMACh*)&PS2MEM_HW[0xc400])
#define sif2dma ((DMACh*)&PS2MEM_HW[0xc800])
#define ipu0dma ((DMACh *)&PS2MEM_HW[0xb000])
#define ipu1dma ((DMACh *)&PS2MEM_HW[0xb400])
// From Gif.h
#define GSCSRr *((u64*)(g_RealGSMem+0x1000))
#define GSIMR *((u32*)(g_RealGSMem+0x1010))
#define GSSIGLBLID ((GSRegSIGBLID*)(g_RealGSMem+0x1080))
#define PSM(mem) (vtlb_GetPhyPtr((mem)&0x1fffffff)) //pcsx2 is a competition.The one with most hacks wins :D
#define psHs8(mem) (*(s8 *)&PS2MEM_HW[(mem) & 0xffff])
#define psHs16(mem) (*(s16*)&PS2MEM_HW[(mem) & 0xffff])
#define psHs32(mem) (*(s32*)&PS2MEM_HW[(mem) & 0xffff])
#define psHs64(mem) (*(s64*)&PS2MEM_HW[(mem) & 0xffff])
#define psHu8(mem) (*(u8 *)&PS2MEM_HW[(mem) & 0xffff])
#define psHu16(mem) (*(u16*)&PS2MEM_HW[(mem) & 0xffff])
#define psHu32(mem) (*(u32*)&PS2MEM_HW[(mem) & 0xffff])
#define psHu64(mem) (*(u64*)&PS2MEM_HW[(mem) & 0xffff])
#define psMs8(mem) (*(s8 *)&PS2MEM_BASE[(mem) & 0x1ffffff])
#define psMs16(mem) (*(s16*)&PS2MEM_BASE[(mem) & 0x1ffffff])
#define psMs32(mem) (*(s32*)&PS2MEM_BASE[(mem) & 0x1ffffff])
@ -114,15 +146,6 @@ extern u8 g_RealGSMem[Ps2MemSize::GSregs];
#define psSu32(mem) (*(u32*)&PS2MEM_SCRATCH[(mem) & 0x3fff])
#define psSu64(mem) (*(u64*)&PS2MEM_SCRATCH[(mem) & 0x3fff])
//#define PSMs8(mem) (*(s8 *)PSM(mem))
//#define PSMs16(mem) (*(s16*)PSM(mem))
//#define PSMs32(mem) (*(s32*)PSM(mem))
//#define PSMs64(mem) (*(s64*)PSM(mem))
//#define PSMu8(mem) (*(u8 *)PSM(mem))
//#define PSMu16(mem) (*(u16*)PSM(mem))
//#define PSMu32(mem) (*(u32*)PSM(mem))
//#define PSMu64(mem) (*(u64*)PSM(mem))
extern void memAlloc();
extern void memReset(); // clears PS2 ram and loads the bios. Throws Exception::FileNotFound on error.
extern void memShutdown();
@ -134,8 +157,6 @@ extern void memClearPageAddr(u32 vaddr);
extern void memMapVUmicro();
#include "vtlb.h"
extern int mmap_GetRamPageInfo(void* ptr);
extern void mmap_MarkCountedRamPage(void* ptr,u32 vaddr);
extern void mmap_ResetBlockTracking();

View File

@ -20,13 +20,14 @@
#include "System.h"
#include "MemoryCard.h"
#include "Paths.h"
#include <wx/file.h>
#ifdef WIN32
extern void NTFS_CompressFile( const char* file, bool compressMode );
extern void NTFS_CompressFile( const wxString& file, bool compressMode );
#endif
FILE* MemoryCard::cardfile[2] = { NULL, NULL };
wxFile MemoryCard::cardfile[2];
// Ensures memory card files are created/initialized.
@ -34,8 +35,8 @@ void MemoryCard::Init()
{
for( int i=0; i<2; i++ )
{
if( Config.Mcd[i].Enabled && cardfile[i] == NULL )
cardfile[i] = Load(i);
if( Config.Mcd[i].Enabled && !cardfile[i].IsOpened() )
Load( i );
}
}
@ -48,88 +49,79 @@ void MemoryCard::Shutdown()
void MemoryCard::Unload( uint mcd )
{
jASSUME( mcd < 2 );
if(cardfile[mcd] == NULL) return;
fclose( cardfile[mcd] );
cardfile[mcd] = NULL;
cardfile[mcd].Close();
}
bool MemoryCard::IsPresent( uint mcd )
{
jASSUME( mcd < 2 );
return cardfile[mcd] != NULL;
return cardfile[mcd].IsOpened();
}
FILE *MemoryCard::Load( uint mcd )
void MemoryCard::Load( uint mcd )
{
FILE *f;
jASSUME( mcd < 2 );
string str( Config.Mcd[mcd].Filename );
wxFileName fname( g_Conf.Files.Mcd( mcd ) );
wxString str( fname.GetFullPath() );
if( str.empty() )
str = Path::Combine( MEMCARDS_DIR, fmt_string( "Mcd00%d.ps2", mcd ) );
if( !Path::Exists(str) )
Create( str.c_str() );
if( !fname.FileExists() )
Create( str );
#ifdef WIN32
NTFS_CompressFile( str.c_str(), Config.McdEnableNTFS );
NTFS_CompressFile( str, Config.McdEnableNTFS );
#endif
f = fopen( str.c_str(), "r+b" );
cardfile[mcd].Open( str.c_str(), wxFile::write );
if (f == NULL)
if( !cardfile[mcd].IsOpened() )
{
Msgbox::Alert("Failed loading MemoryCard from file: %hs", params &str);
return NULL;
// Translation note: detailed description should mention that the memory card will be disabled
// for the duration of this session.
Msgbox::Alert( wxsFormat( _("Could not load MemoryCard from file: %s"), str.c_str() ) );
}
return f;
}
void MemoryCard::Seek( FILE *f, u32 adr )
void MemoryCard::Seek( wxFile& f, u32 adr )
{
u32 size;
fseek(f, 0, SEEK_END); size = ftell(f);
u32 size = f.Length();
if (size == MCD_SIZE + 64)
fseek(f, adr + 64, SEEK_SET);
f.Seek( adr + 64 );
else if (size == MCD_SIZE + 3904)
fseek(f, adr + 3904, SEEK_SET);
f.Seek( adr + 3904 );
else
fseek(f, adr, SEEK_SET);
f.Seek( adr );
}
void MemoryCard::Read( uint mcd, u8 *data, u32 adr, int size )
{
jASSUME( mcd < 2 );
FILE* const mcfp = cardfile[mcd];
wxFile& mcfp( cardfile[mcd] );
if( mcfp == NULL )
if( !mcfp.IsOpened() )
{
Console::Error( "MemoryCard > Ignoring attempted read from disabled card." );
DevCon::Error( "MemoryCard > Ignoring attempted read from disabled card." );
memset(data, 0, size);
return;
}
Seek(mcfp, adr);
fread(data, 1, size, mcfp);
mcfp.Read( data, size );
}
void MemoryCard::Save( uint mcd, const u8 *data, u32 adr, int size )
{
jASSUME( mcd < 2 );
FILE* const mcfp = cardfile[mcd];
wxFile& mcfp( cardfile[mcd] );
if( mcfp == NULL )
if( !mcfp.IsOpened() )
{
Console::Error( "MemoryCard > Ignoring attempted save/write to disabled card." );
DevCon::Error( "MemoryCard > Ignoring attempted save/write to disabled card." );
return;
}
Seek(mcfp, adr);
u8 *currentdata = (u8 *)malloc(size);
fread(currentdata, 1, size, mcfp);
mcfp.Read( currentdata, size);
for (int i=0; i<size; i++)
{
@ -139,7 +131,7 @@ void MemoryCard::Save( uint mcd, const u8 *data, u32 adr, int size )
}
Seek(mcfp, adr);
fwrite(currentdata, 1, size, mcfp);
mcfp.Write( currentdata, size );
free(currentdata);
}
@ -150,46 +142,51 @@ void MemoryCard::Erase( uint mcd, u32 adr )
memset8_obj<0xff>(data); // clears to -1's
jASSUME( mcd < 2 );
FILE* const mcfp = cardfile[mcd];
wxFile& mcfp( cardfile[mcd] );
if( mcfp == NULL )
if( !mcfp.IsOpened() )
{
DevCon::Notice( "MemoryCard > Ignoring seek for disabled card." );
DevCon::Error( "MemoryCard > Ignoring seek for disabled card." );
return;
}
Seek(mcfp, adr);
fwrite(data, 1, 528*16, mcfp);
mcfp.Write( data, 528*16 );
}
void MemoryCard::Create( const char *mcdFile )
void MemoryCard::Create( const wxString& mcdFile )
{
//int enc[16] = {0x77,0x7f,0x7f,0x77,0x7f,0x7f,0x77,0x7f,0x7f,0x77,0x7f,0x7f,0,0,0,0};
FILE* fp = fopen( mcdFile, "wb" );
if( fp == NULL ) return;
wxFile fp( mcdFile, wxFile::write );
if( !fp.IsOpened() ) return;
u8 effeffs[528];
memset8_obj<0xff>( effeffs );
for( uint i=0; i<16384; i++ )
{
for( uint j=0; j<528; j++ ) fputc( 0xFF,fp );
// for(j=0; j<16; j++) fputc(enc[j],fp);
for( uint j=0; j<528; j++ )
fp.Write( effeffs, sizeof(effeffs) );
//for(j=0; j<16; j++) fputc(enc[j],fp);
}
fclose( fp );
}
u64 MemoryCard::GetCRC( uint mcd )
{
jASSUME( mcd < 2 );
FILE* const mcfp = cardfile[mcd];
if( mcfp == NULL ) return 0;
wxFile& mcfp( cardfile[mcd] );
if( !mcfp.IsOpened() ) return 0;
Seek( mcfp, 0 );
u64 retval = 0;
for( uint i=MC2_SIZE/sizeof(u64); i; --i )
{
u64 temp; fread( &temp, sizeof(temp), 1, mcfp );
u64 temp; mcfp.Read( &temp, sizeof(temp) );
retval ^= temp;
}

View File

@ -25,11 +25,12 @@ static const int MC2_SIZE = 1024 * 528 * 16;
class MemoryCard
{
protected:
static FILE* cardfile[2];
static FILE* Load( uint mcdId );
static void Seek( FILE* mcdfp, u32 adr );
static void Create( const char *mcd );
static wxFile cardfile[2];
public:
static void Load( uint mcdId );
static void Seek( wxFile& mcdfp, u32 adr );
static void Create( const wxString& mcd );
public:
static void Init();

View File

@ -25,6 +25,7 @@
#endif
#include <ctype.h>
#include <wx/file.h>
#include "IopCommon.h"
#include "HostGui.h"
@ -40,14 +41,13 @@
#include "COP0.h"
#include "Cache.h"
#include "Paths.h"
#include "Dump.h"
using namespace std;
using namespace R5900;
PcsxConfig Config;
u32 BiosVersion;
char CdromId[12];
static int g_Pcsx2Recording = 0; // true 1 if recording video and sound
bool renderswitch = 0;
@ -64,7 +64,8 @@ extern wxString strgametitle;
#pragma pack(1)
#endif
struct romdir{
struct romdir
{
char fileName[10];
u16 extInfoSize;
u32 fileSize;
@ -115,43 +116,46 @@ u32 GetBiosVersion() {
}
//2002-09-22 (Florin)
int IsBIOS(const char *filename, char *description)
bool IsBIOS(const wxString& filename, wxString& description)
{
char ROMVER[14+1];
FILE *fp;
unsigned int fileOffset=0, found=FALSE;
struct romdir rd;
uint fileOffset=0;
romdir rd;
wxString Bios( Path::Combine( Config.BiosDir, filename ) );
wxFileName Bios( g_Conf.Folders.Bios + filename );
wxFile fp( Bios.GetFullPath().c_str() );
int biosFileSize = Path::getFileSize( Bios );
if( biosFileSize <= 0) return FALSE;
if( !fp.IsOpened() ) return FALSE;
fp = fopen(Bios.c_str(), "rb");
if (fp == NULL) return FALSE;
int biosFileSize = fp.Length();
if( biosFileSize <= 0) return FALSE;
while ((ftell(fp)<512*1024) && (fread(&rd, DIRENTRY_SIZE, 1, fp)==1))
while( (fp.Tell() < 512*1024) && (fp.Read( &rd, DIRENTRY_SIZE ) == DIRENTRY_SIZE) )
{
if (strcmp(rd.fileName, "RESET") == 0)
break; /* found romdir */
break; // found romdir
}
if ((strcmp(rd.fileName, "RESET") != 0) || (rd.fileSize == 0)) {
fclose(fp);
return FALSE; //Unable to locate ROMDIR structure in file or a ioprpXXX.img
}
bool found = false;
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
char aROMVER[14+1]; // ascii version loaded from disk.
const char zonefail[2] = { ROMVER[4], '\0' }; // the default "zone" (unknown code)
uint filepos = fp.Tell();
fp.Seek( fileOffset );
if( fp.Read( &aROMVER, 14 ) == 0 ) break;
fp.Seek( filepos ); //go back
const char zonefail[2] = { aROMVER[4], '\0' }; // the default "zone" (unknown code)
const char* zone = zonefail;
switch(ROMVER[4])
switch(aROMVER[4])
{
case 'T': zone = "T10K "; break;
case 'X': zone = "Test "; break;
@ -163,15 +167,17 @@ int IsBIOS(const char *filename, char *description)
case 'C': zone = "China "; break;
}
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" : ""
const wxString romver( wxString::FromAscii(aROMVER) );
description.Printf( wxT("%s v%c%c.%c%c(%c%c/%c%c/%c%c%c%c) %s"), wxString::FromAscii(zone).ToAscii().data(),
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!
(aROMVER[5]=='C') ? wxT("Console") : (aROMVER[5]=='D') ? wxT("Devel") : wxT("")
);
found = TRUE;
found = true;
}
if ((rd.fileSize % 0x10)==0)
@ -179,29 +185,26 @@ int IsBIOS(const char *filename, char *description)
else
fileOffset += (rd.fileSize + 0x10) & 0xfffffff0;
if (fread(&rd, DIRENTRY_SIZE, 1, fp)==0) break;
if (fp.Read( &rd, DIRENTRY_SIZE ) != DIRENTRY_SIZE) break;
}
fileOffset-=((rd.fileSize + 0x10) & 0xfffffff0) - rd.fileSize;
fclose(fp);
if (found)
{
char percent[6];
if ( biosFileSize < (int)fileOffset)
{
sprintf(percent, " %d%%", biosFileSize*100/(int)fileOffset);
strcat(description, percent);//we force users to have correct bioses,
//not that lame scph10000 of 513KB ;-)
description << ((biosFileSize*100)/(int)fileOffset) << wxT("%");
// we force users to have correct bioses,
// not that lame scph10000 of 513KB ;-)
}
return TRUE;
return true;
}
return FALSE; //fail quietly
return false; //fail quietly
}
int GetPS2ElfName(char *name){
int GetPS2ElfName( wxString& name )
{
int f;
char buffer[g_MaxPath];//if a file is longer...it should be shorter :D
char *pos;
@ -231,18 +234,17 @@ int GetPS2ElfName(char *name){
return 1;
}
pos+=strlen("BOOT2");
while (pos && *pos && pos<=&buffer[255]
while (pos && *pos && pos<&buffer[g_MaxPath]
&& (*pos<'A' || (*pos>'Z' && *pos<'a') || *pos>'z'))
pos++;
if (!pos || *pos==0)
return 0;
sscanf(pos, "%s", name);
// the filename is everything up to the first CR/LF/tab.. ?
// Or up to any whitespace? (I'm opting for first CRLF/tab, although the old code
// apparently stopped on spaces too) --air
name = wxStringTokenizer( wxString::FromAscii( pos ) ).GetNextToken();
if (strncmp("cdrom0:\\", name, 8) == 0) {
strncpy(CdromId, name+8, 11); CdromId[11] = 0;
}
#ifdef PCSX2_DEVBUILD
FILE *fp;
int i;
@ -281,7 +283,7 @@ void SaveGSState(const wxString& file)
if( g_SaveGSStream ) return;
Console::WriteLn( "Saving GS State..." );
Console::WriteLn( "\t%hs", params file.c_str() );
Console::WriteLn( "\t%s", params file.mb_str() );
g_fGSSave = new gzSavingState( file );
@ -305,9 +307,9 @@ void LoadGSState(const wxString& file)
catch( Exception::FileNotFound& )
{
// file not found? try prefixing with sstates folder:
if( !Path::isRooted( file ) )
if( !Path::IsRooted( file ) )
{
f = new gzLoadingState( Path::Combine( SSTATES_DIR, file ).c_str() );
f = new gzLoadingState( Path::Combine( g_Conf.Folders.Savestates, file ) );
// If this load attempt fails, then let the exception bubble up to
// the caller to deal with...
@ -350,9 +352,7 @@ char* mystrlwr( char* string )
static wxString GetGSStateFilename()
{
wxString gsText;
gsText.Printf( "/%8.8X.%d.gs", ElfCRC, StatesC );
return Path::Combine( SSTATES_DIR, gsText );
return Path::Combine( g_Conf.Folders.Savestates, wxsFormat( wxT("/%8.8X.%d.gs"), ElfCRC, StatesC ) );
}
void CycleFrameLimit(int dir)
@ -430,10 +430,11 @@ void ProcessFKeys(int fkey, struct KeyModifiers *keymod)
catch( Exception::BaseException& ex )
{
// 99% of the time this is a file permission error and the
// cpu state is intact so just display a passive msg to console.
// cpu state is intact so just display a passive msg to console without
// raising an exception.
Console::Error( "Error > Could not save state to slot %d", params StatesC );
Console::Error( ex.cMessage() );
Console::Error( "Error! Could not save state to slot %d", params StatesC );
Console::Error( ex.LogMessage() );
}
break;
@ -446,7 +447,7 @@ void ProcessFKeys(int fkey, struct KeyModifiers *keymod)
Console::Notice( " > Selected savestate slot %d", params StatesC);
if( GSchangeSaveState != NULL )
GSchangeSaveState(StatesC, SaveState::GetFilename(StatesC).c_str());
GSchangeSaveState(StatesC, SaveState::GetFilename(StatesC).mb_str());
break;
case 3:
@ -471,16 +472,15 @@ void ProcessFKeys(int fkey, struct KeyModifiers *keymod)
// This is the bad one. Chances are the cpu has been reset, so emulation has
// to be aborted. Sorry user! We'll give you some info for your trouble:
Console::Error( "An error occured while trying to load saveslot %d", params StatesC );
Console::Error( ex.cMessage() );
Msgbox::Alert(
"Pcsx2 encountered an error while trying to load the savestate\n"
"and emulation had to be aborted." );
ClosePlugins( true );
throw Exception::CpuStateShutdown(
"Saveslot load failed; PS2 emulated state had to be shut down." ); // let the GUI handle the error "gracefully"
// english log message:
wxsFormat( wxT("Error! Could not load from saveslot %d\n"), StatesC ) + ex.LogMessage(),
// translated message:
wxsFormat( _("Error loading saveslot %d. Emulator reset."), StatesC )
);
}
break;
@ -490,7 +490,7 @@ void ProcessFKeys(int fkey, struct KeyModifiers *keymod)
// note: VK_F5-VK_F7 are reserved for GS
case 8:
GSmakeSnapshot( SNAPSHOTS_DIR "/" );
GSmakeSnapshot( g_Conf.Folders.Snapshots.ToAscii().data() );
break;
case 9: //gsdx "on the fly" renderer switching
@ -539,16 +539,16 @@ void ProcessFKeys(int fkey, struct KeyModifiers *keymod)
// only take the first two words
wxString gsText;
wxStringTokenizer parts( strgametitle, " " );
wxStringTokenizer parts( strgametitle, L" " );
wxString name( parts.GetNextToken() ); // first part
wxString part2( parts.GetNextToken() );
if( !!part2 )
name += "_" + part2;
gsText.Printf( "%s.%d.gs", name.c_str(), StatesC );
Text = Path::Combine( SSTATES_DIR, gsText );
if( !!part2 )
name += wxT("_") + part2;
gsText.Printf( wxT("%s.%d.gs"), name.c_str(), StatesC );
Text = Path::Combine( g_Conf.Folders.Savestates, gsText );
}
else
{

View File

@ -34,7 +34,7 @@ extern uptr pDsp; //Used in GS, MTGS, Plugins, Misc
u32 GetBiosVersion(); // Used in Misc, Memory
extern u32 BiosVersion; // Used in Memory, Misc, CDVD
int GetPS2ElfName(char*); // Used in Misc, System, Linux, CDVD
int GetPS2ElfName( wxString& dest ); // Used in Misc, System, Linux, CDVD
// Not sure what header these should go in. Probably not this one.
void SetCPUState(u32 sseMXCSR, u32 sseVUMXCSR);
@ -65,7 +65,7 @@ extern u64 GetTickFrequency();
// Used in Misc,and Windows/Linux files.
extern void ProcessFKeys(int fkey, struct KeyModifiers *keymod); // processes fkey related commands value 1-12
extern int IsBIOS(const char *filename, char *description);
extern bool IsBIOS(const wxString& filename, wxString& description);
//extern const char *LabelAuthors;
//extern const char *LabelGreets;

View File

@ -63,4 +63,5 @@ void DispatcherReg();
}
#endif
#endif
#endif

View File

@ -24,190 +24,7 @@
#include "System.h"
class MainEmuFrame;
class IniInterface // abstract base class!
{
protected:
wxConfigBase& m_Config;
public:
virtual ~IniInterface();
explicit IniInterface();
explicit IniInterface( wxConfigBase& config );
void SetPath( const wxString& path );
void Flush();
virtual void Entry( const wxString& var, wxString& value, const wxString& defvalue=wxString() )=0;
virtual void Entry( const wxString& var, int& value, const int defvalue=0 )=0;
virtual void Entry( const wxString& var, uint& value, const uint defvalue=0 )=0;
virtual void Entry( const wxString& var, bool& value, const bool defvalue=0 )=0;
virtual void Entry( const wxString& var, wxPoint& value, const wxPoint& defvalue=wxDefaultPosition )=0;
virtual void Entry( const wxString& var, wxSize& value, const wxSize& defvalue=wxDefaultSize )=0;
virtual void Entry( const wxString& var, wxRect& value, const wxRect& defvalue=wxDefaultRect )=0;
virtual void EnumEntry( const wxString& var, int& value, const char* const* enumArray, const int defvalue=0 )=0;
};
class IniLoader : public IniInterface
{
public:
virtual ~IniLoader();
explicit IniLoader();
explicit IniLoader( wxConfigBase& config );
void Entry( const wxString& var, wxString& value, const wxString& defvalue=wxString() );
void Entry( const wxString& var, int& value, const int defvalue=0 );
void Entry( const wxString& var, uint& value, const uint defvalue=0 );
void Entry( const wxString& var, bool& value, const bool defvalue=false );
void Entry( const wxString& var, wxPoint& value, const wxPoint& defvalue=wxDefaultPosition );
void Entry( const wxString& var, wxSize& value, const wxSize& defvalue=wxDefaultSize );
void Entry( const wxString& var, wxRect& value, const wxRect& defvalue=wxDefaultRect );
void EnumEntry( const wxString& var, int& value, const char* const* enumArray, const int defvalue=0 );
};
class IniSaver : public IniInterface
{
public:
virtual ~IniSaver();
explicit IniSaver();
explicit IniSaver( wxConfigBase& config );
void Entry( const wxString& var, wxString& value, const wxString& defvalue=wxString() );
void Entry( const wxString& var, int& value, const int defvalue=0 );
void Entry( const wxString& var, uint& value, const uint defvalue=0 );
void Entry( const wxString& var, bool& value, const bool defvalue=false );
void Entry( const wxString& var, wxPoint& value, const wxPoint& defvalue=wxDefaultPosition );
void Entry( const wxString& var, wxSize& value, const wxSize& defvalue=wxDefaultSize );
void Entry( const wxString& var, wxRect& value, const wxRect& defvalue=wxDefaultRect );
void EnumEntry( const wxString& var, int& value, const char* const* enumArray, const int defvalue=0 );
};
//////////////////////////////////////////////////////////////////////////////////////////
//
class AppConfig
{
public:
struct ConsoleLogOptions
{
bool Visible;
// if true, DisplayPos is ignored and the console is automatically docked to the main window.
bool AutoDock;
// Display position used if AutoDock is false (ignored otherwise)
wxPoint DisplayPosition;
wxSize DisplaySize;
void LoadSave( IniInterface& conf );
};
struct FolderOptions
{
wxString Plugins;
wxString Bios;
wxString Snapshots;
wxString Savestates;
wxString MemoryCards;
};
// Options struct for each memory card.
struct McdOptions
{
wxString Filename; // user-configured location of this memory card
bool Enabled; // memory card enabled (if false, memcard will not show up in-game)
};
struct McdSysOptions
{
McdOptions Mcd[2];
bool EnableNTFS; // enables automatic ntfs compression of memory cards (Win32 only)
bool EnableEjection; // enables simulated ejection of memory cards when loading savestates
void LoadSave( IniInterface& conf );
};
struct CpuRecompilerOptions
{
struct
{
bool
Enabled:1, // universal toggle for the profiler.
RecBlocks_EE:1, // Enables per-block profiling for the EE recompiler [unimplemented]
RecBlocks_IOP:1, // Enables per-block profiling for the IOP recompiler [unimplemented]
RecBlocks_VU1:1; // Enables per-block profiling for the VU1 recompiler [unimplemented]
} Profiler;
struct
{
bool
EnableEE:1,
EnableIOP:1,
EnableVU0:1,
EnableVU1:1;
} Recompiler;
void LoadSave( IniInterface& conf );
};
struct VideoOptions
{
bool MultithreadGS; // Uses the multithreaded GS interface.
bool closeOnEsc; // Closes the GS/Video port on escape (good for fullscreen activity)
bool UseFramelimiter;
int RegionMode; // 0=NTSC and 1=PAL
int CustomFps;
int CustomFrameSkip;
int CustomConsecutiveFrames;
int CustomConsecutiveSkip;
void LoadSave( IniInterface& conf );
};
struct GamefixOptions
{
bool
VuAddSubHack:1, // Fix for Tri-ace games, they use an encryption algorithm that requires VU addi opcode to be bit-accurate.
VuClipFlagHack:1, // Fix for Digimon Rumble Arena 2, fixes spinning/hanging on intro-menu.
FpuCompareHack:1, // Fix for Persona games, maybe others. It's to do with the VU clip flag (again).
FpuMulHack:1; // Fix for Tales of Destiny hangs.
void LoadSave();
};
struct SpeedhackOptions
{
int
EECycleRate:3, // EE cyclerate selector (1.0, 1.5, 2.0, 3.0)
IopCycleRate_X2:1, // enables the x2 multiplier of the IOP cyclerate
ExtWaitcycles:1, // enables extended waitcycles duration
IntcStat:1; // tells Pcsx2 to fast-forward through intc_stat waits.
void LoadSave( IniInterface& conf );
};
public:
wxPoint MainGuiPosition;
bool CdvdVerboseReads; // enables cdvd read activity verbosely dumped to the console
CpuRecompilerOptions Cpu;
SpeedhackOptions Speedhacks;
GamefixOptions Gamefixes;
VideoOptions Video;
ConsoleLogOptions ConLogBox;
FolderOptions Folders;
public:
void LoadSave( IniInterface& ini );
};
class IniInterface;
//////////////////////////////////////////////////////////////////////////////////////////
//
@ -229,6 +46,7 @@ public:
virtual void OnClear(wxCommandEvent& event);
virtual void Write( const wxChar* text );
virtual void Write( const char* text );
void Newline();
void SetColor( Console::Colors color );
@ -264,8 +82,12 @@ protected:
public:
Pcsx2App();
wxFrame* GetMainWindow() const;
bool OnInit();
int OnExit();
void OnInitCmdLine( wxCmdLineParser& parser );
bool OnCmdLineParsed( wxCmdLineParser& parser );
const wxBitmap& GetLogoBitmap() const;
MainEmuFrame& GetMainFrame() const
@ -281,5 +103,3 @@ public:
};
DECLARE_APP(Pcsx2App)
extern AppConfig g_Conf;

View File

@ -18,147 +18,130 @@
#include "PrecompiledHeader.h"
#include "App.h"
#include "IniInterface.h"
IniInterface::IniInterface( wxConfigBase& config ) :
m_Config( config )
{
}
IniInterface::IniInterface() :
m_Config( *wxConfigBase::Get() )
{
}
IniInterface::~IniInterface()
{
Flush();
}
void IniInterface::SetPath( const wxString& path )
{
m_Config.SetPath( path );
}
void IniInterface::Flush()
{
m_Config.Flush();
}
#include <wx/stdpaths.h>
//////////////////////////////////////////////////////////////////////////////////////////
// PathDefs Namespace -- contains default values for various pcsx2 path names and locations.
//
IniLoader::IniLoader( wxConfigBase& config ) : IniInterface( config )
// Note: The members of this namespace are intended for default value initialization only.
// Most of the time you should use the path folder assignments in Conf() instead, since those
// are user-configurable.
//
namespace PathDefs
{
}
IniLoader::IniLoader() : IniInterface() {}
IniLoader::~IniLoader() {}
void IniLoader::Entry( const wxString& var, wxString& value, const wxString& defvalue )
{
m_Config.Read( var, &value, defvalue );
}
void IniLoader::Entry( const wxString& var, int& value, const int defvalue )
{
m_Config.Read( var, &value, defvalue );
}
void IniLoader::Entry( const wxString& var, uint& value, const uint defvalue )
{
m_Config.Read( var, (int*)&value, (int)defvalue );
}
void IniLoader::Entry( const wxString& var, bool& value, const bool defvalue )
{
wxString dest;
m_Config.Read( var, &dest, defvalue ? "enabled" : "disabled" );
value = (dest == "enabled") || (dest == "1");
}
void IniLoader::Entry( const wxString& var, wxPoint& value, const wxPoint& defvalue )
{
TryParse( value, m_Config.Read( var, ToString( defvalue ) ), defvalue );
}
void IniLoader::Entry( const wxString& var, wxSize& value, const wxSize& defvalue )
{
TryParse( value, m_Config.Read( var, ToString( defvalue ) ), defvalue );
}
void IniLoader::Entry( const wxString& var, wxRect& value, const wxRect& defvalue )
{
TryParse( value, m_Config.Read( var, ToString( defvalue ) ), defvalue );
}
void IniLoader::EnumEntry( const wxString& var, int& value, const char* const* enumArray, const int defvalue )
{
wxString retval;
m_Config.Read( var, &retval, enumArray[defvalue] );
int i=0;
while( enumArray[i] != NULL && ( retval != enumArray[i] ) ) i++;
if( enumArray[i] == NULL )
const wxDirName Snapshots( wxT("snaps") );
const wxDirName Savestates( wxT("sstates") );
const wxDirName MemoryCards( wxT("memcards") );
const wxDirName Configs( wxT("inis") );
const wxDirName Plugins( wxT("plugins") );
// Fetches the path location for user-consumable documents -- stuff users are likely to want to
// share with other programs: screenshots, memory cards, and savestates.
wxDirName GetDocuments()
{
Console::Notice( "Loadini Warning > Unrecognized value '%s' on key '%s'\n\tUsing the default setting of '%s'.",
params retval.c_str(), var.c_str(), enumArray[defvalue] );
value = defvalue;
return (wxDirName)wxStandardPaths::Get().GetDocumentsDir() + (wxDirName)wxGetApp().GetAppName();
}
else
value = i;
}
//////////////////////////////////////////////////////////////////////////////////////////
//
wxDirName GetSnapshots()
{
return (wxDirName)GetDocuments() + Snapshots;
}
wxDirName GetBios()
{
return (wxDirName)wxT("bios");
}
wxDirName GetSavestates()
{
return (wxDirName)GetDocuments() + Savestates;
}
wxDirName GetMemoryCards()
{
return (wxDirName)GetDocuments() + MemoryCards;
}
wxDirName GetConfigs()
{
return (wxDirName)GetDocuments()+ Configs;
}
IniSaver::IniSaver( wxConfigBase& config ) : IniInterface( config )
wxDirName GetPlugins()
{
return (wxDirName)Plugins;
}
};
namespace FilenameDefs
{
}
wxFileName GetConfig()
{
// TODO : ini extension on Win32 is normal. Linux ini filename default might differ
// from this? like pcsx2_conf or something ... ?
IniSaver::IniSaver() : IniInterface() {}
IniSaver::~IniSaver() {}
return wxGetApp().GetAppName() + wxT(".ini");
}
wxFileName Memcard[2] =
{
wxT("Mcd001.ps2"),
wxT("Mcd002.ps2")
};
};
void IniSaver::Entry( const wxString& var, wxString& value, const wxString& defvalue )
// ------------------------------------------------------------------------
wxFileName wxDirName::Combine( const wxFileName& right ) const
{
m_Config.Write( var, value );
wxASSERT_MSG( IsDir(), L"Warning: Malformed directory name detected during wxDirName concatenation." );
if( right.IsAbsolute() )
return right;
// Append any directory parts from right, and then set the filename.
// Except we can't do that because our m_members are private (argh!) and there is no API
// for getting each component of the path. So instead let's use Normalize:
wxFileName result( right );
result.Normalize( wxPATH_NORM_ENV_VARS | wxPATH_NORM_DOTS, GetPath() );
return result;
}
void IniSaver::Entry( const wxString& var, int& value, const int defvalue )
wxDirName wxDirName::Combine( const wxDirName& right ) const
{
m_Config.Write( var, value );
wxASSERT_MSG( IsDir() && right.IsDir(), L"Warning: Malformed directory name detected during wDirName concatenation." );
wxDirName result( right );
result.Normalize( wxPATH_NORM_ENV_VARS | wxPATH_NORM_DOTS, GetPath() );
return result;
}
void IniSaver::Entry( const wxString& var, uint& value, const uint defvalue )
void wxDirName::Rmdir()
{
m_Config.Write( var, (int)value );
if( !Exists() ) return;
wxFileName::Rmdir();
// TODO : Throw exception if operation failed? Do we care?
}
void IniSaver::Entry( const wxString& var, bool& value, const bool defvalue )
bool wxDirName::Mkdir()
{
m_Config.Write( var, value ? "enabled" : "disabled" );
if( Exists() ) return true;
return wxFileName::Mkdir();
}
void IniSaver::Entry( const wxString& var, wxPoint& value, const wxPoint& defvalue )
{
m_Config.Write( var, ToString( value ) );
}
// ------------------------------------------------------------------------
wxString AppConfig::FullpathHelpers::Bios() const { return Path::Combine( m_conf.Folders.Bios, m_conf.BaseFilenames.Bios ); }
wxString AppConfig::FullpathHelpers::CDVD() const { return Path::Combine( m_conf.Folders.Plugins, m_conf.BaseFilenames.CDVD ); }
wxString AppConfig::FullpathHelpers::GS() const { return Path::Combine( m_conf.Folders.Plugins, m_conf.BaseFilenames.GS ); }
wxString AppConfig::FullpathHelpers::PAD1() const { return Path::Combine( m_conf.Folders.Plugins, m_conf.BaseFilenames.PAD1 ); }
wxString AppConfig::FullpathHelpers::PAD2() const { return Path::Combine( m_conf.Folders.Plugins, m_conf.BaseFilenames.PAD2 ); }
wxString AppConfig::FullpathHelpers::SPU2() const { return Path::Combine( m_conf.Folders.Plugins, m_conf.BaseFilenames.SPU2 ); }
wxString AppConfig::FullpathHelpers::DEV9() const { return Path::Combine( m_conf.Folders.Plugins, m_conf.BaseFilenames.DEV9 ); }
wxString AppConfig::FullpathHelpers::USB() const { return Path::Combine( m_conf.Folders.Plugins, m_conf.BaseFilenames.USB ); }
wxString AppConfig::FullpathHelpers::FW() const { return Path::Combine( m_conf.Folders.Plugins, m_conf.BaseFilenames.FW ); }
void IniSaver::Entry( const wxString& var, wxSize& value, const wxSize& defvalue )
{
m_Config.Write( var, ToString( value ) );
}
void IniSaver::Entry( const wxString& var, wxRect& value, const wxRect& defvalue )
{
m_Config.Write( var, ToString( value ) );
}
void IniSaver::EnumEntry( const wxString& var, int& value, const char* const* enumArray, const int defvalue )
{
m_Config.Write( var, enumArray[value] );
}
wxString AppConfig::FullpathHelpers::Mcd( uint mcdidx ) const { return Path::Combine( m_conf.Folders.MemoryCards, m_conf.MemoryCards.Mcd[mcdidx].Filename ); }
//////////////////////////////////////////////////////////////////////////////////////////
//

View File

@ -59,7 +59,7 @@ static bool OpenLogFile(wxFile& file, wxString& filename, wxWindow *parent)
return false;
default:
wxFAIL_MSG( "invalid message box return value" );
wxFAIL_MSG( L"invalid message box return value" );
}
return ( bAppend ) ?
@ -211,3 +211,14 @@ void ConsoleLogFrame::Write( const wxChar* text )
m_TextCtrl.AppendText( text );
}
void ConsoleLogFrame::Write( const char* text )
{
// remove selection (WriteText is in fact ReplaceSelection)
#ifdef __WXMSW__
wxTextPos nLen = m_TextCtrl.GetLastPosition();
m_TextCtrl.SetSelection(nLen, nLen);
#endif
m_TextCtrl.AppendText( wxString::FromAscii(text) );
}

View File

@ -52,7 +52,7 @@ AboutBoxDialog::AboutBoxDialog( wxWindow* parent, int id ):
m_bitmap_ps2system( this, wxID_ANY, wxBitmap( EmbeddedImage<png_ps2_silver>().GetImage() ),
wxDefaultPosition, wxDefaultSize, wxBORDER_SUNKEN )
{
static const wxString LabelAuthors = _(
static const wxString LabelAuthors = wxString::FromAscii(
"PCSX2, a PS2 emulator\n\n"
"Active Devs: Arcum42, Refraction,"
"drk||raziel, cottonvibes, gigaherz,"
@ -69,7 +69,7 @@ AboutBoxDialog::AboutBoxDialog( wxWindow* parent, int id ):
"Webmasters: CKemu, Falcon4ever"
);
static const wxString LabelGreets = _(
static const wxString LabelGreets = wxString::FromAscii(
"Contributors: Hiryu and Sjeep for libcvd (the iso parsing and\n"
"filesystem driver code), nneeve, pseudonym\n"
"\n"

52
pcsx2/NewGUI/HostGui.cpp Normal file
View File

@ -0,0 +1,52 @@
/* Pcsx2 - Pc Ps2 Emulator
* Copyright (C) 2002-2009 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
*/
#include "PrecompiledHeader.h"
#include "App.h"
// This API is likely obsolete for the most part, so I've just included a few dummies
// to keep things compiling until I can get to the point of tying up loose ends.
namespace HostGui
{
// Sets the status bar message without mirroring the output to the console.
void SetStatusMsg( const wxString& text )
{
wxGetApp().GetMainWindow()->SetStatusText( text );
}
void Notice( const wxString& text )
{
// mirror output to the console!
Console::Status( text.c_str() );
SetStatusMsg( text );
}
void ResetMenuSlots()
{
// Probably obsolete if we do a savestate dialog.
}
void BeginExecution()
{
}
void __fastcall KeyEvent( keyEvent* ev )
{
}
}

View File

@ -0,0 +1,165 @@
/* Pcsx2 - Pc Ps2 Emulator
* Copyright (C) 2002-2009 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
*/
#include "PrecompiledHeader.h"
#include "System.h"
#include "IniInterface.h"
//////////////////////////////////////////////////////////////////////////////////////////
//
IniInterface::IniInterface( wxConfigBase& config ) :
m_Config( config )
{
}
IniInterface::IniInterface() :
m_Config( *wxConfigBase::Get() )
{
}
IniInterface::~IniInterface()
{
Flush();
}
void IniInterface::SetPath( const wxString& path )
{
m_Config.SetPath( path );
}
void IniInterface::Flush()
{
m_Config.Flush();
}
//////////////////////////////////////////////////////////////////////////////////////////
//
IniLoader::IniLoader( wxConfigBase& config ) : IniInterface( config )
{
}
IniLoader::IniLoader() : IniInterface() {}
IniLoader::~IniLoader() {}
void IniLoader::Entry( const wxString& var, wxString& value, const wxString& defvalue )
{
m_Config.Read( var, &value, defvalue );
}
void IniLoader::Entry( const wxString& var, int& value, const int defvalue )
{
m_Config.Read( var, &value, defvalue );
}
void IniLoader::Entry( const wxString& var, uint& value, const uint defvalue )
{
m_Config.Read( var, (int*)&value, (int)defvalue );
}
void IniLoader::Entry( const wxString& var, bool& value, const bool defvalue )
{
wxString dest;
m_Config.Read( var, &dest, defvalue ? L"enabled" : L"disabled" );
value = (dest == L"enabled") || (dest == L"1");
}
void IniLoader::Entry( const wxString& var, wxPoint& value, const wxPoint& defvalue )
{
TryParse( value, m_Config.Read( var, ToString( defvalue ) ), defvalue );
}
void IniLoader::Entry( const wxString& var, wxSize& value, const wxSize& defvalue )
{
TryParse( value, m_Config.Read( var, ToString( defvalue ) ), defvalue );
}
void IniLoader::Entry( const wxString& var, wxRect& value, const wxRect& defvalue )
{
TryParse( value, m_Config.Read( var, ToString( defvalue ) ), defvalue );
}
void IniLoader::EnumEntry( const wxString& var, int& value, const wxChar* const* enumArray, const int defvalue )
{
wxString retval;
m_Config.Read( var, &retval, enumArray[defvalue] );
int i=0;
while( enumArray[i] != NULL && ( retval != enumArray[i] ) ) i++;
if( enumArray[i] == NULL )
{
Console::Notice( wxsFormat( L"Loadini Warning: Unrecognized value '%s' on key '%s'\n\tUsing the default setting of '%s'.",
params retval.c_str(), var.c_str(), enumArray[defvalue]
) );
value = defvalue;
}
else
value = i;
}
//////////////////////////////////////////////////////////////////////////////////////////
//
IniSaver::IniSaver( wxConfigBase& config ) : IniInterface( config )
{
}
IniSaver::IniSaver() : IniInterface() {}
IniSaver::~IniSaver() {}
void IniSaver::Entry( const wxString& var, wxString& value, const wxString& defvalue )
{
m_Config.Write( var, value );
}
void IniSaver::Entry( const wxString& var, int& value, const int defvalue )
{
m_Config.Write( var, value );
}
void IniSaver::Entry( const wxString& var, uint& value, const uint defvalue )
{
m_Config.Write( var, (int)value );
}
void IniSaver::Entry( const wxString& var, bool& value, const bool defvalue )
{
m_Config.Write( var, value ? L"enabled" : L"disabled" );
}
void IniSaver::Entry( const wxString& var, wxPoint& value, const wxPoint& defvalue )
{
m_Config.Write( var, ToString( value ) );
}
void IniSaver::Entry( const wxString& var, wxSize& value, const wxSize& defvalue )
{
m_Config.Write( var, ToString( value ) );
}
void IniSaver::Entry( const wxString& var, wxRect& value, const wxRect& defvalue )
{
m_Config.Write( var, ToString( value ) );
}
void IniSaver::EnumEntry( const wxString& var, int& value, const wxChar* const* enumArray, const int defvalue )
{
m_Config.Write( var, enumArray[value] );
}

109
pcsx2/NewGUI/IniInterface.h Normal file
View File

@ -0,0 +1,109 @@
/* Pcsx2 - Pc Ps2 Emulator
* Copyright (C) 2002-2009 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
*/
#pragma once
#include <wx/config.h>
//////////////////////////////////////////////////////////////////////////////////////////
// IniInterface class (abstract base class)
//
// This is used as an interchangable interface for both loading and saving options from an
// ini/configuration file. The LoadSave code takes an IniInterface, and the interface
// implementation defines whether the options are read or written.
//
// See also: IniLoader, IniSaver
//
class IniInterface
{
protected:
wxConfigBase& m_Config;
public:
virtual ~IniInterface();
explicit IniInterface();
explicit IniInterface( wxConfigBase& config );
void SetPath( const wxString& path );
void Flush();
virtual void Entry( const wxString& var, wxString& value, const wxString& defvalue=wxString() )=0;
virtual void Entry( const wxString& var, int& value, const int defvalue=0 )=0;
virtual void Entry( const wxString& var, uint& value, const uint defvalue=0 )=0;
virtual void Entry( const wxString& var, bool& value, const bool defvalue=0 )=0;
virtual void Entry( const wxString& var, wxPoint& value, const wxPoint& defvalue=wxDefaultPosition )=0;
virtual void Entry( const wxString& var, wxSize& value, const wxSize& defvalue=wxDefaultSize )=0;
virtual void Entry( const wxString& var, wxRect& value, const wxRect& defvalue=wxDefaultRect )=0;
virtual void EnumEntry( const wxString& var, int& value, const wxChar* const* enumArray, const int defvalue=0 )=0;
};
//////////////////////////////////////////////////////////////////////////////////////////
// IniLoader class
//
// Implementation of the IniInterface base class, which maps ini actions to loading from
// an ini source file.
//
// See also: IniInterface
//
class IniLoader : public IniInterface
{
public:
virtual ~IniLoader();
explicit IniLoader();
explicit IniLoader( wxConfigBase& config );
void Entry( const wxString& var, wxString& value, const wxString& defvalue=wxString() );
void Entry( const wxString& var, int& value, const int defvalue=0 );
void Entry( const wxString& var, uint& value, const uint defvalue=0 );
void Entry( const wxString& var, bool& value, const bool defvalue=false );
void Entry( const wxString& var, wxPoint& value, const wxPoint& defvalue=wxDefaultPosition );
void Entry( const wxString& var, wxSize& value, const wxSize& defvalue=wxDefaultSize );
void Entry( const wxString& var, wxRect& value, const wxRect& defvalue=wxDefaultRect );
void EnumEntry( const wxString& var, int& value, const wxChar* const* enumArray, const int defvalue=0 );
};
//////////////////////////////////////////////////////////////////////////////////////////
// IniSaver class
//
// Implementation of the IniInterface base class, which maps ini actions to saving to
// an ini dest file.
//
// See also: IniInterface
//
class IniSaver : public IniInterface
{
public:
virtual ~IniSaver();
explicit IniSaver();
explicit IniSaver( wxConfigBase& config );
void Entry( const wxString& var, wxString& value, const wxString& defvalue=wxString() );
void Entry( const wxString& var, int& value, const int defvalue=0 );
void Entry( const wxString& var, uint& value, const uint defvalue=0 );
void Entry( const wxString& var, bool& value, const bool defvalue=false );
void Entry( const wxString& var, wxPoint& value, const wxPoint& defvalue=wxDefaultPosition );
void Entry( const wxString& var, wxSize& value, const wxSize& defvalue=wxDefaultSize );
void Entry( const wxString& var, wxRect& value, const wxRect& defvalue=wxDefaultRect );
void EnumEntry( const wxString& var, int& value, const wxChar* const* enumArray, const int defvalue=0 );
};

View File

@ -140,7 +140,7 @@ void MainEmuFrame::OnLogBoxHidden()
MainEmuFrame::MainEmuFrame(wxWindow* parent, int id, const wxString& title, const wxPoint& pos, const wxSize& size, long style):
wxFrame(parent, id, title, pos, size, wxCAPTION|wxCLOSE_BOX|wxSYSTEM_MENU|wxBORDER_THEME),
m_logbox( this, "Pcsx2 Log" ),
m_logbox( this, L"Pcsx2 Log" ),
m_statusbar( *CreateStatusBar(2, 0) ),
m_background( this, wxID_ANY, wxGetApp().GetLogoBitmap() ),
@ -161,7 +161,7 @@ MainEmuFrame::MainEmuFrame(wxWindow* parent, int id, const wxString& title, cons
m_LoadStatesSubmenu( *MakeStatesSubMenu( Menu_State_Load01 ) ),
m_SaveStatesSubmenu( *MakeStatesSubMenu( Menu_State_Save01 ) ),
m_MenuItem_Console( *new wxMenuItem( &m_menuMisc, Menu_Console, _T("Show Console"), wxEmptyString, wxITEM_CHECK ) )
m_MenuItem_Console( *new wxMenuItem( &m_menuMisc, Menu_Console, L"Show Console", wxEmptyString, wxITEM_CHECK ) )
{
wxGetApp().SetConsoleFrame( m_logbox );

View File

@ -17,12 +17,13 @@
*/
#include "PrecompiledHeader.h"
#include "IniInterface.h"
#include "MainFrame.h"
#include "Resources/EmbeddedImage.h"
#include "Resources/BackgroundLogo.h"
#include <wx/stdpaths.h>
#include <wx/cmdline.h>
IMPLEMENT_APP(Pcsx2App)
@ -30,81 +31,14 @@ AppConfig g_Conf;
const wxRect wxDefaultRect( wxDefaultCoord, wxDefaultCoord, wxDefaultCoord, wxDefaultCoord );
//////////////////////////////////////////////////////////////////////////////////////////
// PathDefs Namespace -- contains default values for various pcsx2 path names and locations.
//
// Note: The members of this namespace are intended for default value initialization only.
// Most of the time you should use the path folder assignments in Conf() instead, since those
// are user-configurable.
//
namespace PathDefs
{
const wxString Snapshots( "snaps" );
const wxString Savestates( "sstates" );
const wxString MemoryCards( "memcards" );
const wxString Configs( "inis" );
const wxString Plugins( "plugins" );
// Fetches the path location for user-consumable documents -- stuff users are likely to want to
// share with other programs: screenshots, memory cards, and savestates.
wxString GetDocuments()
{
return Path::Combine( wxStandardPaths::Get().GetDocumentsDir(), wxGetApp().GetAppName() );
}
wxString GetSnapshots()
{
return Path::Combine( GetDocuments(), Snapshots );
}
wxString GetBios()
{
return "bios";
}
wxString GetSavestates()
{
return Path::Combine( GetDocuments(), Savestates );
}
wxString GetMemoryCards()
{
return Path::Combine( GetDocuments(), MemoryCards );
}
wxString GetConfigs()
{
return Path::Combine( GetDocuments(), Configs );
}
wxString GetPlugins()
{
return Plugins;
}
wxString GetWorking()
{
return wxGetCwd();
}
};
namespace FilenameDefs
{
wxString GetConfig()
{
// TODO : ini extension on Win32 is normal. Linux ini filename default might differ
// from this? like pcsx2_conf or something ... ?
return wxGetApp().GetAppName() + ".ini";
}
};
Pcsx2App::Pcsx2App() :
m_ConsoleFrame( NULL )
{
SetAppName( "Pcsx2" );
SetAppName( L"Pcsx2" );
}
wxFrame* Pcsx2App::GetMainWindow() const { return m_MainFrame; }
wxFileConfig* OpenConfig( const wxString& filename )
{
return new wxFileConfig( wxEmptyString, wxEmptyString, filename, wxEmptyString, wxCONFIG_USE_RELATIVE_PATH );
@ -114,21 +48,65 @@ wxFileConfig* OpenConfig( const wxString& filename )
// returns false if not (in which case the calling code should fall back on using OpenConfigUserLocal())
bool Pcsx2App::TryOpenConfigCwd()
{
wxString inipath_cwd( Path::Combine( wxGetCwd(), PathDefs::Configs ) );
if( !Path::isDirectory( inipath_cwd ) ) return false;
wxDirName inipath_cwd( (wxDirName)wxGetCwd() + PathDefs::Configs );
if( !inipath_cwd.IsReadable() ) return false;
wxString inifile_cwd( Path::Combine( inipath_cwd, FilenameDefs::GetConfig() ) );
if( !Path::isFile( inifile_cwd ) ) return false;
if( Path::getFileSize( inifile_cwd ) <= 1 ) return false;
if( !Path::IsFile( inifile_cwd ) ) return false;
if( Path::GetFileSize( inifile_cwd ) <= 1 ) return false;
wxConfigBase::Set( OpenConfig( inifile_cwd ) );
return true;
}
void Pcsx2App::OnInitCmdLine( wxCmdLineParser& parser )
{
parser.SetLogo( _(
" >> Pcsx2 -- A Playstation2 Emulator for the PC\n"
) );
parser.AddParam( _( "CDVD/ELF" ), wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL );
parser.AddSwitch( wxT("h"), wxT("help"), _("displays this list of command line options"), wxCMD_LINE_OPTION_HELP );
parser.AddSwitch( wxT("nogui"), wxT("nogui"), _("disables display of the gui and enables the Escape Hack.") );
parser.AddOption( wxT("bootmode"), wxEmptyString, _("0 - quick (default), 1 - bios, 2 - load elf"), wxCMD_LINE_VAL_NUMBER );
parser.AddOption( wxEmptyString, wxT("cfg"), _("configuration file override"), wxCMD_LINE_VAL_STRING );
parser.AddOption( wxEmptyString,wxT("cdvd"), _("uses filename as the CDVD plugin for this session only.") );
parser.AddOption( wxEmptyString,wxT("gs"), _("uses filename as the GS plugin for this session only.") );
parser.AddOption( wxEmptyString,wxT("spu"), _("uses filename as the SPU2 plugin for this session only.") );
parser.AddOption( wxEmptyString,wxT("pad"), _("uses filename as *both* PAD plugins for this session only.") );
parser.AddOption( wxEmptyString,wxT("pad1"), _("uses filename as the PAD1 plugin for this session only.") );
parser.AddOption( wxEmptyString,wxT("pad2"), _("uses filename as the PAD2 plugin for this session only.") );
parser.AddOption( wxEmptyString,wxT("dev9"), _("uses filename as the DEV9 plugin for this session only.") );
parser.AddOption( wxEmptyString,wxT("usb"), _("uses filename as the USB plugin for this session only.") );
parser.SetSwitchChars( wxT("-") );
}
bool Pcsx2App::OnCmdLineParsed(wxCmdLineParser& parser)
{
if( parser.GetParamCount() >= 1 )
{
// [TODO] : Unnamed parameter is taken as an "autorun" option for a cdvd/iso.
parser.GetParam( 0 );
}
// Suppress wxWidgets automatic options parsing since none of them pertain to Pcsx2 needs.
//wxApp::OnCmdLineParsed( parser );
bool yay = parser.Found( wxT("nogui") );
return true;
}
bool Pcsx2App::OnInit()
{
wxInitAllImageHandlers();
wxApp::OnInit();
// Ini Startup: The ini file could be in one of two locations, depending on how Pcsx2 has
// been installed or configured. The first place we look is in our program's working
// directory. If the ini there exist, and is *not* empty, then we'll use it. Otherwise
@ -136,8 +114,8 @@ bool Pcsx2App::OnInit()
if( !TryOpenConfigCwd() )
{
Path::CreateDirectory( PathDefs::GetDocuments() );
Path::CreateDirectory( PathDefs::GetConfigs() );
PathDefs::GetDocuments().Mkdir();
PathDefs::GetConfigs().Mkdir();
// Allow wx to use our config, and enforces auto-cleanup as well
wxConfigBase::Set( OpenConfig( Path::Combine( PathDefs::GetConfigs(), FilenameDefs::GetConfig() ) ) );

View File

@ -24,7 +24,6 @@
#define _PC_ // disables MIPS opcode macros.
#include "IopCommon.h"
#include "Paths.h"
#include "Patch.h"
#include "VU.h"
@ -462,20 +461,25 @@ void patchFunc_comment( char * text1, char * text2 )
void patchFunc_gametitle( char * text1, char * text2 )
{
Console::WriteLn( "gametitle: %s", params text2 );
strgametitle = text2;
Console::SetTitle(strgametitle);
strgametitle.FromAscii( text2 );
Console::SetTitle( strgametitle );
}
void patchFunc_patch( char * cmd, char * param )
{
char * pText;
char* pText;
if ( patchnumber >= MAX_PATCH )
{
// TODO : Use wxLogError for this, once we have full unicode compliance on cmd/params vars.
//wxLogError( wxT("Patch ERROR: Maximum number of patches reached: %s=%s"), cmd, param );
Console::Error( "Patch ERROR: Maximum number of patches reached: %s=%s", params cmd, param );
return;
}
//SafeList<wxString> pieces;
//SplitString( pieces, param, "," );
pText = strtok( param, "," );
pText = param;
@ -536,7 +540,10 @@ void inifile_command( char * cmd )
code = PatchTableExecute( command, parameter, commands );
}
void inifile_trim( char * buffer )
#define USE_CRAZY_BASHIT_INSANE_TRIM
#ifdef USE_CRAZY_BASHIT_INSANE_TRIM
void inifile_trim( char* buffer )
{
char * pInit = buffer;
char * pEnd = NULL;
@ -574,6 +581,33 @@ void inifile_trim( char * buffer )
buffer[ pEnd - pInit + 1 ] = '\0';
}
#else
// New version of trim (untested), which I coded but can't use yet because the
// rest of Patch needs to be more wxString-involved first.
void inifile_trim( wxString& buffer )
{
buffer.Trim( false ); // trims left side.
if( buffer.Length() <= 1 ) // this I'm not sure about... - air
{
buffer.Clear();
return;
}
if( buffer.Left( 2 ) == "//" )
{
buffer.Clear();
return;
}
buffer.Trim(true); // trims right side.
}
#endif
void inisection_process( FILE * f1 )
{
char buffer[ 1024 ];
@ -621,7 +655,7 @@ void inifile_read( const char * name )
if( !f1 )
{
Console::WriteLn("No patch found.Resuming execution without a patch (this is NOT an error)." );
Console::WriteLn("No patch found. Resuming execution without a patch (this is NOT an error)." );
return;
}

View File

@ -115,8 +115,8 @@ extern int g_ZeroGSOptions;
extern u32 g_sseMXCSR;
extern u32 g_sseVUMXCSR;
void SetRoundMode(u32 ee, u32 vu);
int LoadPatch(const std::string& patchfile);
extern void SetRoundMode(u32 ee, u32 vu);
extern int LoadPatch(const wxString& patchfile);
#endif /* __PATCH_H__ */

View File

@ -36,65 +36,79 @@ namespace Path
#ifdef WIN32
// Path Separator used when creating new paths.
static const char Separator( '\\' );
static const wxChar Separator( wxT('\\') );
// Path separators used when breaking existing paths into parts and pieces.
static const wxString Delimiters( "\\/" );
static const wxString Delimiters( wxT("\\/") );
static const wxChar SeparatorExt( wxT('.') );
#else
static const char Separator = '/';
static const char Delimiters( '/' );
#endif
static bool IsPathSeparator( wxChar src )
{
#ifdef WIN32
return (src == Separator) || (src == wxT('/'));
#else
return src == Separator;
#endif
}
bool Exists( const wxString& path )
{
struct stat sbuf;
return stat( path.c_str(), &sbuf ) == 0;
wxStructStat sbuf;
return wxStat( path.c_str(), &sbuf ) == 0;
}
// This function returns false if the path does not exist, or if the path exists and
// is a file.
bool isDirectory( const wxString& path )
bool IsDirectory( const wxString& path )
{
struct stat sbuf;
if( stat( path.c_str(), &sbuf ) == -1 ) return false;
wxStructStat sbuf;
if( wxStat( path.c_str(), &sbuf ) == -1 ) return false;
return !!(sbuf.st_mode & _S_IFDIR);
}
// This function returns false if the path does not exist, or if the path exists and
// is a directory.
bool isFile( const wxString& path )
bool IsFile( const wxString& path )
{
struct stat sbuf;
if( stat( path.c_str(), &sbuf ) == -1 ) return false;
wxStructStat sbuf;
if( wxStat( path.c_str(), &sbuf ) == -1 ) return false;
return !!(sbuf.st_mode & _S_IFREG);
}
// Returns the length of the file.
// returns -1 if the file is not found.
int getFileSize( const wxString& path )
int GetFileSize( const wxString& path )
{
struct stat sbuf;
if( stat( path.c_str(), &sbuf ) == -1 ) return -1;
wxStructStat sbuf;
if( wxStat( path.c_str(), &sbuf ) == -1 ) return -1;
return sbuf.st_size;
}
bool isRooted( const wxString& path )
bool IsRooted( const wxString& path )
{
// if the first character is a backslash or period, or the second character
// a colon, it's a safe bet we're rooted.
if( path[0] == 0 ) return FALSE;
if( path[0] == 0 ) return false;
#ifdef WIN32
return (path[0] == '/') || (path[0] == '\\') || (path[1] == ':');
return IsPathSeparator(path[0]) || ( (path[1] == ':') && IsPathSeparator(path[2]) );
#else
return (path[0] == Separator);
return IsPathSeparator(path[0]);
#endif
}
// ------------------------------------------------------------------------
// Concatenates two pathnames together, inserting delimiters (backslash on win32)
// as needed! Assumes the 'dest' is allocated to at least g_MaxPath length.
wxString Combine( const wxString& srcPath, const wxString& srcFile )
{
int pathlen, guesslen;
#if 0
int pathlen;
if( srcFile.empty() )
{
@ -102,7 +116,7 @@ wxString Combine( const wxString& srcPath, const wxString& srcFile )
return srcPath;
}
if( isRooted( srcFile ) || srcPath.empty() )
if( IsRooted( srcFile ) || srcPath.empty() )
{
// No source path? Or source filename is rooted?
// Return the filename unmodified.
@ -114,7 +128,7 @@ wxString Combine( const wxString& srcPath, const wxString& srcFile )
// This might be a problem on Linux builds or maybe it doesn't matter?
pathlen = srcPath.length();
while( pathlen > 0 && ((srcPath[pathlen-1] == '\\') || (srcPath[pathlen-1] == '/')) )
while( pathlen > 0 && IsPathSeparator(srcPath[pathlen-1]) )
--pathlen;
// Concatenate strings:
@ -129,14 +143,31 @@ wxString Combine( const wxString& srcPath, const wxString& srcFile )
dest += Separator;
dest += srcFile;
return dest;
#else
// Use wx's Path system for concatenation because it's pretty smart.
return (wxDirName( srcPath ) + srcFile).GetFullPath();
#endif
}
wxString Combine( const wxDirName& srcPath, const wxFileName& srcFile )
{
return (srcPath + srcFile).GetFullPath();
}
wxString Combine( const wxString& srcPath, const wxDirName& srcFile )
{
return ((wxDirName)srcPath + srcFile).ToString();
}
// Replaces the extension of the file with the one given.
// This function works for path names as well as file names.
wxString ReplaceExtension( const wxString& src, const wxString& ext )
{
wxString dest;
int pos = src.find_last_of( '.' );
int pos = src.find_last_of( SeparatorExt );
if( pos == wxString::npos || pos == 0 )
dest = src;
else
@ -151,97 +182,32 @@ wxString ReplaceExtension( const wxString& src, const wxString& ext )
return dest;
}
// finds the starting character position of a filename for the given source path.
static int _findFilenamePosition( const wxString& src)
{
// note: the source path could have multiple trailing slashes. We want to ignore those.
unsigned int startpos = src.find_last_not_of( Delimiters );
if(startpos == wxString::npos )
return 0;
int pos;
if( startpos < src.length() )
{
wxString trimmed( src.begin(), src.begin()+startpos );
pos = trimmed.find_last_of( Delimiters );
}
else
{
pos = src.find_last_of( Delimiters );
}
if( pos == wxString::npos )
return 0;
return pos;
}
wxString ReplaceFilename( const wxString& src, const wxString& newfilename )
{
wxString dest;
int pos = _findFilenamePosition( src );
// Implementation note: use wxWidgets to do this job.
if( pos == 0 )
dest = src;
else
dest.assign( src.begin(), src.begin()+pos );
if( !newfilename.empty() )
{
dest += Separator;
dest += newfilename;
}
return dest;
wxFileName jojo( src );
jojo.SetFullName( newfilename );
return jojo.GetFullPath();
}
wxString GetFilename( const wxString& src )
{
int pos = _findFilenamePosition( src );
return wxString( src.begin()+pos, src.end() );
return wxFileName(src).GetFullName();
}
wxString GetFilenameWithoutExt( const wxString& src )
{
wxString fname( GetFilename( src ) );
int pos = fname.find_last_of( '.' );
if( pos == wxString::npos || pos == 0 )
return fname;
else
return wxString( fname.begin(), fname.begin()+pos );
return wxFileName(src).GetName();
}
wxString GetDirectory( const wxString& src )
{
int pos = _findFilenamePosition( src );
if( pos == 0 )
return wxString();
else
return wxString( src.begin(), src.begin()+pos );
return wxFileName(src).GetPath();
}
// This function mimics the old ANSI C splitpath function. It's more or less superceeded
// by one of the many other Path utility functions, but someone might find it useful.
void Split( const wxString& src, wxString& destpath, wxString& destfile )
{
int pos = _findFilenamePosition( src );
if( pos == 0 )
{
destpath.clear();
destfile = src;
}
else
{
destpath.assign( src.begin(), src.begin()+pos );
destfile.assign( src.begin()+pos, src.end() );
}
}
// Assigns the base/root directory of the given path into dest.
// returns the base/root directory of the given path.
// Example /this/that/something.txt -> dest == "/"
wxString GetRootDirectory( const wxString& src )
{
@ -254,11 +220,12 @@ wxString GetRootDirectory( const wxString& src )
void CreateDirectory( const wxString& src )
{
#ifdef _WIN32
_mkdir( src.c_str() );
#else
mkdir( src.c_str(), 0755);
#endif
wxFileName::Mkdir( src );
}
void RemoveDirectory( const wxString& src )
{
wxFileName::Rmdir( src );
}
}

View File

@ -7,6 +7,11 @@
extern char MAIN_DIR[g_MaxPath];
#endif
//////////////////////////////////////////////////////////////////////////////////////////
// Obsolete Values in wxWidgets Branch!
// The following set of macros has been superceeded by the PathDefs and FilenameDefs namespaces,
// and furethermore by a set of user-configurable paths in g_Conf.
//
#define DEFAULT_INIS_DIR "inis"
#define DEFAULT_BIOS_DIR "bios"
#define DEFAULT_PLUGINS_DIR "plugins"
@ -25,25 +30,170 @@ extern char MAIN_DIR[g_MaxPath];
// Windows.h namespace pollution!
#undef CreateDirectory
//////////////////////////////////////////////////////////////////////////////////////////
//
class wxDirName : protected wxFileName
{
public:
explicit wxDirName( const wxFileName& src )
{
wxASSERT_MSG( src.IsDir(), L"Warning: Creating a directory from what looks to be a filename..." );
Assign( src.GetPath() );
}
wxDirName() : wxFileName() {}
wxDirName( const wxDirName& src ) : wxFileName( src ) { }
explicit wxDirName( const char* src ) { Assign( wxString::FromAscii(src) ); }
explicit wxDirName( const wxString& src ) { Assign( src ); }
// ------------------------------------------------------------------------
void Assign( const wxString& volume, const wxString& path )
{
wxFileName::Assign( volume, path, wxEmptyString );
}
void Assign( const wxString& path )
{
wxFileName::Assign( path, wxEmptyString );
}
void Assign( const wxDirName& path )
{
wxFileName::Assign( path );
}
void Clear() { wxFileName::Clear(); }
wxCharBuffer ToAscii() const { return GetPath().ToAscii(); }
wxString ToString() const { return GetPath(); }
// ------------------------------------------------------------------------
bool IsWritable() const { return IsDirWritable(); }
bool IsReadable() const { return IsDirReadable(); }
bool Exists() const { return DirExists(); }
bool IsOk() const { return wxFileName::IsOk(); }
bool SameAs( const wxDirName& filepath ) const
{
return wxFileName::SameAs( filepath );
}
// Returns the number of sub folders in this directory path
size_t GetCount() const { return GetDirCount(); }
// ------------------------------------------------------------------------
wxFileName Combine( const wxFileName& right ) const;
wxDirName Combine( const wxDirName& right ) const;
// removes the lastmost directory from the path
void RemoveLast() { wxFileName::RemoveDir(GetCount() - 1); }
// ------------------------------------------------------------------------
bool Normalize( int flags = wxPATH_NORM_ALL, const wxString& cwd = wxEmptyString )
{
wxASSERT_MSG( IsDir(), L"Warning: Malformed directory name detected during wDirName normalization." );
return wxFileName::Normalize( flags, cwd );
}
bool MakeRelativeTo( const wxString& pathBase = wxEmptyString )
{
wxASSERT_MSG( IsDir(), L"Warning: Malformed directory name detected during wDirName normalization." );
return wxFileName::MakeRelativeTo( pathBase );
}
bool MakeAbsolute( const wxString& cwd = wxEmptyString )
{
wxASSERT_MSG( IsDir(), L"Warning: Malformed directory name detected during wDirName normalization." );
return wxFileName::MakeAbsolute( cwd );
}
// ------------------------------------------------------------------------
void AssignCwd( const wxString& volume = wxEmptyString ) { wxFileName::AssignCwd( volume ); }
bool SetCwd() { wxFileName::SetCwd(); }
// wxWidgets is missing the const qualifier for this one! Shame!
void Rmdir();
bool Mkdir();
// ------------------------------------------------------------------------
wxDirName& operator=(const wxDirName& dirname) { Assign( dirname ); return *this; }
wxDirName& operator=(const wxString& dirname) { Assign( dirname ); return *this; }
wxDirName& operator=(const char* dirname) { Assign( wxString::FromAscii(dirname) ); return *this; }
wxFileName operator+( const wxFileName& right ) const { return Combine( right ); }
wxDirName operator+( const wxDirName& right ) const { return Combine( right ); }
bool operator==(const wxDirName& filename) const { return SameAs(filename); }
bool operator!=(const wxDirName& filename) const { return !SameAs(filename); }
bool operator==(const wxFileName& filename) const { return SameAs(wxDirName(filename)); }
bool operator!=(const wxFileName& filename) const { return !SameAs(wxDirName(filename)); }
// compare with a filename string interpreted as a native file name
bool operator==(const wxString& filename) const { return SameAs(wxDirName(filename)); }
bool operator!=(const wxString& filename) const { return !SameAs(wxDirName(filename)); }
};
// remove windows.h namespace pollution:
#undef GetFileSize
#undef CreateDirectory
//////////////////////////////////////////////////////////////////////////////////////////
// Path Namespace
// Cross-platform utilities for manipulation of paths and filenames.
//
namespace Path
{
extern bool isRooted( const wxString& path );
extern bool isDirectory( const wxString& path );
extern bool isFile( const wxString& path );
extern bool IsRooted( const wxString& path );
extern bool IsDirectory( const wxString& path );
extern bool IsFile( const wxString& path );
extern bool Exists( const wxString& path );
extern int getFileSize( const wxString& path );
extern int GetFileSize( const wxString& path );
extern wxString Combine( const wxString& srcPath, const wxString& srcFile );
extern wxString Combine( const wxDirName& srcPath, const wxFileName& srcFile );
extern wxString Combine( const wxString& srcPath, const wxDirName& srcFile );
extern wxString ReplaceExtension( const wxString& src, const wxString& ext );
extern wxString ReplaceFilename( const wxString& src, const wxString& newfilename );
extern wxString GetFilename( const wxString& src );
extern wxString GetDirectory( const wxString& src );
extern wxString GetFilenameWithoutExt( const string& src );
extern wxString GetRootDirectory( const wxString& src );
extern void Split( const wxString& src, wxString& destpath, wxString& destfile );
extern void CreateDirectory( const wxString& src );
extern void RemoveDirectory( const wxString& src );
}
//////////////////////////////////////////////////////////////////////////////////////////
// PathDefs Namespace -- contains default values for various pcsx2 path names and locations.
//
// Note: The members of this namespace are intended for default value initialization only.
// Most of the time you should use the path folder assignments in g_Conf instead, since those
// are user-configurable.
//
namespace PathDefs
{
extern const wxDirName Snapshots;
extern const wxDirName Savestates;
extern const wxDirName MemoryCards;
extern const wxDirName Configs;
extern const wxDirName Plugins;
extern wxDirName GetDocuments();
extern wxDirName GetSnapshots();
extern wxDirName GetBios();
extern wxDirName GetSavestates();
extern wxDirName GetMemoryCards();
extern wxDirName GetConfigs();
extern wxDirName GetPlugins();
}
namespace FilenameDefs
{
extern wxFileName GetConfig();
extern wxFileName Memcard[2];
};
#endif

View File

@ -216,6 +216,9 @@ _FWabout FWabout;
DEV9handler dev9Handler;
USBhandler usbHandler;
uptr pDsp;
#ifdef _not_wxWidgets_Land_
#define Sfy(x) #x
#define Strfy(x) Sfy(x)
@ -695,7 +698,6 @@ void ShutdownPlugins()
initp = false;
}
uptr pDsp;
extern void spu2DMA4Irq();
extern void spu2DMA7Irq();
extern void spu2Irq();
@ -922,3 +924,25 @@ void PluginsResetGS()
int ret = GSinit();
if (ret != 0) { Msgbox::Alert("GSinit error: %d", params ret); }
}
#else
int OpenPlugins(const char* pTitleFilename)
{
return 0;
}
void ClosePlugins( bool closegs )
{
}
void ShutdownPlugins()
{
}
void CloseGS()
{
}
#endif

View File

@ -36,12 +36,16 @@
#include <wx/string.h>
#include <wx/tokenzr.h>
#include <wx/gdicmn.h> // for wxPoint/wxRect stuff
#include <wx/intl.h>
#include <wx/log.h>
#include <wx/filename.h>
extern const wxRect wxDefaultRect; // wxWidgets lacks one of its own.
//////////////////////////////////////////////////////////////////////////////////////////
// Include the STL junk that's actually handy.
#include <stdexcept>
#include <algorithm>
#include <vector>
#include <string>
@ -67,10 +71,19 @@ using std::max;
typedef int BOOL;
# undef TRUE
# undef FALSE
# define TRUE 1
# define FALSE 0
#undef TRUE
#undef FALSE
#define TRUE 1
#define FALSE 0
// This should prove useful....
#define wxsFormat wxString::Format
// macro provided for tagging translation strings, without actually running them through the
// translator (which the _() does automatically, and sometimes we don't want that)
#define wxLt(a) a
#define wxASSERT_MSG_A( cond, msg ) wxASSERT_MSG( cond, wxString::FromAscii(msg).c_str() );
//////////////////////////////////////////////////////////////////////////////////////////
// Begin Pcsx2 Includes: Add items here that are local to Pcsx2 but stay relatively
@ -79,6 +92,8 @@ typedef int BOOL;
#include "zlib/zlib.h"
#include "PS2Etypes.h"
#include "Paths.h"
#include "Config.h"
#include "StringUtils.h"
#include "Exceptions.h"
#include "MemcpyFast.h"
@ -141,24 +156,33 @@ static __forceinline u32 timeGetTime()
# define __releaseinline __forceinline
#endif
//////////////////////////////////////////////////////////////////////////////////////////
// Emitter Instance Identifiers. If you add a new emitter, do it here also.
// Note: Currently most of the instances map back to 0, since existing dynarec code all
// shares iCore and must therefore all share the same emitter instance.
// (note: these don't really belong here per-se, but it's an easy spot to use for now)
enum
{
EmitterId_R5900 = 0,
EmitterId_R3000a = EmitterId_R5900,
EmitterId_VU0micro = EmitterId_R5900,
EmitterId_VU1micro = EmitterId_R5900,
// Cotton's new microVU, which is iCore-free
EmitterId_microVU0,
EmitterId_microVU1,
//////////////////////////////////////////////////////////////
// Dev / Debug conditionals --
// Consts for using if() statements instead of uglier #ifdef macros.
// Abbreviated macros for dev/debug only consoles and msgboxes.
// Air's eventual IopRec, which will also be iCore-free
EmitterId_R3000air,
EmitterId_Count // must always be last!
};
#ifdef PCSX2_DEVBUILD
# define DevCon Console
# define DevMsg MsgBox
static const bool IsDevBuild = true;
#else
# define DevCon 0&&Console
# define DevMsg
static const bool IsDevBuild = false;
#endif
#ifdef _DEBUG
# define DbgCon Console
static const bool IsDebugBuild = true;
#else
# define DbgCon 0&&Console
static const bool IsDebugBuild = false;
#endif

View File

@ -224,7 +224,7 @@ static __forceinline void _psxTestInterrupts()
}
}
void psxBranchTest()
__releaseinline void psxBranchTest()
{
if( psxTestCycle( psxNextsCounter, psxNextCounter ) )
{

View File

@ -126,14 +126,14 @@ extern s32 psxCycleEE; // tracks IOP's current sych status with the EE
#ifndef _PC_
#define _i32(x) (s32)x
#define _u32(x) (u32)x
#define _i32(x) (s32)x //R3000A
#define _u32(x) (u32)x //R3000A
#define _i16(x) (s16)x
#define _u16(x) (u16)x
#define _i16(x) (s16)x // Not used
#define _u16(x) (u16)x // Not used
#define _i8(x) (s8)x
#define _u8(x) (u8)x
#define _i8(x) (s8)x // Not used
#define _u8(x) (u8)x //R3000A - once
/**** R3000A Instruction Macros ****/
#define _PC_ psxRegs.pc // The next PC to be executed
@ -200,7 +200,7 @@ extern R3000Acpu psxRec;
void psxReset();
void psxShutdown();
void psxException(u32 code, u32 step);
void psxBranchTest();
extern void psxBranchTest();
void psxExecuteBios();
void psxMemReset();

View File

@ -35,8 +35,6 @@
#include "SPR.h"
#include "Sif.h"
#include "Paths.h"
#include "R5900Exceptions.h"
using namespace R5900; // for R5900 disasm tools
@ -82,11 +80,11 @@ void cpuReset()
g_nextBranchCycle = cpuRegs.cycle + 4;
EEsCycle = 0;
EEoCycle = cpuRegs.cycle;
eeWaitCycles = CHECK_WAITCYCLE_HACK ? 3072 : 768;
eeWaitCycles = Config.Hacks.WaitCycleExt ? 3072 : 768;
// Cyclerate hacks effectively speed up the rate of event tests, so we can safely boost
// the WaitCycles value here for x2 and x3 modes:
if( CHECK_EE_CYCLERATE > 1 )
if( Config.Hacks.EECycleRate > 1 )
eeWaitCycles += 1024;
hwReset();
@ -106,7 +104,7 @@ void cpuShutdown()
disR5900FreeSyms();
}
__releaseinline void __fastcall cpuException(u32 code, u32 bd)
__releaseinline void cpuException(u32 code, u32 bd)
{
cpuRegs.branch = 0; // Tells the interpreter that an exception occurred during a branch.
bool errLevel2, checkStatus;
@ -244,7 +242,7 @@ void cpuTestMissingHwInts() {
}
// sets a branch test to occur some time from an arbitrary starting point.
__forceinline int __fastcall cpuSetNextBranch( u32 startCycle, s32 delta )
__forceinline void cpuSetNextBranch( u32 startCycle, s32 delta )
{
// typecast the conditional to signed so that things don't blow up
// if startCycle is greater than our next branch cycle.
@ -252,20 +250,18 @@ __forceinline int __fastcall cpuSetNextBranch( u32 startCycle, s32 delta )
if( (int)(g_nextBranchCycle - startCycle) > delta )
{
g_nextBranchCycle = startCycle + delta;
return 1;
}
return 0;
}
// sets a branch to occur some time from the current cycle
__forceinline int __fastcall cpuSetNextBranchDelta( s32 delta )
__forceinline void cpuSetNextBranchDelta( s32 delta )
{
return cpuSetNextBranch( cpuRegs.cycle, delta );
cpuSetNextBranch( cpuRegs.cycle, delta );
}
// tests the cpu cycle agaisnt the given start and delta values.
// Returns true if the delta time has passed.
__forceinline int __fastcall cpuTestCycle( u32 startCycle, s32 delta )
__forceinline int cpuTestCycle( u32 startCycle, s32 delta )
{
// typecast the conditional to signed so that things don't explode
// if the startCycle is ahead of our current cpu cycle.
@ -279,7 +275,7 @@ __forceinline void cpuSetBranch()
g_nextBranchCycle = cpuRegs.cycle;
}
void cpuClearInt( uint i )
__forceinline void cpuClearInt( uint i )
{
jASSUME( i < 32 );
cpuRegs.interrupt &= ~(1 << i);

View File

@ -121,16 +121,16 @@ union CP0regs {
};
struct cpuRegisters {
GPRregs GPR; // GPR regs
GPRregs GPR; // GPR regs
// NOTE: don't change order since recompiler uses it
GPR_reg HI;
GPR_reg LO; // hi & log 128bit wide
CP0regs CP0; // is COP0 32bit?
u32 sa; // shift amount (32bit), needs to be 16 byte aligned
u32 IsDelaySlot; // set true when the current instruction is a delay slot.
u32 pc; // Program counter, when changing offset in struct, check iR5900-X.S to make sure offset is correct
u32 code; // current instruction
PERFregs PERF;
u32 pc; // Program counter, when changing offset in struct, check iR5900-X.S to make sure offset is correct
u32 code; // current instruction
PERFregs PERF;
u32 eCycle[32];
u32 sCycle[32]; // for internal counters
u32 cycle; // calculate cpucycles..
@ -180,7 +180,7 @@ struct tlbs
#ifndef _PC_
#define _i64(x) (s64)x
/*#define _i64(x) (s64)x
#define _u64(x) (u64)x
#define _i32(x) (s32)x
@ -190,12 +190,12 @@ struct tlbs
#define _u16(x) (u16)x
#define _i8(x) (s8)x
#define _u8(x) (u8)x
#define _u8(x) (u8)x*/
////////////////////////////////////////////////////////////////////
// R5900 Instruction Macros
#define _PC_ cpuRegs.pc // The next PC to be executed
#define _PC_ cpuRegs.pc // The next PC to be executed - only used in this header and R3000A.h
#define _Funct_ ((cpuRegs.code ) & 0x3F) // The funct part of the instruction register
#define _Rd_ ((cpuRegs.code >> 11) & 0x1F) // The rd part of the instruction register
@ -257,14 +257,14 @@ extern void cpuInit();
extern void cpuReset(); // can throw Exception::FileNotFound.
extern void cpuShutdown();
extern void cpuExecuteBios();
extern void __fastcall cpuException(u32 code, u32 bd);
extern void cpuException(u32 code, u32 bd);
extern void cpuTlbMissR(u32 addr, u32 bd);
extern void cpuTlbMissW(u32 addr, u32 bd);
extern void cpuTestHwInts();
extern int __fastcall cpuSetNextBranch( u32 startCycle, s32 delta );
extern int __fastcall cpuSetNextBranchDelta( s32 delta );
extern int __fastcall cpuTestCycle( u32 startCycle, s32 delta );
extern void cpuSetNextBranch( u32 startCycle, s32 delta );
extern void cpuSetNextBranchDelta( s32 delta );
extern int cpuTestCycle( u32 startCycle, s32 delta );
extern void cpuSetBranch();
extern bool _cpuBranchTest_Shared(); // for internal use by the Dynarecs and Ints inside R5900:

View File

@ -23,10 +23,13 @@ namespace R5900Exception
{
using Exception::Ps2Generic;
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
// Abstract base class for R5900 exceptions; contains the cpuRegs instance at the
// time the exception is raised.
//
// Translation note: EE Emulation exceptions are untranslated only. There's really no
// point in providing translations for this hardcore mess. :)
//
class BaseExcept : public Ps2Generic
{
public:
@ -35,8 +38,8 @@ namespace R5900Exception
public:
virtual ~BaseExcept() throw()=0;
explicit BaseExcept( const std::string& msg ) :
Exception::Ps2Generic( "(EE) " + msg ),
explicit BaseExcept( const wxString& msg ) :
Exception::Ps2Generic( wxT("(EE) ") + msg ),
cpuState( cpuRegs )
{
}
@ -57,7 +60,7 @@ namespace R5900Exception
virtual ~AddressError() throw() {}
explicit AddressError( u32 ps2addr, bool onWrite ) :
BaseExcept( fmt_string( "Address error, addr=0x%x [%s]", ps2addr, onWrite ? "store" : "load" ) ),
BaseExcept( wxsFormat( wxT("Address error, addr=0x%x [%s]"), ps2addr, onWrite ? wxT("store") : wxT("load") ) ),
OnWrite( onWrite ),
Address( ps2addr )
{}
@ -75,7 +78,7 @@ namespace R5900Exception
virtual ~TLBMiss() throw() {}
explicit TLBMiss( u32 ps2addr, bool onWrite ) :
BaseExcept( fmt_string( "Tlb Miss, addr=0x%x [%s]", ps2addr, onWrite ? "store" : "load" ) ),
BaseExcept( wxsFormat( wxT("Tlb Miss, addr=0x%x [%s]"), ps2addr, onWrite ? wxT("store") : wxT("load") ) ),
OnWrite( onWrite ),
Address( ps2addr )
{}
@ -94,7 +97,7 @@ namespace R5900Exception
//
explicit BusError( u32 ps2addr, bool onWrite ) :
BaseExcept( fmt_string( "Bus Error, addr=0x%x [%s]", ps2addr, onWrite ? "store" : "load" ) ),
BaseExcept( wxsFormat( wxT("Bus Error, addr=0x%x [%s]"), ps2addr, onWrite ? wxT("store") : wxT("load") ) ),
OnWrite( onWrite ),
Address( ps2addr )
{}
@ -108,7 +111,7 @@ namespace R5900Exception
virtual ~SystemCall() throw() {}
explicit SystemCall() :
BaseExcept( "SystemCall [SYSCALL]" )
BaseExcept( wxT("SystemCall [SYSCALL]") )
{}
};
@ -124,14 +127,14 @@ namespace R5900Exception
// Generates a trap for immediate-style Trap opcodes
explicit Trap() :
BaseExcept( "Trap" ),
BaseExcept( wxT("Trap") ),
TrapCode( 0 )
{}
// Generates a trap for register-style Trap instructions, which contain an
// error code in the opcode
explicit Trap( u16 trapcode ) :
BaseExcept( "Trap" ),
BaseExcept( wxT("Trap") ),
TrapCode( trapcode )
{}
};
@ -144,7 +147,7 @@ namespace R5900Exception
virtual ~Break() throw() {}
explicit Break() :
BaseExcept( "Break Instruction" )
BaseExcept( wxT("Break Instruction") )
{}
};
@ -156,7 +159,7 @@ namespace R5900Exception
virtual ~Overflow() throw() {}
explicit Overflow() :
BaseExcept( "Overflow" )
BaseExcept( wxT("Overflow") )
{}
};
@ -168,7 +171,7 @@ namespace R5900Exception
virtual ~DebugBreakpoint() throw() {}
explicit DebugBreakpoint() :
BaseExcept( "Debug Breakpoint" )
BaseExcept( wxT("Debug Breakpoint") )
{}
};
}

View File

@ -106,13 +106,10 @@ namespace R5900
static const int MMI_Div = 22*8;
static const int MMI_Default = 14;
static const int FPU_Mult = 12;
static const int FPU_Mult = 4*8;
static const int Store = 28;
static const int Load = 22;
static const int StoreFast = 14;
static const int LoadFast = 12;
static const int Store = 8;
static const int Load = 8;
}
using namespace Cycles;
@ -263,28 +260,28 @@ namespace R5900
MakeOpcode( LB, Load );
MakeOpcode( LH, Load );
MakeOpcode( LWL, Load );
MakeOpcode( LW, LoadFast );
MakeOpcode( LW, Load );
MakeOpcode( LBU, Load );
MakeOpcode( LHU, Load );
MakeOpcode( LWR, Load );
MakeOpcode( LWU, Load );
MakeOpcode( LWC1, Load );
MakeOpcode( LQC2, Load );
MakeOpcode( LD, LoadFast );
MakeOpcode( LD, Load );
// Stores!
MakeOpcode( SQ, Store );
MakeOpcode( SB, Store );//slow
MakeOpcode( SH, Store );//slow
MakeOpcode( SB, Store );
MakeOpcode( SH, Store );
MakeOpcode( SWL, Store );
MakeOpcode( SW, StoreFast );
MakeOpcode( SW, Store );
MakeOpcode( SDL, Store );
MakeOpcode( SDR, Store );
MakeOpcode( SWR, Store );
MakeOpcode( SWC1, Store );
MakeOpcode( SQC2, Store );
MakeOpcode( SD, StoreFast );
MakeOpcode( SD, Store );
// Multimedia Instructions!
@ -435,9 +432,9 @@ namespace R5900
MakeOpcode1( MIN_S, CopDefault );
MakeOpcode1( MUL_S, FPU_Mult );
MakeOpcode1( DIV_S, 3*8 );
MakeOpcode1( SQRT_S, 3*8 );
MakeOpcode1( RSQRT_S, 4*8 );
MakeOpcode1( DIV_S, 6*8 );
MakeOpcode1( SQRT_S, 6*8 );
MakeOpcode1( RSQRT_S, 8*8 );
MakeOpcode1( MULA_S, FPU_Mult );
MakeOpcode1( MADD_S, FPU_Mult );
MakeOpcode1( MSUB_S, FPU_Mult );

View File

@ -18,8 +18,6 @@
#ifndef _R5900_OPCODETABLES_H
#define _R5900_OPCODETABLES_H
#include <string>
#include "PS2Etypes.h"
// TODO : Move these into the OpcodeTables namespace

View File

@ -120,10 +120,10 @@ namespace StateRecovery {
// have likely been cleared out. So save from the Recovery buffer instead of
// doing a "standard" save:
gzFile fileptr = gzopen( file.c_str(), "wb" );
gzFile fileptr = gzopen( file.ToAscii().data(), "wb" );
if( fileptr == NULL )
{
Msgbox::Alert( "File permissions error while trying to save to file:\n\t%ts", params &file );
Msgbox::Alert( wxsFormat( _("Error while trying to save to file: %s"), file.c_str() ) );
return;
}
gzwrite( fileptr, &g_SaveVersion, sizeof( u32 ) );
@ -138,7 +138,7 @@ namespace StateRecovery {
{
if( !g_EmulationInProgress )
{
Msgbox::Alert( "You need to start a game first before you can save it's state." );
Msgbox::Alert( _("No emulation state to save") ); // translate: You need to start a game first before you can save it's state
return;
}
@ -187,9 +187,10 @@ namespace StateRecovery {
}
catch( Exception::RuntimeError& ex )
{
Msgbox::Alert(
"Pcsx2 gamestate recovery failed. Some options may have been reverted to protect your game's state.\n"
"Error: %s", params ex.cMessage() );
Msgbox::Alert( wxsFormat( // fixme: this error needs proper translation stuffs.
wxT("Pcsx2 gamestate recovery failed. Some options may have been reverted to protect your game's state.\n")
wxT("Error: %s"), ex.DisplayMessage().c_str() )
);
safe_delete( g_RecoveryState );
}
}

View File

@ -23,10 +23,6 @@
#include "iR5900.h"
#include "VUmicro.h"
#define spr0 ((DMACh*)&PS2MEM_HW[0xD000])
#define spr1 ((DMACh*)&PS2MEM_HW[0xD400])
#define gif ((DMACh*)&PS2MEM_HW[0xA000])
extern void mfifoGIFtransfer(int);
/* Both of these should be bools. Again, next savestate break. --arcum42 */
@ -66,12 +62,15 @@ int _SPR0chain()
if ((psHu32(DMAC_CTRL) & 0xC) >= 0x8) // 0x8 VIF1 MFIFO, 0xC GIF MFIFO
{
if ((spr0->madr & ~psHu32(DMAC_RBSR)) != psHu32(DMAC_RBOR)) Console::WriteLn("SPR MFIFO Write outside MFIFO area");
if ((spr0->madr & ~psHu32(DMAC_RBSR)) != psHu32(DMAC_RBOR))
Console::WriteLn("SPR MFIFO Write outside MFIFO area");
else
mfifotransferred += spr0->qwc;
hwMFIFOWrite(spr0->madr, (u8*)&PS2MEM_SCRATCH[spr0->sadr & 0x3fff], spr0->qwc << 4);
spr0->madr += spr0->qwc << 4;
spr0->madr = psHu32(DMAC_RBOR) + (spr0->madr & psHu32(DMAC_RBSR));
mfifotransferred += spr0->qwc;
}
else
{
@ -88,9 +87,11 @@ int _SPR0chain()
return (spr0->qwc) * BIAS; // bus is 1/2 the ee speed
}
#define SPR0chain() \
cycles += _SPR0chain(); \
__forceinline void SPR0chain()
{
_SPR0chain();
spr0->qwc = 0;
}
void _SPR0interleave()
@ -98,7 +99,6 @@ void _SPR0interleave()
int qwc = spr0->qwc;
int sqwc = psHu32(DMAC_SQWC) & 0xff;
int tqwc = (psHu32(DMAC_SQWC) >> 16) & 0xff;
//int cycles = 0;
u32 *pMem;
if (tqwc == 0) tqwc = qwc;
@ -123,9 +123,8 @@ void _SPR0interleave()
TestClearVUs(spr0->madr, spr0->qwc << 2);
memcpy_fast((u8*)pMem, &PS2MEM_SCRATCH[spr0->sadr & 0x3fff], spr0->qwc << 4);
}
//cycles += tqwc * BIAS;
spr0->sadr += spr0->qwc * 16;
spr0->madr += (sqwc + spr0->qwc) * 16; //qwc-= sqwc;
spr0->madr += (sqwc + spr0->qwc) * 16;
}
spr0->qwc = 0;
@ -142,15 +141,12 @@ static __forceinline void _dmaSPR0()
// Transfer Dn_QWC from SPR to Dn_MADR
if ((spr0->chcr & 0xc) == 0x0) // Normal Mode
{
int cycles = 0;
SPR0chain();
spr0finished = 1;
return;
}
else if ((spr0->chcr & 0xc) == 0x4)
{
int cycles = 0;
u32 *ptag;
int id;
bool done = FALSE;
@ -166,7 +162,6 @@ static __forceinline void _dmaSPR0()
spr0->sadr += 16;
// Transfer dma tag if tte is set
spr0->chcr = (spr0->chcr & 0xFFFF) | ((*ptag) & 0xFFFF0000); //Transfer upper part of tag to CHCR bits 31-15
id = (ptag[0] >> 28) & 0x7; //ID for DmaChain copied from bit 28 of the tag
@ -200,7 +195,6 @@ static __forceinline void _dmaSPR0()
{
//Console::WriteLn("SPR0 TIE");
done = TRUE;
spr0->qwc = 0;
}
spr0finished = (done) ? 1 : 0;
@ -208,9 +202,7 @@ static __forceinline void _dmaSPR0()
if (!done)
{
ptag = (u32*) & PS2MEM_SCRATCH[spr0->sadr & 0x3fff]; //Set memory pointer to SADR
//spr0->qwc = (u16)ptag[0]; //QWC set to lower 16bits of the tag
CPU_INT(8, ((u16)ptag[0]) / BIAS); //spr0->qwc / BIAS);
spr0->qwc = 0;
CPU_INT(8, ((u16)ptag[0]) / BIAS); // the lower 16bits of the tag / BIAS);
return;
}
SPR_LOG("spr0 dmaChain complete %8.8x_%8.8x size=%d, id=%d, addr=%lx spr=%lx",
@ -226,23 +218,27 @@ void SPRFROMinterrupt()
{
_dmaSPR0();
if ((psHu32(DMAC_CTRL) & 0xC) == 0xC) // GIF MFIFO
if(mfifotransferred != 0)
{
if ((spr0->madr & ~psHu32(DMAC_RBSR)) != psHu32(DMAC_RBOR)) Console::WriteLn("GIF MFIFO Write outside MFIFO area");
spr0->madr = psHu32(DMAC_RBOR) + (spr0->madr & psHu32(DMAC_RBSR));
//Console::WriteLn("mfifoGIFtransfer %x madr %x, tadr %x", params gif->chcr, gif->madr, gif->tadr);
mfifoGIFtransfer(mfifotransferred);
mfifotransferred = 0;
}
else
if ((psHu32(DMAC_CTRL) & 0xC) == 0x8) // VIF1 MFIFO
if ((psHu32(DMAC_CTRL) & 0xC) == 0xC) // GIF MFIFO
{
if ((spr0->madr & ~psHu32(DMAC_RBSR)) != psHu32(DMAC_RBOR)) Console::WriteLn("GIF MFIFO Write outside MFIFO area");
spr0->madr = psHu32(DMAC_RBOR) + (spr0->madr & psHu32(DMAC_RBSR));
//Console::WriteLn("mfifoGIFtransfer %x madr %x, tadr %x", params gif->chcr, gif->madr, gif->tadr);
mfifoGIFtransfer(mfifotransferred);
mfifotransferred = 0;
return;
}
else if ((psHu32(DMAC_CTRL) & 0xC) == 0x8) // VIF1 MFIFO
{
if ((spr0->madr & ~psHu32(DMAC_RBSR)) != psHu32(DMAC_RBOR)) Console::WriteLn("VIF MFIFO Write outside MFIFO area");
spr0->madr = psHu32(DMAC_RBOR) + (spr0->madr & psHu32(DMAC_RBSR));
//Console::WriteLn("mfifoVIF1transfer %x madr %x, tadr %x", params vif1ch->chcr, vif1ch->madr, vif1ch->tadr);
mfifoVIF1transfer(mfifotransferred);
mfifotransferred = 0;
return;
}
}
if (spr0finished == 0) return;
spr0->chcr &= ~0x100;
hwDmacIrq(8);
@ -289,9 +285,11 @@ int _SPR1chain()
return (spr1->qwc) * BIAS;
}
#define SPR1chain() \
cycles += _SPR1chain(); \
spr1->qwc = 0;
__forceinline void SPR1chain()
{
_SPR1chain();
spr1->qwc = 0;
}
void _SPR1interleave()
@ -299,7 +297,6 @@ void _SPR1interleave()
int qwc = spr1->qwc;
int sqwc = psHu32(DMAC_SQWC) & 0xff;
int tqwc = (psHu32(DMAC_SQWC) >> 16) & 0xff;
//int cycles = 0;
u32 *pMem;
if (tqwc == 0) tqwc = qwc;
@ -313,8 +310,7 @@ void _SPR1interleave()
pMem = (u32*)dmaGetAddr(spr1->madr);
memcpy_fast(&PS2MEM_SCRATCH[spr1->sadr & 0x3fff], (u8*)pMem, spr1->qwc << 4);
spr1->sadr += spr1->qwc * 16;
//cycles += spr1->qwc * BIAS;
spr1->madr += (sqwc + spr1->qwc) * 16; //qwc-= sqwc;
spr1->madr += (sqwc + spr1->qwc) * 16;
}
spr1->qwc = 0;
@ -325,7 +321,7 @@ void _dmaSPR1() // toSPR work function
{
if ((spr1->chcr & 0xc) == 0) // Normal Mode
{
int cycles = 0;
//int cycles = 0;
// Transfer Dn_QWC from Dn_MADR to SPR1
SPR1chain();
spr1finished = 1;
@ -333,7 +329,6 @@ void _dmaSPR1() // toSPR work function
}
else if ((spr1->chcr & 0xc) == 0x4)
{
int cycles = 0;
u32 *ptag;
int id;
bool done = FALSE;
@ -360,7 +355,7 @@ void _dmaSPR1() // toSPR work function
spr1->chcr = (spr1->chcr & 0xFFFF) | ((*ptag) & 0xFFFF0000); //Transfer upper part of tag to CHCR bits 31-15
id = (ptag[0] >> 28) & 0x7; //ID for DmaChain copied from bit 28 of the tag
spr1->qwc = (u16)ptag[0]; //QWC set to lower 16bits of the tag
spr1->qwc = (u16)ptag[0]; //QWC set to lower 16bits of the tag until SPR1chain is called in a few lines.
spr1->madr = ptag[1]; //MADR = ADDR field
// Transfer dma tag if tte is set
@ -381,7 +376,6 @@ void _dmaSPR1() // toSPR work function
SPR_LOG("dmaIrq Set");
//Console::WriteLn("SPR1 TIE");
spr1->qwc = 0;
done = TRUE;
}
@ -389,9 +383,7 @@ void _dmaSPR1() // toSPR work function
if (!done)
{
ptag = (u32*)dmaGetAddr(spr1->tadr); //Set memory pointer to TADR
//spr1->qwc = (u16)ptag[0]; //QWC set to lower 16bits of the tag
CPU_INT(9, (((u16)ptag[0]) / BIAS));// spr1->qwc / BIAS);
spr1->qwc = 0;
CPU_INT(9, (((u16)ptag[0]) / BIAS));// the lower 16 bits of the tag / BIAS);
}
}
else // Interleave Mode
@ -408,7 +400,7 @@ void dmaSPR1() // toSPR
spr1->chcr, spr1->madr, spr1->qwc,
spr1->tadr, spr1->sadr);
if ((spr1->chcr & 0xc) == 0x4 && spr1->qwc == 0)
if (((spr1->chcr & 0xc) == 0x4) && (spr1->qwc == 0))
{
u32 *ptag;
ptag = (u32*)dmaGetAddr(spr1->tadr); //Set memory pointer to TADR

View File

@ -76,25 +76,25 @@ public:
static const int DefaultChunkSize = 0x1000 * sizeof(T);
public:
const std::string Name; // user-assigned block name
const wxString 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;
const static wxString m_str_Unnamed;
protected:
// Internal constructor for use by derived classes. This allows a derived class to
// use its own memory allocation (with an aligned memory, for example).
// Throws:
// Exception::OutOfMemory if the allocated_mem pointer is NULL.
explicit SafeArray( const std::string& name, T* allocated_mem, int initSize ) :
Name( name )
, ChunkSize( DefaultChunkSize )
, m_ptr( allocated_mem )
, m_size( initSize )
explicit SafeArray( const wxString& name, T* allocated_mem, int initSize ) :
Name( name )
, ChunkSize( DefaultChunkSize )
, m_ptr( allocated_mem )
, m_size( initSize )
{
if( m_ptr == NULL )
throw Exception::OutOfMemory();
@ -111,19 +111,37 @@ public:
safe_free( m_ptr );
}
explicit SafeArray( const std::string& name="Unnamed" ) :
Name( name )
, ChunkSize( DefaultChunkSize )
, m_ptr( NULL )
, m_size( 0 )
explicit SafeArray( const wxString& name=wxT("Unnamed") ) :
Name( name )
, ChunkSize( DefaultChunkSize )
, m_ptr( NULL )
, m_size( 0 )
{
}
explicit SafeArray( int initialSize, const std::string& name="Unnamed" ) :
Name( name )
, ChunkSize( DefaultChunkSize )
, m_ptr( (T*)malloc( initialSize * sizeof(T) ) )
, m_size( initialSize )
explicit SafeArray( const char* name ) :
Name( wxString::FromAscii(name) )
, ChunkSize( DefaultChunkSize )
, m_ptr( NULL )
, m_size( 0 )
{
}
explicit SafeArray( int initialSize, const wxString& name=wxT("Unnamed") ) :
Name( name )
, ChunkSize( DefaultChunkSize )
, m_ptr( (T*)malloc( initialSize * sizeof(T) ) )
, m_size( initialSize )
{
if( m_ptr == NULL )
throw Exception::OutOfMemory();
}
explicit SafeArray( int initialSize, const char* name ) :
Name( wxString::FromAscii(name) )
, ChunkSize( DefaultChunkSize )
, m_ptr( (T*)malloc( initialSize * sizeof(T) ) )
, m_size( initialSize )
{
if( m_ptr == NULL )
throw Exception::OutOfMemory();
@ -145,9 +163,11 @@ public:
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"
wxsFormat( // english (for diagnostic)
wxT("Out-of-memory on SafeArray block re-allocation.\n")
wxT("Old size: %d bytes, New size: %d bytes."),
m_size, newalloc
)
);
}
m_size = newalloc;
@ -181,15 +201,8 @@ protected:
T* _getPtr( uint i ) const
{
#ifdef PCSX2_DEVBUILD
if( i >= (uint)m_size )
{
assert( 0 ); // makes debugging easier sometimes. :)
throw Exception::IndexBoundsFault(
"Index out of bounds on SafeArray: " + Name +
" (index=" + to_string(i) +
", size=" + to_string(m_size) + ")"
);
}
if( IsDevBuild && i >= (uint)m_size )
throw Exception::IndexBoundsFault( Name, i, m_size );
#endif
return &m_ptr[i];
}
@ -206,7 +219,7 @@ public:
static const int DefaultChunkSize = 0x80 * sizeof(T);
public:
const std::string Name; // user-assigned block name
const wxString Name; // user-assigned block name
int ChunkSize; // assigned DefaultChunkSize on init, reconfigurable at any time.
protected:
@ -214,7 +227,7 @@ protected:
int m_allocsize; // size of the allocation of memory
uint m_length; // length of the array (active items, not buffer allocation)
const static std::string m_str_Unnamed;
const static wxString m_str_Unnamed;
protected:
virtual T* _virtual_realloc( int newsize )
@ -224,17 +237,8 @@ protected:
void _boundsCheck( uint i ) const
{
#ifdef PCSX2_DEVBUILD
if( i >= (uint)m_length )
{
assert( 0 ); // makes debugging easier sometimes. :)
throw Exception::IndexBoundsFault(
"Index out of bounds on SafeArray: " + Name +
" (index=" + to_string(i) +
", length=" + to_string(m_length) + ")"
);
}
#endif
if( IsDevBuild && i >= (uint)m_length )
throw Exception::IndexBoundsFault( Name, i, m_length );
}
public:
@ -242,7 +246,7 @@ public:
{
}
explicit SafeList( const std::string& name="Unnamed" ) :
explicit SafeList( const wxString& name=wxT("Unnamed") ) :
Name( name )
, ChunkSize( DefaultChunkSize )
, m_ptr( NULL )
@ -251,7 +255,16 @@ public:
{
}
explicit SafeList( int initialSize, const std::string& name="Unnamed" ) :
explicit SafeList( const char* name ) :
Name( wxString::FromAscii(name) )
, ChunkSize( DefaultChunkSize )
, m_ptr( NULL )
, m_allocsize( 0 )
, m_length( 0 )
{
}
explicit SafeList( int initialSize, const wxString& name=wxT("Unnamed") ) :
Name( name )
, ChunkSize( DefaultChunkSize )
, m_ptr( (T*)malloc( initialSize * sizeof(T) ) )
@ -262,6 +275,17 @@ public:
throw Exception::OutOfMemory();
}
explicit SafeList( int initialSize, const char* name ) :
Name( wxString::FromAscii(name) )
, ChunkSize( DefaultChunkSize )
, m_ptr( (T*)malloc( initialSize * sizeof(T) ) )
, m_allocsize( initialSize )
, m_length( 0 )
{
if( m_ptr == NULL )
throw Exception::OutOfMemory();
}
// Returns the size of the list, as according to the array type. This includes
// mapped items only. The actual size of the allocation may differ.
int GetLength() const { return m_length; }
@ -281,9 +305,12 @@ public:
if( m_ptr == NULL )
{
throw Exception::OutOfMemory(
"Out-of-memory on list re-allocation. "
"Old size: " + to_string( m_allocsize ) + " bytes, "
"New size: " + to_string( newalloc ) + " bytes"
// English Diagonstic message:
wxsFormat(
wxT("Out-of-memory on SafeList block re-allocation.\n")
wxT("Old size: %d bytes, New size: %d bytes"),
m_allocsize, newalloc
)
);
}
m_allocsize = newalloc;
@ -350,12 +377,12 @@ protected:
// Appends "(align: xx)" to the name of the allocation in devel builds.
// Maybe useful,maybe not... no harm in attaching it. :D
string _getName( const string& src )
wxString _getName( const wxString& src )
{
#ifdef PCSX2_DEVBUILD
return src + "(align:" + to_string(Alignment) + ")";
#endif
return src;
if( IsDevBuild )
return src + wxsFormat( wxT("(align: %d)"), Alignment );
else
return src;
}
public:
@ -365,12 +392,17 @@ public:
// mptr is set to null, so the parent class's destructor won't re-free it.
}
explicit SafeAlignedArray( const std::string& name="Unnamed" ) :
explicit SafeAlignedArray( const wxString& name=wxT("Unnamed") ) :
SafeArray<T>::SafeArray( name )
{
}
explicit SafeAlignedArray( int initialSize, const std::string& name="Unnamed" ) :
explicit SafeAlignedArray( const char* name ) :
SafeArray<T>::SafeArray( name )
{
}
explicit SafeAlignedArray( int initialSize, const wxString& name=wxT("Unnamed") ) :
SafeArray<T>::SafeArray(
_getName(name),
(T*)_aligned_malloc( initialSize * sizeof(T), Alignment ),
@ -379,6 +411,15 @@ public:
{
}
explicit SafeAlignedArray( int initialSize, const char* name ) :
SafeArray<T>::SafeArray(
_getName(wxString::FromAscii(name)),
(T*)_aligned_malloc( initialSize * sizeof(T), Alignment ),
initialSize
)
{
}
virtual SafeAlignedArray<T,Alignment>* Clone() const
{
SafeAlignedArray<T,Alignment>* retval = new SafeAlignedArray<T,Alignment>( this->m_size );
@ -387,4 +428,9 @@ public:
}
};
// For lack of a better place for now (they depend on SafeList so they can't go in StringUtil)
extern void SplitString( SafeList<wxString>& dest, const wxString& src, const wxString& delims );
extern void JoinString( wxString& dest, const SafeList<wxString>& src, const wxString& separator );
#endif

View File

@ -6,7 +6,7 @@
// The profiler does not have a Linux version yet.
// So for now we turn it into duds for non-Win32 platforms.
#ifdef _WIN32
#ifdef WIN32
void ProfilerInit();
void ProfilerTerm();

View File

@ -50,16 +50,15 @@ static void PostLoadPrep()
wxString SaveState::GetFilename( int slot )
{
wxString arrgh;
arrgh.Printf( "%8.8X.%3.3d", ElfCRC, slot );
return Path::Combine( SSTATES_DIR, arrgh );
return (g_Conf.Folders.Savestates +
wxsFormat( wxT("%8.8X.%3.3d"), ElfCRC, slot )).GetFullPath();
}
SaveState::SaveState( const char* msg, const wxString& destination ) :
m_version( g_SaveVersion )
, m_tagspace( 128 )
{
Console::WriteLn( "%s %hs", params msg, &destination );
Console::WriteLn( "%s %s", params msg, destination.ToAscii().data() );
}
s32 CALLBACK gsSafeFreeze( int mode, freezeData *data )
@ -92,7 +91,10 @@ void SaveState::FreezeTag( const char* src )
if( strcmp( m_tagspace.GetPtr(), src ) != 0 )
{
assert( 0 );
throw Exception::BadSavedState( string( "Tag: " )+src );
throw Exception::BadSavedState(
// Untranslated diagnostic msg (use default msg for translation)
wxT("Savestate data corruption detected while reading tag: ") + wxString::FromAscii(src)
);
}
}
@ -105,10 +107,10 @@ void SaveState::FreezeAll()
// doesn't match the bios currently being used (chances are it'll still
// work fine, but some games are very picky).
char descout[128], descin[128];
memzero_obj( descout );
IsBIOS( Config.Bios, descout );
memcpy_fast( descin, descout, 128 );
char descin[128];
wxString descout;
IsBIOS( g_Conf.Files.Bios(), descout );
memcpy_fast( descin, descout.ToAscii().data(), 128 );
Freeze( descin );
if( memcmp( descin, descout, 128 ) != 0 )
@ -117,7 +119,7 @@ void SaveState::FreezeAll()
"\n\tWarning: BIOS Version Mismatch, savestate may be unstable!\n"
"\t\tCurrent BIOS: %s\n"
"\t\tSavestate BIOS: %s\n",
params descout, descin
params descout.ToAscii().data(), descin
);
}
@ -205,7 +207,7 @@ gzBaseStateInfo::~gzBaseStateInfo()
gzSavingState::gzSavingState( const wxString& filename ) :
gzBaseStateInfo( "Saving state to: ", filename )
{
m_file = gzopen(filename.c_str(), "wb");
m_file = gzopen(filename.ToAscii().data(), "wb");
if( m_file == NULL )
throw Exception::FileNotFound();
@ -217,7 +219,7 @@ gzSavingState::gzSavingState( const wxString& filename ) :
gzLoadingState::gzLoadingState( const wxString& filename ) :
gzBaseStateInfo( "Loading state from: ", filename )
{
m_file = gzopen(filename.c_str(), "rb");
m_file = gzopen(filename.ToAscii().data(), "rb");
if( m_file == NULL )
throw Exception::FileNotFound();
@ -299,9 +301,9 @@ void gzLoadingState::FreezePlugin( const char* name, s32 (CALLBACK *freezer)(int
// uncompressed to/from memory state saves implementation
memBaseStateInfo::memBaseStateInfo( SafeArray<u8>& memblock, const char* msg ) :
SaveState( msg, "Memory" )
, m_memory( memblock )
, m_idx( 0 )
SaveState( msg, wxT("Memory") )
, m_memory( memblock )
, m_idx( 0 )
{
// Always clear the MTGS thread state.
mtgsWaitGS();
@ -376,7 +378,7 @@ void memLoadingState::FreezePlugin( const char* name, s32 (CALLBACK *freezer)(in
if( ( fP.size + m_idx ) > m_memory.GetSizeInBytes() )
{
assert(0);
throw Exception::BadSavedState( "memory" );
throw Exception::BadSavedState( wxT("memory") );
}
fP.data = ((s8*)m_memory.GetPtr()) + m_idx;

View File

@ -217,4 +217,5 @@ namespace StateRecovery
extern void Clear();
}
#endif
#endif

View File

@ -34,7 +34,7 @@ bool States_isSlotUsed(int num)
if (ElfCRC == 0)
return false;
else
return Path::isFile(SaveState::GetFilename( num ));
return wxFileExists( SaveState::GetFilename( num ) );
}
//////////////////////////////////////////////////////////////////////////////////////////
@ -62,11 +62,11 @@ void States_Load( const wxString& file )
try
{
_loadStateOrExcept( file );
HostGui::Notice( fmt_string( "*PCSX2*: Loaded State %s", file.c_str() ) );
HostGui::Notice( wxsFormat( _("Loaded State %s"), file.c_str() ) );
}
catch( Exception::StateLoadError_Recoverable& ex)
{
Console::Notice( "Could not load savestate file: %hs.\n\n%s", params &file, ex.cMessage() );
Console::Notice( ex.LogMessage() );
// At this point the cpu hasn't been reset, so we can return
// control to the user safely... (that's why we use a console notice instead of a popup)
@ -76,16 +76,12 @@ void States_Load( const wxString& file )
catch( Exception::BaseException& ex )
{
// The emulation state is ruined. Might as well give them a popup and start the gui.
// Translation Tip: Since the savestate load was incomplete, the emulator has been reset.
string message( fmt_string(
"Encountered an error while loading savestate from file: %s.\n", file.c_str() ) );
if( g_EmulationInProgress )
message += "Since the savestate load was incomplete, the emulator must reset.\n";
message += "\nError: " + ex.Message();
Msgbox::Alert( message.c_str() );
Msgbox::Alert(
wxsFormat( _("Error loading savestate from file: %s"), file.c_str() ) +
L"\n\n" + _("Error details:") + ex.DisplayMessage()
);
SysReset();
return;
}
@ -94,9 +90,9 @@ void States_Load( const wxString& file )
void States_Load(int num)
{
string file( SaveState::GetFilename( num ) );
wxString file( SaveState::GetFilename( num ) );
if( !Path::isFile( file ) )
if( !Path::IsFile( file ) )
{
Console::Notice( "Saveslot %d is empty.", params num );
return;
@ -105,11 +101,11 @@ void States_Load(int num)
try
{
_loadStateOrExcept( file );
HostGui::Notice( fmt_string( "*PCSX2*: Loaded State %d", num ) );
HostGui::Notice( wxsFormat( _("Loaded State %d"), num ) );
}
catch( Exception::StateLoadError_Recoverable& ex)
{
Console::Notice( "Could not load savestate slot %d.\n\n%s", params num, ex.cMessage() );
Console::Notice( wxsFormat( L"Could not load savestate slot %d.\n\n%s", num, ex.LogMessage() ) );
// At this point the cpu hasn't been reset, so we can return
// control to the user safely... (that's why we use a console notice instead of a popup)
@ -119,16 +115,13 @@ void States_Load(int num)
catch( Exception::BaseException& ex )
{
// The emulation state is ruined. Might as well give them a popup and start the gui.
// Translation Tip: Since the savestate load was incomplete, the emulator has been reset.
string message( fmt_string(
"Encountered an error while loading savestate from slot %d.\n", num ) );
Msgbox::Alert(
wxsFormat( _("Error loading savestate from slot %d"), file.c_str() ) +
L"\n\n" + _("Error details:") + ex.DisplayMessage()
);
if( g_EmulationInProgress )
message += "Since the savestate load was incomplete, the emulator has been reset.\n";
message += "\nError: " + ex.Message();
Msgbox::Alert( message.c_str() );
SysEndExecution();
return;
}
@ -144,13 +137,23 @@ void States_Save( const wxString& file )
try
{
StateRecovery::SaveToFile( file );
HostGui::Notice( fmt_string( "State saved to file: %s", file.c_str() ) );
HostGui::Notice( wxsFormat( _("State saved to file: %s"), file.c_str() ) );
}
catch( Exception::BaseException& ex )
{
Console::Error( (fmt_string(
"An error occurred while trying to save to file %s\n", file.c_str() ) +
"Your emulation state has not been saved!\n\nError: " + ex.Message()).c_str()
// TODO: Implement a "pause the action and issue a popup" thing here.
// *OR* some kind of GS overlay... [for now we use the console]
// Translation Tip: "Your emulation state has not been saved!"
/*Msgbox::Alert(
wxsFormat( _("Error saving state to file: %s"), file.c_str() ) +
L"\n\n" + _("Error details:") + ex.DisplayMessage()
);*/
Console::Error( wxsFormat(
L"An error occurred while trying to save to file %s\n", file.c_str() ) +
L"Your emulation state has not been saved!\n\nError: " + ex.LogMessage()
);
}
@ -163,14 +166,17 @@ void States_Save(int num)
try
{
StateRecovery::SaveToSlot( num );
HostGui::Notice( fmt_string( "State saved to slot %d", num ) );
HostGui::Notice( wxsFormat( _("State saved to slot %d"), num ) );
}
catch( Exception::BaseException& ex )
{
Console::Error( (fmt_string(
"An error occurred while trying to save to slot %d\n", num ) +
"Your emulation state has not been saved!\n\nError: " + ex.Message()).c_str()
);
// TODO: Implement a "pause the action and issue a popup" thing here.
// *OR* some kind of GS overlay... [for now we use the console]
Console::Error( wxsFormat(
L"An error occurred while trying to save to slot %d\n", num ) +
L"Your emulation state has not been saved!\n\nError: " + ex.LogMessage()
);
}
HostGui::ResetMenuSlots();
}

View File

@ -25,10 +25,6 @@
using namespace std;
#define sif0dma ((DMACh*)&PS2MEM_HW[0xc000])
#define sif1dma ((DMACh*)&PS2MEM_HW[0xc400])
#define sif2dma ((DMACh*)&PS2MEM_HW[0xc800])
DMACh *sif0ch;
DMACh *sif1ch;
DMACh *sif2ch;
@ -206,7 +202,10 @@ __forceinline void SIF0Dma()
//SIF_LOG(" EE SIF doing transfer %04Xqw to %08X", readSize, sif0dma->madr);
SIF_LOG("----------- %lX of %lX", readSize << 2, size << 2);
_dmaGetAddr(sif0dma, ptag, sif0dma->madr, 5);
ptag = _dmaGetAddr(sif0dma, sif0dma->madr, 5);
if (ptag == NULL) return;
//_dmaGetAddr(sif0dma, *ptag, sif0dma->madr, 5);
SIF0read((u32*)ptag, readSize << 2);
@ -285,7 +284,12 @@ __forceinline void SIF1Dma()
{
// Process DMA tag at sif1dma->tadr
done = FALSE;
_dmaGetAddr(sif1dma, ptag, sif1dma->tadr, 6);
ptag = _dmaGetAddr(sif1dma, sif1dma->tadr, 6);
if (ptag == NULL) return;
//_dmaGetAddr(sif1dma, *ptag, sif1dma->tadr, 6);
sif1dma->chcr = (sif1dma->chcr & 0xFFFF) | ((*ptag) & 0xFFFF0000); // Copy the tag
sif1dma->qwc = (u16)ptag[0];
@ -348,7 +352,10 @@ __forceinline void SIF1Dma()
int qwTransfer = sif1dma->qwc;
u32 *data;
_dmaGetAddr(sif1dma, data, sif1dma->madr, 6);
data = _dmaGetAddr(sif1dma, sif1dma->madr, 6);
if (data == NULL) return;
//_dmaGetAddr(sif1dma, *data, sif1dma->madr, 6);
if (qwTransfer > (FIFO_SIF1_W - sif1.fifoSize) / 4) // Copy part of sif1dma into FIFO
qwTransfer = (FIFO_SIF1_W - sif1.fifoSize) / 4;

View File

@ -152,7 +152,6 @@ void SIO_CommandWrite(u8 value,int way) {
case 3:
// No pad connected.
sio.parp++;
sio.bufcount = 6;
if (sio.parp == sio.bufcount) { sio.padst = 0; return; }
SIO_INT();
return;
@ -451,16 +450,16 @@ void SIO_CommandWrite(u8 value,int way) {
break;
case 0x21:
// Set pad slot.
sio.mtapst = 0x21;
sio.mtapst = value;
sio.bufcount = 6; // No idea why this is 6, saved from old code.
break;
case 0x22:
// Set memcard slot.
sio.mtapst = 0x22;
sio.mtapst = value;
sio.bufcount = 6; // No idea why this is 6, saved from old code.
break;
}
// Commented out values are from original code. Break multitap in bios.
// Commented out values are from original code. They break multitap in bios.
sio.buf[sio.bufcount-1]=0;//'+';
sio.buf[sio.bufcount]=0;//'Z';
return;
@ -508,7 +507,7 @@ void InitializeSIO(u8 value)
sio.StatReg &= ~TX_EMPTY; // Now the Buffer is not empty
sio.StatReg |= RX_RDY; // Transfer is Ready
sio.bufcount = 2;
sio.bufcount = 4; // Default size, when no pad connected.
sio.parp = 0;
sio.padst = 1;
sio.packetsize = 1;
@ -517,7 +516,7 @@ void InitializeSIO(u8 value)
switch (sio.CtrlReg&0x2002) {
case 0x0002:
if (!PAD1setSlot(1, 1+sio.activePadSlot[0])) {
if (!PAD1setSlot(1, 1+sio.activePadSlot[0]) && sio.activePadSlot[0]) {
// Pad is not present. Don't send poll, just return a bunch of 0's.
sio2.packet.recvVal1 = 0x1D100;
sio.padst = 3;
@ -527,7 +526,7 @@ void InitializeSIO(u8 value)
}
break;
case 0x2002:
if (!PAD2setSlot(1, 1+sio.activePadSlot[1])) {
if (!PAD2setSlot(2, 1+sio.activePadSlot[1]) && sio.activePadSlot[1]) {
// Pad is not present. Don't send poll, just return a bunch of 0's.
sio2.packet.recvVal1 = 0x1D100;
sio.padst = 3;
@ -554,6 +553,7 @@ void InitializeSIO(u8 value)
int port = sio.GetMultitapPort();
if (!IsMtapPresent(port))
{
// If "unplug" multitap mid game, set active slots to 0.
sio.activePadSlot[port] = 0;
sio.activeMemcardSlot[port] = 0;
}

View File

@ -66,7 +66,7 @@ void __Log( const char* fmt, ... )
assert( length <= 2020 );
if( length > 2020 )
{
Msgbox::Alert("Source Log Stack Corruption Detected. Program execution may become unstable.");
Msgbox::Alert( _("Source log buffer overrun") );
// fixme: should throw an exception here once we have proper exception handling implemented.
}
@ -97,7 +97,7 @@ static __forceinline void _vSourceLog( u16 protocol, u8 source, u32 cpuPc, u32 c
assert( length <= 2020 );
if( length > 2020 )
{
Msgbox::Alert("Source Log Stack Corruption Detected. Program execution may become unstable.");
Msgbox::Alert( _("Source log buffer overrun") );
// fixme: should throw an exception here once we have proper exception handling implemented.
}

View File

@ -23,8 +23,6 @@
#include "IopCommon.h"
#include "Stats.h"
#include "Paths.h"
void statsOpen() {
stats.vsyncCount = 0;
stats.vsyncTime = time(NULL);

View File

@ -36,6 +36,7 @@ std::string to_string(const T& value)
}
//////////////////////////////////////////////////////////////////////////////////////////
// Helpers for wxWidgets stuff!
//
extern wxString ToString( const wxPoint& src, const wxString& separator=wxT(",") );
extern wxString ToString( const wxSize& src, const wxString& separator=wxT(",") );

View File

@ -37,12 +37,6 @@ SessionOverrideFlags g_Session = {false};
bool sysInitialized = false;
namespace Exception
{
BaseException::~BaseException() throw() {}
}
// I can't believe I had to make my own version of trim. C++'s STL is totally whack.
// And I still had to fix it too. I found three samples of trim online and *all* three
// were buggy. People really need to learn to code before they start posting trim
@ -172,16 +166,16 @@ bool SysAllocateMem()
psxMemAlloc();
vuMicroMemAlloc();
}
catch( Exception::OutOfMemory& ex )
catch( Exception::OutOfMemory& )
{
// TODO : Should this error be handled here or allowed to be handled by the main
// exception handler?
// Failures on the core initialization of memory is bad, since it means the emulator is
// completely non-functional. If the failure is in the VM build then we can try running
// the VTLB build instead. If it's the VTLB build then ... ouch.
// VTLB build must fail outright...
Msgbox::Alert( "Failed to allocate memory needed to run pcsx2.\n\nError: %s", params ex.cMessage() );
// completely non-functional.
//Msgbox::Alert( "Failed to allocate memory needed to run pcsx2.\n\nError: %s", params ex.cMessage() );
SysShutdownMem();
return false;
}
@ -207,14 +201,17 @@ void SysAllocateDynarecs()
recCpu.Allocate();
psxRec.Allocate();
}
catch( Exception::BaseException& ex )
catch( Exception::BaseException& )
{
Msgbox::Alert(
// TODO : Fix this message. It should respond according to the user's
// currently configured recompiler.interpreter options, for example.
/*Msgbox::Alert(
"The EE/IOP recompiler failed to initialize with the following error:\n\n"
"%s"
"\n\nThe EE/IOP interpreter will be used instead (slow!).", params
ex.cMessage()
);
);*/
g_Session.ForceDisableEErec = true;
@ -226,14 +223,19 @@ void SysAllocateDynarecs()
{
VU0micro::recAlloc();
}
catch( Exception::BaseException& ex )
catch( Exception::BaseException& )
{
// TODO : Fix this message. It should respond according to the user's
// currently configured recompiler.interpreter options, for example.
/*
Msgbox::Alert(
"The VU0 recompiler failed to initialize with the following error:\n\n"
"%s"
"\n\nThe VU0 interpreter will be used for this session (may slow down some games).", params
ex.cMessage()
);
*/
g_Session.ForceDisableVU0rec = true;
VU0micro::recShutdown();
@ -243,14 +245,19 @@ void SysAllocateDynarecs()
{
VU1micro::recAlloc();
}
catch( Exception::BaseException& ex )
catch( Exception::BaseException& )
{
// TODO : Fix this message. It should respond according to the user's
// currently configured recompiler.interpreter options, for example.
/*
Msgbox::Alert(
"The VU1 recompiler failed to initialize with the following error:\n\n"
"%s"
"\n\nThe VU1 interpreter will be used for this session (will slow down most games).", params
ex.cMessage()
);
*/
g_Session.ForceDisableVU1rec = true;
VU1micro::recShutdown();
@ -362,7 +369,7 @@ void SysExecute()
}
catch( R5900Exception::BaseExcept& ex )
{
Console::Error( ex.cMessage() );
Console::Error( ex.LogMessage() );
Console::Error( fmt_string( "(EE) PC: 0x%8.8x \tCycle: 0x%8.8x", ex.cpuState.pc, ex.cpuState.cycle ).c_str() );
}
}
@ -383,7 +390,7 @@ void SysEndExecution()
// Used by Run::FromCD, and Run->Execute when no active emulation state is present.
// elf_file - if NULL, the CDVD plugin is queried for the ELF file.
// use_bios - forces the game to boot through the PS2 bios, instead of bypassing it.
void SysPrepareExecution( const char* elf_file, bool use_bios )
void SysPrepareExecution( const wxString& elf_file, bool use_bios )
{
if( !g_EmulationInProgress )
{
@ -393,22 +400,21 @@ void SysPrepareExecution( const char* elf_file, bool use_bios )
}
catch( Exception::BaseException& ex )
{
Msgbox::Alert( ex.cMessage() );
Msgbox::Alert( ex.DisplayMessage() );
return;
}
if (OpenPlugins(NULL) == -1)
return;
if( elf_file == NULL )
if( elf_file.IsEmpty() )
{
if( !StateRecovery::HasState() )
{
// Not recovering a state, so need to execute the bios and load the ELF information.
// (note: gsRecoveries are done from ExecuteCpu)
char ename[g_MaxPath];
ename[0] = 0;
wxString ename;
if( !use_bios )
GetPS2ElfName( ename );
@ -440,8 +446,8 @@ void SysReset()
// so the status bar won't receive the WM_PAINT messages needed to update itself anyway.
// Oops! (air)
HostGui::Notice("Resetting...");
Console::SetTitle("Resetting...");
HostGui::Notice( _("Resetting...") );
Console::SetTitle( _("Resetting...") );
g_EmulationInProgress = false;
StateRecovery::Clear();
@ -454,8 +460,8 @@ void SysReset()
// Note : No need to call cpuReset() here. It gets called automatically before the
// emulator resumes execution.
HostGui::Notice("Ready");
Console::SetTitle("*PCSX2* Emulation state is reset.");
HostGui::Notice( _("Ready") );
Console::SetTitle( _("Emulation state is reset.") );
}
u8 *SysMmapEx(uptr base, u32 size, uptr bounds, const char *caller)
@ -482,8 +488,3 @@ u8 *SysMmapEx(uptr base, u32 size, uptr bounds, const char *caller)
}
return Mem;
}
void *SysLoadLibrary(const char *lib) { return HostSys::LoadLibrary( lib ); }
void *SysLoadSym(void *lib, const char *sym) { return HostSys::LoadSym( lib, sym ); }
const char *SysLibError() { return HostSys::LibError(); }
void SysCloseLibrary(void *lib) { HostSys::CloseLibrary( lib ); }

View File

@ -21,7 +21,6 @@
#include "PS2Etypes.h"
#include "Pcsx2Config.h"
#include "Paths.h"
#include "SafeArray.h"
#include "Misc.h"
#include "Threading.h" // to use threading stuff, include the Threading namespace in your file.
@ -39,14 +38,6 @@ enum PageProtectionMode
// versions defined in System.h/cpp.
namespace HostSys
{
// Damn windows.h namespace pollution!!
#undef LoadLibrary
extern void *LoadLibrary(const char *lib); // Loads Library
extern void *LoadSym(void *lib, const char *sym); // Loads Symbol from Library
extern const char *LibError(); // Gets previous error loading symbols
extern void CloseLibrary(void *lib); // Closes Library
// Maps a block of memory for use as a recompiled code buffer.
// The allocated block has code execution privileges.
// Returns NULL on allocation failure.
@ -76,7 +67,7 @@ extern void SysShutdownMem();
extern void SysRestorableReset(); // Saves the current emulation state prior to spu reset.
extern void SysClearExecutionCache(); // clears recompiled execution caches!
extern void SysEndExecution(); // terminates plugins, saves GS state (if enabled), and signals emulation loop to end.
extern void SysPrepareExecution( const char* elf_file, bool use_bios=false );
extern void SysPrepareExecution( const wxString& elf_file, bool use_bios=false );
// initiates high-speed execution of the emulation state. This function is currently
// designed to be run from an event loop, but will eventually be re-tooled with threading
@ -85,13 +76,6 @@ extern void SysPrepareExecution( const char* elf_file, bool use_bios=false );
extern void SysExecute();
// Library Helpers for HostSys functions, left in for now for convenience.
extern void *SysLoadLibrary(const char *lib); // Loads Library
extern void *SysLoadSym(void *lib, const char *sym); // Loads Symbol from Library
extern const char *SysLibError(); // Gets previous error loading symbols
extern void SysCloseLibrary(void *lib); // Closes Library
// Maps a block of memory for use as a recompiled code buffer, and ensures that the
// allocation is below a certain memory address (specified in "bounds" parameter).
// The allocated block has code execution privileges.
@ -183,6 +167,16 @@ namespace Console
// Newline is automatically appended.
extern bool Status( const char* fmt, VARG_PARAM dummy, ... );
extern bool __fastcall Status( const char* text );
extern bool __fastcall Write( const wxString& text );
extern bool __fastcall Write( Colors color, const wxString& text );
extern bool __fastcall WriteLn( const wxString& text );
extern bool __fastcall WriteLn( Colors color, const wxString& text );
extern bool __fastcall Error( const wxString& text );
extern bool __fastcall Notice( const wxString& text );
extern bool __fastcall Status( const wxString& text );
}
// Different types of message boxes that the emulator can employ from the friendly confines
@ -193,12 +187,11 @@ namespace Msgbox
{
// Pops up an alert Dialog Box with a singular "OK" button.
// Always returns false. Replacement for SysMessage.
extern bool Alert( const char* fmt, VARG_PARAM dummy, ... );
extern bool Alert( const char* text );
extern bool Alert( const wxString& text );
// Pops up a dialog box with Ok/Cancel buttons. Returns the result of the inquiry,
// true if OK, false if cancel.
extern bool OkCancel( const char* fmt, VARG_PARAM dummy, ... );
extern bool OkCancel( const wxString& text );
}
using Console::Color_Red;
@ -209,35 +202,4 @@ using Console::Color_Cyan;
using Console::Color_Yellow;
using Console::Color_White;
//////////////////////////////////////////////////////////////
// Dev / Debug conditionals --
// Consts for using if() statements instead of uglier #ifdef macros.
// Abbreviated macros for dev/debug only consoles and msgboxes.
#ifdef PCSX2_DEVBUILD
# define DevCon Console
# define DevMsg MsgBox
static const bool IsDevBuild = true;
#else
# define DevCon 0&&Console
# define DevMsg
static const bool IsDevBuild = false;
#endif
#ifdef _DEBUG
# define DbgCon Console
static const bool IsDebugBuild = true;
#else
# define DbgCon 0&&Console
static const bool IsDebugBuild = false;
#endif
#endif /* __SYSTEM_H__ */

View File

@ -0,0 +1,46 @@
/* Pcsx2 - Pc Ps2 Emulator
* Copyright (C) 2002-2009 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
*/
#pragma once
#include <wx/file.h>
//////////////////////////////////////////////////////////////////////////////////////////
// Helper class for wxFile which provides old-school ASCII interfaces (char* style),
// for saving some scrodom-kicking pain involved in converting log dumps and stuff over
// to unicode.
//
// This is an ideal solution on several fronts since it is both faster, and fully func-
// tional (since the dumps are only ever english/ascii only).
//
class AsciiFile : public wxFile
{
public:
using wxFile::Write;
AsciiFile( const wxString& src, OpenMode mode = read ) :
wxFile( src, mode ) {}
void Printf( const char* fmt, ... );
void Write( const char* fmt )
{
Write( fmt, strlen( fmt ) );
}
};

View File

@ -0,0 +1,29 @@
/* Pcsx2 - Pc Ps2 Emulator
* Copyright (C) 2002-2009 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
*/
#include "PrecompiledHeader.h"
#include "AsciiFile.h"
void AsciiFile::Printf( const char* fmt, ... )
{
va_list list;
va_start( list, fmt );
string writeme; vssprintf( writeme, fmt, list );
va_end( list );
Write( writeme.c_str(), writeme.length() );
}

View File

@ -0,0 +1,7 @@
Folder: pcsx2/Utilities
Purpose: To hold general non-pcsx2-specific utility classes which may (or may not) be shared out into a
common folder at a later date. This includes unicode utils, file manipulators, threading, etc.
Details: I plan to move files into this folder here ont he wxGui branch over time, and then move the
whole lot over to common as a whole library of sorts. I thinkit'll be easier that way than trying
to piecemeal individual files over (especially since some of them have inter-dependencies)

View File

@ -38,26 +38,6 @@ using namespace R5900;
#define VF_VAL(x) ((x==0x80000000)?0:(x))
void iDumpVU0Registers()
{
// fixme: This code is outdated, broken, and lacks printed labels.
// Needs heavy mods to be useful.
#if 0
int i;
for(i = 1; i < 32; ++i) {
__Log("v%d: %x %x %x %x, vi: ", i, VF_VAL(VU0.VF[i].UL[3]), VF_VAL(VU0.VF[i].UL[2]),
VF_VAL(VU0.VF[i].UL[1]), VF_VAL(VU0.VF[i].UL[0]));
if( i == REG_Q || i == REG_P ) __Log("%f\n", VU0.VI[i].F);
else if( i == REG_MAC_FLAG ) __Log("%x\n", 0);//VU0.VI[i].UL&0xff);
else if( i == REG_STATUS_FLAG ) __Log("%x\n", 0);//VU0.VI[i].UL&0x03);
else if( i == REG_CLIP_FLAG ) __Log("0\n");
else __Log("%x\n", VU0.VI[i].UL);
}
__Log("vfACC: %f %f %f %f\n", VU0.ACC.F[3], VU0.ACC.F[2], VU0.ACC.F[1], VU0.ACC.F[0]);
#endif
}
// This is called by the COP2 as per the CTC instruction
void vu0ResetRegs()
{

View File

@ -38,27 +38,6 @@ u32 vudump = 0;
#define VF_VAL(x) ((x==0x80000000)?0:(x))
void iDumpVU1Registers()
{
// fixme: This code is outdated, broken, and lacks printed labels.
// Needs heavy mods to be useful.
#if 0
int i;
// static int icount = 0;
// __Log("%x\n", icount);
for(i = 1; i < 32; ++i) {
// __Log("v%d: w%f(%x) z%f(%x) y%f(%x) x%f(%x), vi: ", i, VU1.VF[i].F[3], VU1.VF[i].UL[3], VU1.VF[i].F[2], VU1.VF[i].UL[2],
// VU1.VF[i].F[1], VU1.VF[i].UL[1], VU1.VF[i].F[0], VU1.VF[i].UL[0]);
//__Log("v%d: %f %f %f %f, vi: ", i, VU1.VF[i].F[3], VU1.VF[i].F[2], VU1.VF[i].F[1], VU1.VF[i].F[0]);
__Log("v%d: %x %x %x %x, vi: ", i, VF_VAL(VU1.VF[i].UL[3]), VF_VAL(VU1.VF[i].UL[2]), VF_VAL(VU1.VF[i].UL[1]), VF_VAL(VU1.VF[i].UL[0]));
if( i == REG_Q || i == REG_P ) __Log("%f\n", VU1.VI[i].F);
//else __Log("%x\n", VU1.VI[i].UL);
else __Log("%x\n", (i==REG_STATUS_FLAG||i==REG_MAC_FLAG||i==REG_CLIP_FLAG)?0:VU1.VI[i].UL);
}
__Log("vfACC: %f %f %f %f\n", VU1.ACC.F[3], VU1.ACC.F[2], VU1.ACC.F[1], VU1.ACC.F[0]);
#endif
}
// This is called by the COP2 as per the CTC instruction
void vu1ResetRegs()
{

View File

@ -1585,7 +1585,7 @@ void _vuLQ(VURegs * VU) {
if (_Ft_ == 0) return;
imm = (VU->code & 0x400) ? (VU->code & 0x3ff) | 0xfc00 : (VU->code & 0x3ff);
addr = (imm + VU->VI[_Fs_].SS[0]) * 16;
addr = ((imm + VU->VI[_Fs_].SS[0]) * 16)& (VU == &VU1 ? 0x3fff : 0xfff);
ptr = (u32*)GET_VU_MEM(VU, addr);
if (_X) VU->VF[_Ft_].UL[0] = ptr[0];
@ -1601,7 +1601,7 @@ void _vuLQD( VURegs * VU ) {
if (_Fs_ != 0) VU->VI[_Fs_].US[0]--;
if (_Ft_ == 0) return;
addr = VU->VI[_Fs_].US[0] * 16;
addr = (VU->VI[_Fs_].US[0] * 16) & (VU == &VU1 ? 0x3fff : 0xfff);
ptr = (u32*)GET_VU_MEM(VU, addr);
if (_X) VU->VF[_Ft_].UL[0] = ptr[0];
if (_Y) VU->VF[_Ft_].UL[1] = ptr[1];
@ -1614,7 +1614,7 @@ void _vuLQI(VURegs * VU) {
u32 addr;
u32 *ptr;
addr = VU->VI[_Fs_].US[0] * 16;
addr = (VU->VI[_Fs_].US[0] * 16)& (VU == &VU1 ? 0x3fff : 0xfff);
ptr = (u32*)GET_VU_MEM(VU, addr);
if (_X) VU->VF[_Ft_].UL[0] = ptr[0];
if (_Y) VU->VF[_Ft_].UL[1] = ptr[1];
@ -1631,7 +1631,7 @@ void _vuSQ(VURegs * VU) {
u32 *ptr;
imm = (VU->code & 0x400) ? (VU->code & 0x3ff) | 0xfc00 : (VU->code & 0x3ff);
addr = (imm + VU->VI[_Ft_].SS[0]) * 16;
addr = ((imm + VU->VI[_Ft_].SS[0]) * 16)& (VU == &VU1 ? 0x3fff : 0xfff);
ptr = (u32*)GET_VU_MEM(VU, addr);
if (_X) ptr[0] = VU->VF[_Fs_].UL[0];
if (_Y) ptr[1] = VU->VF[_Fs_].UL[1];
@ -1644,7 +1644,7 @@ void _vuSQD(VURegs * VU) {
u32 *ptr;
if(_Ft_ != 0) VU->VI[_Ft_].US[0]--;
addr = VU->VI[_Ft_].US[0] * 16;
addr = (VU->VI[_Ft_].US[0] * 16)& (VU == &VU1 ? 0x3fff : 0xfff);
ptr = (u32*)GET_VU_MEM(VU, addr);
if (_X) ptr[0] = VU->VF[_Fs_].UL[0];
if (_Y) ptr[1] = VU->VF[_Fs_].UL[1];
@ -1656,7 +1656,7 @@ void _vuSQI(VURegs * VU) {
u32 addr;
u32 *ptr;
addr = VU->VI[_Ft_].US[0] * 16;
addr = (VU->VI[_Ft_].US[0] * 16)& (VU == &VU1 ? 0x3fff : 0xfff);
ptr = (u32*)GET_VU_MEM(VU, addr);
if (_X) ptr[0] = VU->VF[_Fs_].UL[0];
if (_Y) ptr[1] = VU->VF[_Fs_].UL[1];
@ -1673,7 +1673,7 @@ void _vuILW(VURegs * VU) {
if (_Ft_ == 0) return;
imm = (VU->code & 0x400) ? (VU->code & 0x3ff) | 0xfc00 : (VU->code & 0x3ff);
addr = (imm + VU->VI[_Fs_].SS[0]) * 16;
addr = ((imm + VU->VI[_Fs_].SS[0]) * 16)& (VU == &VU1 ? 0x3fff : 0xfff);
ptr = (u16*)GET_VU_MEM(VU, addr);
if (_X) VU->VI[_Ft_].US[0] = ptr[0];
if (_Y) VU->VI[_Ft_].US[0] = ptr[2];
@ -1687,7 +1687,7 @@ void _vuISW(VURegs * VU) {
u16 *ptr;
imm = (VU->code & 0x400) ? (VU->code & 0x3ff) | 0xfc00 : (VU->code & 0x3ff);
addr = (imm + VU->VI[_Fs_].SS[0]) * 16;
addr = ((imm + VU->VI[_Fs_].SS[0]) * 16)& (VU == &VU1 ? 0x3fff : 0xfff);
ptr = (u16*)GET_VU_MEM(VU, addr);
if (_X) { ptr[0] = VU->VI[_Ft_].US[0]; ptr[1] = 0; }
if (_Y) { ptr[2] = VU->VI[_Ft_].US[0]; ptr[3] = 0; }
@ -1700,7 +1700,7 @@ void _vuILWR(VURegs * VU) {
u16 *ptr;
if (_Ft_ == 0) return;
addr = VU->VI[_Fs_].US[0] * 16;
addr = (VU->VI[_Fs_].US[0] * 16)& (VU == &VU1 ? 0x3fff : 0xfff);
ptr = (u16*)GET_VU_MEM(VU, addr);
if (_X) VU->VI[_Ft_].US[0] = ptr[0];
if (_Y) VU->VI[_Ft_].US[0] = ptr[2];
@ -1712,7 +1712,7 @@ void _vuISWR(VURegs * VU) {
u32 addr;
u16 *ptr;
addr = VU->VI[_Fs_].US[0] * 16;
addr = (VU->VI[_Fs_].US[0] * 16) & (VU == &VU1 ? 0x3fff : 0xfff);
ptr = (u16*)GET_VU_MEM(VU, addr);
if (_X) { ptr[0] = VU->VI[_Ft_].US[0]; ptr[1] = 0; }
if (_Y) { ptr[2] = VU->VI[_Ft_].US[0]; ptr[3] = 0; }
@ -2045,9 +2045,20 @@ void _vuXITOP(VURegs * VU) {
void _vuXGKICK(VURegs * VU)
{
u32* ptr = (u32*)GET_VU_MEM(VU, (VU->VI[_Fs_].US[0]*16) & (VU == &VU1 ? 0x3fff : 0xfff));
// int temp = 0x4000 - ((VU->VI[_Fs_].US[0]*16) & 0x3fff);
// u32 tempmem[0x8000];
// flush all pipelines first (in the right order)
_vuFlushAll(VU);
GSGIFTRANSFER1((u32*)VU->Mem, (VU->VI[_Fs_].US[0]*16) & 0x3fff);
//Gonna be slow but reshuffles the memory so overflows wont occur
/* memset(tempmem, 0, sizeof(tempmem));
memcpy(tempmem, ptr, temp);
ptr = (u32*)GET_VU_MEM(VU, 0);
memcpy(&tempmem[temp], ptr, ((VU->VI[_Fs_].US[0]*16) & 0x3fff));
GSGIFTRANSFER1((u32*)&tempmem[0], 0);
} else*/ GSGIFTRANSFER1((u32*)VU->Mem, (VU->VI[_Fs_].US[0]*16) & 0x3fff);
}
void _vuXTOP(VURegs * VU) {
@ -2508,13 +2519,23 @@ void _vuRegsMTIR(VURegs * VU, _VURegsNum *VUregsn) {
VUregsn->pipe = VUPIPE_FMAC;
VUregsn->VFwrite = 0;
VUregsn->VFread0 = _Fs_;
VUregsn->VFr0xyzw= _XYZW;
VUregsn->VFr0xyzw= 1 << (3-_Fsf_);
VUregsn->VFread1 = 0;
VUregsn->VIwrite = 1 << _Ft_;
VUregsn->VIread = GET_VF0_FLAG(_Fs_);
}
VUREGS_FTFS(MR32);
void _vuRegsMR32(VURegs * VU, _VURegsNum *VUregsn) {
VUregsn->pipe = VUPIPE_FMAC;
VUregsn->VFwrite = _Ft_;
VUregsn->VFwxyzw = _XYZW;
VUregsn->VFread0 = _Fs_;
VUregsn->VFr0xyzw= (_XYZW >> 1) | ((_XYZW << 3) & 0xf); //rotate
VUregsn->VFread1 = 0;
VUregsn->VFr1xyzw = 0xff;
VUregsn->VIwrite = 0;
VUregsn->VIread = (_Ft_ ? GET_VF0_FLAG(_Fs_) : 0);
}
void _vuRegsLQ(VURegs * VU, _VURegsNum *VUregsn) {
VUregsn->pipe = VUPIPE_FMAC;

Some files were not shown because too many files have changed in this diff Show More