wxgui branch: Full merge of trunk into the new wxgui, including a revision from way long ago that somehow got missed (when I renamed Windows folders in some plugin dirs)

git-svn-id: http://pcsx2.googlecode.com/svn/branches/wxgui@821 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
Jake.Stine 2009-03-19 12:14:37 +00:00
commit 6ce8ac189c
191 changed files with 5266 additions and 3692 deletions

View File

@ -3,8 +3,8 @@
ProjectType="Visual C++" ProjectType="Visual C++"
Version="8.00" Version="8.00"
Name="3rdparty" Name="3rdparty"
OutputDirectory="$(ProjectDir)..\..\deps\$(PlatformName)\$(ConfigurationName)" OutputDirectory="..\..\deps\$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(ProjectDir)\$(PlatformName)\$(ConfigurationName)" IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
> >
<Tool <Tool
Name="VCCLCompilerTool" Name="VCCLCompilerTool"

View File

@ -142,7 +142,7 @@
ConfigurationType="4" ConfigurationType="4"
InheritedPropertySheets="..\3rdparty.vsprops" InheritedPropertySheets="..\3rdparty.vsprops"
CharacterSet="2" CharacterSet="2"
WholeProgramOptimization="1" WholeProgramOptimization="0"
> >
<Tool <Tool
Name="VCPreBuildEventTool" Name="VCPreBuildEventTool"
@ -166,6 +166,7 @@
EnableIntrinsicFunctions="true" EnableIntrinsicFunctions="true"
FavorSizeOrSpeed="1" FavorSizeOrSpeed="1"
OmitFramePointers="true" OmitFramePointers="true"
WholeProgramOptimization="false"
StringPooling="true" StringPooling="true"
RuntimeLibrary="0" RuntimeLibrary="0"
BufferSecurityCheck="false" BufferSecurityCheck="false"

View File

@ -157,7 +157,7 @@
ConfigurationType="4" ConfigurationType="4"
InheritedPropertySheets="..\3rdparty.vsprops" InheritedPropertySheets="..\3rdparty.vsprops"
CharacterSet="2" CharacterSet="2"
WholeProgramOptimization="1" WholeProgramOptimization="0"
> >
<Tool <Tool
Name="VCPreBuildEventTool" Name="VCPreBuildEventTool"
@ -181,6 +181,7 @@
EnableIntrinsicFunctions="true" EnableIntrinsicFunctions="true"
FavorSizeOrSpeed="1" FavorSizeOrSpeed="1"
EnableFiberSafeOptimizations="true" EnableFiberSafeOptimizations="true"
WholeProgramOptimization="false"
AdditionalIncludeDirectories="&quot;$(ProjectDir)&quot;;&quot;$(ProjectDir)\include&quot;" AdditionalIncludeDirectories="&quot;$(ProjectDir)&quot;;&quot;$(ProjectDir)\include&quot;"
PreprocessorDefinitions="PTW32_STATIC_LIB;PTW32_BUILD_INLINED;__CLEANUP_SEH;WIN32;NDEBUG;_LIB" PreprocessorDefinitions="PTW32_STATIC_LIB;PTW32_BUILD_INLINED;__CLEANUP_SEH;WIN32;NDEBUG;_LIB"
StringPooling="true" StringPooling="true"

View File

@ -168,8 +168,6 @@ ptw32_InterlockedExchange (volatile PTW32_INTERLOCKED_LPLONG location,
#pragma disable_message (200) #pragma disable_message (200)
#endif #endif
LONG result;
/* /*
* The XCHG instruction always locks the bus with or without the * The XCHG instruction always locks the bus with or without the
* LOCKED prefix. This makes it significantly slower than CMPXCHG on * LOCKED prefix. This makes it significantly slower than CMPXCHG on
@ -186,14 +184,15 @@ ptw32_InterlockedExchange (volatile PTW32_INTERLOCKED_LPLONG location,
#if defined(_MSC_VER) || defined(__WATCOMC__) || (defined(__BORLANDC__) && defined(HAVE_TASM32)) #if defined(_MSC_VER) || defined(__WATCOMC__) || (defined(__BORLANDC__) && defined(HAVE_TASM32))
#define HAVE_INLINABLE_INTERLOCKED_XCHG #define HAVE_INLINABLE_INTERLOCKED_XCHG
// pcsx2: Optimized this slightly for MSVC, which automatically knowns when to
// push/pop registers and how to return eax as a result without using a temp var.
{ {
_asm { _asm {
//PUSH ecx MOV ecx,dword ptr [location]
MOV ecx,dword ptr [location] MOV eax,dword ptr [value]
MOV eax,dword ptr [value] XCHG dword ptr [ecx],eax
XCHG dword ptr [ecx],eax //MOV dword ptr [result], eax
MOV dword ptr [result], eax
//POP ecx
} }
} }
else else
@ -215,22 +214,20 @@ ptw32_InterlockedExchange (volatile PTW32_INTERLOCKED_LPLONG location,
* Can we do without the PUSH/POP instructions? * Can we do without the PUSH/POP instructions?
*/ */
_asm { _asm {
//PUSH ecx MOV ecx,dword ptr [location]
//PUSH edx MOV edx,dword ptr [value]
MOV ecx,dword ptr [location] L1: MOV eax,dword ptr [ecx]
MOV edx,dword ptr [value] CMPXCHG dword ptr [ecx],edx
L1: MOV eax,dword ptr [ecx] JNZ L1
CMPXCHG dword ptr [ecx],edx //MOV dword ptr [result], eax
JNZ L1
MOV dword ptr [result], eax
//POP edx
//POP ecx
} }
} }
#elif defined(__GNUC__) #elif defined(__GNUC__)
#define HAVE_INLINABLE_INTERLOCKED_XCHG #define HAVE_INLINABLE_INTERLOCKED_XCHG
LONG result;
{ {
__asm__ __volatile__ __asm__ __volatile__
( (
@ -264,6 +261,8 @@ L1: MOV eax,dword ptr [ecx]
:"m" (*location), "r" (value)); :"m" (*location), "r" (value));
} }
return result;
#endif #endif
#else #else
@ -279,8 +278,6 @@ L1: MOV eax,dword ptr [ecx]
/* *INDENT-ON* */ /* *INDENT-ON* */
return result;
#if defined(__WATCOMC__) #if defined(__WATCOMC__)
#pragma enable_message (200) #pragma enable_message (200)
#endif #endif

View File

@ -179,7 +179,7 @@
InheritedPropertySheets="..\..\..\3rdparty.vsprops" InheritedPropertySheets="..\..\..\3rdparty.vsprops"
UseOfMFC="0" UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false" ATLMinimizesCRunTimeLibraryUsage="false"
WholeProgramOptimization="1" WholeProgramOptimization="0"
> >
<Tool <Tool
Name="VCPreBuildEventTool" Name="VCPreBuildEventTool"
@ -202,7 +202,7 @@
Optimization="3" Optimization="3"
InlineFunctionExpansion="1" InlineFunctionExpansion="1"
FavorSizeOrSpeed="2" FavorSizeOrSpeed="2"
WholeProgramOptimization="true" WholeProgramOptimization="false"
AdditionalIncludeDirectories="..\..\Include;..\..\Include\msvc;..\..\..\zlib" AdditionalIncludeDirectories="..\..\Include;..\..\Include\msvc;..\..\..\zlib"
PreprocessorDefinitions="WIN32;_LIB;__WXMSW__;wxUSE_GUI=0;wxUSE_BASE=1;_CRT_SECURE_NO_WARNINGS" PreprocessorDefinitions="WIN32;_LIB;__WXMSW__;wxUSE_GUI=0;wxUSE_BASE=1;_CRT_SECURE_NO_WARNINGS"
StringPooling="true" StringPooling="true"
@ -5732,6 +5732,10 @@
<Filter <Filter
Name="Setup Headers" Name="Setup Headers"
> >
<File
RelativePath="..\..\include\wx\univ\setup.h"
>
</File>
<File <File
RelativePath="..\..\include\wx\msw\setup.h" RelativePath="..\..\include\wx\msw\setup.h"
> >
@ -5796,10 +5800,6 @@
/> />
</FileConfiguration> </FileConfiguration>
</File> </File>
<File
RelativePath="..\..\include\wx\univ\setup.h"
>
</File>
</Filter> </Filter>
<Filter <Filter
Name="MSW Headers" Name="MSW Headers"

View File

@ -178,7 +178,7 @@
InheritedPropertySheets="..\..\..\3rdparty.vsprops" InheritedPropertySheets="..\..\..\3rdparty.vsprops"
UseOfMFC="0" UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false" ATLMinimizesCRunTimeLibraryUsage="false"
WholeProgramOptimization="1" WholeProgramOptimization="0"
> >
<Tool <Tool
Name="VCPreBuildEventTool" Name="VCPreBuildEventTool"
@ -201,7 +201,7 @@
Optimization="3" Optimization="3"
InlineFunctionExpansion="1" InlineFunctionExpansion="1"
FavorSizeOrSpeed="2" FavorSizeOrSpeed="2"
WholeProgramOptimization="true" WholeProgramOptimization="false"
AdditionalIncludeDirectories="..\..\Include;..\..\Include\msvc;..\..\..\zlib;..\..\src\png" 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;_CRT_SECURE_NO_WARNINGS"
StringPooling="true" StringPooling="true"
@ -16948,10 +16948,6 @@
<Filter <Filter
Name="Setup Headers" Name="Setup Headers"
> >
<File
RelativePath="..\..\include\wx\univ\setup.h"
>
</File>
<File <File
RelativePath="..\..\include\wx\msw\setup.h" RelativePath="..\..\include\wx\msw\setup.h"
> >
@ -17016,6 +17012,10 @@
/> />
</FileConfiguration> </FileConfiguration>
</File> </File>
<File
RelativePath="..\..\include\wx\univ\setup.h"
>
</File>
</Filter> </Filter>
<Filter <Filter
Name="MSW Headers" Name="MSW Headers"

View File

@ -140,7 +140,7 @@
ConfigurationType="4" ConfigurationType="4"
InheritedPropertySheets="..\3rdparty.vsprops" InheritedPropertySheets="..\3rdparty.vsprops"
CharacterSet="2" CharacterSet="2"
WholeProgramOptimization="1" WholeProgramOptimization="0"
> >
<Tool <Tool
Name="VCPreBuildEventTool" Name="VCPreBuildEventTool"
@ -164,6 +164,7 @@
EnableIntrinsicFunctions="true" EnableIntrinsicFunctions="true"
FavorSizeOrSpeed="1" FavorSizeOrSpeed="1"
OmitFramePointers="true" OmitFramePointers="true"
WholeProgramOptimization="false"
StringPooling="true" StringPooling="true"
RuntimeLibrary="0" RuntimeLibrary="0"
WarningLevel="3" WarningLevel="3"

View File

@ -5,12 +5,12 @@
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or * the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
@ -27,7 +27,7 @@
*/ */
/* /*
Notes: Notes:
* Since this is still beta things may change. * Since this is still beta things may change.
* OSflags: * OSflags:
@ -41,7 +41,7 @@
* reserved keys: * reserved keys:
F1 to F10 are reserved for the emulator F1 to F10 are reserved for the emulator
* plugins should NOT change the current * plugins should NOT change the current
working directory. working directory.
(on win32, add flag OFN_NOCHANGEDIR for (on win32, add flag OFN_NOCHANGEDIR for
GetOpenFileName) GetOpenFileName)
@ -548,6 +548,7 @@ typedef void (CALLBACK* _PADgsDriverInfo)(GSdriverInfo *info);
typedef void (CALLBACK* _PADconfigure)(); typedef void (CALLBACK* _PADconfigure)();
typedef s32 (CALLBACK* _PADtest)(); typedef s32 (CALLBACK* _PADtest)();
typedef void (CALLBACK* _PADabout)(); typedef void (CALLBACK* _PADabout)();
typedef int (CALLBACK* _PADfreeze)(int mode, freezeData *data);
// SIO // SIO
typedef s32 (CALLBACK* _SIOinit)(u32 port, u32 slot, SIOchangeSlotCB f); typedef s32 (CALLBACK* _SIOinit)(u32 port, u32 slot, SIOchangeSlotCB f);
@ -732,6 +733,7 @@ extern _PADgsDriverInfo PAD1gsDriverInfo;
extern _PADconfigure PAD1configure; extern _PADconfigure PAD1configure;
extern _PADtest PAD1test; extern _PADtest PAD1test;
extern _PADabout PAD1about; extern _PADabout PAD1about;
extern _PADfreeze PAD1freeze;
// PAD2 // PAD2
extern _PADinit PAD2init; extern _PADinit PAD2init;
@ -748,6 +750,7 @@ extern _PADgsDriverInfo PAD2gsDriverInfo;
extern _PADconfigure PAD2configure; extern _PADconfigure PAD2configure;
extern _PADtest PAD2test; extern _PADtest PAD2test;
extern _PADabout PAD2about; extern _PADabout PAD2about;
extern _PADfreeze PAD2freeze;
// SIO[2] // SIO[2]
extern _SIOinit SIOinit[2][9]; extern _SIOinit SIOinit[2][9];

View File

@ -82,7 +82,7 @@ typedef unsigned int uint;
// Note: building the 'extern' into PCSX2_ALIGNED16_DECL fixes Visual Assist X's intellisense. // Note: building the 'extern' into PCSX2_ALIGNED16_DECL fixes Visual Assist X's intellisense.
#define PCSX2_ALIGNED(alig,x) __declspec(align(alig)) x #define PCSX2_ALIGNED(alig,x) __declspec(align(alig)) x
#define PCSX2_ALIGNED_EXTERN(alig,x) __declspec(align(alig)) x #define PCSX2_ALIGNED_EXTERN(alig,x) extern __declspec(align(alig)) x
#define PCSX2_ALIGNED16(x) __declspec(align(16)) x #define PCSX2_ALIGNED16(x) __declspec(align(16)) x
#define PCSX2_ALIGNED16_EXTERN(x) extern __declspec(align(16)) x #define PCSX2_ALIGNED16_EXTERN(x) extern __declspec(align(16)) x
@ -146,8 +146,8 @@ typedef union _LARGE_INTEGER
// fixme - is this needed for recent versions of GCC? Or can we just use the macros // fixme - is this needed for recent versions of GCC? Or can we just use the macros
// above instead for both definitions (implementations) and declarations (includes)? -- air // above instead for both definitions (implementations) and declarations (includes)? -- air
#define PCSX2_ALIGNED_EXTERN(alig,x) extern x #define PCSX2_ALIGNED_EXTERN(alig,x) extern x __attribute((aligned(alig)))
#define PCSX2_ALIGNED16_EXTERN(x) extern x #define PCSX2_ALIGNED16_EXTERN(x) extern x __attribute((aligned(16)))
#endif // _MSC_VER #endif // _MSC_VER

99
common/include/Pcsx2Api.h Normal file
View File

@ -0,0 +1,99 @@
/* 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
*/
#ifndef __PCSX2API_H__
#define __PCSX2API_H__
// Note; this header is experimental, and will be a shifting target. Only use this if you are willing to repeatedly fix breakage.
/*
* Based on PS2E Definitions by
linuzappz@hotmail.com,
* shadowpcsx2@yahoo.gr,
* and florinsasu@hotmail.com
*/
#include "Pcsx2Types.h"
#include "Pcsx2Defs.h"
#include "Pcsx2Config.h"
// Indicate to use the new versions.
#define NEW_PLUGIN_APIS
#ifdef _MSC_VER
#define EXPORT_C(type) extern "C" __declspec(dllexport) type CALLBACK
#else
#define EXPORT_C(type) extern "C" type
#endif
EXPORT_C(u32) PS2EgetLibType(void);
EXPORT_C(u32) PS2EgetLibVersion2(u32 type);
EXPORT_C(char*) PS2EgetLibName(void);
// Extended functions.
// allows the plugin to see the whole configuration when started up.
// Intended for them to get the ini and plugin paths, but could allow for other things as well.
EXPORT_C_(void) PS2EpassConfig(PcsxConfig Config);
// PS2EgetLibType returns (may be OR'd)
enum {
PS2E_LT_GS = 0x01,
PS2E_LT_PAD = 0x02, // -=[ OBSOLETE ]=-
PS2E_LT_SPU2 = 0x04,
PS2E_LT_CDVD = 0x08,
PS2E_LT_DEV9 = 0x10,
PS2E_LT_USB = 0x20,
PS2E_LT_FW = 0x40,
PS2E_LT_SIO = 0x80
} PluginLibType;
// PS2EgetLibVersion2 (high 16 bits)
enum {
PS2E_GS_VERSION = 0x0006,
PS2E_PAD_VERSION = 0x0002, // -=[ OBSOLETE ]=-
PS2E_SPU2_VERSION = 0x0005,
PS2E_CDVD_VERSION = 0x0005,
PS2E_DEV9_VERSION = 0x0003,
PS2E_USB_VERSION = 0x0003,
PS2E_FW_VERSION = 0x0002,
PS2E_SIO_VERSION = 0x0001
} PluginLibVersion;
// freeze modes:
enum {
FREEZE_LOAD = 0,
FREEZE_SAVE = 1,
FREEZE_SIZE = 2
} FreezeModes;
typedef struct _GSdriverInfo {
char name[8];
void *common;
} GSdriverInfo;
#ifdef _MSC_VER
typedef struct _winInfo { // unsupported values must be set to zero
HWND hWnd;
HMENU hMenu;
HWND hStatusWnd;
} winInfo;
#endif
#endif // __PCSX2API_H__

View File

@ -66,7 +66,7 @@ extern SessionOverrideFlags g_Session;
//------------ SPECIAL GAME FIXES!!! --------------- //------------ 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_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_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 God of War, fixes SPS. #define CHECK_FPUMULHACK (Config.GameFixes & 0x8) // Special Fix for Tales of Destiny hangs.
//------------ Advanced Options!!! --------------- //------------ Advanced Options!!! ---------------
#define CHECK_VU_OVERFLOW (Config.vuOptions & 0x1) #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 #define CHECK_VU_EXTRA_OVERFLOW (Config.vuOptions & 0x2) // If enabled, Operands are clamped before being used in the VU recs
@ -77,7 +77,6 @@ extern SessionOverrideFlags g_Session;
#define CHECK_FPU_EXTRA_OVERFLOW (Config.eeOptions & 0x2) // If enabled, Operands are checked for infinities before being used in the FPU recs #define CHECK_FPU_EXTRA_OVERFLOW (Config.eeOptions & 0x2) // If enabled, Operands are checked for infinities before being used in the FPU recs
#define CHECK_FPU_EXTRA_FLAGS 1 // Always enabled now // Sets D/I flags on FPU instructions #define CHECK_FPU_EXTRA_FLAGS 1 // Always enabled now // Sets D/I flags on FPU instructions
#define CHECK_FPU_FULL (Config.eeOptions & 0x4) #define CHECK_FPU_FULL (Config.eeOptions & 0x4)
#define CHECK_FPU_ATTEMPT_MUL (Config.eeOptions & 0x8)
#define DEFAULT_eeOptions 0x01 #define DEFAULT_eeOptions 0x01
#define DEFAULT_vuOptions 0x01 #define DEFAULT_vuOptions 0x01
//------------ DEFAULT sseMXCSR VALUES!!! --------------- //------------ DEFAULT sseMXCSR VALUES!!! ---------------

115
common/include/Pcsx2Defs.h Normal file
View File

@ -0,0 +1,115 @@
/* Pcsx2 - Pc Ps2 Emulator
* Copyright (C) 2002-2008 Pcsx2 Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef __PCSX2DEFS_H__
#define __PCSX2DEFS_H__
#if defined (__linux__) && !defined(__LINUX__) // some distributions are lower case
#define __LINUX__
#endif
#ifdef __CYGWIN__
#define __LINUX__
#endif
// Renamed ARRAYSIZE to ArraySize -- looks nice and gets rid of Windows.h conflicts (air)
#ifndef ArraySize
#define ArraySize(x) (sizeof(x)/sizeof((x)[0]))
#endif
//////////////////////////////////////////////////////////////////////////////////////////
// jASSUME - give hints to the optimizer
// This is primarily useful for the default case switch optimizer, which enables VC to
// generate more compact switches.
#ifdef NDEBUG
# define jBREAKPOINT() ((void) 0)
# ifdef _MSC_VER
# define jASSUME(exp) (__assume(exp))
# else
# define jASSUME(exp) ((void) sizeof(exp))
# endif
#else
# if defined(_MSC_VER)
# define jBREAKPOINT() do { __asm int 3 } while(0)
# else
# define jBREAKPOINT() ((void) *(volatile char *) 0)
# endif
# define jASSUME(exp) if(exp) ; else jBREAKPOINT()
#endif
// disable the default case in a switch
#define jNO_DEFAULT \
{ \
break; \
\
default: \
jASSUME(0); \
break; \
}
/* common defines */
#ifndef C_ASSERT
#define C_ASSERT(e) typedef char __C_ASSERT__[(e)?1:-1]
#endif
#ifdef _MSC_VER
// Note: building the 'extern' into PCSX2_ALIGNED16_DECL fixes Visual Assist X's intellisense.
#define PCSX2_ALIGNED(alig,x) __declspec(align(alig)) x
#define PCSX2_ALIGNED_EXTERN(alig,x) extern __declspec(align(alig)) x
#define PCSX2_ALIGNED16(x) __declspec(align(16)) x
#define PCSX2_ALIGNED16_EXTERN(x) extern __declspec(align(16)) x
#define __naked __declspec(naked)
#define CALLBACK __stdcall
#else
// fixme - is this needed for recent versions of GCC? Or can we just use the first two macros
// instead for both definitions (implementations) and declarations (includes)? -- air
#define PCSX2_ALIGNED(alig,x) x __attribute((aligned(alig)))
#define PCSX2_ALIGNED16(x) x __attribute((aligned(16)))
#define PCSX2_ALIGNED_EXTERN(alig,x) extern x __attribute((aligned(alig)))
#define PCSX2_ALIGNED16_EXTERN(x) extern x __attribute((aligned(16)))
#define __naked // GCC lacks the naked specifier
#define CALLBACK // CALLBACK is a win32-specific mess
// GCC uses attributes for a lot of things that Visual C+ doesn't.
#define __fastcall __attribute__((fastcall))
#define __unused __attribute__((unused))
#define _inline __inline__ __attribute__((unused))
#define __forceinline __attribute__((always_inline,unused))
#endif
typedef struct {
int size;
s8 *data;
} freezeData;
// event values:
#define KEYPRESS 1
#define KEYRELEASE 2
typedef struct _keyEvent {
u32 key;
u32 evt;
} keyEvent;
#endif

151
common/include/Pcsx2Types.h Normal file
View File

@ -0,0 +1,151 @@
/* Pcsx2 - Pc Ps2 Emulator
* Copyright (C) 2002-2008 Pcsx2 Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef __PCSX2TYPES_H__
#define __PCSX2TYPES_H__
// Note; this header is experamental, and will be a shifting target. Only use this if you are willing to repeatedly fix breakage.
/*
* Based on PS2E Definitions by
linuzappz@hotmail.com,
* shadowpcsx2@yahoo.gr,
* and florinsasu@hotmail.com
*/
//////////////////////////////////////////////////////////////////////////////////////////
// Basic Atomic Types
#if defined(_MSC_VER)
typedef __int8 s8;
typedef __int16 s16;
typedef __int32 s32;
typedef __int64 s64;
typedef unsigned __int8 u8;
typedef unsigned __int16 u16;
typedef unsigned __int32 u32;
typedef unsigned __int64 u64;
typedef unsigned int uint;
typedef u32 uptr;
typedef s32 sptr;
#else // _MSC_VER
#ifdef __LINUX__
#ifdef HAVE_STDINT_H
#include "stdint.h"
typedef int8_t s8;
typedef int16_t s16;
typedef int32_t s32;
typedef int64_t s64;
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef uint64_t u64;
typedef uintptr_t uptr;
typedef intptr_t sptr;
#else // HAVE_STDINT_H
typedef char s8;
typedef short s16;
typedef int s32;
typedef long long s64;
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long long u64;
typedef u32 uptr;
typedef s32 sptr;
#endif // HAVE_STDINT_H
typedef unsigned int uint;
#define LONG long
typedef union _LARGE_INTEGER
{
long long QuadPart;
} LARGE_INTEGER;
#endif // __LINUX__
#endif //_MSC_VER
//////////////////////////////////////////////////////////////////////////////////////////
// A rough-and-ready cross platform 128-bit datatype, Non-SSE style.
#ifdef __cplusplus
struct u128
{
u64 lo;
u64 hi;
// Implicit conversion from u64
u128( u64 src ) :
lo( src )
, hi( 0 ) {}
// Implicit conversion from u32
u128( u32 src ) :
lo( src )
, hi( 0 ) {}
};
struct s128
{
s64 lo;
s64 hi;
// Implicit conversion from u64
s128( s64 src ) :
lo( src )
, hi( 0 ) {}
// Implicit conversion from u32
s128( s32 src ) :
lo( src )
, hi( 0 ) {}
};
#else
typedef union _u128_t
{
u64 lo;
u64 hi;
} u128;
typedef union _s128_t
{
s64 lo;
s64 hi;
} s128;
#endif
#endif

View File

@ -0,0 +1,430 @@
/* 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
*/
#ifndef __PLUGINCALLBACKS_H__
#define __PLUGINCALLBACKS_H__
extern "C"
{
// General
typedef u32 (CALLBACK* _PS2EgetLibType)(void);
typedef u32 (CALLBACK* _PS2EgetLibVersion2)(u32 type);
typedef char*(CALLBACK* _PS2EgetLibName)(void);
typedef void (CALLBACK* _PS2EpassConfig)(PcsxConfig *Config);
// GS
// NOTE: GSreadFIFOX/GSwriteCSR functions CANNOT use XMM/MMX regs
// If you want to use them, need to save and restore current ones
typedef s32 (CALLBACK* _GSinit)(char *configpath);
typedef s32 (CALLBACK* _GSopen)(void *pDisplay, char *Title, bool multithread);
typedef void (CALLBACK* _GSclose)();
typedef void (CALLBACK* _GSshutdown)();
typedef void (CALLBACK* _GSvsync)(int field);
typedef void (CALLBACK* _GSgifTransfer1)(u32 *pMem, u32 addr);
typedef void (CALLBACK* _GSgifTransfer2)(u32 *pMem, u32 size);
typedef void (CALLBACK* _GSgifTransfer3)(u32 *pMem, u32 size);
typedef void (CALLBACK* _GSgetLastTag)(u64* ptag); // returns the last tag processed (64 bits)
typedef void (CALLBACK* _GSgifSoftReset)(u32 mask);
typedef void (CALLBACK* _GSreadFIFO)(u64 *pMem);
typedef void (CALLBACK* _GSreadFIFO2)(u64 *pMem, int qwc);
typedef void (CALLBACK* _GSkeyEvent)(keyEvent* ev);
typedef void (CALLBACK* _GSchangeSaveState)(s32 state, const char* filename);
typedef void (CALLBACK* _GSirqCallback)(void (*callback)());
typedef void (CALLBACK* _GSprintf)(s32 timeout, char *fmt, ...);
typedef void (CALLBACK* _GSsetBaseMem)(void*);
typedef void (CALLBACK* _GSsetGameCRC)(s32 crc, s32 gameoptions);
typedef void (CALLBACK* _GSsetFrameSkip)(int frameskip);
typedef bool (CALLBACK* _GSsetupRecording)(bool start);
typedef void (CALLBACK* _GSreset)();
typedef void (CALLBACK* _GSwriteCSR)(u32 value);
typedef void (CALLBACK* _GSgetDriverInfo)(GSdriverInfo *info);
#ifdef _WINDOWS_
typedef s32 (CALLBACK* _GSsetWindowInfo)(winInfo *info);
#endif
typedef void (CALLBACK* _GSmakeSnapshot)(const char *path);
typedef void (CALLBACK* _GSmakeSnapshot2)(const char *path, int*, int);
typedef s32 (CALLBACK* _GSfreeze)(u8 mode, freezeData *data);
typedef void (CALLBACK* _GSconfigure)();
typedef s32 (CALLBACK* _GStest)();
typedef void (CALLBACK* _GSabout)();
// PAD
typedef s32 (CALLBACK* _PADinit)(char *configpath, u32 flags);
typedef s32 (CALLBACK* _PADopen)(void *pDisplay);
typedef void (CALLBACK* _PADclose)();
typedef void (CALLBACK* _PADshutdown)();
typedef keyEvent* (CALLBACK* _PADkeyEvent)();
typedef u8 (CALLBACK* _PADstartPoll)(u8 pad);
typedef u8 (CALLBACK* _PADpoll)(u8 value);
typedef u32 (CALLBACK* _PADquery)();
typedef void (CALLBACK* _PADupdate)(u8 pad);
typedef void (CALLBACK* _PADgsDriverInfo)(GSdriverInfo *info);
typedef s32 (CALLBACK* _PADfreeze)(u8 mode, freezeData *data);
typedef void (CALLBACK* _PADconfigure)();
typedef s32 (CALLBACK* _PADtest)();
typedef void (CALLBACK* _PADabout)();
// SIO
typedef s32 (CALLBACK* _SIOinit)(int types, SIOchangeSlotCB f);
typedef s32 (CALLBACK* _SIOopen)(void *pDisplay);
typedef void (CALLBACK* _SIOclose)();
typedef void (CALLBACK* _SIOshutdown)();
typedef s32 (CALLBACK* _SIOstartPoll)(u8 deviceType, u32 port, u32 slot, u8 *returnValue);
typedef s32 (CALLBACK* _SIOpoll)(u8 value, u8 *returnValue);
typedef u32 (CALLBACK* _SIOquery)();
typedef void (CALLBACK* _SIOkeyEvent)(keyEvent* ev);
typedef s32 (CALLBACK* _SIOfreeze)(u8 mode, freezeData *data);
typedef void (CALLBACK* _SIOconfigure)();
typedef s32 (CALLBACK* _SIOtest)();
typedef void (CALLBACK* _SIOabout)();
// SPU2
// NOTE: The read/write functions CANNOT use XMM/MMX regs
// If you want to use them, need to save and restore current ones
typedef s32 (CALLBACK* _SPU2init)(char *configpath);
typedef s32 (CALLBACK* _SPU2open)(void *pDisplay);
typedef void (CALLBACK* _SPU2close)();
typedef void (CALLBACK* _SPU2shutdown)();
typedef void (CALLBACK* _SPU2write)(u32 mem, u16 value);
typedef u16 (CALLBACK* _SPU2read)(u32 mem);
typedef void (CALLBACK* _SPU2readDMA4Mem)(u16 *pMem, u32 size);
typedef void (CALLBACK* _SPU2writeDMA4Mem)(u16 *pMem, u32 size);
typedef void (CALLBACK* _SPU2interruptDMA4)();
typedef void (CALLBACK* _SPU2readDMA7Mem)(u16 *pMem, u32 size);
typedef void (CALLBACK* _SPU2writeDMA7Mem)(u16 *pMem, u32 size);
typedef void (CALLBACK* _SPU2interruptDMA7)();
typedef void (CALLBACK* _SPU2readDMAMem)(u16 *pMem, u32 size, u8 core);
typedef void (CALLBACK* _SPU2writeDMAMem)(u16 *pMem, u32 size, u8 core);
typedef void (CALLBACK* _SPU2interruptDMA)(u8 core);
typedef void (CALLBACK* _SPU2setDMABaseAddr)(uptr baseaddr);
typedef void (CALLBACK* _SPU2irqCallback)(void (*SPU2callback)(),void (*DMA4callback)(),void (*DMA7callback)());
typedef bool (CALLBACK* _SPU2setupRecording)(bool start);
typedef void (CALLBACK* _SPU2setClockPtr)(u32*ptr);
typedef void (CALLBACK* _SPU2setTimeStretcher)(short int enable);
typedef u32 (CALLBACK* _SPU2ReadMemAddr)(u8 core);
typedef void (CALLBACK* _SPU2WriteMemAddr)(u8 core,u32 value);
typedef void (CALLBACK* _SPU2async)(u32 cycles);
typedef s32 (CALLBACK* _SPU2freeze)(u8 mode, freezeData *data);
typedef void (CALLBACK* _SPU2keyEvent)(keyEvent* ev);
typedef void (CALLBACK* _SPU2configure)();
typedef s32 (CALLBACK* _SPU2test)();
typedef void (CALLBACK* _SPU2about)();
// CDVD
// NOTE: The read/write functions CANNOT use XMM/MMX regs
// If you want to use them, need to save and restore current ones
typedef s32 (CALLBACK* _CDVDinit)(char *configpath);
typedef s32 (CALLBACK* _CDVDopen)(const char* pTitleFilename);
typedef void (CALLBACK* _CDVDclose)();
typedef void (CALLBACK* _CDVDshutdown)();
typedef s32 (CALLBACK* _CDVDreadTrack)(u32 lsn, int mode);
typedef u8* (CALLBACK* _CDVDgetBuffer)();
typedef s32 (CALLBACK* _CDVDreadSubQ)(u32 lsn, cdvdSubQ* subq);
typedef s32 (CALLBACK* _CDVDgetTN)(cdvdTN *Buffer);
typedef s32 (CALLBACK* _CDVDgetTD)(u8 Track, cdvdTD *Buffer);
typedef s32 (CALLBACK* _CDVDgetTOC)(void* toc);
typedef s32 (CALLBACK* _CDVDgetDiskType)();
typedef s32 (CALLBACK* _CDVDgetTrayStatus)();
typedef s32 (CALLBACK* _CDVDctrlTrayOpen)();
typedef s32 (CALLBACK* _CDVDctrlTrayClose)();
typedef void (CALLBACK* _CDVDkeyEvent)(keyEvent* ev);
typedef s32 (CALLBACK* _CDVDfreeze)(u8 mode, freezeData *data);
typedef void (CALLBACK* _CDVDconfigure)();
typedef s32 (CALLBACK* _CDVDtest)();
typedef void (CALLBACK* _CDVDabout)();
typedef void (CALLBACK* _CDVDnewDiskCB)(void (*callback)());
// DEV9
// NOTE: The read/write functions CANNOT use XMM/MMX regs
// If you want to use them, need to save and restore current ones
typedef s32 (CALLBACK* _DEV9init)(char *configpath);
typedef s32 (CALLBACK* _DEV9open)(void *pDisplay);
typedef void (CALLBACK* _DEV9close)();
typedef void (CALLBACK* _DEV9shutdown)();
typedef u8 (CALLBACK* _DEV9read8)(u32 mem);
typedef u16 (CALLBACK* _DEV9read16)(u32 mem);
typedef u32 (CALLBACK* _DEV9read32)(u32 mem);
typedef void (CALLBACK* _DEV9write8)(u32 mem, u8 value);
typedef void (CALLBACK* _DEV9write16)(u32 mem, u16 value);
typedef void (CALLBACK* _DEV9write32)(u32 mem, u32 value);
typedef void (CALLBACK* _DEV9readDMA8Mem)(u32 *pMem, int size);
typedef void (CALLBACK* _DEV9writeDMA8Mem)(u32 *pMem, int size);
typedef void (CALLBACK* _DEV9irqCallback)(DEV9callback callback);
typedef DEV9handler (CALLBACK* _DEV9irqHandler)(void);
typedef void (CALLBACK* _DEV9keyEvent)(keyEvent* ev);
typedef s32 (CALLBACK* _DEV9freeze)(int mode, freezeData *data);
typedef void (CALLBACK* _DEV9configure)();
typedef s32 (CALLBACK* _DEV9test)();
typedef void (CALLBACK* _DEV9about)();
// USB
// NOTE: The read/write functions CANNOT use XMM/MMX regs
// If you want to use them, need to save and restore current ones
typedef s32 (CALLBACK* _USBinit)(char *configpath);
typedef s32 (CALLBACK* _USBopen)(void *pDisplay);
typedef void (CALLBACK* _USBclose)();
typedef void (CALLBACK* _USBshutdown)();
typedef u8 (CALLBACK* _USBread8)(u32 mem);
typedef u16 (CALLBACK* _USBread16)(u32 mem);
typedef u32 (CALLBACK* _USBread32)(u32 mem);
typedef void (CALLBACK* _USBwrite8)(u32 mem, u8 value);
typedef void (CALLBACK* _USBwrite16)(u32 mem, u16 value);
typedef void (CALLBACK* _USBwrite32)(u32 mem, u32 value);
typedef void (CALLBACK* _USBasync)(u32 cycles);
typedef void (CALLBACK* _USBirqCallback)(USBcallback callback);
typedef USBhandler (CALLBACK* _USBirqHandler)(void);
typedef void (CALLBACK* _USBsetRAM)(void *mem);
typedef void (CALLBACK* _USBkeyEvent)(keyEvent* ev);
typedef s32 (CALLBACK* _USBfreeze)(int mode, freezeData *data);
typedef void (CALLBACK* _USBconfigure)();
typedef s32 (CALLBACK* _USBtest)();
typedef void (CALLBACK* _USBabout)();
//FW
typedef s32 (CALLBACK* _FWinit)(char *configpath);
typedef s32 (CALLBACK* _FWopen)(void *pDisplay);
typedef void (CALLBACK* _FWclose)();
typedef void (CALLBACK* _FWshutdown)();
typedef u32 (CALLBACK* _FWread32)(u32 mem);
typedef void (CALLBACK* _FWwrite32)(u32 mem, u32 value);
typedef void (CALLBACK* _FWirqCallback)(void (*callback)());
typedef void (CALLBACK* _FWkeyEvent)(keyEvent* ev);
typedef s32 (CALLBACK* _FWfreeze)(int mode, freezeData *data);
typedef void (CALLBACK* _FWconfigure)();
typedef s32 (CALLBACK* _FWtest)();
typedef void (CALLBACK* _FWabout)();
// General
extern _PS2EgetLibType PS2EgetLibType;
extern _PS2EgetLibVersion2 PS2EgetLibVersion2;
extern _PS2EgetLibName PS2EgetLibName;
extern _PS2EpassConfig PS2EpassConfig;
// GS
extern _GSinit GSinit;
extern _GSopen GSopen;
extern _GSclose GSclose;
extern _GSshutdown GSshutdown;
extern _GSvsync GSvsync;
extern _GSgifTransfer1 GSgifTransfer1;
extern _GSgifTransfer2 GSgifTransfer2;
extern _GSgifTransfer3 GSgifTransfer3;
extern _GSgetLastTag GSgetLastTag;
extern _GSgifSoftReset GSgifSoftReset;
extern _GSreadFIFO GSreadFIFO;
extern _GSreadFIFO2 GSreadFIFO2;
extern _GSkeyEvent GSkeyEvent;
extern _GSchangeSaveState GSchangeSaveState;
extern _GSmakeSnapshot GSmakeSnapshot;
extern _GSmakeSnapshot2 GSmakeSnapshot2;
extern _GSirqCallback GSirqCallback;
extern _GSprintf GSprintf;
extern _GSsetBaseMem GSsetBaseMem;
extern _GSsetGameCRC GSsetGameCRC;
extern _GSsetFrameSkip GSsetFrameSkip;
extern _GSsetupRecording GSsetupRecording;
extern _GSreset GSreset;
extern _GSwriteCSR GSwriteCSR;
extern _GSgetDriverInfo GSgetDriverInfo;
#ifdef _WINDOWS_
extern _GSsetWindowInfo GSsetWindowInfo;
#endif
extern _GSfreeze GSfreeze;
extern _GSconfigure GSconfigure;
extern _GStest GStest;
extern _GSabout GSabout;
// PAD1
extern _PADinit PAD1init;
extern _PADopen PAD1open;
extern _PADclose PAD1close;
extern _PADshutdown PAD1shutdown;
extern _PADkeyEvent PAD1keyEvent;
extern _PADstartPoll PAD1startPoll;
extern _PADpoll PAD1poll;
extern _PADquery PAD1query;
extern _PADupdate PAD1update;
extern _PADfreeze PAD1freeze;
extern _PADgsDriverInfo PAD1gsDriverInfo;
extern _PADconfigure PAD1configure;
extern _PADtest PAD1test;
extern _PADabout PAD1about;
// PAD2
extern _PADinit PAD2init;
extern _PADopen PAD2open;
extern _PADclose PAD2close;
extern _PADshutdown PAD2shutdown;
extern _PADkeyEvent PAD2keyEvent;
extern _PADstartPoll PAD2startPoll;
extern _PADpoll PAD2poll;
extern _PADquery PAD2query;
extern _PADupdate PAD2update;
extern _PADfreeze PAD2freeze;
extern _PADgsDriverInfo PAD2gsDriverInfo;
extern _PADconfigure PAD2configure;
extern _PADtest PAD2test;
extern _PADabout PAD2about;
// SIO[2]
extern _SIOinit SIOinit[2][9];
extern _SIOopen SIOopen[2][9];
extern _SIOclose SIOclose[2][9];
extern _SIOshutdown SIOshutdown[2][9];
extern _SIOstartPoll SIOstartPoll[2][9];
extern _SIOpoll SIOpoll[2][9];
extern _SIOquery SIOquery[2][9];
extern _SIOkeyEvent SIOkeyEvent;
extern _SIOfreeze SIOfreeze[2][9];
extern _SIOconfigure SIOconfigure[2][9];
extern _SIOtest SIOtest[2][9];
extern _SIOabout SIOabout[2][9];
// SPU2
extern _SPU2init SPU2init;
extern _SPU2open SPU2open;
extern _SPU2close SPU2close;
extern _SPU2shutdown SPU2shutdown;
extern _SPU2write SPU2write;
extern _SPU2read SPU2read;
extern _SPU2readDMA4Mem SPU2readDMA4Mem;
extern _SPU2writeDMA4Mem SPU2writeDMA4Mem;
extern _SPU2interruptDMA4 SPU2interruptDMA4;
extern _SPU2readDMA7Mem SPU2readDMA7Mem;
extern _SPU2writeDMA7Mem SPU2writeDMA7Mem;
extern _SPU2setDMABaseAddr SPU2setDMABaseAddr;
extern _SPU2interruptDMA7 SPU2interruptDMA7;
extern _SPU2ReadMemAddr SPU2ReadMemAddr;
extern _SPU2setupRecording SPU2setupRecording;
extern _SPU2WriteMemAddr SPU2WriteMemAddr;
extern _SPU2irqCallback SPU2irqCallback;
extern _SPU2setClockPtr SPU2setClockPtr;
extern _SPU2setTimeStretcher SPU2setTimeStretcher;
extern _SPU2keyEvent SPU2keyEvent;
extern _SPU2async SPU2async;
extern _SPU2freeze SPU2freeze;
extern _SPU2configure SPU2configure;
extern _SPU2test SPU2test;
extern _SPU2about SPU2about;
// CDVD
extern _CDVDinit CDVDinit;
extern _CDVDopen CDVDopen;
extern _CDVDclose CDVDclose;
extern _CDVDshutdown CDVDshutdown;
extern _CDVDreadTrack CDVDreadTrack;
extern _CDVDgetBuffer CDVDgetBuffer;
extern _CDVDreadSubQ CDVDreadSubQ;
extern _CDVDgetTN CDVDgetTN;
extern _CDVDgetTD CDVDgetTD;
extern _CDVDgetTOC CDVDgetTOC;
extern _CDVDgetDiskType CDVDgetDiskType;
extern _CDVDgetTrayStatus CDVDgetTrayStatus;
extern _CDVDctrlTrayOpen CDVDctrlTrayOpen;
extern _CDVDctrlTrayClose CDVDctrlTrayClose;
extern _CDVDkeyEvent CDVDkeyEvent;
extern _CDVDfreeze CDVDfreeze;
extern _CDVDconfigure CDVDconfigure;
extern _CDVDtest CDVDtest;
extern _CDVDabout CDVDabout;
extern _CDVDnewDiskCB CDVDnewDiskCB;
// DEV9
extern _DEV9init DEV9init;
extern _DEV9open DEV9open;
extern _DEV9close DEV9close;
extern _DEV9shutdown DEV9shutdown;
extern _DEV9read8 DEV9read8;
extern _DEV9read16 DEV9read16;
extern _DEV9read32 DEV9read32;
extern _DEV9write8 DEV9write8;
extern _DEV9write16 DEV9write16;
extern _DEV9write32 DEV9write32;
extern _DEV9readDMA8Mem DEV9readDMA8Mem;
extern _DEV9writeDMA8Mem DEV9writeDMA8Mem;
extern _DEV9irqCallback DEV9irqCallback;
extern _DEV9irqHandler DEV9irqHandler;
extern _DEV9keyEvent DEV9keyEvent;
extern _DEV9configure DEV9configure;
extern _DEV9freeze DEV9freeze;
extern _DEV9test DEV9test;
extern _DEV9about DEV9about;
// USB
extern _USBinit USBinit;
extern _USBopen USBopen;
extern _USBclose USBclose;
extern _USBshutdown USBshutdown;
extern _USBread8 USBread8;
extern _USBread16 USBread16;
extern _USBread32 USBread32;
extern _USBwrite8 USBwrite8;
extern _USBwrite16 USBwrite16;
extern _USBwrite32 USBwrite32;
extern _USBasync USBasync;
extern _USBirqCallback USBirqCallback;
extern _USBirqHandler USBirqHandler;
extern _USBsetRAM USBsetRAM;
extern _USBkeyEvent USBkeyEvent;
extern _USBconfigure USBconfigure;
extern _USBfreeze USBfreeze;
extern _USBtest USBtest;
extern _USBabout USBabout;
// FW
extern _FWinit FWinit;
extern _FWopen FWopen;
extern _FWclose FWclose;
extern _FWshutdown FWshutdown;
extern _FWread32 FWread32;
extern _FWwrite32 FWwrite32;
extern _FWirqCallback FWirqCallback;
extern _FWkeyEvent FWkeyEvent;
extern _FWconfigure FWconfigure;
extern _FWfreeze FWfreeze;
extern _FWtest FWtest;
extern _FWabout FWabout;
}
#endif // __PLUGINCALLBACKS_H__

View File

@ -0,0 +1,135 @@
/* 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
*/
#ifndef __CDVDAPI_H__
#define __CDVDAPI_H__
// Note; this header is experimental, and will be a shifting target. Only use this if you are willing to repeatedly fix breakage.
/*
* Based on PS2E Definitions by
linuzappz@hotmail.com,
* shadowpcsx2@yahoo.gr,
* and florinsasu@hotmail.com
*/
#include "Pcsx2Api.h"
/* CDVD plugin API */
// Basic functions.
EXPORT_C_(s32) CDVDinit();
EXPORT_C_(s32) CDVDopen(void *pDisplay, const char* pTitleFilename);
EXPORT_C_(void) CDVDclose();
EXPORT_C_(void) CDVDshutdown();
EXPORT_C_(s32) CDVDreadTrack(u32 lsn, int mode);
// return can be NULL (for async modes)
EXPORT_C_(u8*) CDVDgetBuffer();
EXPORT_C_(s32) CDVDreadSubQ(u32 lsn, cdvdSubQ* subq);//read subq from disc (only cds have subq data)
EXPORT_C_(s32) CDVDgetTN(cdvdTN *Buffer); //disk information
EXPORT_C_(s32) CDVDgetTD(u8 Track, cdvdTD *Buffer); //track info: min,sec,frame,type
EXPORT_C_(s32) CDVDgetTOC(void* toc); //gets ps2 style toc from disc
EXPORT_C_(s32) CDVDgetDiskType(); //CDVD_TYPE_xxxx
EXPORT_C_(s32) CDVDgetTrayStatus(); //CDVD_TRAY_xxxx
EXPORT_C_(s32) CDVDctrlTrayOpen(); //open disc tray
EXPORT_C_(s32) CDVDctrlTrayClose(); //close disc tray
// Extended functions
EXPORT_C_(void) CDVDkeyEvent(keyEvent *ev);
EXPORT_C_(void) CDVDconfigure();
EXPORT_C_(s32) CDVDfreeze(u8 mode, freezeData *data);
EXPORT_C_(void) CDVDabout();
EXPORT_C_(s32) CDVDtest();
EXPORT_C_(void) CDVDnewDiskCB(void (*callback)());
typedef struct _cdvdSubQ {
u8 ctrl:4; // control and mode bits
u8 mode:4; // control and mode bits
u8 trackNum; // current track number (1 to 99)
u8 trackIndex; // current index within track (0 to 99)
u8 trackM; // current minute location on the disc (BCD encoded)
u8 trackS; // current sector location on the disc (BCD encoded)
u8 trackF; // current frame location on the disc (BCD encoded)
u8 pad; // unused
u8 discM; // current minute offset from first track (BCD encoded)
u8 discS; // current sector offset from first track (BCD encoded)
u8 discF; // current frame offset from first track (BCD encoded)
} cdvdSubQ;
typedef struct _cdvdTD { // NOT bcd coded
u32 lsn;
u8 type;
} cdvdTD;
typedef struct _cdvdTN {
u8 strack; //number of the first track (usually 1)
u8 etrack; //number of the last track
} cdvdTN;
// CDVDreadTrack mode values:
enum {
CDVD_MODE_2352 0, // full 2352 bytes
CDVD_MODE_2340 1, // skip sync (12) bytes
CDVD_MODE_2328 2, // skip sync+head+sub (24) bytes
CDVD_MODE_2048 3, // skip sync+head+sub (24) bytes
CDVD_MODE_2368 4 // full 2352 bytes + 16 subq
} TrackModes
// CDVDgetDiskType returns:
enum {
CDVD_TYPE_ILLEGAL = 0xff, // Illegal Disc
CDVD_TYPE_DVDV = 0xfe, // DVD Video
CDVD_TYPE_CDDA = 0xfd, // Audio CD
CDVD_TYPE_PS2DVD = 0x14, // PS2 DVD
CDVD_TYPE_PS2CDDA = 0x13, // PS2 CD (with audio)
CDVD_TYPE_PS2CD = 0x12, // PS2 CD
CDVD_TYPE_PSCDDA = 0x11, // PS CD (with audio)
CDVD_TYPE_PSCD = 0x10, // PS CD
CDVD_TYPE_UNKNOWN = 0x05, // Unknown
CDVD_TYPE_DETCTDVDD = 0x04, // Detecting Dvd Dual Sided
CDVD_TYPE_DETCTDVDS = 0x03, // Detecting Dvd Single Sided
CDVD_TYPE_DETCTCD = 0x02, // Detecting Cd
CDVD_TYPE_DETCT = 0x01, // Detecting
CDVD_TYPE_NODISC = 0x00 // No Disc
} DiskType;
// CDVDgetTrayStatus returns:
enum {
CDVD_TRAY_CLOSE = 0x00,
CDVD_TRAY_OPEN = 0x01
} TrayStatus;
// cdvdTD.type (track types for cds)
enum {
CDVD_AUDIO_TRACK = 0x01,
CDVD_MODE1_TRACK = 0x41,
CDVD_MODE2_TRACK = 0x61
} CDVDTDType;
enum {
CDVD_AUDIO_MASK = 0x00,
CDVD_DATA_MASK = 0x40
// CDROM_DATA_TRACK 0x04 //do not enable this! (from linux kernel)
} CDVD_Masks;
#endif // __CDVDAPI_H__

View File

@ -0,0 +1,68 @@
/* 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
*/
#ifndef __DEV9API_H__
#define __DEV9API_H__
// Note; this header is experimental, and will be a shifting target. Only use this if you are willing to repeatedly fix breakage.
/*
* Based on PS2E Definitions by
* linuzappz@hotmail.com,
* shadowpcsx2@yahoo.gr,
* and florinsasu@hotmail.com
*/
#include "Pcsx2Api.h"
typedef void (*DEV9callback)(int cycles);
typedef int (*DEV9handler)(void);
// Basic functions.
// NOTE: The read/write functions CANNOT use XMM/MMX regs
// If you want to use them, need to save and restore current ones
EXPORT_C_(s32) DEV9init();
// pDisplay normally is passed a handle to the GS plugins window.
EXPORT_C_(s32) DEV9open(void *pDisplay);
EXPORT_C_(void) DEV9close();
EXPORT_C_(void) DEV9shutdown();
EXPORT_C_(u8) DEV9read8(u32 addr);
EXPORT_C_(u16) DEV9read16(u32 addr);
EXPORT_C_(u32) DEV9read32(u32 addr);
EXPORT_C_(void) DEV9write8(u32 addr, u8 value);
EXPORT_C_(void) DEV9write16(u32 addr, u16 value);
EXPORT_C_(void) DEV9write32(u32 addr, u32 value);
EXPORT_C_(void) DEV9readDMA8Mem(u32 *pMem, int size);
EXPORT_C_(void) DEV9writeDMA8Mem(u32 *pMem, int size);
// cycles = IOP cycles before calling callback,
// if callback returns 1 the irq is triggered, else not
EXPORT_C_(void) DEV9irqCallback(DEV9callback callback);
EXPORT_C_(DEV9handler) DEV9irqHandler(void);
// Extended functions
EXPORT_C_(void) DEV9keyEvent(keyEvent *ev);
EXPORT_C_(s32) DEV9freeze(u8 mode, freezeData *data);
EXPORT_C_(void) DEV9configure();
EXPORT_C_(void) DEV9about();
EXPORT_C_(s32) DEV9test();
#endif // __DEV9API_H__

View File

@ -0,0 +1,58 @@
/* 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
*/
#ifndef __FWAPI_H__
#define __FWAPI_H__
// Note; this header is experimental, and will be a shifting target. Only use this if you are willing to repeatedly fix breakage.
/*
* Based on PS2E Definitions by
linuzappz@hotmail.com,
* shadowpcsx2@yahoo.gr,
* and florinsasu@hotmail.com
*/
#include "Pcsx2Api.h"
/* FW plugin API */
// Basic functions.
// NOTE: The read/write functions CANNOT use XMM/MMX regs
// If you want to use them, need to save and restore current ones
EXPORT_C_(s32) FWinit();
// pDisplay normally is passed a handle to the GS plugins window.
EXPORT_C_(s32) FWopen(void *pDisplay);
EXPORT_C_(void) FWclose();
EXPORT_C_(void) FWshutdown();
EXPORT_C_(u32) FWread32(u32 addr);
EXPORT_C_(void) FWwrite32(u32 addr, u32 value);
EXPORT_C_(void) FWirqCallback(void (*callback)());
// Extended functions
EXPORT_C_(void) FWkeyEvent(keyEvent *ev);
EXPORT_C_(s32) FWfreeze(u8 mode, freezeData *data);
EXPORT_C_(void) FWconfigure();
EXPORT_C_(void) FWabout();
EXPORT_C_(s32) FWtest();
#endif
#endif // __USBAPI_H__

View File

@ -0,0 +1,85 @@
/* 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
*/
#ifndef __GSAPI_H__
#define __GSAPI_H__
// Note; this header is experimental, and will be a shifting target. Only use this if you are willing to repeatedly fix breakage.
/*
* Based on PS2E Definitions by
linuzappz@hotmail.com,
* shadowpcsx2@yahoo.gr,
* and florinsasu@hotmail.com
*/
#include "Pcsx2Api.h"
typedef struct _GSdriverInfo {
char name[8];
void *common;
} GSdriverInfo;
// Basic functions.
EXPORT_C_(s32) GSinit();
// pDisplay normally is passed a handle to the GS plugins window.
EXPORT_C_(s32) GSopen(void *pDisplay, char *Title, bool multithread);
EXPORT_C_(void) GSclose();
EXPORT_C_(void) GSshutdown();
EXPORT_C_(void) GSvsync(int field);
EXPORT_C_(void) GSgifTransfer1(u32 *pMem, u32 addr);
EXPORT_C_(void) GSgifTransfer2(u32 *pMem, u32 size);
EXPORT_C_(void) GSgifTransfer3(u32 *pMem, u32 size);
EXPORT_C_(void) GSgetLastTag(u64* ptag); // returns the last tag processed (64 bits)
EXPORT_C_(void) GSgifSoftReset(u32 mask);
EXPORT_C_(void) GSreadFIFO(u64 *mem);
EXPORT_C_(void) GSreadFIFO2(u64 *mem, int qwc);
// Extended functions
// GSkeyEvent gets called when there is a keyEvent from the PAD plugin
EXPORT_C_(void) GSkeyEvent(keyEvent *ev);
EXPORT_C_(void) GSchangeSaveState(s32 state, const char* filename);
EXPORT_C_(void) GSmakeSnapshot(char *path);
EXPORT_C_(void) GSmakeSnapshot2(char *pathname, int* snapdone, int savejpg);
EXPORT_C_(void) GSirqCallback(void (*callback)());
EXPORT_C_(void) CALLBACK GSprintf(s32 timeout, char *fmt, ...);
EXPORT_C_(void) GSsetBaseMem(void*);
EXPORT_C_(void) GSsetGameCRC(s32 crc, s32 gameoptions);
// controls frame skipping in the GS, if this routine isn't present, frame skipping won't be done
EXPORT_C_(void) GSsetFrameSkip(int frameskip);
// if start is true, starts recording spu2 data, else stops
// returns true if successful
// for now, pData is not used
EXPORT_C_(bool) GSsetupRecording(bool start);
EXPORT_C_(void) GSreset();
EXPORT_C_(void) GSwriteCSR(u32 value);
EXPORT_C_(void ) GSgetDriverInfo(GSdriverInfo *info);
#ifdef _WIN32
EXPORT_C_(s32) CALLBACK GSsetWindowInfo(winInfo *info);
#endif
EXPORT_C_(s32) GSfreeze(u8 mode, freezeData *data);
EXPORT_C_(void) GSconfigure();
EXPORT_C_(void) GSabout();
EXPORT_C_(s32) GStest();
#endif // __GSAPI_H__

View File

@ -0,0 +1,68 @@
/* 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
*/
#ifndef __PADAPI_H__
#define __PADAPI_H__
// Note; this header is experimental, and will be a shifting target. Only use this if you are willing to repeatedly fix breakage.
/*
* Based on PS2E Definitions by
linuzappz@hotmail.com,
* shadowpcsx2@yahoo.gr,
* and florinsasu@hotmail.com
*/
#include "Pcsx2Api.h"
/* PAD plugin API */
/* So obsolete that everyone uses it. */
// Basic functions.
EXPORT_C_(s32) PADinit(u32 flags);
// pDisplay normally is passed a handle to the GS plugins window.
EXPORT_C_(s32) PADopen(void *pDisplay);
EXPORT_C_(void) PADclose();
EXPORT_C_(void) PADshutdown();
// PADkeyEvent is called every vsync (return NULL if no event)
EXPORT_C_(keyEvent*) PADkeyEvent();
EXPORT_C_(u8) PADstartPoll(u8 pad);
EXPORT_C_(u8) PADpoll(u8 value);
// returns: 1 if supported pad1
// 2 if supported pad2
// 3 if both are supported
EXPORT_C_(u8) PADquery();
// call to give a hint to the PAD plugin to query for the keyboard state. A
// good plugin will query the OS for keyboard state ONLY in this function.
// This function is necessary when multithreading because otherwise
// the PAD plugin can get into deadlocks with the thread that really owns
// the window (and input). Note that PADupdate can be called from a different
// thread than the other functions, so mutex or other multithreading primitives
// have to be added to maintain data integrity.
EXPORT_C_(void) PADupdate(u8 pad);
// Extended functions
EXPORT_C_(void) PADgsDriverInfo(GSdriverInfo *info);
EXPORT_C_(s32) PADfreeze(u8 mode, freezeData *data);
EXPORT_C_(void) PADconfigure();
EXPORT_C_(void) PADabout();
EXPORT_C_(s32) PADtest();
#endif // __PADAPI_H__

View File

@ -0,0 +1,86 @@
/* 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
*/
#ifndef __SIOAPI_H__
#define __SIOAPI_H__
// Note; this header is experimental, and will be a shifting target. Only use this if you are willing to repeatedly fix breakage.
/*
* Based on PS2E Definitions by
linuzappz@hotmail.com,
* shadowpcsx2@yahoo.gr,
* and florinsasu@hotmail.com
*/
#include "Pcsx2Api.h"
/* SIO plugin API */
// Called by SIO_TYPE_MTAP plugins to change the slot.
// Slot is then passed to memcard and pad plugins on SIOstartPoll.
// MTAP SIO plugins should ignore slot values on startPoll, as should RMs (probably).
// Port isn't strictly necessary, but doesn't hurt.
typedef int (CALLBACK * SIOchangeSlotCB)(int port, int slot);
// Basic functions.
// Types is an or-ed combination of SioTypes to initialize. It'd probably be simplest
// just to make each SIO plugin support only one type, for simplicity.
// SIOchangeSlotCB should *only* be called by MTAP plugins.
EXPORT_C_(s32) SIOinit(int types, SIOchangeSlotCB f);
// Single plugin can only be PAD, MTAP, RM, or MC. Only load one plugin of each type,
// but not both a PAD and MTAP. Simplifies plugin selection and interface, as well
// as API.
// pDisplay normally is passed a handle to the GS plugins window.
EXPORT_C_(s32) SIOopen(void *pDisplay);
EXPORT_C_(void) SIOclose();
EXPORT_C_(void) SIOshutdown();
// Returns 0 if device doesn't exist. Means old pad plugins can just say nothing
// connected to other slots, and SIOpoll won't be called on those slots, ideally.
EXPORT_C_(s32) SIOstartPoll(u8 deviceType, u32 port, u32 slot, u8 *returnValue);
// Returns 0 on the last output byte.
EXPORT_C_(s32) SIOpoll(u8 value, u8 *returnValue);
// returns: SIO_TYPE_{PAD,MTAP,RM,MC}
EXPORT_C_(u32) SIOquery();
// extended funcs
EXPORT_C_(void) SIOconfigure();
EXPORT_C_(keyEvent*) CALLBACK SIOkeyEvent();
// Save one type at a time. If a plugin supports all 4 types,
// should expect 4 calls. Increases savestate compatibility.
EXPORT_C_(s32) SIOfreeze(u8 mode, freezeData *data, int type);
EXPORT_C_(void) SIOabout();
EXPORT_C_(s32) SIOtest();
enum {
SIO_TYPE_PAD = 0x00000001,
SIO_TYPE_MTAP = 0x00000004,
SIO_TYPE_RM = 0x00000040,
SIO_TYPE_MC = 0x00000100
} SioTypes;
#endif // __SIOAPI_H__

View File

@ -0,0 +1,77 @@
/* 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
*/
#ifndef __SPU2API_H__
#define __SPU2API_H__
// Note; this header is experimental, and will be a shifting target. Only use this if you are willing to repeatedly fix breakage.
/*
* Based on PS2E Definitions by
linuzappz@hotmail.com,
* shadowpcsx2@yahoo.gr,
* and florinsasu@hotmail.com
*/
#include "Pcsx2Api.h"
EXPORT_C_(s32) SPU2init();
// pDisplay normally is passed a handle to the GS plugins window.
EXPORT_C_(s32) SPU2open(void *pDisplay);
EXPORT_C_(void) SPU2close();
EXPORT_C_(void) SPU2shutdown();
EXPORT_C_(void) SPU2write(u32 mem, u16 value);
EXPORT_C_(u16) SPU2read(u32 mem);
// The following calls are depreciated.
EXPORT_C_(void) SPU2readDMA4Mem(u16 *pMem, u32 size);
EXPORT_C_(void) SPU2readDMA7Mem(u16 *pMem, u32 size);
EXPORT_C_(void) SPU2writeDMA4Mem(u16 *pMem, u32 size);
EXPORT_C_(void) SPU2writeDMA7Mem(u16 *pMem, u32 size);
EXPORT_C_(void) SPU2interruptDMA4();
EXPORT_C_(void) SPU2interruptDMA7();
// These calls replace the calls above.
EXPORT_C_(void) SPU2readDMAMem(u16 *pMem, u32 size, u8 core);
EXPORT_C_(void) SPU2writeDMAMem(u16 *pMem, u32 size, u8 core);
EXPORT_C_(void) SPU2interruptDMA(u8 core);
// all addresses passed by dma will be pointers to the array starting at baseaddr
// This function is necessary to successfully save and reload the spu2 state
EXPORT_C_(void) SPU2setDMABaseAddr(uptr baseaddr);
EXPORT_C_(u32) SPU2ReadMemAddr(u8 core);
EXPORT_C_(void) SPU2WriteMemAddr(u8 core,u32 value);
EXPORT_C_(void) SPU2irqCallback(void (*SPU2callback)(),void (*DMA4callback)(),void (*DMA7callback)());
// extended funcs
// if start is true, starts recording spu2 data, else stops
// returns true if successful
EXPORT_C_(bool) SPU2setupRecording(bool start);
EXPORT_C_(void) SPU2keyEvent(keyEvent *ev);
EXPORT_C_(void) SPU2setClockPtr(u32* ptr);
EXPORT_C_(void) SPU2async(u32 cycles);
EXPORT_C_(s32) SPU2freeze(u8 mode, freezeData *data);
EXPORT_C_(void) SPU2configure();
EXPORT_C_(void) SPU2about();
EXPORT_C_(s32) SPU2test();
#endif

View File

@ -0,0 +1,65 @@
/* 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
*/
#ifndef __USBAPI_H__
#define __USBAPI_H__
// Note; this header is experimental, and will be a shifting target. Only use this if you are willing to repeatedly fix breakage.
/*
* Based on PS2E Definitions by
linuzappz@hotmail.com,
* shadowpcsx2@yahoo.gr,
* and florinsasu@hotmail.com
*/
#include "Pcsx2Api.h"
typedef void (*USBcallback)(int cycles);
typedef int (*USBhandler)(void);
// Basic functions.
EXPORT_C_(s32) USBinit();
// pDisplay normally is passed a handle to the GS plugins window.
EXPORT_C_(s32) USBopen(void *pDisplay);
EXPORT_C_(void) USBclose();
EXPORT_C_(void) USBshutdown();
EXPORT_C_(u8) USBread8(u32 addr);
EXPORT_C_(u16) USBread16(u32 addr);
EXPORT_C_(u32) USBread32(u32 addr);
EXPORT_C_(void) USBwrite8(u32 addr, u8 value);
EXPORT_C_(void) USBwrite16(u32 addr, u16 value);
EXPORT_C_(void) USBwrite32(u32 addr, u32 value);
EXPORT_C_(void) USBasync(u32 cycles);
// cycles = IOP cycles before calling callback,
// if callback returns 1 the irq is triggered, else not
EXPORT_C_(void) USBirqCallback(USBcallback callback);
EXPORT_C_(USBhandler) USBirqHandler(void);
EXPORT_C_(void) USBsetRAM(void *mem);
// Extended functions
EXPORT_C_(void) USBkeyEvent(keyEvent *ev);
EXPORT_C_(s32) USBfreeze(u8 mode, freezeData *data);
EXPORT_C_(void) USBconfigure();
EXPORT_C_(void) USBabout();
EXPORT_C_(s32) USBtest();
#endif // __USBAPI_H__

View File

@ -79,35 +79,53 @@ enum cdvdActions
, cdvdAction_Read // note: not used yet. , cdvdAction_Read // note: not used yet.
}; };
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
// -- Cdvd Block Read Cycle Timings -- // Cdvd Block Read Cycle Timings
// These timings are based on a median average block read speed. In theory the read //
// speeds differ based on the location of the sector being read (outer rings have // The PS2 CDVD effectively has two seek modes -- the normal/slow one (est. avg seeks being
// a different read speed from inner rings). But for our purposes an average is good // around 120-160ms), and a faster seek which has an estimated seek time of about 35-40ms.
// enough, since all of Pcsx2's instruction cycle counting is hardly accurate anyway. // Fast seeks happen when the destination sector is within a certain range of the starting
// point, such that abs(start-dest) is less than the value in the tbl_FastSeekDelta.
//
// CDVDs also have a secondary seeking method used when the destination is close enough
// that a contiguous sector read can reach the sector faster than initiating a full seek.
// Typically this value is very low.
// Morale of the story: don't get too caught up micro-managing your cycle timings. :) enum CDVD_MODE_TYPE
{
MODE_CDROM = 0,
MODE_DVDROM,
};
static const uint tbl_FastSeekDelta[3] =
{
4371, // CD-ROM
14764, // Single-layer DVD-ROM
13360 // dual-layer DVD-ROM [currently unused]
};
// if a seek is within this many blocks, read instead of seek.
// These values are arbitrary assumptions. Not sure what the real PS2 uses.
static const uint tbl_ContigiousSeekDelta[3] =
{
8, // CD-ROM
16, // single-layer DVD-ROM
16, // dual-layer DVD-ROM [currently unused]
};
// Note: DVD read times are modified to be faster, because games seem to be a lot more // Note: DVD read times are modified to be faster, because games seem to be a lot more
// concerned with accurate(ish) seek delays and less concerned with actual block read speeds. // concerned with accurate(ish) seek delays and less concerned with actual block read speeds.
// Translation: it's a minor speedhack :D
static const uint PSX_CD_READSPEED = 153600; // 1 Byte Time @ x1 (150KB = cd x 1) static const uint PSX_CD_READSPEED = 153600; // 1 Byte Time @ x1 (150KB = cd x 1)
static const uint PSX_DVD_READSPEED = 1382400 + 256000; // normal is 1 Byte Time @ x1 (1350KB = dvd x 1). static const uint PSX_DVD_READSPEED = 1382400 + 256000; // normal is 1 Byte Time @ x1 (1350KB = dvd x 1).
enum CDVD_MODE_TYPE
{
MODE_DVDROM,
MODE_CDROM
};
// if a seek is within this many blocks, read instead of seek.
// I picked 9 as an arbitrary value. Not sure what the real PS2 uses.
static const int Cdvd_Contigious_Seek = 9;
//Note: This timing causes many games to load very slow, but it likely not the real problem.
//Games breaking with it set to PSXCLK*40 : "wrath unleashed" and "Shijou Saikyou no Deshi Kenichi".
static const uint Cdvd_Avg_SeekCycles = (PSXCLK*95) / 1000; // average number of cycles per seek (95ms)
// Legacy Note: FullSeek timing causes many games to load very slow, but it likely not the real problem.
// Games breaking with it set to PSXCLK*40 : "wrath unleashed" and "Shijou Saikyou no Deshi Kenichi".
static const uint Cdvd_FullSeek_Cycles = (PSXCLK*100) / 1000; // average number of cycles per fullseek (100ms)
static const uint Cdvd_FastSeek_Cycles = (PSXCLK*30) / 1000; // average number of cycles per fastseek (37ms)
static const char *mg_zones[8] = {"Japan", "USA", "Europe", "Oceania", "Asia", "Russia", "China", "Mexico"}; static const char *mg_zones[8] = {"Japan", "USA", "Europe", "Oceania", "Asia", "Russia", "China", "Mexico"};
@ -768,6 +786,7 @@ struct Freeze_v10Compat
void SaveState::cdvdFreeze() void SaveState::cdvdFreeze()
{ {
FreezeTag( "cdvd" );
Freeze( cdvd ); Freeze( cdvd );
if( IsLoading() ) if( IsLoading() )
@ -941,8 +960,8 @@ __forceinline void cdvdActionInterrupt()
} }
// inlined due to being referenced in only one place. // inlined due to being referenced in only one place.
__forceinline void cdvdReadInterrupt() { __forceinline void cdvdReadInterrupt()
{
//SysPrintf("cdvdReadInterrupt %x %x %x %x %x\n", cpuRegs.interrupt, cdvd.Readed, cdvd.Reading, cdvd.nSectors, (HW_DMA3_BCR_H16 * HW_DMA3_BCR_L16) *4); //SysPrintf("cdvdReadInterrupt %x %x %x %x %x\n", cpuRegs.interrupt, cdvd.Readed, cdvd.Reading, cdvd.nSectors, (HW_DMA3_BCR_H16 * HW_DMA3_BCR_L16) *4);
cdvd.Ready = 0x00; cdvd.Ready = 0x00;
@ -1265,7 +1284,7 @@ u8 cdvdRead3A(void) { // DEC_SET
// Returns the number of IOP cycles until the event completes. // Returns the number of IOP cycles until the event completes.
static uint cdvdStartSeek( uint newsector ) static uint cdvdStartSeek( uint newsector, CDVD_MODE_TYPE mode )
{ {
cdvd.SeekToSector = newsector; cdvd.SeekToSector = newsector;
@ -1283,10 +1302,21 @@ static uint cdvdStartSeek( uint newsector )
seektime = PSXCLK / 3; // 333ms delay seektime = PSXCLK / 3; // 333ms delay
cdvd.Spinning = true; cdvd.Spinning = true;
} }
else if( (Cdvd_Contigious_Seek >= 0) && (delta >= Cdvd_Contigious_Seek) ) else if( (tbl_ContigiousSeekDelta[mode] == 0) || (delta >= tbl_ContigiousSeekDelta[mode]) )
{ {
CDR_LOG( "CdSeek Begin > to sector %d, from %d - delta=%d\n", cdvd.SeekToSector, cdvd.Sector, delta ); // Select either Full or Fast seek depending on delta:
seektime = Cdvd_Avg_SeekCycles;
if( delta >= tbl_FastSeekDelta[mode] )
{
// Full Seek
CDR_LOG( "CdSeek Begin > to sector %d, from %d - delta=%d [FULL]\n", cdvd.SeekToSector, cdvd.Sector, delta );
seektime = Cdvd_FullSeek_Cycles;
}
else
{
CDR_LOG( "CdSeek Begin > to sector %d, from %d - delta=%d [FAST]\n", cdvd.SeekToSector, cdvd.Sector, delta );
seektime = Cdvd_FastSeek_Cycles;
}
} }
else else
{ {
@ -1332,7 +1362,7 @@ void cdvdWrite04(u8 rt) { // NCOMMAND
DevCon::Notice( "CdStandby : %d", params rt ); DevCon::Notice( "CdStandby : %d", params rt );
cdvd.Action = cdvdAction_Standby; cdvd.Action = cdvdAction_Standby;
cdvd.ReadTime = cdvdBlockReadTime( MODE_DVDROM ); cdvd.ReadTime = cdvdBlockReadTime( MODE_DVDROM );
CDVD_INT( cdvdStartSeek( 0 ) ); CDVD_INT( cdvdStartSeek( 0, MODE_DVDROM ) );
break; break;
case 0x03: // CdStop case 0x03: // CdStop
@ -1349,7 +1379,7 @@ void cdvdWrite04(u8 rt) { // NCOMMAND
case 0x05: // CdSeek case 0x05: // CdSeek
cdvd.Action = cdvdAction_Seek; cdvd.Action = cdvdAction_Seek;
cdvd.ReadTime = cdvdBlockReadTime( MODE_DVDROM ); cdvd.ReadTime = cdvdBlockReadTime( MODE_DVDROM );
CDVD_INT( cdvdStartSeek( *(uint*)(cdvd.Param+0) ) ); CDVD_INT( cdvdStartSeek( *(uint*)(cdvd.Param+0), MODE_DVDROM ) );
break; break;
case 0x06: // CdRead case 0x06: // CdRead
@ -1372,7 +1402,7 @@ void cdvdWrite04(u8 rt) { // NCOMMAND
params cdvd.Sector, cdvd.nSectors,cdvd.BlockSize,cdvd.Speed); params cdvd.Sector, cdvd.nSectors,cdvd.BlockSize,cdvd.Speed);
cdvd.ReadTime = cdvdBlockReadTime( MODE_CDROM ); cdvd.ReadTime = cdvdBlockReadTime( MODE_CDROM );
CDVDREAD_INT( cdvdStartSeek( cdvd.SeekToSector ) ); CDVDREAD_INT( cdvdStartSeek( cdvd.SeekToSector,MODE_CDROM ) );
// Read-ahead by telling the plugin about the track now. // Read-ahead by telling the plugin about the track now.
// This helps improve performance on actual from-cd emulation // This helps improve performance on actual from-cd emulation
@ -1413,7 +1443,7 @@ void cdvdWrite04(u8 rt) { // NCOMMAND
params cdvd.Sector, cdvd.nSectors,cdvd.BlockSize,cdvd.Speed); params cdvd.Sector, cdvd.nSectors,cdvd.BlockSize,cdvd.Speed);
cdvd.ReadTime = cdvdBlockReadTime( MODE_CDROM ); cdvd.ReadTime = cdvdBlockReadTime( MODE_CDROM );
CDVDREAD_INT( cdvdStartSeek( cdvd.SeekToSector ) ); CDVDREAD_INT( cdvdStartSeek( cdvd.SeekToSector, MODE_CDROM ) );
// Read-ahead by telling the plugin about the track now. // Read-ahead by telling the plugin about the track now.
// This helps improve performance on actual from-cd emulation // This helps improve performance on actual from-cd emulation
@ -1444,7 +1474,7 @@ void cdvdWrite04(u8 rt) { // NCOMMAND
params cdvd.Sector, cdvd.nSectors,cdvd.BlockSize,cdvd.Speed); params cdvd.Sector, cdvd.nSectors,cdvd.BlockSize,cdvd.Speed);
cdvd.ReadTime = cdvdBlockReadTime( MODE_DVDROM ); cdvd.ReadTime = cdvdBlockReadTime( MODE_DVDROM );
CDVDREAD_INT( cdvdStartSeek( cdvd.SeekToSector ) ); CDVDREAD_INT( cdvdStartSeek( cdvd.SeekToSector, MODE_DVDROM ) );
// Read-ahead by telling the plugin about the track now. // Read-ahead by telling the plugin about the track now.
// This helps improve performance on actual from-cd emulation // This helps improve performance on actual from-cd emulation

View File

@ -84,6 +84,7 @@
* Macros for sceCdGetDiskType() //comments translated from japanese;) * Macros for sceCdGetDiskType() //comments translated from japanese;)
*/ */
// These are already declared with different names in PS2Edefs.h. And aren't used.
#define SCECdIllgalMedia 0xff // ILIMEDIA (Illegal Media) A non-PS / non-PS2 Disc. #define SCECdIllgalMedia 0xff // ILIMEDIA (Illegal Media) A non-PS / non-PS2 Disc.
#define SCECdDVDV 0xfe // DVDV (DVD Video) A non-PS / non-PS2 Disc, but a DVD Video Disc #define SCECdDVDV 0xfe // DVDV (DVD Video) A non-PS / non-PS2 Disc, but a DVD Video Disc
#define SCECdCDDA 0xfd // CDDA (CD DA) A non-PS / non-PS2 Disc that include a DA track #define SCECdCDDA 0xfd // CDDA (CD DA) A non-PS / non-PS2 Disc that include a DA track
@ -95,7 +96,6 @@
#define SCECdDETCT 0x01 // DETCT (Detecting) Disc distinction action #define SCECdDETCT 0x01 // DETCT (Detecting) Disc distinction action
#define SCECdNODISC 0x00 // NODISC (No disc) No disc entered #define SCECdNODISC 0x00 // NODISC (No disc) No disc entered
/* /*
* Media mode * Media mode
*/ */

View File

@ -27,6 +27,7 @@ namespace R5900{
namespace Interpreter namespace Interpreter
{ {
// fixme - this code no longer compiles if PCSX2_CACHE_EMU_MEM is defined - do we need it any more?
#ifdef PCSX2_CACHE_EMU_MEM #ifdef PCSX2_CACHE_EMU_MEM
int getFreeCache(u32 mem, int mode, int * way) { int getFreeCache(u32 mem, int mode, int * way) {
u8 * out; u8 * out;

View File

@ -944,15 +944,9 @@ void cdrReset() {
cdReadTime = (PSXCLK / 1757) * BIAS; cdReadTime = (PSXCLK / 1757) * BIAS;
} }
void SaveState::cdrFreeze() { void SaveState::cdrFreeze()
{
FreezeTag( "cdrom" );
Freeze(cdr); Freeze(cdr);
// Alrighty! This code used to, for some reason, recalculate the pTransfer value
// even though it's being saved as part of the cdr struct. Probably a backwards
// compat fix with an earlier save version.
int tmp; // = (int)(cdr.pTransfer - cdr.Transfer);
Freeze(tmp);
//if (Mode == 0) cdr.pTransfer = cdr.Transfer + tmp;
} }

View File

@ -43,7 +43,9 @@ int gates = 0;
// Counter 4 takes care of scanlines - hSync/hBlanks // Counter 4 takes care of scanlines - hSync/hBlanks
// Counter 5 takes care of vSync/vBlanks // Counter 5 takes care of vSync/vBlanks
Counter counters[6]; Counter counters[4];
SyncCounter hsyncCounter;
SyncCounter vsyncCounter;
u32 nextsCounter; // records the cpuRegs.cycle value of the last call to rcntUpdate() u32 nextsCounter; // records the cpuRegs.cycle value of the last call to rcntUpdate()
s32 nextCounter; // delta from nextsCounter, in cycles, until the next rcntUpdate() s32 nextCounter; // delta from nextsCounter, in cycles, until the next rcntUpdate()
@ -101,7 +103,7 @@ static __forceinline void cpuRcntSet()
int i; int i;
nextsCounter = cpuRegs.cycle; nextsCounter = cpuRegs.cycle;
nextCounter = (counters[5].sCycle + counters[5].CycleT) - cpuRegs.cycle; nextCounter = (vsyncCounter.sCycle + vsyncCounter.CycleT) - cpuRegs.cycle;
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
_rcntSet( i ); _rcntSet( i );
@ -124,10 +126,10 @@ void rcntInit() {
counters[2].interrupt = 11; counters[2].interrupt = 11;
counters[3].interrupt = 12; counters[3].interrupt = 12;
counters[4].modeval = MODE_HRENDER; hsyncCounter.Mode = MODE_HRENDER;
counters[4].sCycle = cpuRegs.cycle; hsyncCounter.sCycle = cpuRegs.cycle;
counters[5].modeval = MODE_VRENDER; vsyncCounter.Mode = MODE_VRENDER;
counters[5].sCycle = cpuRegs.cycle; vsyncCounter.sCycle = cpuRegs.cycle;
UpdateVSyncRate(); UpdateVSyncRate();
@ -136,7 +138,7 @@ void rcntInit() {
} }
// debug code, used for stats // debug code, used for stats
int g_nCounters[4]; int g_nhsyncCounter;
static uint iFrame = 0; static uint iFrame = 0;
#ifndef _WIN32 #ifndef _WIN32
@ -235,8 +237,8 @@ u32 UpdateVSyncRate()
vSyncInfoCalc( &vSyncInfo, FRAMERATE_NTSC, SCANLINES_TOTAL_NTSC ); vSyncInfoCalc( &vSyncInfo, FRAMERATE_NTSC, SCANLINES_TOTAL_NTSC );
} }
counters[4].CycleT = vSyncInfo.hRender; // Amount of cycles before the counter will be updated hsyncCounter.CycleT = vSyncInfo.hRender; // Amount of cycles before the counter will be updated
counters[5].CycleT = vSyncInfo.Render; // Amount of cycles before the counter will be updated vsyncCounter.CycleT = vSyncInfo.Render; // Amount of cycles before the counter will be updated
if (Config.CustomFps > 0) if (Config.CustomFps > 0)
{ {
@ -393,28 +395,28 @@ static int vblankinc = 0;
__forceinline void rcntUpdate_hScanline() __forceinline void rcntUpdate_hScanline()
{ {
if( !cpuTestCycle( counters[4].sCycle, counters[4].CycleT ) ) return; if( !cpuTestCycle( hsyncCounter.sCycle, hsyncCounter.CycleT ) ) return;
//iopBranchAction = 1; //iopBranchAction = 1;
if (counters[4].modeval & MODE_HBLANK) { //HBLANK Start if (hsyncCounter.Mode & MODE_HBLANK) { //HBLANK Start
rcntStartGate(false, counters[4].sCycle); rcntStartGate(false, hsyncCounter.sCycle);
psxCheckStartGate16(0); psxCheckStartGate16(0);
// Setup the hRender's start and end cycle information: // Setup the hRender's start and end cycle information:
counters[4].sCycle += vSyncInfo.hBlank; // start (absolute cycle value) hsyncCounter.sCycle += vSyncInfo.hBlank; // start (absolute cycle value)
counters[4].CycleT = vSyncInfo.hRender; // endpoint (delta from start value) hsyncCounter.CycleT = vSyncInfo.hRender; // endpoint (delta from start value)
counters[4].modeval = MODE_HRENDER; hsyncCounter.Mode = MODE_HRENDER;
} }
else { //HBLANK END / HRENDER Begin else { //HBLANK END / HRENDER Begin
if (CSRw & 0x4) GSCSRr |= 4; // signal if (CSRw & 0x4) GSCSRr |= 4; // signal
if (!(GSIMR&0x400)) gsIrq(); if (!(GSIMR&0x400)) gsIrq();
if (gates) rcntEndGate(false, counters[4].sCycle); if (gates) rcntEndGate(false, hsyncCounter.sCycle);
if (psxhblankgate) psxCheckEndGate16(0); if (psxhblankgate) psxCheckEndGate16(0);
// set up the hblank's start and end cycle information: // set up the hblank's start and end cycle information:
counters[4].sCycle += vSyncInfo.hRender; // start (absolute cycle value) hsyncCounter.sCycle += vSyncInfo.hRender; // start (absolute cycle value)
counters[4].CycleT = vSyncInfo.hBlank; // endpoint (delta from start value) hsyncCounter.CycleT = vSyncInfo.hBlank; // endpoint (delta from start value)
counters[4].modeval = MODE_HBLANK; hsyncCounter.Mode = MODE_HBLANK;
# ifdef VSYNC_DEBUG # ifdef VSYNC_DEBUG
hsc++; hsc++;
@ -424,30 +426,30 @@ __forceinline void rcntUpdate_hScanline()
__forceinline bool rcntUpdate_vSync() __forceinline bool rcntUpdate_vSync()
{ {
s32 diff = (cpuRegs.cycle - counters[5].sCycle); s32 diff = (cpuRegs.cycle - vsyncCounter.sCycle);
if( diff < counters[5].CycleT ) return false; if( diff < vsyncCounter.CycleT ) return false;
//iopBranchAction = 1; //iopBranchAction = 1;
if (counters[5].modeval == MODE_VSYNC) if (vsyncCounter.Mode == MODE_VSYNC)
{ {
VSyncEnd(counters[5].sCycle); VSyncEnd(vsyncCounter.sCycle);
counters[5].sCycle += vSyncInfo.Blank; vsyncCounter.sCycle += vSyncInfo.Blank;
counters[5].CycleT = vSyncInfo.Render; vsyncCounter.CycleT = vSyncInfo.Render;
counters[5].modeval = MODE_VRENDER; vsyncCounter.Mode = MODE_VRENDER;
return true; return true;
} }
else // VSYNC end / VRENDER begin else // VSYNC end / VRENDER begin
{ {
VSyncStart(counters[5].sCycle); VSyncStart(vsyncCounter.sCycle);
counters[5].sCycle += vSyncInfo.Render; vsyncCounter.sCycle += vSyncInfo.Render;
counters[5].CycleT = vSyncInfo.Blank; vsyncCounter.CycleT = vSyncInfo.Blank;
counters[5].modeval = MODE_VSYNC; vsyncCounter.Mode = MODE_VSYNC;
// Accumulate hsync rounding errors: // Accumulate hsync rounding errors:
counters[4].sCycle += vSyncInfo.hSyncError; hsyncCounter.sCycle += vSyncInfo.hSyncError;
# ifdef VSYNC_DEBUG # ifdef VSYNC_DEBUG
vblankinc++; vblankinc++;
@ -766,15 +768,12 @@ u32 __fastcall rcntCycle(int index)
void SaveState::rcntFreeze() void SaveState::rcntFreeze()
{ {
Freeze(counters); Freeze( counters );
Freeze(nextCounter); Freeze( hsyncCounter );
Freeze(nextsCounter); Freeze( vsyncCounter );
Freeze( nextCounter );
// New in version 1 -- save the PAL/NTSC info! Freeze( nextsCounter );
if( GetVersion() >= 0x1 ) Freeze( Config.PsxType );
{
Freeze( Config.PsxType );
}
if( IsLoading() ) if( IsLoading() )
{ {

View File

@ -66,7 +66,8 @@ struct EECNT_MODE
// fixme: Cycle and sCycleT members are unused. // fixme: Cycle and sCycleT members are unused.
// But they can't be removed without making a new savestate version. // But they can't be removed without making a new savestate version.
struct Counter { struct Counter
{
u32 count; u32 count;
union union
{ {
@ -75,10 +76,14 @@ struct Counter {
}; };
u32 target, hold; u32 target, hold;
u32 rate, interrupt; u32 rate, interrupt;
u32 Cycle; u32 sCycleT; // delta values should be signed.
};
struct SyncCounter
{
u32 Mode;
u32 sCycle; // start cycle of timer u32 sCycle; // start cycle of timer
s32 CycleT; s32 CycleT;
u32 sCycleT; // delta values should be signed.
}; };
//------------------------------------------------------------------ //------------------------------------------------------------------
@ -124,7 +129,10 @@ struct Counter {
#define MODE_HBLANK 0x1 //Set for the remaining ~1/6 of 1 Scanline #define MODE_HBLANK 0x1 //Set for the remaining ~1/6 of 1 Scanline
extern Counter counters[6]; extern Counter counters[4];
extern SyncCounter hsyncCounter;
extern SyncCounter vsyncCounter;
extern s32 nextCounter; // delta until the next counter event (must be signed) extern s32 nextCounter; // delta until the next counter event (must be signed)
extern u32 nextsCounter; extern u32 nextsCounter;

View File

@ -250,6 +250,13 @@ void GIFdma()
GIFchain(); //Transfers the data set by the switch GIFchain(); //Transfers the data set by the switch
FreezeRegs(0); FreezeRegs(0);
if(gif->qwc == 0 && (gif->chcr & 0xc) == 0) gspath3done = 1; if(gif->qwc == 0 && (gif->chcr & 0xc) == 0) gspath3done = 1;
else
{
if(psHu32(GIF_MODE) & 0x4)
CPU_INT(2, min( 8, (int)gif->qwc )/** BIAS*/);
else
CPU_INT(2, gif->qwc/* * BIAS*/);
}
return; return;
} }
else { else {
@ -308,15 +315,28 @@ void GIFdma()
prevcycles = 0; prevcycles = 0;
if (!(vif1Regs->mskpath3 || (psHu32(GIF_MODE) & 0x1))) { if (!(vif1Regs->mskpath3 || (psHu32(GIF_MODE) & 0x1))) {
if(gspath3done == 0){ if(gspath3done == 0)
ptag = (u32*)dmaGetAddr(gif->tadr); //Set memory pointer to TADR {
gif->qwc = (u16)ptag[0]; //QWC set to lower 16bits of the tag if((psHu32(GIF_MODE) & 0x4) && gif->qwc != 0)
gif->chcr = ( gif->chcr & 0xFFFF ) | ( (*ptag) & 0xFFFF0000 ); //Transfer upper part of tag to CHCR bits 31-15 {
CPU_INT(2, gif->qwc * BIAS); CPU_INT(2, min( 8, (int)gif->qwc )/** BIAS*/);
gif->qwc = 0; }
return; else
{
ptag = (u32*)dmaGetAddr(gif->tadr); //Set memory pointer to TADR
gif->qwc = (u16)ptag[0]; //QWC set to lower 16bits of the tag
gif->chcr = ( gif->chcr & 0xFFFF ) | ( (*ptag) & 0xFFFF0000 ); //Transfer upper part of tag to CHCR bits 31-15
if(psHu32(GIF_MODE) & 0x4)
CPU_INT(2, min( 8, (int)gif->qwc )/** BIAS*/);
else
CPU_INT(2, gif->qwc /** BIAS*/);
gif->qwc = 0;
return;
}
} }
//CPU_INT(2, gif->qwc * BIAS); //CPU_INT(2, gif->qwc /** BIAS*/);
gscycles = 0; gscycles = 0;
} }
} }
@ -348,7 +368,14 @@ void dmaGIF() {
ptag = (u32*)dmaGetAddr(gif->tadr); ptag = (u32*)dmaGetAddr(gif->tadr);
gif->qwc = (u16)ptag[0]; //QWC set to lower 16bits of the tag 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 gif->chcr = ( gif->chcr & 0xFFFF ) | ( (*ptag) & 0xFFFF0000 ); //Transfer upper part of tag to CHCR bits 31-15
CPU_INT(2, gif->qwc * BIAS); if((psHu32(GIF_MODE) & 0x4) && gif->qwc != 0)
{
CPU_INT(2, min( 8, (int)gif->qwc ) /** BIAS*/);
}
else
{
CPU_INT(2, gif->qwc /** BIAS*/);
}
gif->qwc = 0; gif->qwc = 0;
return; return;
} }
@ -356,15 +383,28 @@ void dmaGIF() {
if(gif->qwc > 0 && (gif->chcr & 0x4) == 0x4) { if(gif->qwc > 0 && (gif->chcr & 0x4) == 0x4) {
//SysPrintf("HL Hack\n"); //SysPrintf("HL Hack\n");
gspath3done = 1; //Halflife sets a QWC amount in chain mode, no tadr set. gspath3done = 1; //Halflife sets a QWC amount in chain mode, no tadr set.
CPU_INT(2, gif->qwc * BIAS); if((psHu32(GIF_MODE) & 0x4) && gif->qwc != 0)
GIFdma(); {
CPU_INT(2, min( 8, (int)gif->qwc ) /** BIAS*/);
}
else
{
CPU_INT(2, gif->qwc /** BIAS*/);
}
return; return;
} }
//GIFdma(); //GIFdma();
CPU_INT(2, gif->qwc * BIAS); if((psHu32(GIF_MODE) & 0x4) && gif->qwc != 0)
{
CPU_INT(2, min( 8, (int)gif->qwc ) /** BIAS*/);
}
else
{
CPU_INT(2, gif->qwc /** BIAS*/);
}
} }
@ -575,13 +615,12 @@ void gifMFIFOInterrupt()
void SaveState::gifFreeze() void SaveState::gifFreeze()
{ {
if( GetVersion() >= 0x04 ) FreezeTag( "GIFdma" );
{
Freeze( gifstate );
Freeze( gifqwc );
Freeze( gspath3done );
Freeze( gscycles );
// Note: mfifocycles is not a persistent var, so no need to save it here. Freeze( gifstate );
} Freeze( gifqwc );
Freeze( gspath3done );
Freeze( gscycles );
// Note: mfifocycles is not a persistent var, so no need to save it here.
} }

View File

@ -36,8 +36,11 @@ using namespace R5900;
static __forceinline void IntCHackCheck() static __forceinline void IntCHackCheck()
{ {
cpuRegs.cycle = g_nextBranchCycle; // Sanity check: To protect from accidentally "rewinding" the cyclecount
// on the few times nextBranchCycle can be behind our current cycle.
s32 diff = g_nextBranchCycle - cpuRegs.cycle;
if( diff > 0 ) cpuRegs.cycle = g_nextBranchCycle;
// Threshold method, might fix games that have problems with the simple // Threshold method, might fix games that have problems with the simple
// implementation above (none known that break yet) // implementation above (none known that break yet)
/*if( ( g_nextBranchCycle - cpuRegs.cycle ) > 500 ) /*if( ( g_nextBranchCycle - cpuRegs.cycle ) > 500 )

View File

@ -163,14 +163,14 @@ void ipuShutdown()
// fixme - ipuFreeze looks fairly broken. Should probably take a closer look at some point. // fixme - ipuFreeze looks fairly broken. Should probably take a closer look at some point.
void SaveState::ipuFreeze() { void SaveState::ipuFreeze()
{
IPUProcessInterrupt(); IPUProcessInterrupt();
if( GetVersion() < 0x04 ) FreezeTag( "IPU" );
{
// old versions saved the IPU regs, but they're already saved as part of HW! // old versions saved the IPU regs, but they're already saved as part of HW!
FreezeMem(ipuRegs, sizeof(IPUregisters)); //FreezeMem(ipuRegs, sizeof(IPUregisters));
}
Freeze(g_nDMATransfer); Freeze(g_nDMATransfer);
Freeze(FIreadpos); Freeze(FIreadpos);

View File

@ -215,7 +215,7 @@ ihatemsvc:
jne tworows jne tworows
} }
#elif defined(__GNUC__) #elif defined(__GNUC__)
asm( __asm__(
".intel_syntax noprefix\n" ".intel_syntax noprefix\n"
"mov eax, 1\n" "mov eax, 1\n"
"xor esi, esi\n" "xor esi, esi\n"

View File

@ -751,6 +751,8 @@ void psxRcntSetGates()
void SaveState::psxRcntFreeze() void SaveState::psxRcntFreeze()
{ {
FreezeTag( "iopCounters" );
Freeze(psxCounters); Freeze(psxCounters);
Freeze(psxNextCounter); Freeze(psxNextCounter);
Freeze(psxNextsCounter); Freeze(psxNextsCounter);

View File

@ -19,14 +19,10 @@
#ifndef __PSXCOUNTERS_H__ #ifndef __PSXCOUNTERS_H__
#define __PSXCOUNTERS_H__ #define __PSXCOUNTERS_H__
// fixme: sCycle, Cycle, and otarget are unused
// Can't remove them without making a new savestate version though.
struct psxCounter { struct psxCounter {
u64 count, target; u64 count, target;
u32 mode; u32 mode;
u32 rate, interrupt, otarget; u32 rate, interrupt;
u32 sCycle, Cycle;
u32 sCycleT; u32 sCycleT;
s32 CycleT; s32 CycleT;
}; };

View File

@ -17,319 +17,12 @@
*/ */
#include "PrecompiledHeader.h" #include "PrecompiledHeader.h"
#include "IopCommon.h" #include "IopCommon.h"
#include "VU.h"
#include "iCore.h"
#include "Hw.h"
#include "iR3000A.h"
int g_psxWriteOk=1;
static u32 writectrl;
#ifdef PCSX2_VIRTUAL_MEM
void psxMemAlloc()
{
// In VirtualMemory land all mem taken care by memAlloc
}
void psxMemReset()
{
memzero_ptr<Ps2MemSize::IopRam>(psxM);
}
void psxMemShutdown()
{
}
u8 iopMemRead8(u32 mem)
{
u32 t = (mem >> 16) & 0x1fff;
switch(t) {
case 0x1f80:
mem&= 0x1fffffff;
if (mem < 0x1f801000)
return psxHu8(mem);
else
return psxHwRead8(mem);
break;
#ifdef _DEBUG
case 0x1d00: assert(0);
#endif
case 0x1f40:
mem &= 0x1fffffff;
return psxHw4Read8(mem);
case 0x1000: return DEV9read8(mem & 0x1FFFFFFF);
default:
assert( g_psxWriteOk );
return *(u8*)PSXM(mem);
}
}
u16 iopMemRead16(u32 mem)
{
u32 t = (mem >> 16) & 0x1fff;
switch(t) {
case 0x1f80:
mem&= 0x1fffffff;
if (mem < 0x1f801000)
return psxHu16(mem);
else
return psxHwRead16(mem);
break;
case 0x1d00:
SIF_LOG("Sif reg read %x value %x\n", mem, psxHu16(mem));
switch(mem & 0xF0)
{
case 0x40: return psHu16(0x1000F240) | 0x0002;
case 0x60: return 0;
default: return *(u16*)(PS2MEM_HW+0xf200+(mem&0xf0));
}
break;
case 0x1f90:
return SPU2read(mem & 0x1FFFFFFF);
case 0x1000:
return DEV9read16(mem & 0x1FFFFFFF);
default:
assert( g_psxWriteOk );
return *(u16*)PSXM(mem);
}
}
u32 iopMemRead32(u32 mem)
{
u32 t = (mem >> 16) & 0x1fff;
switch(t) {
case 0x1f80:
mem&= 0x1fffffff;
if (mem < 0x1f801000)
return psxHu32(mem);
else
return psxHwRead32(mem);
break;
case 0x1d00:
SIF_LOG("Sif reg read %x value %x\n", mem, psxHu32(mem));
switch(mem & 0xF0)
{
case 0x40: return psHu32(0x1000F240) | 0xF0000002;
case 0x60: return 0;
default: return *(u32*)(PS2MEM_HW+0xf200+(mem&0xf0));
}
break;
case 0x1fff: return g_psxWriteOk;
case 0x1000:
return DEV9read32(mem & 0x1FFFFFFF);
default:
//assert(g_psxWriteOk);
if( mem == 0xfffe0130 )
return writectrl;
else if( mem == 0xffffffff )
return writectrl;
else if( g_psxWriteOk )
return *(u32*)PSXM(mem);
else return 0;
}
}
void iopMemWrite8(u32 mem, u8 value)
{
u32 t = (mem >> 16) & 0x1fff;
switch(t) {
case 0x1f80:
mem&= 0x1fffffff;
if (mem < 0x1f801000)
psxHu8(mem) = value;
else
psxHwWrite8(mem, value);
break;
case 0x1f40:
mem&= 0x1fffffff;
psxHw4Write8(mem, value);
break;
case 0x1d00:
SysPrintf("sw8 [0x%08X]=0x%08X\n", mem, value);
*(u8*)(PS2MEM_HW+0xf200+(mem&0xff)) = value;
break;
case 0x1000:
DEV9write8(mem & 0x1fffffff, value);
return;
default:
assert(g_psxWriteOk);
*(u8 *)PSXM(mem) = value;
psxCpu->Clear(mem&~3, 1);
break;
}
}
void iopMemWrite16(u32 mem, u16 value)
{
u32 t = (mem >> 16) & 0x1fff;
switch(t) {
case 0x1600:
//HACK: DEV9 VM crash fix
break;
case 0x1f80:
mem&= 0x1fffffff;
if (mem < 0x1f801000)
psxHu16(mem) = value;
else
psxHwWrite16(mem, value);
break;
case 0x1d00:
switch (mem & 0xf0) {
case 0x10:
// write to ps2 mem
psHu16(0x1000F210) = value;
return;
case 0x40:
{
u32 temp = value & 0xF0;
// write to ps2 mem
if(value & 0x20 || value & 0x80)
{
psHu16(0x1000F240) &= ~0xF000;
psHu16(0x1000F240) |= 0x2000;
}
if(psHu16(0x1000F240) & temp) psHu16(0x1000F240) &= ~temp;
else psHu16(0x1000F240) |= temp;
return;
}
case 0x60:
psHu32(0x1000F260) = 0;
return;
default:
assert(0);
}
return;
case 0x1f90:
SPU2write(mem & 0x1FFFFFFF, value); return;
case 0x1000:
DEV9write16(mem & 0x1fffffff, value); return;
default:
assert( g_psxWriteOk );
*(u16 *)PSXM(mem) = value;
psxCpu->Clear(mem&~3, 1);
break;
}
}
void iopMemWrite32(u32 mem, u32 value)
{
u32 t = (mem >> 16) & 0x1fff;
switch(t) {
case 0x1f80:
mem&= 0x1fffffff;
if (mem < 0x1f801000)
psxHu32(mem) = value;
else
psxHwWrite32(mem, value);
break;
case 0x1d00:
switch (mem & 0xf0) {
case 0x10:
// write to ps2 mem
psHu32(0x1000F210) = value;
return;
case 0x20:
// write to ps2 mem
psHu32(0x1000F220) &= ~value;
return;
case 0x30:
// write to ps2 mem
psHu32(0x1000F230) |= value;
return;
case 0x40:
{
u32 temp = value & 0xF0;
// write to ps2 mem
if(value & 0x20 || value & 0x80)
{
psHu32(0x1000F240) &= ~0xF000;
psHu32(0x1000F240) |= 0x2000;
}
if(psHu32(0x1000F240) & temp) psHu32(0x1000F240) &= ~temp;
else psHu32(0x1000F240) |= temp;
return;
}
case 0x60:
psHu32(0x1000F260) = 0;
return;
default:
*(u32*)(PS2MEM_HW+0xf200+(mem&0xf0)) = value;
}
return;
case 0x1000:
DEV9write32(mem & 0x1fffffff, value);
return;
case 0x1ffe:
if( mem == 0xfffe0130 ) {
writectrl = value;
switch (value) {
case 0x800: case 0x804:
case 0xc00: case 0xc04:
case 0xcc0: case 0xcc4:
case 0x0c4:
g_psxWriteOk = 0;
//PSXMEM_LOG("writectrl: writenot ok\n");
break;
case 0x1e988:
case 0x1edd8:
g_psxWriteOk = 1;
//PSXMEM_LOG("writectrl: write ok\n");
break;
default:
PSXMEM_LOG("unk %8.8lx = %x\n", mem, value);
break;
}
}
break;
default:
if( g_psxWriteOk ) {
*(u32 *)PSXM(mem) = value;
psxCpu->Clear(mem&~3, 1);
}
break;
}
}
#else
u8 *psxM = NULL; u8 *psxM = NULL;
u8 *psxP = NULL; u8 *psxP = NULL;
u8 *psxH = NULL; u8 *psxH = NULL; // standard hardware registers (0x000->0x3ff is the scratchpad)
u8 *psxS = NULL; u8 *psxS = NULL; // 'undocumented' SIF communication registers
uptr *psxMemWLUT = NULL; uptr *psxMemWLUT = NULL;
const uptr *psxMemRLUT = NULL; const uptr *psxMemRLUT = NULL;
@ -339,7 +32,7 @@ static const uint m_psxMemSize =
Ps2MemSize::IopRam + Ps2MemSize::IopRam +
Ps2MemSize::IopHardware + Ps2MemSize::IopHardware +
0x00010000 + // psxP 0x00010000 + // psxP
0x00010000 ; // psxS 0x00000100 ; // psxS
void psxMemAlloc() void psxMemAlloc()
{ {
@ -355,8 +48,8 @@ void psxMemAlloc()
psxH = curpos; curpos += Ps2MemSize::IopHardware; psxH = curpos; curpos += Ps2MemSize::IopHardware;
psxS = curpos; //curpos += 0x00010000; psxS = curpos; //curpos += 0x00010000;
psxMemWLUT = (uptr*)_aligned_malloc(0x10000 * sizeof(uptr) * 2, 16); psxMemWLUT = (uptr*)_aligned_malloc(0x2000 * sizeof(uptr) * 2, 16);
psxMemRLUT = psxMemWLUT + 0x10000; //(uptr*)_aligned_malloc(0x10000 * sizeof(uptr),16); psxMemRLUT = psxMemWLUT + 0x2000; //(uptr*)_aligned_malloc(0x10000 * sizeof(uptr),16);
} }
// Note! Resetting the IOP's memory state is dependent on having *all* psx memory allocated, // Note! Resetting the IOP's memory state is dependent on having *all* psx memory allocated,
@ -368,53 +61,53 @@ void psxMemReset()
DbgCon::Status( "psxMemReset > Resetting core memory!" ); DbgCon::Status( "psxMemReset > Resetting core memory!" );
memzero_ptr<0x10000 * sizeof(uptr) * 2>( psxMemWLUT ); // clears both allocations, RLUT and WLUT memzero_ptr<0x2000 * sizeof(uptr) * 2>( psxMemWLUT ); // clears both allocations, RLUT and WLUT
memzero_ptr<m_psxMemSize>( m_psxAllMem ); memzero_ptr<m_psxMemSize>( m_psxAllMem );
// Trick! We're accessing RLUT here through WLUT, since it's the non-const pointer. // Trick! We're accessing RLUT here through WLUT, since it's the non-const pointer.
// So the ones with a 1 prefixed (ala 0x18000, etc) are RLUT tables. // So the ones with a 0x2000 prefixed are RLUT tables.
// Map IOP main memory, which is Read/Write, and mirrored three times // Map IOP main memory, which is Read/Write, and mirrored three times
// at 0x0, 0x8000, and 0xa000: // at 0x0, 0x8000, and 0xa000:
for (int i=0; i<0x0080; i++) for (int i=0; i<0x0080; i++)
{ {
psxMemWLUT[i + 0x0000] = (uptr)&psxM[(i & 0x1f) << 16]; psxMemWLUT[i + 0x0000] = (uptr)&psxM[(i & 0x1f) << 16];
psxMemWLUT[i + 0x8000] = (uptr)&psxM[(i & 0x1f) << 16]; //psxMemWLUT[i + 0x8000] = (uptr)&psxM[(i & 0x1f) << 16];
psxMemWLUT[i + 0xa000] = (uptr)&psxM[(i & 0x1f) << 16]; //psxMemWLUT[i + 0xa000] = (uptr)&psxM[(i & 0x1f) << 16];
// RLUTs, accessed through WLUT. // RLUTs, accessed through WLUT.
psxMemWLUT[i + 0x10000] = (uptr)&psxM[(i & 0x1f) << 16]; psxMemWLUT[i + 0x2000] = (uptr)&psxM[(i & 0x1f) << 16];
psxMemWLUT[i + 0x18000] = (uptr)&psxM[(i & 0x1f) << 16]; //psxMemWLUT[i + 0x18000] = (uptr)&psxM[(i & 0x1f) << 16];
psxMemWLUT[i + 0x1a000] = (uptr)&psxM[(i & 0x1f) << 16]; //psxMemWLUT[i + 0x1a000] = (uptr)&psxM[(i & 0x1f) << 16];
} }
// A few single-page allocations for things we store in special locations. // A few single-page allocations for things we store in special locations.
psxMemWLUT[0x11f00] = (uptr)psxP; psxMemWLUT[0x2000 + 0x1f00] = (uptr)psxP;
psxMemWLUT[0x11f80] = (uptr)psxH; psxMemWLUT[0x2000 + 0x1f80] = (uptr)psxH;
psxMemWLUT[0x1bf80] = (uptr)psxH; //psxMemWLUT[0x1bf80] = (uptr)psxH;
psxMemWLUT[0x1f00] = (uptr)psxP; psxMemWLUT[0x1f00] = (uptr)psxP;
psxMemWLUT[0x1f80] = (uptr)psxH; psxMemWLUT[0x1f80] = (uptr)psxH;
psxMemWLUT[0xbf80] = (uptr)psxH; //psxMemWLUT[0xbf80] = (uptr)psxH;
// Read-only memory areas, so don't map WLUT for these... // Read-only memory areas, so don't map WLUT for these...
for (int i=0; i<0x0040; i++) for (int i=0; i<0x0040; i++)
{ {
psxMemWLUT[i + 0x11fc0] = (uptr)&PS2MEM_ROM[i << 16]; psxMemWLUT[i + 0x2000 + 0x1fc0] = (uptr)&PS2MEM_ROM[i << 16];
psxMemWLUT[i + 0x19fc0] = (uptr)&PS2MEM_ROM[i << 16]; //psxMemWLUT[i + 0x19fc0] = (uptr)&PS2MEM_ROM[i << 16];
psxMemWLUT[i + 0x1bfc0] = (uptr)&PS2MEM_ROM[i << 16]; //psxMemWLUT[i + 0x1bfc0] = (uptr)&PS2MEM_ROM[i << 16];
} }
for (int i=0; i<0x0004; i++) for (int i=0; i<0x0004; i++)
{ {
psxMemWLUT[i + 0x11e00] = (uptr)&PS2MEM_ROM1[i << 16]; psxMemWLUT[i + 0x2000 + 0x1e00] = (uptr)&PS2MEM_ROM1[i << 16];
psxMemWLUT[i + 0x19e00] = (uptr)&PS2MEM_ROM1[i << 16]; //psxMemWLUT[i + 0x19e00] = (uptr)&PS2MEM_ROM1[i << 16];
psxMemWLUT[i + 0x1be00] = (uptr)&PS2MEM_ROM1[i << 16]; //psxMemWLUT[i + 0x1be00] = (uptr)&PS2MEM_ROM1[i << 16];
} }
// Scratchpad! (which is read only? (air)) // sif!! (which is read only? (air))
psxMemWLUT[0x11d00] = (uptr)psxS; psxMemWLUT[0x2000 + 0x1d00] = (uptr)psxS;
psxMemWLUT[0x1bd00] = (uptr)psxS; //psxMemWLUT[0x1bd00] = (uptr)psxS;
// why isn't scratchpad read/write? (air) // why isn't scratchpad read/write? (air)
//for (i=0; i<0x0001; i++) psxMemWLUT[i + 0x1d00] = (uptr)&psxS[i << 16]; //for (i=0; i<0x0001; i++) psxMemWLUT[i + 0x1d00] = (uptr)&psxS[i << 16];
@ -436,48 +129,58 @@ void psxMemShutdown()
psxMemRLUT = NULL; psxMemRLUT = NULL;
} }
u8 iopMemRead8(u32 mem) { u8 iopMemRead8(u32 mem)
const u8* p; {
u32 t; mem &= 0x1fffffff;
u32 t = mem >> 16;
t = (mem >> 16) & 0x1fff; if (t == 0x1f80)
if (t == 0x1f80) { {
mem&= 0x1fffffff;
if (mem < 0x1f801000) if (mem < 0x1f801000)
return psxHu8(mem); return psxHu8(mem);
else else
return psxHwRead8(mem); return psxHwRead8(mem);
} else }
if (t == 0x1f40) { else if (t == 0x1f40)
mem&= 0x1fffffff; {
return psxHw4Read8(mem); return psxHw4Read8(mem);
} else { }
p = (const u8*)(psxMemRLUT[mem >> 16]); else
if (p != NULL) { {
const u8* p = (const u8*)(psxMemRLUT[mem >> 16]);
if (p != NULL)
{
return *(const u8 *)(p + (mem & 0xffff)); return *(const u8 *)(p + (mem & 0xffff));
} else { }
if (t == 0x1000) return DEV9read8(mem & 0x1FFFFFFF); else
{
if (t == 0x1000)
return DEV9read8(mem);
PSXMEM_LOG("err lb %8.8lx\n", mem); PSXMEM_LOG("err lb %8.8lx\n", mem);
return 0; return 0;
} }
} }
} }
u16 iopMemRead16(u32 mem) { u16 iopMemRead16(u32 mem)
const u8* p; {
u32 t; mem &= 0x1fffffff;
u32 t = mem >> 16;
t = (mem >> 16) & 0x1fff; if (t == 0x1f80)
if (t == 0x1f80) { {
mem&= 0x1fffffff;
if (mem < 0x1f801000) if (mem < 0x1f801000)
return psxHu16(mem); return psxHu16(mem);
else else
return psxHwRead16(mem); return psxHwRead16(mem);
} else { }
p = (const u8*)(psxMemRLUT[mem >> 16]); else
if (p != NULL) { {
if (t == 0x1d00) { const u8* p = (const u8*)(psxMemRLUT[mem >> 16]);
if (p != NULL)
{
if (t == 0x1d00)
{
u16 ret; u16 ret;
switch(mem & 0xF0) switch(mem & 0xF0)
{ {
@ -501,31 +204,38 @@ u16 iopMemRead16(u32 mem) {
return ret; return ret;
} }
return *(const u16 *)(p + (mem & 0xffff)); return *(const u16 *)(p + (mem & 0xffff));
} else { }
else
{
if (t == 0x1F90) if (t == 0x1F90)
return SPU2read(mem & 0x1FFFFFFF); return SPU2read(mem);
if (t == 0x1000) return DEV9read16(mem & 0x1FFFFFFF); if (t == 0x1000)
return DEV9read16(mem);
PSXMEM_LOG("err lh %8.8lx\n", mem); PSXMEM_LOG("err lh %8.8lx\n", mem);
return 0; return 0;
} }
} }
} }
u32 iopMemRead32(u32 mem) { u32 iopMemRead32(u32 mem)
const u8* p; {
u32 t; mem &= 0x1fffffff;
t = (mem >> 16) & 0x1fff; u32 t = mem >> 16;
if (t == 0x1f80) {
mem&= 0x1fffffff; if (t == 0x1f80)
{
if (mem < 0x1f801000) if (mem < 0x1f801000)
return psxHu32(mem); return psxHu32(mem);
else else
return psxHwRead32(mem); return psxHwRead32(mem);
} else { } else
{
//see also Hw.c //see also Hw.c
p = (const u8*)(psxMemRLUT[mem >> 16]); const u8* p = (const u8*)(psxMemRLUT[mem >> 16]);
if (p != NULL) { if (p != NULL)
if (t == 0x1d00) { {
if (t == 0x1d00)
{
u32 ret; u32 ret;
switch(mem & 0xF0) switch(mem & 0xF0)
{ {
@ -555,215 +265,191 @@ u32 iopMemRead32(u32 mem) {
return ret; return ret;
} }
return *(const u32 *)(p + (mem & 0xffff)); return *(const u32 *)(p + (mem & 0xffff));
} else { }
if (t == 0x1000) return DEV9read32(mem & 0x1FFFFFFF); else
{
if (mem != 0xfffe0130) { if (t == 0x1000)
if (g_psxWriteOk) PSXMEM_LOG("err lw %8.8lx\n", mem); return DEV9read32(mem);
} else {
return writectrl;
}
return 0; return 0;
} }
} }
} }
void iopMemWrite8(u32 mem, u8 value) { void iopMemWrite8(u32 mem, u8 value)
char *p; {
u32 t; mem &= 0x1fffffff;
u32 t = mem >> 16;
t = (mem >> 16) & 0x1fff;
if (t == 0x1f80) { if (t == 0x1f80)
mem&= 0x1fffffff; {
if (mem < 0x1f801000) if (mem < 0x1f801000)
psxHu8(mem) = value; psxHu8(mem) = value;
else else
psxHwWrite8(mem, value); psxHwWrite8(mem, value);
} else }
if (t == 0x1f40) { else if (t == 0x1f40)
mem&= 0x1fffffff; {
psxHw4Write8(mem, value); psxHw4Write8(mem, value);
} else { }
p = (char *)(psxMemWLUT[mem >> 16]); else
if (p != NULL) { {
u8* p = (u8 *)(psxMemWLUT[mem >> 16]);
if (p != NULL && !(psxRegs.CP0.n.Status & 0x10000) )
{
*(u8 *)(p + (mem & 0xffff)) = value; *(u8 *)(p + (mem & 0xffff)) = value;
psxCpu->Clear(mem&~3, 1); psxCpu->Clear(mem&~3, 1);
} else { }
if ((t & 0x1FFF)==0x1D00) SysPrintf("sw8 [0x%08X]=0x%08X\n", mem, value); else
{
if (t == 0x1D00) SysPrintf("sw8 [0x%08X]=0x%08X\n", mem, value);
if (t == 0x1d00) { if (t == 0x1d00) {
psxSu8(mem) = value; return; psxSu8(mem) = value; return;
} }
if (t == 0x1000) { if (t == 0x1000) {
DEV9write8(mem & 0x1fffffff, value); return; DEV9write8(mem, value); return;
} }
PSXMEM_LOG("err sb %8.8lx = %x\n", mem, value); PSXMEM_LOG("err sb %8.8lx = %x\n", mem, value);
} }
} }
} }
void iopMemWrite16(u32 mem, u16 value) { void iopMemWrite16(u32 mem, u16 value)
char *p; {
u32 t; mem &= 0x1fffffff;
u32 t = mem >> 16;
t = (mem >> 16) & 0x1fff; if (t == 0x1f80)
if (t == 0x1f80) { {
mem&= 0x1fffffff;
if (mem < 0x1f801000) if (mem < 0x1f801000)
psxHu16(mem) = value; psxHu16(mem) = value;
else else
psxHwWrite16(mem, value); psxHwWrite16(mem, value);
} else { } else
p = (char *)(psxMemWLUT[mem >> 16]); {
if (p != NULL) { u8* p = (u8 *)(psxMemWLUT[mem >> 16]);
if ((t & 0x1FFF)==0x1D00) SysPrintf("sw16 [0x%08X]=0x%08X\n", mem, value); if (p != NULL && !(psxRegs.CP0.n.Status & 0x10000) )
{
if( t==0x1D00 ) SysPrintf("sw16 [0x%08X]=0x%08X\n", mem, value);
*(u16 *)(p + (mem & 0xffff)) = value; *(u16 *)(p + (mem & 0xffff)) = value;
psxCpu->Clear(mem&~3, 1); psxCpu->Clear(mem&~3, 1);
} else { }
if (t == 0x1d00) { else
switch (mem & 0xf0) { {
case 0x10: if (t == 0x1d00)
// write to ps2 mem {
psHu16(0x1000F210) = value; switch (mem & 0xf0)
return; {
case 0x40: case 0x10:
// write to ps2 mem
psHu16(0x1000F210) = value;
return;
case 0x40:
{
u32 temp = value & 0xF0;
// write to ps2 mem
if(value & 0x20 || value & 0x80)
{ {
u32 temp = value & 0xF0; psHu16(0x1000F240) &= ~0xF000;
// write to ps2 mem psHu16(0x1000F240) |= 0x2000;
if(value & 0x20 || value & 0x80)
{
psHu16(0x1000F240) &= ~0xF000;
psHu16(0x1000F240) |= 0x2000;
}
if(psHu16(0x1000F240) & temp) psHu16(0x1000F240) &= ~temp;
else psHu16(0x1000F240) |= temp;
return;
} }
case 0x60:
psHu32(0x1000F260) = 0;
return;
if(psHu16(0x1000F240) & temp) psHu16(0x1000F240) &= ~temp;
else psHu16(0x1000F240) |= temp;
return;
} }
case 0x60:
psHu32(0x1000F260) = 0;
return;
}
psxSu16(mem) = value; return; psxSu16(mem) = value; return;
} }
if (t == 0x1F90) { if (t == 0x1F90) {
SPU2write(mem & 0x1FFFFFFF, value); return; SPU2write(mem, value); return;
} }
if (t == 0x1000) { if (t == 0x1000) {
DEV9write16(mem & 0x1fffffff, value); return; DEV9write16(mem, value); return;
} }
PSXMEM_LOG("err sh %8.8lx = %x\n", mem, value); PSXMEM_LOG("err sh %8.8lx = %x\n", mem, value);
} }
} }
} }
void iopMemWrite32(u32 mem, u32 value) { void iopMemWrite32(u32 mem, u32 value)
char *p; {
u32 t; mem &= 0x1fffffff;
u32 t = mem >> 16;
t = (mem >> 16) & 0x1fff; if (t == 0x1f80)
if (t == 0x1f80) { {
mem&= 0x1fffffff;
if (mem < 0x1f801000) if (mem < 0x1f801000)
psxHu32(mem) = value; psxHu32(mem) = value;
else else
psxHwWrite32(mem, value); psxHwWrite32(mem, value);
} else { } else
{
//see also Hw.c //see also Hw.c
p = (char *)(psxMemWLUT[mem >> 16]); u8* p = (u8 *)(psxMemWLUT[mem >> 16]);
if (p != NULL) { if( p != NULL && !(psxRegs.CP0.n.Status & 0x10000) )
{
*(u32 *)(p + (mem & 0xffff)) = value; *(u32 *)(p + (mem & 0xffff)) = value;
psxCpu->Clear(mem&~3, 1); psxCpu->Clear(mem&~3, 1);
} else { }
if (mem != 0xfffe0130) { else
if (t == 0x1d00) { {
if (t == 0x1d00)
{
MEM_LOG("iop Sif reg write %x value %x\n", mem, value); MEM_LOG("iop Sif reg write %x value %x\n", mem, value);
switch (mem & 0xf0) { switch (mem & 0xf0)
case 0x10: {
// write to ps2 mem case 0x00: // EE write path (EE/IOP readable)
psHu32(0x1000F210) = value; return; // this is the IOP, so read-only (do nothing)
return;
case 0x20: case 0x10: // IOP write path (EE/IOP readable)
// write to ps2 mem psHu32(0x1000F210) = value;
psHu32(0x1000F220) &= ~value; return;
return;
case 0x30: case 0x20: // Bits cleared when written from IOP.
// write to ps2 mem psHu32(0x1000F220) &= ~value;
psHu32(0x1000F230) |= value; return;
return;
case 0x40: case 0x30: // bits set when written from IOP
psHu32(0x1000F230) |= value;
return;
case 0x40: // Control Register
{
u32 temp = value & 0xF0;
if(value & 0x20 || value & 0x80)
{ {
u32 temp = value & 0xF0; psHu32(0x1000F240) &= ~0xF000;
// write to ps2 mem psHu32(0x1000F240) |= 0x2000;
if(value & 0x20 || value & 0x80)
{
psHu32(0x1000F240) &= ~0xF000;
psHu32(0x1000F240) |= 0x2000;
}
if(psHu32(0x1000F240) & temp) psHu32(0x1000F240) &= ~temp;
else psHu32(0x1000F240) |= temp;
return;
} }
case 0x60:
psHu32(0x1000F260) = 0;
return;
if(psHu32(0x1000F240) & temp)
psHu32(0x1000F240) &= ~temp;
else
psHu32(0x1000F240) |= temp;
return;
} }
psxSu32(mem) = value;
// write to ps2 mem case 0x60:
if( (mem & 0xf0) != 0x60 ) psHu32(0x1000F260) = 0;
*(u32*)(PS2MEM_HW+0xf200+(mem&0xf0)) = value; return;
return;
}
if (t == 0x1000) {
DEV9write32(mem & 0x1fffffff, value); return;
} }
psxSu32(mem) = value;
//if (!g_psxWriteOk) psxCpu->Clear(mem&~3, 1); // wtf? why were we writing to the EE's sif space? Commenting this out doesn't
if (g_psxWriteOk) { PSXMEM_LOG("err sw %8.8lx = %x\n", mem, value); } // break any of my games, and should be more correct, but I guess we'll see. --air
} else { //*(u32*)(PS2MEM_HW+0xf200+(mem&0xf0)) = value;
writectrl = value; return;
switch (value) { }
case 0x800: case 0x804: else if (t == 0x1000)
case 0xc00: case 0xc04: {
case 0xcc0: case 0xcc4: DEV9write32(mem, value); return;
case 0x0c4:
if (g_psxWriteOk == 0) break;
g_psxWriteOk = 0;
// Performance note: Use a for loop instead of memset/memzero
// This generates *much* more efficient code in this particular case (due to few iterations)
for (int i=0; i<0x0080; i++)
{
psxMemWLUT[i + 0x0000] = 0;
psxMemWLUT[i + 0x8000] = 0;
psxMemWLUT[i + 0xa000] = 0;
}
//PSXMEM_LOG("writectrl: writenot ok\n");
break;
case 0x1e988:
case 0x1edd8:
if (g_psxWriteOk == 1) break;
g_psxWriteOk = 1;
for (int i=0; i<0x0080; i++)
{
psxMemWLUT[i + 0x0000] = (uptr)&psxM[(i & 0x1f) << 16];
psxMemWLUT[i + 0x8000] = (uptr)&psxM[(i & 0x1f) << 16];
psxMemWLUT[i + 0xa000] = (uptr)&psxM[(i & 0x1f) << 16];
}
//PSXMEM_LOG("writectrl: write ok\n");
break;
default:
PSXMEM_LOG("unk %8.8lx = %x\n", mem, value);
break;
}
} }
} }
} }
} }
#endif

View File

@ -46,7 +46,8 @@ static __forceinline T* iopVirtMemW( u32 mem )
template<typename T> template<typename T>
static __forceinline const T* iopVirtMemR( u32 mem ) static __forceinline const T* iopVirtMemR( u32 mem )
{ {
return (psxMemRLUT[(mem) >> 16] == 0) ? NULL : (const T*)(psxMemRLUT[(mem) >> 16] + ((mem) & 0xffff)); mem &= 0x1fffffff;
return (psxMemRLUT[mem >> 16] == 0) ? NULL : (const T*)(psxMemRLUT[mem >> 16] + (mem & 0xffff));
} }
// Obtains a pointer to the IOP's physical mapping (bypasses the TLB) // Obtains a pointer to the IOP's physical mapping (bypasses the TLB)
@ -56,11 +57,11 @@ static __forceinline u8* iopPhysMem( u32 addr )
} }
#define psxSs8(mem) psxS[(mem) & 0xffff] #define psxSs8(mem) psxS[(mem) & 0xffff]
#define psxSs16(mem) (*(s16*)&psxS[(mem) & 0xffff]) #define psxSs16(mem) (*(s16*)&psxS[(mem) & 0x00ff])
#define psxSs32(mem) (*(s32*)&psxS[(mem) & 0xffff]) #define psxSs32(mem) (*(s32*)&psxS[(mem) & 0x00ff])
#define psxSu8(mem) (*(u8*) &psxS[(mem) & 0xffff]) #define psxSu8(mem) (*(u8*) &psxS[(mem) & 0x00ff])
#define psxSu16(mem) (*(u16*)&psxS[(mem) & 0xffff]) #define psxSu16(mem) (*(u16*)&psxS[(mem) & 0x00ff])
#define psxSu32(mem) (*(u32*)&psxS[(mem) & 0xffff]) #define psxSu32(mem) (*(u32*)&psxS[(mem) & 0x00ff])
#define psxPs8(mem) psxP[(mem) & 0xffff] #define psxPs8(mem) psxP[(mem) & 0xffff]
#define psxPs16(mem) (*(s16*)&psxP[(mem) & 0xffff]) #define psxPs16(mem) (*(s16*)&psxP[(mem) & 0xffff])

View File

@ -203,6 +203,7 @@ u8 sio2_fifoOut(){
void SaveState::sio2Freeze() void SaveState::sio2Freeze()
{ {
FreezeTag( "sio2" );
Freeze(sio2); Freeze(sio2);
} }

View File

@ -24,9 +24,9 @@ GtkWidget *GameFixDlg, *SpeedHacksDlg;
{ {
GameFixDlg = create_GameFixDlg(); GameFixDlg = create_GameFixDlg();
set_checked(GameFixDlg, "check_FPU_Compare", (Config.GameFixes & FLAG_FPU_Compare));
set_checked(GameFixDlg, "check_VU_Add_Sub", (Config.GameFixes & FLAG_VU_ADD_SUB)); set_checked(GameFixDlg, "check_VU_Add_Sub", (Config.GameFixes & FLAG_VU_ADD_SUB));
set_checked(GameFixDlg, "check_VU_Clip", (Config.GameFixes & FLAG_VU_CLIP)); set_checked(GameFixDlg, "check_FPU_Mul", (Config.GameFixes & FLAG_FPU_MUL));
set_checked(GameFixDlg, "check_FPU_Clamp", (Config.GameFixes & FLAG_FPU_CLAMP));
gtk_widget_show_all(GameFixDlg); gtk_widget_show_all(GameFixDlg);
gtk_widget_set_sensitive(MainWindow, FALSE); gtk_widget_set_sensitive(MainWindow, FALSE);
@ -37,9 +37,9 @@ void on_Game_Fix_OK(GtkButton *button, gpointer user_data)
{ {
Config.GameFixes = 0; Config.GameFixes = 0;
Config.GameFixes |= is_checked(GameFixDlg, "check_FPU_Compare") ? FLAG_FPU_Compare : 0;
Config.GameFixes |= is_checked(GameFixDlg, "check_VU_Add_Sub") ? FLAG_VU_ADD_SUB : 0; Config.GameFixes |= is_checked(GameFixDlg, "check_VU_Add_Sub") ? FLAG_VU_ADD_SUB : 0;
Config.GameFixes |= is_checked(GameFixDlg, "check_VU_Clip") ? FLAG_VU_CLIP : 0; Config.GameFixes |= is_checked(GameFixDlg, "check_FPU_Mul") ? FLAG_FPU_MUL : 0;
Config.GameFixes |= is_checked(GameFixDlg, "check_FPU_Clamp") ? FLAG_FPU_CLAMP : 0;
SaveConfig(); SaveConfig();
gtk_widget_destroy(GameFixDlg); gtk_widget_destroy(GameFixDlg);

View File

@ -100,12 +100,12 @@ char iop_log_names[9][32] =
"Cdr Log", "Cdr Log",
"GPU Log" "GPU Log"
}; };
//Tri-Ace - IDC_GAMEFIX2
#define FLAG_VU_ADD_SUB 0x1 #define FLAG_VU_ADD_SUB 0x1
#define FLAG_VU_CLIP 0x2 // Digimon Rumble Arena - IDC_GAMEFIX3
#define FLAG_FPU_CLAMP 0x4 #define FLAG_FPU_Compare 0x4
#define FLAG_VU_FCOR_HACK 0x8 //Tales of Destiny - IDC_GAMEFIX5
#define FLAG_AVOID_DELAY_HANDLING 0x10 #define FLAG_FPU_MUL 0x8
#define FLAG_VU_NO_OVERFLOW 0x2 #define FLAG_VU_NO_OVERFLOW 0x2
#define FLAG_VU_EXTRA_OVERFLOW 0x40 #define FLAG_VU_EXTRA_OVERFLOW 0x40

View File

@ -16,7 +16,6 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/ */
#include "Threading.h"
#include "Linux.h" #include "Linux.h"
#include "../x86/ix86/ix86.h" #include "../x86/ix86/ix86.h"

View File

@ -109,30 +109,6 @@ void
OnDebug_memWrite32 (GtkButton *button, OnDebug_memWrite32 (GtkButton *button,
gpointer user_data); gpointer user_data);
void
OnConfConf_Pad2Conf (GtkButton *button,
gpointer user_data);
void
OnConfConf_Pad2Test (GtkButton *button,
gpointer user_data);
void
OnConfConf_Pad2About (GtkButton *button,
gpointer user_data);
void
OnConfConf_Pad1Conf (GtkButton *button,
gpointer user_data);
void
OnConfConf_Pad1Test (GtkButton *button,
gpointer user_data);
void
OnConfConf_Pad1About (GtkButton *button,
gpointer user_data);
void void
OnConfButton (GtkButton *button, OnConfButton (GtkButton *button,
gpointer user_data); gpointer user_data);

View File

@ -888,9 +888,9 @@ create_GameFixDlg (void)
GtkWidget *GameSettings; GtkWidget *GameSettings;
GtkWidget *alignment5; GtkWidget *alignment5;
GtkWidget *vbox30; GtkWidget *vbox30;
GtkWidget *check_FPU_Clamp; GtkWidget *check_FPU_Compare;
GtkWidget *check_VU_Add_Sub; GtkWidget *check_VU_Add_Sub;
GtkWidget *check_VU_Clip; GtkWidget *check_FPU_Mul;
GtkWidget *label42; GtkWidget *label42;
GtkWidget *dialog_action_area1; GtkWidget *dialog_action_area1;
GtkWidget *cancelbutton1; GtkWidget *cancelbutton1;
@ -922,20 +922,20 @@ create_GameFixDlg (void)
gtk_widget_show (vbox30); gtk_widget_show (vbox30);
gtk_container_add (GTK_CONTAINER (alignment5), vbox30); gtk_container_add (GTK_CONTAINER (alignment5), vbox30);
check_FPU_Clamp = gtk_check_button_new_with_mnemonic (_("FPU Clamp Hack - Special fix for Tekken 5 and maybe other games.")); check_FPU_Compare = gtk_check_button_new_with_mnemonic (_("FPU Compare Hack - Special fix for Digimon Rumble Arena 2."));
gtk_widget_set_name (check_FPU_Clamp, "check_FPU_Clamp"); gtk_widget_set_name (check_FPU_Compare, "check_FPU_Compare");
gtk_widget_show (check_FPU_Clamp); gtk_widget_show (check_FPU_Compare);
gtk_box_pack_start (GTK_BOX (vbox30), check_FPU_Clamp, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (vbox30), check_FPU_Compare, FALSE, FALSE, 0);
check_VU_Add_Sub = gtk_check_button_new_with_mnemonic (_("VU Add / Sub Hack - Special fix for Tri-Ace games!")); check_VU_Add_Sub = gtk_check_button_new_with_mnemonic (_("VU Add / Sub Hack - Special fix for Tri-Ace games!"));
gtk_widget_set_name (check_VU_Add_Sub, "check_VU_Add_Sub"); gtk_widget_set_name (check_VU_Add_Sub, "check_VU_Add_Sub");
gtk_widget_show (check_VU_Add_Sub); gtk_widget_show (check_VU_Add_Sub);
gtk_box_pack_start (GTK_BOX (vbox30), check_VU_Add_Sub, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (vbox30), check_VU_Add_Sub, FALSE, FALSE, 0);
check_VU_Clip = gtk_check_button_new_with_mnemonic (_("VU Clip Hack - Special fix for God of War")); check_FPU_Mul = gtk_check_button_new_with_mnemonic (_("FPU Mul Hack - Special fix for Tales of Destiny (possibly other games)."));
gtk_widget_set_name (check_VU_Clip, "check_VU_Clip"); gtk_widget_set_name (check_FPU_Mul, "check_FPU_Mul");
gtk_widget_show (check_VU_Clip); gtk_widget_show (check_FPU_Mul);
gtk_box_pack_start (GTK_BOX (vbox30), check_VU_Clip, FALSE, TRUE, 0); gtk_box_pack_start (GTK_BOX (vbox30), check_FPU_Mul, FALSE, TRUE, 0);
label42 = gtk_label_new (_("<b>Some games need special settings.\nConfigure them here.</b>")); label42 = gtk_label_new (_("<b>Some games need special settings.\nConfigure them here.</b>"));
gtk_widget_set_name (label42, "label42"); gtk_widget_set_name (label42, "label42");
@ -973,9 +973,9 @@ create_GameFixDlg (void)
GLADE_HOOKUP_OBJECT (GameFixDlg, GameSettings, "GameSettings"); GLADE_HOOKUP_OBJECT (GameFixDlg, GameSettings, "GameSettings");
GLADE_HOOKUP_OBJECT (GameFixDlg, alignment5, "alignment5"); GLADE_HOOKUP_OBJECT (GameFixDlg, alignment5, "alignment5");
GLADE_HOOKUP_OBJECT (GameFixDlg, vbox30, "vbox30"); GLADE_HOOKUP_OBJECT (GameFixDlg, vbox30, "vbox30");
GLADE_HOOKUP_OBJECT (GameFixDlg, check_FPU_Clamp, "check_FPU_Clamp"); GLADE_HOOKUP_OBJECT (GameFixDlg, check_FPU_Compare, "check_FPU_Compare");
GLADE_HOOKUP_OBJECT (GameFixDlg, check_VU_Add_Sub, "check_VU_Add_Sub"); GLADE_HOOKUP_OBJECT (GameFixDlg, check_VU_Add_Sub, "check_VU_Add_Sub");
GLADE_HOOKUP_OBJECT (GameFixDlg, check_VU_Clip, "check_VU_Clip"); GLADE_HOOKUP_OBJECT (GameFixDlg, check_FPU_Mul, "check_FPU_Mul");
GLADE_HOOKUP_OBJECT (GameFixDlg, label42, "label42"); GLADE_HOOKUP_OBJECT (GameFixDlg, label42, "label42");
GLADE_HOOKUP_OBJECT_NO_REF (GameFixDlg, dialog_action_area1, "dialog_action_area1"); GLADE_HOOKUP_OBJECT_NO_REF (GameFixDlg, dialog_action_area1, "dialog_action_area1");
GLADE_HOOKUP_OBJECT (GameFixDlg, cancelbutton1, "cancelbutton1"); GLADE_HOOKUP_OBJECT (GameFixDlg, cancelbutton1, "cancelbutton1");
@ -3425,8 +3425,11 @@ create_PatchFinderWindow (void)
GtkWidget *radiobutton6; GtkWidget *radiobutton6;
GSList *radiobutton6_group = NULL; GSList *radiobutton6_group = NULL;
GtkWidget *radiobutton5; GtkWidget *radiobutton5;
GSList *radiobutton5_group = NULL;
GtkWidget *radiobutton4; GtkWidget *radiobutton4;
GSList *radiobutton4_group = NULL;
GtkWidget *radiobutton3; GtkWidget *radiobutton3;
GSList *radiobutton3_group = NULL;
GtkWidget *label56; GtkWidget *label56;
GtkWidget *frame21; GtkWidget *frame21;
GtkWidget *alignment16; GtkWidget *alignment16;
@ -3553,8 +3556,8 @@ create_PatchFinderWindow (void)
gtk_table_attach (GTK_TABLE (table6), radiobutton5, 0, 1, 1, 2, gtk_table_attach (GTK_TABLE (table6), radiobutton5, 0, 1, 1, 2,
(GtkAttachOptions) (0), (GtkAttachOptions) (0),
(GtkAttachOptions) (0), 0, 0); (GtkAttachOptions) (0), 0, 0);
gtk_radio_button_set_group (GTK_RADIO_BUTTON (radiobutton5), radiobutton6_group); gtk_radio_button_set_group (GTK_RADIO_BUTTON (radiobutton5), radiobutton5_group);
radiobutton6_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radiobutton5)); radiobutton5_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radiobutton5));
radiobutton4 = gtk_radio_button_new_with_mnemonic (NULL, _("16 bits")); radiobutton4 = gtk_radio_button_new_with_mnemonic (NULL, _("16 bits"));
gtk_widget_set_name (radiobutton4, "radiobutton4"); gtk_widget_set_name (radiobutton4, "radiobutton4");
@ -3562,8 +3565,8 @@ create_PatchFinderWindow (void)
gtk_table_attach (GTK_TABLE (table6), radiobutton4, 1, 2, 0, 1, gtk_table_attach (GTK_TABLE (table6), radiobutton4, 1, 2, 0, 1,
(GtkAttachOptions) (0), (GtkAttachOptions) (0),
(GtkAttachOptions) (0), 0, 0); (GtkAttachOptions) (0), 0, 0);
gtk_radio_button_set_group (GTK_RADIO_BUTTON (radiobutton4), radiobutton6_group); gtk_radio_button_set_group (GTK_RADIO_BUTTON (radiobutton4), radiobutton4_group);
radiobutton6_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radiobutton4)); radiobutton4_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radiobutton4));
radiobutton3 = gtk_radio_button_new_with_mnemonic (NULL, _("8 bits")); radiobutton3 = gtk_radio_button_new_with_mnemonic (NULL, _("8 bits"));
gtk_widget_set_name (radiobutton3, "radiobutton3"); gtk_widget_set_name (radiobutton3, "radiobutton3");
@ -3571,8 +3574,8 @@ create_PatchFinderWindow (void)
gtk_table_attach (GTK_TABLE (table6), radiobutton3, 0, 1, 0, 1, gtk_table_attach (GTK_TABLE (table6), radiobutton3, 0, 1, 0, 1,
(GtkAttachOptions) (0), (GtkAttachOptions) (0),
(GtkAttachOptions) (0), 0, 0); (GtkAttachOptions) (0), 0, 0);
gtk_radio_button_set_group (GTK_RADIO_BUTTON (radiobutton3), radiobutton6_group); gtk_radio_button_set_group (GTK_RADIO_BUTTON (radiobutton3), radiobutton3_group);
radiobutton6_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radiobutton3)); radiobutton3_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radiobutton3));
label56 = gtk_label_new (_("<b>Values of Size</b>")); label56 = gtk_label_new (_("<b>Values of Size</b>"));
gtk_widget_set_name (label56, "label56"); gtk_widget_set_name (label56, "label56");

View File

@ -109,14 +109,14 @@ static __forceinline void memset_8( void *dest )
( (
".intel_syntax noprefix\n" ".intel_syntax noprefix\n"
"cld\n" "cld\n"
// "mov edi, %0\n" // "mov edi, %[dest]\n"
// "mov eax, %1\n" // "mov eax, %[data32]\n"
"stosd\n" "stosd\n"
"stosd\n" "stosd\n"
"stosd\n" "stosd\n"
".att_syntax\n" ".att_syntax\n"
: :
: "D"(dest), "a"(data32) : [dest]"D"(dest), [data32]"a"(data32)
// D - edi, a -- eax, c ecx // D - edi, a -- eax, c ecx
: :
); );
@ -127,15 +127,15 @@ static __forceinline void memset_8( void *dest )
( (
".intel_syntax noprefix\n" ".intel_syntax noprefix\n"
"cld\n" "cld\n"
// "mov edi, %0\n" // "mov edi, %[dest]\n"
// "mov eax, %1\n" // "mov eax, %[data32]\n"
"stosd\n" "stosd\n"
"stosd\n" "stosd\n"
"stosd\n" "stosd\n"
"stosd\n" "stosd\n"
".att_syntax\n" ".att_syntax\n"
: :
: "D"(dest), "a"(data32) : [dest]"D"(dest), [data32]"a"(data32)
: :
); );
@ -146,8 +146,8 @@ static __forceinline void memset_8( void *dest )
( (
".intel_syntax noprefix\n" ".intel_syntax noprefix\n"
"cld\n" "cld\n"
// "mov edi, %0\n" // "mov edi, %[dest]\n"
// "mov eax, %1\n" // "mov eax, %[data32]\n"
"stosd\n" "stosd\n"
"stosd\n" "stosd\n"
"stosd\n" "stosd\n"
@ -155,7 +155,7 @@ static __forceinline void memset_8( void *dest )
"stosd\n" "stosd\n"
".att_syntax\n" ".att_syntax\n"
: :
: "D"(dest), "a"(data32) : [dest]"D"(dest), [data32]"a"(data32)
: :
); );
@ -166,13 +166,13 @@ static __forceinline void memset_8( void *dest )
( (
".intel_syntax noprefix\n" ".intel_syntax noprefix\n"
"cld\n" "cld\n"
// "mov ecx, %0\n" // "mov ecx, %[remdat]\n"
// "mov edi, %1\n" // "mov edi, %[dest]\n"
// "mov eax, %2\n" // "mov eax, %\[data32]n"
"rep stosd\n" "rep stosd\n"
".att_syntax\n" ".att_syntax\n"
: :
: "c"(remdat), "D"(dest), "a"(data32) : [remdat]"c"(remdat), [dest]"D"(dest), [data32]"a"(data32)
: :
); );
return; return;

View File

@ -1868,10 +1868,10 @@ Known to work well with a couple games, namely Shadow of the Colossus (but break
<property name="spacing">0</property> <property name="spacing">0</property>
<child> <child>
<widget class="GtkCheckButton" id="check_FPU_Clamp"> <widget class="GtkCheckButton" id="check_FPU_Compare">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="can_focus">True</property>
<property name="label" translatable="yes">FPU Clamp Hack - Special fix for Tekken 5 and maybe other games.</property> <property name="label" translatable="yes">FPU Compare Hack - Special fix for Digimon Rumble Arena 2.</property>
<property name="use_underline">True</property> <property name="use_underline">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property> <property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property> <property name="focus_on_click">True</property>
@ -1906,10 +1906,10 @@ Known to work well with a couple games, namely Shadow of the Colossus (but break
</child> </child>
<child> <child>
<widget class="GtkCheckButton" id="check_VU_Clip"> <widget class="GtkCheckButton" id="check_FPU_Mul">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="can_focus">True</property>
<property name="label" translatable="yes">VU Clip Hack - Special fix for God of War</property> <property name="label" translatable="yes">FPU Mul Hack - Special fix for Tales of Destiny (possibly other games).</property>
<property name="use_underline">True</property> <property name="use_underline">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property> <property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property> <property name="focus_on_click">True</property>
@ -5063,7 +5063,7 @@ Version x.x</property>
<property name="visible">True</property> <property name="visible">True</property>
<property name="label" translatable="yes">_Graphics</property> <property name="label" translatable="yes">_Graphics</property>
<property name="use_underline">True</property> <property name="use_underline">True</property>
<signal name="activate" handler="OnConf_Menu" last_modification_time="Fri, 06 Mar 2009 06:06:06 GMT"/> <signal name="activate" handler="OnConf_Menu"/>
</widget> </widget>
</child> </child>
@ -5072,7 +5072,7 @@ Version x.x</property>
<property name="visible">True</property> <property name="visible">True</property>
<property name="label" translatable="yes">C_ontrollers</property> <property name="label" translatable="yes">C_ontrollers</property>
<property name="use_underline">True</property> <property name="use_underline">True</property>
<signal name="activate" handler="OnConf_Menu" last_modification_time="Fri, 06 Mar 2009 06:06:06 GMT"/> <signal name="activate" handler="OnConf_Menu"/>
</widget> </widget>
</child> </child>
@ -5081,7 +5081,7 @@ Version x.x</property>
<property name="visible">True</property> <property name="visible">True</property>
<property name="label" translatable="yes">_Sound</property> <property name="label" translatable="yes">_Sound</property>
<property name="use_underline">True</property> <property name="use_underline">True</property>
<signal name="activate" handler="OnConf_Menu" last_modification_time="Fri, 06 Mar 2009 06:06:06 GMT"/> <signal name="activate" handler="OnConf_Menu"/>
</widget> </widget>
</child> </child>
@ -5090,7 +5090,7 @@ Version x.x</property>
<property name="visible">True</property> <property name="visible">True</property>
<property name="label" translatable="yes">_Cdvdrom</property> <property name="label" translatable="yes">_Cdvdrom</property>
<property name="use_underline">True</property> <property name="use_underline">True</property>
<signal name="activate" handler="OnConf_Menu" last_modification_time="Fri, 06 Mar 2009 06:06:06 GMT"/> <signal name="activate" handler="OnConf_Menu"/>
</widget> </widget>
</child> </child>
@ -5099,7 +5099,7 @@ Version x.x</property>
<property name="visible">True</property> <property name="visible">True</property>
<property name="label" translatable="yes">D_ev9</property> <property name="label" translatable="yes">D_ev9</property>
<property name="use_underline">True</property> <property name="use_underline">True</property>
<signal name="activate" handler="OnConf_Menu" last_modification_time="Fri, 06 Mar 2009 06:06:06 GMT"/> <signal name="activate" handler="OnConf_Menu"/>
</widget> </widget>
</child> </child>
@ -5108,7 +5108,7 @@ Version x.x</property>
<property name="visible">True</property> <property name="visible">True</property>
<property name="label" translatable="yes">U_SB</property> <property name="label" translatable="yes">U_SB</property>
<property name="use_underline">True</property> <property name="use_underline">True</property>
<signal name="activate" handler="OnConf_Menu" last_modification_time="Fri, 06 Mar 2009 06:06:06 GMT"/> <signal name="activate" handler="OnConf_Menu"/>
</widget> </widget>
</child> </child>
@ -5117,7 +5117,7 @@ Version x.x</property>
<property name="visible">True</property> <property name="visible">True</property>
<property name="label" translatable="yes">Fire_Wire</property> <property name="label" translatable="yes">Fire_Wire</property>
<property name="use_underline">True</property> <property name="use_underline">True</property>
<signal name="activate" handler="OnConf_Menu" last_modification_time="Fri, 06 Mar 2009 06:06:06 GMT"/> <signal name="activate" handler="OnConf_Menu"/>
</widget> </widget>
</child> </child>
@ -5774,7 +5774,6 @@ Version x.x</property>
<property name="active">False</property> <property name="active">False</property>
<property name="inconsistent">False</property> <property name="inconsistent">False</property>
<property name="draw_indicator">True</property> <property name="draw_indicator">True</property>
<property name="group">radiobutton6</property>
</widget> </widget>
<packing> <packing>
<property name="left_attach">0</property> <property name="left_attach">0</property>
@ -5797,7 +5796,6 @@ Version x.x</property>
<property name="active">False</property> <property name="active">False</property>
<property name="inconsistent">False</property> <property name="inconsistent">False</property>
<property name="draw_indicator">True</property> <property name="draw_indicator">True</property>
<property name="group">radiobutton6</property>
</widget> </widget>
<packing> <packing>
<property name="left_attach">1</property> <property name="left_attach">1</property>
@ -5820,7 +5818,6 @@ Version x.x</property>
<property name="active">False</property> <property name="active">False</property>
<property name="inconsistent">False</property> <property name="inconsistent">False</property>
<property name="draw_indicator">True</property> <property name="draw_indicator">True</property>
<property name="group">radiobutton6</property>
</widget> </widget>
<packing> <packing>
<property name="left_attach">0</property> <property name="left_attach">0</property>

View File

@ -116,6 +116,8 @@ static void _mtgsFreezeGIF( SaveState& state, GIFPath (&paths)[3] )
void SaveState::mtgsFreeze() void SaveState::mtgsFreeze()
{ {
FreezeTag( "mtgs" );
if( mtgsThread != NULL ) if( mtgsThread != NULL )
{ {
mtgsThread->Freeze( *this ); mtgsThread->Freeze( *this );

View File

@ -104,11 +104,7 @@ void loadBiosRom( const char *ext, u8 *dest, long maxSize )
Bios1 = Path::Combine( Config.BiosDir, ext ) + ".bin"; Bios1 = Path::Combine( Config.BiosDir, ext ) + ".bin";
if( (filesize=Path::getFileSize( Bios1 ) ) <= 0 ) if( (filesize=Path::getFileSize( Bios1 ) ) <= 0 )
{ {
Console::Error( "\n\n\n" Console::Notice( "Bios Warning > %s not found.", params ext );
"**************\n"
"%s NOT FOUND\n"
"**************\n\n\n", params ext
);
return; return;
} }
} }
@ -853,7 +849,7 @@ void mmap_ClearCpuBlock( uint offset )
for (u32 i=0;i<psMPWVA[offset].size();i++) for (u32 i=0;i<psMPWVA[offset].size();i++)
{ {
Cpu->Clear(psMPWVA[offset][i],0x1000); Cpu->Clear(psMPWVA[offset][i],0x400);
} }
psMPWVA[offset].clear(); psMPWVA[offset].clear();
} }

View File

@ -141,9 +141,9 @@ u32 GetBiosVersion() {
} }
//2002-09-22 (Florin) //2002-09-22 (Florin)
int IsBIOS(char *filename, char *description) int IsBIOS(const char *filename, char *description)
{ {
char ROMVER[14+1], zone[12+1]; char ROMVER[14+1];
FILE *fp; FILE *fp;
unsigned int fileOffset=0, found=FALSE; unsigned int fileOffset=0, found=FALSE;
struct romdir rd; struct romdir rd;
@ -165,31 +165,38 @@ int IsBIOS(char *filename, char *description)
return FALSE; //Unable to locate ROMDIR structure in file or a ioprpXXX.img return FALSE; //Unable to locate ROMDIR structure in file or a ioprpXXX.img
} }
while(strlen(rd.fileName) > 0){ while(strlen(rd.fileName) > 0)
if (strcmp(rd.fileName, "ROMVER") == 0){ // found romver {
unsigned int filepos=ftell(fp); if (strcmp(rd.fileName, "ROMVER") == 0) // found romver
{
uint filepos = ftell(fp);
fseek(fp, fileOffset, SEEK_SET); fseek(fp, fileOffset, SEEK_SET);
if (fread(&ROMVER, 14, 1, fp) == 0) break; if (fread(&ROMVER, 14, 1, fp) == 0) break;
fseek(fp, filepos, SEEK_SET);//go back fseek(fp, filepos, SEEK_SET);//go back
switch(ROMVER[4]){ const char zonefail[2] = { ROMVER[4], '\0' }; // the default "zone" (unknown code)
case 'T':sprintf(zone, "T10K "); break; const char* zone = zonefail;
case 'X':sprintf(zone, "Test ");break;
case 'J':sprintf(zone, "Japan "); break; switch(ROMVER[4])
case 'A':sprintf(zone, "USA "); break; {
case 'E':sprintf(zone, "Europe"); break; case 'T': zone = "T10K "; break;
case 'H':sprintf(zone, "HK "); break; case 'X': zone = "Test "; break;
case 'P':sprintf(zone, "Free "); break; case 'J': zone = "Japan "; break;
case 'C':sprintf(zone, "China "); break; case 'A': zone = "USA "; break;
default: sprintf(zone, "%c ",ROMVER[4]); break;//shoudn't show case 'E': zone = "Europe"; break;
case 'H': zone = "HK "; break;
case 'P': zone = "Free "; break;
case 'C': zone = "China "; break;
} }
sprintf(description, "%s vXX.XX(XX/XX/XXXX) %s", zone,
ROMVER[5]=='C'?"Console":ROMVER[5]=='D'?"Devel":""); sprintf(description, "%s v%c%c.%c%c(%c%c/%c%c/%c%c%c%c) %s", zone,
strncpy(description+ 8, ROMVER+ 0, 2);//ver major ROMVER[0], ROMVER[1], // ver major
strncpy(description+11, ROMVER+ 2, 2);//ver minor ROMVER[2], ROMVER[3], // ver minor
strncpy(description+14, ROMVER+12, 2);//day ROMVER[12], ROMVER[13], // day
strncpy(description+17, ROMVER+10, 2);//month ROMVER[10], ROMVER[11], // month
strncpy(description+20, ROMVER+ 6, 4);//year ROMVER[6], ROMVER[7], ROMVER[8], ROMVER[9], // year!
(ROMVER[5]=='C') ? "Console" : (ROMVER[5]=='D') ? "Devel" : ""
);
found = TRUE; found = TRUE;
} }

View File

@ -73,8 +73,9 @@ extern u64 GetCPUTicks();
extern u64 GetTickFrequency(); extern u64 GetTickFrequency();
// Used in Misc,and Windows/Linux files. // Used in Misc,and Windows/Linux files.
void ProcessFKeys(int fkey, int shift); // processes fkey related commands value 1-12 extern void ProcessFKeys(int fkey, int shift); // processes fkey related commands value 1-12
int IsBIOS(char *filename, char *description); extern int IsBIOS(const char *filename, char *description);
extern const char *LabelAuthors; extern const char *LabelAuthors;
extern const char *LabelGreets; extern const char *LabelGreets;
void CycleFrameLimit(int dir); void CycleFrameLimit(int dir);

View File

@ -54,15 +54,11 @@ void svudispfn();
// aR3000A.S // aR3000A.S
void iopJITCompile(); void iopJITCompile();
void iopJITCompileInBlock(); void iopJITCompileInBlock();
void iopDispatcher();
void iopDispatcherClear();
void iopDispatcherReg(); void iopDispatcherReg();
// aR5900-32.S // aR5900-32.S
void JITCompile(); void JITCompile();
void JITCompileInBlock(); void JITCompileInBlock();
void Dispatcher();
void DispatcherClear();
void DispatcherReg(); void DispatcherReg();
} }

View File

@ -74,7 +74,7 @@ wxDialog( parent, id, _T("Logging"), pos, size )
// Connect all the checkboxes to one function, and pass the checkbox id as user data. // Connect all the checkboxes to one function, and pass the checkbox id as user data.
for (i = EE_CPU_LOG; i >= SYMS_LOG; i++) for (i = EE_CPU_LOG; i >= SYMS_LOG; i++)
Connect(i, wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(frmLogging::LogChecked), i); Connect(i, wxEVT_COMMAND_CHECKBOX_CLICKED, i, wxCommandEventHandler(frmLogging::LogChecked));
} }

View File

@ -71,6 +71,7 @@ _PADgsDriverInfo PAD1gsDriverInfo;
_PADconfigure PAD1configure; _PADconfigure PAD1configure;
_PADtest PAD1test; _PADtest PAD1test;
_PADabout PAD1about; _PADabout PAD1about;
_PADfreeze PAD1freeze;
// PAD2 // PAD2
_PADinit PAD2init; _PADinit PAD2init;
@ -87,6 +88,7 @@ _PADgsDriverInfo PAD2gsDriverInfo;
_PADconfigure PAD2configure; _PADconfigure PAD2configure;
_PADtest PAD2test; _PADtest PAD2test;
_PADabout PAD2about; _PADabout PAD2about;
_PADfreeze PAD2freeze;
// SIO[2] // SIO[2]
_SIOinit SIOinit[2][9]; _SIOinit SIOinit[2][9];
@ -330,6 +332,7 @@ void *PAD1plugin;
void CALLBACK PAD1_configure() {} void CALLBACK PAD1_configure() {}
void CALLBACK PAD1_about() {} void CALLBACK PAD1_about() {}
s32 CALLBACK PAD1_test() { return 0; } s32 CALLBACK PAD1_test() { return 0; }
s32 CALLBACK PAD1_freeze(int mode, freezeData *data) { data->size = 0; return 0; }
int LoadPAD1plugin(const string& filename) { int LoadPAD1plugin(const string& filename) {
void *drv; void *drv;
@ -352,6 +355,7 @@ int LoadPAD1plugin(const string& filename) {
MapSymbolPAD_Fallback(PAD1,PAD,configure); MapSymbolPAD_Fallback(PAD1,PAD,configure);
MapSymbolPAD_Fallback(PAD1,PAD,about); MapSymbolPAD_Fallback(PAD1,PAD,about);
MapSymbolPAD_Fallback(PAD1,PAD,test); MapSymbolPAD_Fallback(PAD1,PAD,test);
MapSymbolPAD_Fallback(PAD1,PAD,freeze);
return 0; return 0;
} }
@ -361,6 +365,7 @@ void *PAD2plugin;
void CALLBACK PAD2_configure() {} void CALLBACK PAD2_configure() {}
void CALLBACK PAD2_about() {} void CALLBACK PAD2_about() {}
s32 CALLBACK PAD2_test() { return 0; } s32 CALLBACK PAD2_test() { return 0; }
s32 CALLBACK PAD2_freeze(int mode, freezeData *data) { data->size = 0; return 0; }
int LoadPAD2plugin(const string& filename) { int LoadPAD2plugin(const string& filename) {
void *drv; void *drv;
@ -383,6 +388,7 @@ int LoadPAD2plugin(const string& filename) {
MapSymbolPAD_Fallback(PAD2,PAD,configure); MapSymbolPAD_Fallback(PAD2,PAD,configure);
MapSymbolPAD_Fallback(PAD2,PAD,about); MapSymbolPAD_Fallback(PAD2,PAD,about);
MapSymbolPAD_Fallback(PAD2,PAD,test); MapSymbolPAD_Fallback(PAD2,PAD,test);
MapSymbolPAD_Fallback(PAD2,PAD,freeze);
return 0; return 0;
} }

View File

@ -112,10 +112,10 @@ struct psxRegisters {
u32 code; /* The instruction */ u32 code; /* The instruction */
u32 cycle; u32 cycle;
u32 interrupt; u32 interrupt;
u32 sCycle[64]; // start cycle for signaled ints u32 sCycle[32]; // start cycle for signaled ints
s32 eCycle[64]; // cycle delta for signaled ints (sCycle + eCycle == branch cycle) s32 eCycle[32]; // cycle delta for signaled ints (sCycle + eCycle == branch cycle)
u32 _msflag[32]; //u32 _msflag[32];
u32 _smflag[32]; //u32 _smflag[32];
}; };
PCSX2_ALIGNED16_EXTERN(psxRegisters psxRegs); PCSX2_ALIGNED16_EXTERN(psxRegisters psxRegs);

View File

@ -522,7 +522,7 @@ __forceinline bool _cpuBranchTest_Shared()
cpuSetNextBranchDelta( ((g_psxNextBranchCycle-psxRegs.cycle)*8) - EEsCycle ); cpuSetNextBranchDelta( ((g_psxNextBranchCycle-psxRegs.cycle)*8) - EEsCycle );
// Apply the hsync counter's nextCycle // Apply the hsync counter's nextCycle
cpuSetNextBranch( counters[4].sCycle, counters[4].CycleT ); cpuSetNextBranch( hsyncCounter.sCycle, hsyncCounter.CycleT );
// Apply vsync and other counter nextCycles // Apply vsync and other counter nextCycles
cpuSetNextBranch( nextsCounter, nextCounter ); cpuSetNextBranch( nextsCounter, nextCounter );

View File

@ -26,8 +26,6 @@
#include "deci2_netmp.h" #include "deci2_netmp.h"
#include "deci2_ttyp.h" #include "deci2_ttyp.h"
#include "Threading.h"
#define PROTO_DCMP 0x0001 #define PROTO_DCMP 0x0001
#define PROTO_ITTYP 0x0110 #define PROTO_ITTYP 0x0110
#define PROTO_IDBGP 0x0130 #define PROTO_IDBGP 0x0130

View File

@ -22,7 +22,6 @@
#include "VUmicro.h" #include "VUmicro.h"
#include "deci2.h" #include "deci2.h"
#include "Threading.h"
using namespace Threading; using namespace Threading;
using namespace R5900; using namespace R5900;

View File

@ -454,11 +454,9 @@ void SPRTOinterrupt()
void SaveState::sprFreeze() void SaveState::sprFreeze()
{ {
// Gotta save the weird ref-style DMA timing vars! FreezeTag( "SPRdma" );
if( GetVersion() >= 0x05 )
{ Freeze(spr0finished);
Freeze(spr0finished); Freeze(spr1finished);
Freeze(spr1finished); Freeze(mfifotransferred);
Freeze(mfifotransferred);
}
} }

View File

@ -33,7 +33,6 @@
using namespace R5900; using namespace R5900;
extern int g_psxWriteOk;
extern void recResetEE(); extern void recResetEE();
extern void recResetIOP(); extern void recResetIOP();
@ -54,7 +53,9 @@ string SaveState::GetFilename( int slot )
return Path::Combine( SSTATES_DIR, fmt_string( "%8.8X.%3.3d", ElfCRC, slot ) ); return Path::Combine( SSTATES_DIR, fmt_string( "%8.8X.%3.3d", ElfCRC, slot ) );
} }
SaveState::SaveState( const char* msg, const string& destination ) : m_version( g_SaveVersion ) SaveState::SaveState( const char* msg, const string& destination ) :
m_version( g_SaveVersion )
, m_tagspace( 128 )
{ {
Console::WriteLn( "%s %hs", params msg, &destination ); Console::WriteLn( "%s %hs", params msg, &destination );
} }
@ -78,42 +79,76 @@ s32 CALLBACK gsSafeFreeze( int mode, freezeData *data )
} }
} }
void SaveState::FreezeTag( const char* src )
{
const int length = strlen( src );
m_tagspace.MakeRoomFor( length+1 );
strcpy( m_tagspace.GetPtr(), src );
FreezeMem( m_tagspace.GetPtr(), length );
if( strcmp( m_tagspace.GetPtr(), src ) != 0 )
{
assert( 0 );
throw Exception::BadSavedState( string( "Tag: " )+src );
}
}
void SaveState::FreezeAll() void SaveState::FreezeAll()
{ {
if( IsLoading() ) if( IsLoading() )
PreLoadPrep(); PreLoadPrep();
// Check the BIOS, and issue a warning if the bios for this state
// doesn't match the bios currently being used (chances are it'll still
// work fine, but some games are very picky).
FreezeMem(PS2MEM_BASE, Ps2MemSize::Base); // 32 MB main memory char descout[128], descin[128];
FreezeMem(PS2MEM_ROM, Ps2MemSize::Rom); // 4 mb rom memory memzero_obj( descout );
FreezeMem(PS2MEM_ROM1, Ps2MemSize::Rom1); // 256kb rom1 memory IsBIOS( Config.Bios, descout );
memcpy_fast( descin, descout, 128 );
Freeze( descin );
if( memcmp( descin, descout, 128 ) != 0 )
{
Console::Error(
"\n\tWarning: BIOS Version Mismatch, savestate may be unstable!\n"
"\t\tCurrent BIOS: %s\n"
"\t\tSavestate BIOS: %s\n",
params descout, descin
);
}
// First Block - Memory Dumps
// ---------------------------
FreezeMem(PS2MEM_BASE, Ps2MemSize::Base); // 32 MB main memory
FreezeMem(PS2MEM_SCRATCH, Ps2MemSize::Scratch); // scratch pad FreezeMem(PS2MEM_SCRATCH, Ps2MemSize::Scratch); // scratch pad
FreezeMem(PS2MEM_HW, Ps2MemSize::Hardware); // hardware memory FreezeMem(PS2MEM_HW, Ps2MemSize::Hardware); // hardware memory
FreezeMem(psxM, Ps2MemSize::IopRam); // 2 MB main memory
FreezeMem(psxH, Ps2MemSize::IopHardware); // hardware memory
FreezeMem(psxS, 0x000100); // iop's sif memory
// Second Block - Various CPU Registers and States
// -----------------------------------------------
FreezeTag( "cpuRegs" );
Freeze(cpuRegs); // cpu regs + COP0 Freeze(cpuRegs); // cpu regs + COP0
Freeze(psxRegs); // iop regs Freeze(psxRegs); // iop regs
if (GetVersion() >= 0x6) Freeze(fpuRegs);
Freeze(fpuRegs);
else
{
// Old versiosn didn't save the ACCflags...
FreezeLegacy(fpuRegs, sizeof(u32)); // fpu regs
fpuRegs.ACCflag = 0;
}
Freeze(tlb); // tlbs Freeze(tlb); // tlbs
// Third Block - Cycle Timers and Events
// -------------------------------------
FreezeTag( "Cycles" );
Freeze(EEsCycle); Freeze(EEsCycle);
Freeze(EEoCycle); Freeze(EEoCycle);
Freeze(psxRegs.cycle); // used to be IOPoCycle. This retains compatibility.
Freeze(g_nextBranchCycle); Freeze(g_nextBranchCycle);
Freeze(g_psxNextBranchCycle); Freeze(g_psxNextBranchCycle);
Freeze(s_iLastCOP0Cycle); Freeze(s_iLastCOP0Cycle);
Freeze(s_iLastPERFCycle); Freeze(s_iLastPERFCycle);
Freeze(g_psxWriteOk); // Fourth Block - EE-related systems
// ---------------------------------
//hope didn't forgot any cpu....
rcntFreeze(); rcntFreeze();
gsFreeze(); gsFreeze();
vuMicroFreeze(); vuMicroFreeze();
@ -124,38 +159,27 @@ void SaveState::FreezeAll()
gifFreeze(); gifFreeze();
sprFreeze(); sprFreeze();
// iop now // Fifth Block - iop-related systems
FreezeMem(psxM, Ps2MemSize::IopRam); // 2 MB main memory // ---------------------------------
FreezeMem(psxH, Ps2MemSize::IopHardware); // hardware memory psxRcntFreeze();
//FreezeMem(psxS, 0x00010000); // sif memory
sioFreeze(); sioFreeze();
sio2Freeze();
cdrFreeze(); cdrFreeze();
cdvdFreeze(); cdvdFreeze();
psxRcntFreeze();
sio2Freeze();
// Sixth Block - Plugins Galore!
// -----------------------------
FreezePlugin( "GS", gsSafeFreeze ); FreezePlugin( "GS", gsSafeFreeze );
FreezePlugin( "SPU2", SPU2freeze ); FreezePlugin( "SPU2", SPU2freeze );
FreezePlugin( "DEV9", DEV9freeze ); FreezePlugin( "DEV9", DEV9freeze );
FreezePlugin( "USB", USBfreeze ); FreezePlugin( "USB", USBfreeze );
FreezePlugin( "PAD1", PAD1freeze );
FreezePlugin( "PAD2", PAD2freeze );
if( IsLoading() ) if( IsLoading() )
PostLoadPrep(); PostLoadPrep();
} }
// this function is yet incomplete. Version numbers hare still < 0x12 so it won't be run.
// (which is good because it won't work :P)
void SaveState::_testCdvdCrc()
{
/*if( GetVersion() < 0x0012 ) return;
u32 thiscrc = ElfCRC;
Freeze( thiscrc );
if( thiscrc != ElfCRC )
throw Exception::StateCrcMismatch( thiscrc, ElfCRC );*/
}
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
// gzipped to/from disk state saves implementation // gzipped to/from disk state saves implementation
@ -212,8 +236,6 @@ gzLoadingState::gzLoadingState( const string& filename ) :
"\tThe savestate was created with a newer version of Pcsx2. I don't know how to load it!" ); "\tThe savestate was created with a newer version of Pcsx2. I don't know how to load it!" );
throw Exception::UnsupportedStateVersion( m_version ); throw Exception::UnsupportedStateVersion( m_version );
} }
_testCdvdCrc();
} }
gzLoadingState::~gzLoadingState() { } gzLoadingState::~gzLoadingState() { }
@ -226,34 +248,30 @@ void gzSavingState::FreezeMem( void* data, int size )
void gzLoadingState::FreezeMem( void* data, int size ) void gzLoadingState::FreezeMem( void* data, int size )
{ {
gzread( m_file, data, size ); if( gzread( m_file, data, size ) != size )
if( gzeof( m_file ) )
throw Exception::BadSavedState( m_filename ); throw Exception::BadSavedState( m_filename );
} }
void gzSavingState::FreezePlugin( const char* name, s32 (CALLBACK *freezer)(int mode, freezeData *data) ) void gzSavingState::FreezePlugin( const char* name, s32 (CALLBACK *freezer)(int mode, freezeData *data) )
{ {
Console::WriteLn( "\tSaving %s", params name );
freezeData fP = { 0, NULL }; freezeData fP = { 0, NULL };
Console::WriteLn( "\tSaving %s", params name );
FreezeTag( name );
if (freezer(FREEZE_SIZE, &fP) == -1) if (freezer(FREEZE_SIZE, &fP) == -1)
throw Exception::FreezePluginFailure( name, "saving" ); throw Exception::FreezePluginFailure( name, "saving" );
gzwrite(m_file, &fP.size, sizeof(fP.size)); Freeze( fP.size );
if( fP.size == 0 ) return; if( fP.size == 0 ) return;
fP.data = (s8*)malloc(fP.size); SafeArray<s8> buffer( fP.size );
if (fP.data == NULL) fP.data = buffer.GetPtr();
throw Exception::OutOfMemory();
if(freezer(FREEZE_SAVE, &fP) == -1) if(freezer(FREEZE_SAVE, &fP) == -1)
throw Exception::FreezePluginFailure( name, "saving" ); throw Exception::FreezePluginFailure( name, "saving" );
if (fP.size) FreezeMem( fP.data, fP.size );
{
gzwrite(m_file, fP.data, fP.size);
free(fP.data);
}
} }
void gzLoadingState::FreezePlugin( const char* name, s32 (CALLBACK *freezer)(int mode, freezeData *data) ) void gzLoadingState::FreezePlugin( const char* name, s32 (CALLBACK *freezer)(int mode, freezeData *data) )
@ -261,21 +279,17 @@ void gzLoadingState::FreezePlugin( const char* name, s32 (CALLBACK *freezer)(int
freezeData fP = { 0, NULL }; freezeData fP = { 0, NULL };
Console::WriteLn( "\tLoading %s", params name ); Console::WriteLn( "\tLoading %s", params name );
gzread(m_file, &fP.size, sizeof(fP.size)); FreezeTag( name );
Freeze( fP.size );
if( fP.size == 0 ) return; if( fP.size == 0 ) return;
fP.data = (s8*)malloc(fP.size); SafeArray<s8> buffer( fP.size );
if (fP.data == NULL) fP.data = buffer.GetPtr();
throw Exception::OutOfMemory();
gzread(m_file, fP.data, fP.size);
if( gzeof( m_file ) ) FreezeMem( fP.data, fP.size );
throw Exception::BadSavedState( m_filename );
if(freezer(FREEZE_LOAD, &fP) == -1) if(freezer(FREEZE_LOAD, &fP) == -1)
throw Exception::FreezePluginFailure( name, "loading" ); throw Exception::FreezePluginFailure( name, "loading" );
if (fP.size) free(fP.data);
} }
////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////

View File

@ -24,10 +24,14 @@
#include "PS2Edefs.h" #include "PS2Edefs.h"
#endif #endif
#include "System.h" #include "System.h"
// Savestate Versioning! // Savestate Versioning!
// If you make changes to the savestate version, please increment the value below. // If you make changes to the savestate version, please increment the value below.
// If the change is minor and compatibility with old states is retained, increment
// the lower 16 bit value. IF the change is breaking of all compatibility with old
// states, increment the upper 16 bit value, and clear the lower 16 bits to 0.
static const u32 g_SaveVersion = 0x8b400006; static const u32 g_SaveVersion = 0x8b410000;
// this function is meant to be used in the place of GSfreeze, and provides a safe layer // this function is meant to be used in the place of GSfreeze, and provides a safe layer
// between the GS saving function and the MTGS's needs. :) // between the GS saving function and the MTGS's needs. :)
@ -41,6 +45,7 @@ class SaveState
{ {
protected: protected:
u32 m_version; // version of the savestate being loaded. u32 m_version; // version of the savestate being loaded.
SafeArray<char> m_tagspace;
public: public:
SaveState( const char* msg, const string& destination ); SaveState( const char* msg, const string& destination );
@ -76,6 +81,12 @@ public:
FreezeMem( &data, sizeof( T ) - sizeOfNewStuff ); FreezeMem( &data, sizeof( T ) - sizeOfNewStuff );
} }
// Freezes an identifier value into the savestate for troubleshooting purposes.
// Identifiers can be used to determine where in a savestate that data has become
// skewed (if the value does not match then the error occurs somewhere prior to that
// position).
void FreezeTag( const char* src );
// Loads or saves a plugin. Plugin name is for console logging purposes. // Loads or saves a plugin. Plugin name is for console logging purposes.
virtual void FreezePlugin( const char* name, s32 (CALLBACK* freezer)(int mode, freezeData *data) )=0; virtual void FreezePlugin( const char* name, s32 (CALLBACK* freezer)(int mode, freezeData *data) )=0;
@ -95,11 +106,6 @@ public:
protected: protected:
// Used internally by constructors to check the cdvd's crc against the CRC of the savestate.
// This allows for proper exception handling of changed CDs on-the-fly.
void _testCdvdCrc();
// Load/Save functions for the various components of our glorious emulator! // Load/Save functions for the various components of our glorious emulator!
void rcntFreeze(); void rcntFreeze();

View File

@ -586,22 +586,13 @@ __forceinline void dmaSIF2() {
} }
void SaveState::sifFreeze() { void SaveState::sifFreeze()
{
FreezeTag( "SIFdma" );
Freeze(sif0); Freeze(sif0);
Freeze(sif1); Freeze(sif1);
if( GetVersion() >= 0x0002 ) Freeze(eesifbusy);
{ Freeze(iopsifbusy);
Freeze(eesifbusy);
Freeze(iopsifbusy);
}
else if( IsLoading() )
{
// Old savestate, inferior data so...
// Take an educated guess on what they should be. Or well, set to 1 because
// it more or less forces them to "kick"
iopsifbusy[0] = eesifbusy[0] = 1;
iopsifbusy[1] = eesifbusy[1] = 1;
}
} }

View File

@ -566,22 +566,15 @@ void SaveState::sioFreeze()
// CRCs for memory cards. // CRCs for memory cards.
u64 m_mcdCRCs[2]; u64 m_mcdCRCs[2];
FreezeTag( "sio" );
Freeze( sio ); Freeze( sio );
// versions prior to 3 didn't have CRCs. if( IsSaving() )
if( GetVersion() >= 0x03 )
{ {
if( IsSaving() ) for( int i=0; i<2; ++i )
{ m_mcdCRCs[i] = MemoryCard::GetCRC( i );
for( int i=0; i<2; ++i )
m_mcdCRCs[i] = MemoryCard::GetCRC( i );
}
Freeze( m_mcdCRCs );
}
else
{
m_mcdCRCs[0] = m_mcdCRCs[1] = 0;
} }
Freeze( m_mcdCRCs );
if( IsLoading() && Config.McdEnableEject ) if( IsLoading() && Config.McdEnableEject )
{ {

View File

@ -19,7 +19,6 @@
#include "PrecompiledHeader.h" #include "PrecompiledHeader.h"
#include "Common.h" #include "Common.h"
#include "Threading.h"
#include "HostGui.h" #include "HostGui.h"
#include "VUmicro.h" #include "VUmicro.h"
@ -92,6 +91,7 @@ static void trim( string& line )
} }
//////////////////////////////////////////////////////////////////////////////////////////
// This function should be called once during program execution. // This function should be called once during program execution.
void SysDetect() void SysDetect()
{ {
@ -160,6 +160,7 @@ void SysDetect()
Console::ClearColor(); Console::ClearColor();
} }
//////////////////////////////////////////////////////////////////////////////////////////
// Allocates memory for all PS2 systems. // Allocates memory for all PS2 systems.
bool SysAllocateMem() bool SysAllocateMem()
{ {
@ -187,10 +188,12 @@ bool SysAllocateMem()
return true; return true;
} }
//////////////////////////////////////////////////////////////////////////////////////////
// Allocates memory for all recompilers, and force-disables any recs that fail to initialize. // Allocates memory for all recompilers, and force-disables any recs that fail to initialize.
// This should be done asap, since the recompilers tend to demand a lot of system resources, and prefer // This should be done asap, since the recompilers tend to demand a lot of system resources,
// to have those resources at specific address ranges. The sooner memory is allocated, the better. // and prefer to have those resources at specific address ranges. The sooner memory is
// allocated, the better.
//
// Returns FALSE on *critical* failure (GUI should issue a msg and exit). // Returns FALSE on *critical* failure (GUI should issue a msg and exit).
void SysAllocateDynarecs() void SysAllocateDynarecs()
{ {
@ -259,6 +262,7 @@ void SysAllocateDynarecs()
} }
//////////////////////////////////////////////////////////////////////////////////////////
// This should be called last thing before Pcsx2 exits. // This should be called last thing before Pcsx2 exits.
void SysShutdownMem() void SysShutdownMem()
{ {
@ -269,6 +273,7 @@ void SysShutdownMem()
memShutdown(); memShutdown();
} }
//////////////////////////////////////////////////////////////////////////////////////////
// This should generally be called right before calling SysShutdownMem(), although you can optionally // This should generally be called right before calling SysShutdownMem(), although you can optionally
// use it in conjunction with SysAllocDynarecs to allocate/free the dynarec resources on the fly (as // use it in conjunction with SysAllocDynarecs to allocate/free the dynarec resources on the fly (as
// risky as it might be, since dynarecs could very well fail on the second attempt). // risky as it might be, since dynarecs could very well fail on the second attempt).
@ -285,6 +290,7 @@ void SysShutdownDynarecs()
bool g_ReturnToGui = false; // set to exit the execution of the emulator and return control to the GUI bool g_ReturnToGui = false; // set to exit the execution of the emulator and return control to the GUI
bool g_EmulationInProgress = false; // Set TRUE if a game is actively running (set to false on reset) bool g_EmulationInProgress = false; // Set TRUE if a game is actively running (set to false on reset)
//////////////////////////////////////////////////////////////////////////////////////////
// Resets all PS2 cpu execution caches, which does not affect that actual PS2 state/condition. // Resets all PS2 cpu execution caches, which does not affect that actual PS2 state/condition.
// This can be called at any time outside the context of a Cpu->Execute() block without // This can be called at any time outside the context of a Cpu->Execute() block without
// bad things happening (recompilers will slow down for a brief moment since rec code blocks // bad things happening (recompilers will slow down for a brief moment since rec code blocks

View File

@ -26,6 +26,7 @@
#include "MemcpyFast.h" #include "MemcpyFast.h"
#include "SafeArray.h" #include "SafeArray.h"
#include "Misc.h" #include "Misc.h"
#include "Threading.h" // to use threading stuff, include the Threading namespace in your file.
enum PageProtectionMode enum PageProtectionMode

View File

@ -44,6 +44,7 @@ namespace Threading
void Thread::Close() void Thread::Close()
{ {
if( m_terminated ) return;
pthread_cancel( m_thread ); pthread_cancel( m_thread );
pthread_join( m_thread, NULL ); pthread_join( m_thread, NULL );
} }

View File

@ -67,8 +67,7 @@ namespace Threading
void Unlock(); void Unlock();
}; };
// Returns the number of available logical CPUs (cores plus // Returns the number of available logical CPUs (cores plus hyperthreaded cpus)
// hyperthreaded cpus)
extern void CountLogicalCores( int LogicalCoresPerPhysicalCPU, int PhysicalCoresPerPhysicalCPU ); extern void CountLogicalCores( int LogicalCoresPerPhysicalCPU, int PhysicalCoresPerPhysicalCPU );
// Releases a timeslice to other threads. // Releases a timeslice to other threads.
@ -80,6 +79,24 @@ namespace Threading
// sleeps the current thread for the given number of milliseconds. // sleeps the current thread for the given number of milliseconds.
extern void Sleep( int ms ); extern void Sleep( int ms );
//////////////////////////////////////////////////////////////////////////////////////////
// Thread - Helper class for the basics of starting/managing simple threads.
//
// Use this as a base class for your threaded procedure, and implement the 'int Callback()'
// method. Use Start() and Close() to start and shutdown the thread, and use m_post_event
// internally to post/receive events for the thread (make a public accessor for it in your
// derived class if your thread utilizes the post).
//
// Notes:
// * To ensure thread safety against C++'s bizarre and not-thread-friendly object
// constructors and destructors, you *must* use Start() and Close(). There is a built-
// in Close() called on destruction, which should work for very simple threads (that
// do not have any special shutdown code of their own), but
//
// * Constructing threads as static vars isn't recommended since it can potentially con-
// fuse w32pthreads, if the static initializers are executed out-of-order (C++ offers
// no dependency options for ensuring correct static var initializations).
//
class Thread : NoncopyableObject class Thread : NoncopyableObject
{ {
protected: protected:
@ -106,12 +123,135 @@ namespace Threading
// on linux). // on linux).
static void* _internal_callback( void* func ); static void* _internal_callback( void* func );
// Implemented by derrived class to handle threading actions! // Implemented by derived class to handle threading actions!
virtual int Callback()=0; virtual int Callback()=0;
}; };
// Our fundamental interlocking functions. All other useful interlocks can //////////////////////////////////////////////////////////////////////////////////////////
// be derrived from these little beasties! // ScopedLock: Helper class for using Mutexes.
// Using this class provides an exception-safe (and generally clean) method of locking
// code inside a function or conditional block.
//
class ScopedLock : NoncopyableObject
{
protected:
MutexLock& m_lock;
public:
virtual ~ScopedLock()
{
m_lock.Unlock();
}
ScopedLock( MutexLock& locker ) :
m_lock( locker )
{
m_lock.Lock();
}
};
//////////////////////////////////////////////////////////////////////////////////////////
// BaseTaskThread - an abstract base class which provides simple parallel execution of
// single tasks.
//
// Implementation:
// To use this class your derived class will need to implement its own Task() function
// and also a "StartTask( parameters )" function which suits the need of your task, along
// with any local variables your task needs to do its job. You may additionally want to
// implement a "GetResult()" function, which would be a combination of WaitForResult()
// and a return value of the computational result.
//
// Thread Safety:
// If operating on local variables, you must execute WaitForResult() before leaving the
// variable scope -- or alternatively have your StartTask() implementation make full
// copies of dependent data. Also, by default PostTask() always assumes the previous
// task has completed. If your system can post a new task before the previous one has
// completed, then it needs to explicitly call WaitForResult() or provide a mechanism
// to cancel the previous task (which is probably more work than it's worth).
//
// Performance notes:
// * Remember that thread creation is generally slow, so you should make your object
// instance once early and then feed it tasks repeatedly over the course of program
// execution.
//
// * For threading to be a successful speedup, the task being performed should be as lock
// free as possible. For example using STL containers in parallel usually fails to
// yield any speedup due to the gratuitous amount of locking that the STL performs
// internally.
//
// * The best application of tasking threads is to divide a large loop over a linear array
// into smaller sections. For example, if you have 20,000 items to process, the task
// can be divided into two threads of 10,000 items each.
//
class BaseTaskThread : public Thread
{
protected:
volatile bool m_done;
volatile bool m_TaskComplete;
public:
virtual ~BaseTaskThread() {}
BaseTaskThread() :
m_done( false )
, m_TaskComplete( false )
{
}
// Tells the thread to exit and then waits for thread termination.
// To force-terminate the thread without "nicely" waiting for the task to complete,
// explicitly use the Thread::Close parent implementation instead.
void Close()
{
if( m_terminated ) return;
m_done = true;
m_post_event.Post();
pthread_join( m_thread, NULL );
}
// Initiates the new task. This should be called after your own StartTask has
// initialized internal variables / preparations for task execution.
void PostTask()
{
jASSUME( !m_terminated );
m_TaskComplete = false;
m_post_event.Post();
}
// Blocks current thread execution pending the completion of the parallel task.
void WaitForResult() const
{
if( m_terminated ) return;
while( !m_TaskComplete )
{
Timeslice();
SpinWait();
}
}
protected:
// Abstract method run when a task has been posted. Implementing classes should do
// all your necessary processing work here.
virtual void Task()=0;
int Callback()
{
do
{
// Wait for a job!
m_post_event.Wait();
if( m_done ) break;
Task();
m_TaskComplete = true;
} while( !m_done );
return 0;
}
};
//////////////////////////////////////////////////////////////////////////////////////////
// Our fundamental interlocking functions. All other useful interlocks can be derived
// from these little beasties!
extern long pcsx2_InterlockedExchange(volatile long* Target, long srcval); extern long pcsx2_InterlockedExchange(volatile long* Target, long srcval);
extern long pcsx2_InterlockedCompareExchange( volatile long* target, long srcval, long comp ); extern long pcsx2_InterlockedCompareExchange( volatile long* target, long srcval, long comp );

View File

@ -160,6 +160,8 @@ void vuMicroMemReset()
void SaveState::vuMicroFreeze() void SaveState::vuMicroFreeze()
{ {
FreezeTag( "vuMicro" );
jASSUME( VU0.Mem != NULL ); jASSUME( VU0.Mem != NULL );
jASSUME( VU1.Mem != NULL ); jASSUME( VU1.Mem != NULL );
@ -169,15 +171,7 @@ void SaveState::vuMicroFreeze()
FreezeMem(VU0.Micro, 4*1024); FreezeMem(VU0.Micro, 4*1024);
Freeze(VU0.VF); Freeze(VU0.VF);
if( GetVersion() >= 0x02 ) Freeze(VU0.VI);
Freeze(VU0.VI);
else
{
// Old versions stored the VIregs as 32 bit values...
memzero_obj( VU0.VI );
for(int i=0; i<32; i++ )
Freeze( VU0.VI[i].UL );
}
Freeze(VU1.ACC); Freeze(VU1.ACC);
Freeze(VU1.code); Freeze(VU1.code);
@ -185,14 +179,5 @@ void SaveState::vuMicroFreeze()
FreezeMem(VU1.Micro, 16*1024); FreezeMem(VU1.Micro, 16*1024);
Freeze(VU1.VF); Freeze(VU1.VF);
if( GetVersion() >= 0x02 ) Freeze(VU1.VI);
Freeze(VU1.VI);
else
{
// Old versions stored the VIregs as 32 bit values...
memzero_obj( VU1.VI );
for(int i=0; i<32; i++ )
Freeze( VU1.VI[i].UL );
}
} }

View File

@ -452,7 +452,10 @@ static __forceinline int mfifoVIF1chain() {
int ret; int ret;
/* Is QWC = 0? if so there is nothing to transfer */ /* Is QWC = 0? if so there is nothing to transfer */
if (vif1ch->qwc == 0 && vif1.vifstalled == 0) return 0; if (vif1ch->qwc == 0 && vif1.vifstalled == 0) {
vif1.inprogress = 0;
return 0;
}
if (vif1ch->madr >= psHu32(DMAC_RBOR) && if (vif1ch->madr >= psHu32(DMAC_RBOR) &&
@ -485,16 +488,30 @@ void mfifoVIF1transfer(int qwc) {
g_vifCycles = 0; g_vifCycles = 0;
mfifodmairq = 0; //Clear any previous TIE interrupt
if(qwc > 0){ if(qwc > 0){
vifqwc += qwc; vifqwc += qwc;
if(vif1.inprogress & 0x10)
{
if (vif1ch->madr >= psHu32(DMAC_RBOR) && vif1ch->madr <= (psHu32(DMAC_RBOR)+psHu32(DMAC_RBSR)))
{
CPU_INT(10, min( (int)vifqwc, (int)vif1ch->qwc ) * BIAS);
}
else
{
CPU_INT(10, vif1ch->qwc * BIAS);
}
}
vif1.inprogress &= ~0x10;
SPR_LOG("Added %x qw to mfifo, total now %x - Vif CHCR %x Stalled %x done %x\n", qwc, vifqwc, vif1ch->chcr, vif1.vifstalled, vif1.done); SPR_LOG("Added %x qw to mfifo, total now %x - Vif CHCR %x Stalled %x done %x\n", qwc, vifqwc, vif1ch->chcr, vif1.vifstalled, vif1.done);
if((vif1ch->chcr & 0x100) == 0 || vif1.vifstalled == 1 || vif1.done == 1) return; /*if((vif1ch->chcr & 0x100) == 0 || vif1.vifstalled == 1 || vif1.done == 1 || vif1.inprogress == 1)*/ return;
} }
mfifodmairq = 0; //Clear any previous TIE interrupt
if(vif1ch->qwc == 0){ if(vif1ch->qwc == 0){
ptag = (u32*)dmaGetAddr(vif1ch->tadr); ptag = (u32*)dmaGetAddr(vif1ch->tadr);
@ -505,7 +522,7 @@ void mfifoVIF1transfer(int qwc) {
VIF_LOG("MFIFO Stallon tag\n"); VIF_LOG("MFIFO Stallon tag\n");
vif1.stallontag = 1; vif1.stallontag = 1;
CPU_INT(10,cycles+g_vifCycles); //CPU_INT(10,cycles+g_vifCycles);
return; //IRQ set by VIFTransfer return; //IRQ set by VIFTransfer
} }
} }
@ -524,7 +541,7 @@ void mfifoVIF1transfer(int qwc) {
switch (id) { switch (id) {
case 0: // Refe - Transfer Packet According to ADDR field case 0: // Refe - Transfer Packet According to ADDR field
vif1ch->tadr = psHu32(DMAC_RBOR) + ((vif1ch->tadr + 16) & psHu32(DMAC_RBSR)); vif1ch->tadr = psHu32(DMAC_RBOR) + ((vif1ch->tadr + 16) & psHu32(DMAC_RBSR));
vif1.done = 2; //End Transfer vif1.done = 1; //End Transfer
break; break;
case 1: // CNT - Transfer QWC following the tag. case 1: // CNT - Transfer QWC following the tag.
@ -550,31 +567,33 @@ void mfifoVIF1transfer(int qwc) {
case 7: // End - Transfer QWC following the tag case 7: // End - Transfer QWC following the tag
vif1ch->madr = psHu32(DMAC_RBOR) + ((vif1ch->tadr + 16) & psHu32(DMAC_RBSR)); //Set MADR to data following the tag vif1ch->madr = psHu32(DMAC_RBOR) + ((vif1ch->tadr + 16) & psHu32(DMAC_RBSR)); //Set MADR to data following the tag
vif1ch->tadr = psHu32(DMAC_RBOR) + ((vif1ch->madr + (vif1ch->qwc << 4)) & psHu32(DMAC_RBSR)); //Set TADR to QW following the data vif1ch->tadr = psHu32(DMAC_RBOR) + ((vif1ch->madr + (vif1ch->qwc << 4)) & psHu32(DMAC_RBSR)); //Set TADR to QW following the data
vif1.done = 2; //End Transfer vif1.done = 1; //End Transfer
break; break;
} }
if ((vif1ch->chcr & 0x80) && (ptag[0] >> 31)) { if ((vif1ch->chcr & 0x80) && (ptag[0] >> 31))
VIF_LOG("dmaIrq Set\n"); {
vif1.done = 2; VIF_LOG("dmaIrq Set\n");
mfifodmairq = 1; //Let the handler know we have prematurely ended MFIFO vif1.done = 1;
} mfifodmairq = 1; //Let the handler know we have prematurely ended MFIFO
}
} }
ret = mfifoVIF1chain(); vif1.inprogress |= 1;
if (ret == -1) {
/*if (ret == -1) {
SysPrintf("VIF dmaChain error size=%d, madr=%lx, tadr=%lx\n", SysPrintf("VIF dmaChain error size=%d, madr=%lx, tadr=%lx\n",
vif1ch->qwc, vif1ch->madr, vif1ch->tadr); vif1ch->qwc, vif1ch->madr, vif1ch->tadr);
vif1.done = 1; vif1.done = 1;
CPU_INT(10,g_vifCycles); //CPU_INT(10,g_vifCycles);
} }
if(ret == -2){ if(ret == -2){
VIF_LOG("MFIFO Stall\n"); VIF_LOG("MFIFO Stall\n");
CPU_INT(10,g_vifCycles); //CPU_INT(10,g_vifCycles);
return; return;
} }*/
if(vif1.done == 2 && vif1ch->qwc == 0) vif1.done = 1; //if(vif1.done == 2 && vif1ch->qwc == 0) vif1.done = 1;
CPU_INT(10,g_vifCycles); //CPU_INT(10,g_vifCycles);
SPR_LOG("mfifoVIF1transfer end %x madr %x, tadr %x vifqwc %x\n", vif1ch->chcr, vif1ch->madr, vif1ch->tadr, vifqwc); SPR_LOG("mfifoVIF1transfer end %x madr %x, tadr %x vifqwc %x\n", vif1ch->chcr, vif1ch->madr, vif1ch->tadr, vifqwc);
} }
@ -582,6 +601,10 @@ void vifMFIFOInterrupt()
{ {
g_vifCycles = 0; g_vifCycles = 0;
if(vif1.inprogress == 1) mfifoVIF1chain();
if(vif1.irq && vif1.tag.size == 0) { if(vif1.irq && vif1.tag.size == 0) {
vif1Regs->stat|= VIF1_STAT_INT; vif1Regs->stat|= VIF1_STAT_INT;
hwIntcIrq(INTC_VIF1); hwIntcIrq(INTC_VIF1);
@ -594,15 +617,35 @@ void vifMFIFOInterrupt()
} }
} }
if(vif1.done != 1) {
if(vif1.done != 1 || vif1.inprogress & 1) {
if(vifqwc <= 0){ if(vifqwc <= 0){
//SysPrintf("Empty\n"); //SysPrintf("Empty\n");
vif1.inprogress |= 0x10;
hwDmacIrq(14); hwDmacIrq(14);
return; return;
} }
mfifoVIF1transfer(0); if(!(vif1.inprogress & 0x1)) mfifoVIF1transfer(0);
if (vif1ch->madr >= psHu32(DMAC_RBOR) && vif1ch->madr <= (psHu32(DMAC_RBOR)+psHu32(DMAC_RBSR)))
{
CPU_INT(10, min( (int)vifqwc, (int)vif1ch->qwc ) * BIAS);
}
else
{
CPU_INT(10, vif1ch->qwc * BIAS);
}
return; return;
} } else if(vifqwc <= 0){
//SysPrintf("Empty\n");
//vif1.inprogress |= 0x10;
hwDmacIrq(14);
//return;
}
//On a TIE break we do not clear the MFIFO (Art of Fighting) //On a TIE break we do not clear the MFIFO (Art of Fighting)
//If we dont clear it on MFIFO end, Tekken Tag breaks, understandably (Refraction) //If we dont clear it on MFIFO end, Tekken Tag breaks, understandably (Refraction)

View File

@ -505,15 +505,15 @@ static void VIFunpack(u32 *data, vifCode *v, int size, const unsigned int VIFdma
#else #else
if( VIFdmanum ) { if( VIFdmanum ) {
__asm__(".intel_syntax noprefix\n" __asm__(".intel_syntax noprefix\n"
"movaps xmm6, xmmword ptr [%0]\n" "movaps xmm6, xmmword ptr [%[g_vifRow1]]\n"
"movaps xmm7, xmmword ptr [%1]\n" "movaps xmm7, xmmword ptr [%[g_vifCol1]]\n"
".att_syntax\n" : :"r"(g_vifRow1), "r"(g_vifCol1) ); ".att_syntax\n" : :[g_vifRow1]"r"(g_vifRow1), [g_vifCol1]"r"(g_vifCol1) );
} }
else { else {
__asm__(".intel_syntax noprefix\n" __asm__(".intel_syntax noprefix\n"
"movaps xmm6, xmmword ptr [%0]\n" "movaps xmm6, xmmword ptr [%[g_vifRow0]]\n"
"movaps xmm7, xmmword ptr [%1]\n" "movaps xmm7, xmmword ptr [%[g_vifCol0]]\n"
".att_syntax\n" : : "r"(g_vifRow0), "r"(g_vifCol0) ); ".att_syntax\n" : : [g_vifRow0]"r"(g_vifRow0), [g_vifCol0]"r"(g_vifCol0) );
} }
#endif #endif
@ -1344,23 +1344,17 @@ void vif0Reset() {
void SaveState::vif0Freeze() void SaveState::vif0Freeze()
{ {
FreezeTag( "VIFdma" );
// Dunno if this one is needed, but whatever, it's small. :) // Dunno if this one is needed, but whatever, it's small. :)
if( GetVersion() >= 0x04 ) Freeze( g_vifCycles );
Freeze( g_vifCycles );
Freeze( vif0 ); Freeze( vif0 );
if( GetVersion() >= 0x04 )
{ Freeze( g_vif0HasMask3 );
Freeze( g_vif0HasMask3 ); Freeze( g_vif0Masks );
Freeze( g_vif0Masks ); Freeze( g_vifRow0 );
Freeze( g_vifRow0 ); Freeze( g_vifCol0 );
Freeze( g_vifCol0 );
}
else if( IsLoading() )
{
// Hack to "help" old savestates recover...
SetNewMask(g_vif0Masks, g_vif0HasMask3, vif0Regs->mask, ~vif0Regs->mask);
}
} }
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
@ -1856,23 +1850,23 @@ int VIF1transfer(u32 *data, int size, int istag) {
transferred += size - vif1.vifpacketsize; transferred += size - vif1.vifpacketsize;
g_vifCycles+= (transferred>>2)*BIAS; /* guessing */ g_vifCycles+= (transferred>>2)*BIAS; /* guessing */
vif1.irqoffset = transferred%4; // cannot lose the offset
if (vif1.irq && vif1.cmd == 0) { if (vif1.irq && vif1.cmd == 0) {
vif1.vifstalled = 1; vif1.vifstalled = 1;
if(((vif1Regs->code >> 24) & 0x7f) != 0x7)vif1Regs->stat|= VIF1_STAT_VIS; // Note: commenting this out fixes WALL-E if(((vif1Regs->code >> 24) & 0x7f) != 0x7)vif1Regs->stat|= VIF1_STAT_VIS; // Note: commenting this out fixes WALL-E
// spiderman doesn't break on qw boundaries // spiderman doesn't break on qw boundaries
vif1.irqoffset = transferred%4; // cannot lose the offset
if( istag ) { if( istag ) {
return -2; return -2;
} }
transferred = transferred >> 2; transferred = transferred >> 2;
vif1ch->madr+= (transferred << 4); vif1ch->madr+= (transferred << 4);
vif1ch->qwc-= transferred; vif1ch->qwc-= transferred;
if(vif1ch->qwc == 0 && vif1.irqoffset == 0) vif1.inprogress = 0;
//SysPrintf("Stall on vif1, FromSPR = %x, Vif1MADR = %x Sif0MADR = %x STADR = %x\n", psHu32(0x1000d010), vif1ch->madr, psHu32(0x1000c010), psHu32(DMAC_STADR)); //SysPrintf("Stall on vif1, FromSPR = %x, Vif1MADR = %x Sif0MADR = %x STADR = %x\n", psHu32(0x1000d010), vif1ch->madr, psHu32(0x1000c010), psHu32(DMAC_STADR));
return -2; return -2;
} }
@ -1885,198 +1879,13 @@ int VIF1transfer(u32 *data, int size, int istag) {
transferred = transferred >> 2; transferred = transferred >> 2;
vif1ch->madr+= (transferred << 4); vif1ch->madr+= (transferred << 4);
vif1ch->qwc-= transferred; vif1ch->qwc-= transferred;
if(vif1ch->qwc == 0 && vif1.irqoffset == 0) vif1.inprogress = 0;
} }
return 0; return 0;
} }
int _VIF1chain() { void vif1TransferFromMemory(){
u32 *pMem;
//u32 qwc = vif1ch->qwc;
u32 ret;
if (vif1ch->qwc == 0 && vif1.vifstalled == 0) return 0;
pMem = (u32*)dmaGetAddr(vif1ch->madr);
if (pMem == NULL)
return -1;
VIF_LOG("VIF1chain size=%d, madr=%lx, tadr=%lx\n",
vif1ch->qwc, vif1ch->madr, vif1ch->tadr);
if( vif1.vifstalled ) {
ret = VIF1transfer(pMem+vif1.irqoffset, vif1ch->qwc*4-vif1.irqoffset, 0);
}
else {
ret = VIF1transfer(pMem, vif1ch->qwc*4, 0);
}
/*vif1ch->madr+= (vif1ch->qwc << 4);
vif1ch->qwc-= qwc;*/
return ret;
}
static int prevvifcycles = 0;
static u32* prevviftag = NULL;
u32 *vif1ptag;
int _chainVIF1() {
int id;
int ret;
vif1ptag = (u32*)dmaGetAddr(vif1ch->tadr); //Set memory pointer to TADR
if (vif1ptag == NULL) { //Is vif0ptag empty?
SysPrintf("Vif1 Tag BUSERR\n");
vif1ch->chcr = ( vif1ch->chcr & 0xFFFF ) | ( (*vif1ptag) & 0xFFFF0000 ); //Transfer upper part of tag to CHCR bits 31-15
psHu32(DMAC_STAT)|= 1<<15; //If yes, set BEIS (BUSERR) in DMAC_STAT register
return -1; //Return -1 as an error has occurred
}
id = (vif1ptag[0] >> 28) & 0x7; //ID for DmaChain copied from bit 28 of the tag
vif1ch->qwc = (u16)vif1ptag[0]; //QWC set to lower 16bits of the tag
vif1ch->madr = vif1ptag[1]; //MADR = ADDR field
g_vifCycles+=1; // Add 1 g_vifCycles from the QW read for the tag
vif1ch->chcr = ( vif1ch->chcr & 0xFFFF ) | ( (*vif1ptag) & 0xFFFF0000 ); //Transfer upper part of tag to CHCR bits 31-15
// Transfer dma tag if tte is set
VIF_LOG("VIF1 Tag %8.8x_%8.8x size=%d, id=%d, madr=%lx, tadr=%lx\n",
vif1ptag[1], vif1ptag[0], vif1ch->qwc, id, vif1ch->madr, vif1ch->tadr);
//} else
if (!vif1.done && (psHu32(DMAC_CTRL) & 0xC0) == 0x40 && id == 4) { // STD == VIF1
//vif1.done |= hwDmacSrcChainWithStack(vif1ch, id);
// there are still bugs, need to also check if gif->madr +16*qwc >= stadr, if not, stall
if( (vif1ch->madr + vif1ch->qwc * 16) >= psHu32(DMAC_STADR) ) {
// stalled
hwDmacIrq(13);
return 0;
}
}
if (vif1ch->chcr & 0x40) {
if(vif1.vifstalled == 1) ret = VIF1transfer(vif1ptag+(2+vif1.irqoffset), 2-vif1.irqoffset, 1); //Transfer Tag on stall
else ret = VIF1transfer(vif1ptag+2, 2, 1); //Transfer Tag
if (ret == -1) return -1; //There has been an error
if (ret == -2) {
return -2; //IRQ set by VIFTransfer
}
}
vif1.done |= hwDmacSrcChainWithStack(vif1ch, id);
ret = _VIF1chain(); //Transfers the data set by the switch
if ((vif1ch->chcr & 0x80) && (vif1ptag[0] >> 31)) { //Check TIE bit of CHCR and IRQ bit of tag
VIF_LOG( "dmaIrq Set\n" );
vif1.done = 1;
return 0; //End Transfer
}
return vif1.done;//Return Done
}
__forceinline void vif1Interrupt() {
VIF_LOG("vif1Interrupt: %8.8x\n", cpuRegs.cycle);
g_vifCycles = 0;
if(vif1.irq && vif1.tag.size == 0) {
vif1Regs->stat|= VIF1_STAT_INT;
hwIntcIrq(VIF1intc);
--vif1.irq;
if(vif1Regs->stat & (VIF1_STAT_VSS|VIF1_STAT_VIS|VIF1_STAT_VFS))
{
vif1Regs->stat&= ~0x1F000000; // FQC=0
// One game doesnt like vif stalling at end, cant remember what. Spiderman isnt keen on it tho
vif1ch->chcr &= ~0x100;
return;
}
if(vif1ch->qwc > 0 || vif1.irqoffset > 0){
if(vif1.stallontag == 1) {
_chainVIF1();
}
else _VIF1chain();//CPU_INT(13, vif1ch->qwc * BIAS);
CPU_INT(1, g_vifCycles);
return;
}
}
//}
if((vif1ch->chcr & 0x100) == 0) SysPrintf("Vif1 running when CHCR == %x\n", vif1ch->chcr);
if ((vif1ch->chcr & 0x104) == 0x104 && vif1.done == 0) {
if( !(psHu32(DMAC_CTRL) & 0x1) ) {
SysPrintf("vif1 dma masked\n");
return;
}
_chainVIF1();
CPU_INT(1, g_vifCycles);
return;
}
#ifdef PCSX2_DEVBUILD
if(vif1ch->qwc > 0) SysPrintf("VIF1 Ending with %x QWC left\n");
if(vif1.cmd != 0) SysPrintf("vif1.cmd still set %x\n", vif1.cmd);
#endif
prevviftag = NULL;
prevvifcycles = 0;
vif1ch->chcr &= ~0x100;
g_vifCycles = 0;
hwDmacIrq(DMAC_VIF1);
if(vif1Regs->mskpath3 == 0 || (vif1ch->chcr & 0x1) == 0x1)vif1Regs->stat&= ~0x1F000000; // FQC=0
}
#define spr0 ((DMACh*)&PS2MEM_HW[0xD000])
void dmaVIF1()
{
VIF_LOG("dmaVIF1 chcr = %lx, madr = %lx, qwc = %lx\n"
" tadr = %lx, asr0 = %lx, asr1 = %lx\n",
vif1ch->chcr, vif1ch->madr, vif1ch->qwc,
vif1ch->tadr, vif1ch->asr0, vif1ch->asr1 );
g_vifCycles = 0;
if (((psHu32(DMAC_CTRL) & 0xC) == 0x8)) { // VIF MFIFO
//SysPrintf("VIFMFIFO\n");
if(!(vif1ch->chcr & 0x4)) SysPrintf("MFIFO mode != Chain! %x\n", vif1ch->chcr);
if(vif1ch->madr != spr0->madr)vifMFIFOInterrupt();
return;
}
#ifdef PCSX2_DEVBUILD
if ((psHu32(DMAC_CTRL) & 0xC0) == 0x40) { // STD == VIF1
//SysPrintf("VIF Stall Control Source = %x, Drain = %x\n", (psHu32(0xe000) >> 4) & 0x3, (psHu32(0xe000) >> 6) & 0x3);
//return;
}
#endif
vif1Regs->stat|= 0x10000000; // FQC=16
if (!(vif1ch->chcr & 0x4) || vif1ch->qwc > 0) { // Normal Mode
if ((psHu32(DMAC_CTRL) & 0xC0) == 0x40) {
SysPrintf("DMA Stall Control on VIF1 normal\n");
}
if ((vif1ch->chcr & 0x1)) { // to Memory
if(_VIF1chain() == -2) {
SysPrintf("Stall on normal\n");
//vif1.vifstalled = 1;
}
CPU_INT(1, g_vifCycles);
} else {
int size; int size;
u64* pMem = (u64*)dmaGetAddr(vif1ch->madr); u64* pMem = (u64*)dmaGetAddr(vif1ch->madr);
@ -2122,11 +1931,279 @@ void dmaVIF1()
g_vifCycles += vif1ch->qwc * 2; g_vifCycles += vif1ch->qwc * 2;
vif1ch->madr += vif1ch->qwc * 16; // mgs3 scene changes vif1ch->madr += vif1ch->qwc * 16; // mgs3 scene changes
vif1ch->qwc = 0; vif1ch->qwc = 0;
CPU_INT(1, g_vifCycles); }
int _VIF1chain() {
u32 *pMem;
//u32 qwc = vif1ch->qwc;
u32 ret;
if (vif1ch->qwc == 0 && vif1.vifstalled == 0 && vif1.irqoffset == 0) {
vif1.inprogress = 0;
return 0;
}
if(vif1.dmamode == 1){
vif1TransferFromMemory();
vif1.inprogress = 0;
return 0;
}
pMem = (u32*)dmaGetAddr(vif1ch->madr);
if (pMem == NULL)
return -1;
VIF_LOG("VIF1chain size=%d, madr=%lx, tadr=%lx\n",
vif1ch->qwc, vif1ch->madr, vif1ch->tadr);
if( vif1.vifstalled ) {
ret = VIF1transfer(pMem+vif1.irqoffset, vif1ch->qwc*4-vif1.irqoffset, 0);
}
else {
ret = VIF1transfer(pMem, vif1ch->qwc*4, 0);
}
/*vif1ch->madr+= (vif1ch->qwc << 4);
vif1ch->qwc-= qwc;*/
return ret;
}
static int prevvifcycles = 0;
static u32* prevviftag = NULL;
u32 *vif1ptag;
int _chainVIF1() {
return vif1.done;//Return Done
}
__forceinline void vif1SetupTransfer() {
switch(vif1.dmamode){
case 0: //Normal
case 1: //Normal (From memory)
vif1.inprogress = 1;
vif1.done = 1;
break;
case 2: //Chain
int id;
int ret;
vif1ptag = (u32*)dmaGetAddr(vif1ch->tadr); //Set memory pointer to TADR
if (vif1ptag == NULL) { //Is vif0ptag empty?
SysPrintf("Vif1 Tag BUSERR\n");
vif1ch->chcr = ( vif1ch->chcr & 0xFFFF ) | ( (*vif1ptag) & 0xFFFF0000 ); //Transfer upper part of tag to CHCR bits 31-15
psHu32(DMAC_STAT)|= 1<<15; //If yes, set BEIS (BUSERR) in DMAC_STAT register
return; //Return -1 as an error has occurred
}
id = (vif1ptag[0] >> 28) & 0x7; //ID for DmaChain copied from bit 28 of the tag
vif1ch->qwc = (u16)vif1ptag[0]; //QWC set to lower 16bits of the tag
vif1ch->madr = vif1ptag[1]; //MADR = ADDR field
g_vifCycles+=1; // Add 1 g_vifCycles from the QW read for the tag
vif1ch->chcr = ( vif1ch->chcr & 0xFFFF ) | ( (*vif1ptag) & 0xFFFF0000 ); //Transfer upper part of tag to CHCR bits 31-15
// Transfer dma tag if tte is set
VIF_LOG("VIF1 Tag %8.8x_%8.8x size=%d, id=%d, madr=%lx, tadr=%lx\n",
vif1ptag[1], vif1ptag[0], vif1ch->qwc, id, vif1ch->madr, vif1ch->tadr);
//} else
if (!vif1.done && (psHu32(DMAC_CTRL) & 0xC0) == 0x40 && id == 4) { // STD == VIF1
//vif1.done |= hwDmacSrcChainWithStack(vif1ch, id);
// there are still bugs, need to also check if gif->madr +16*qwc >= stadr, if not, stall
if( (vif1ch->madr + vif1ch->qwc * 16) >= psHu32(DMAC_STADR) ) {
// stalled
hwDmacIrq(13);
return;
}
}
if (vif1ch->chcr & 0x40) {
if(vif1.vifstalled == 1) ret = VIF1transfer(vif1ptag+(2+vif1.irqoffset), 2-vif1.irqoffset, 1); //Transfer Tag on stall
else ret = VIF1transfer(vif1ptag+2, 2, 1); //Transfer Tag
if (ret == -1) return; //There has been an error
if (ret == -2) {
return; //IRQ set by VIFTransfer
}
}
vif1.inprogress = 1;
vif1.done |= hwDmacSrcChainWithStack(vif1ch, id);
if ((vif1ch->chcr & 0x80) && (vif1ptag[0] >> 31)) { //Check TIE bit of CHCR and IRQ bit of tag
VIF_LOG( "dmaIrq Set\n" );
vif1.done = 1;
return; //End Transfer
}
break;
}
}
__forceinline void vif1Interrupt() {
VIF_LOG("vif1Interrupt: %8.8x\n", cpuRegs.cycle);
g_vifCycles = 0;
//}
if((vif1ch->chcr & 0x100) == 0) SysPrintf("Vif1 running when CHCR == %x\n", vif1ch->chcr);
if(vif1.inprogress == 1) _VIF1chain();
if(vif1.irq && vif1.tag.size == 0)
{
vif1Regs->stat|= VIF1_STAT_INT;
hwIntcIrq(VIF1intc);
--vif1.irq;
if(vif1Regs->stat & (VIF1_STAT_VSS|VIF1_STAT_VIS|VIF1_STAT_VFS))
{
vif1Regs->stat&= ~0x1F000000; // FQC=0
// One game doesnt like vif stalling at end, cant remember what. Spiderman isnt keen on it tho
vif1ch->chcr &= ~0x100;
return;
}
else if(vif1ch->qwc > 0 || vif1.irqoffset > 0)
{
if(vif1.stallontag == 1)
{
vif1SetupTransfer();
}
else _VIF1chain();//CPU_INT(13, vif1ch->qwc * BIAS);
} }
vif1.done = 1; }
if (vif1.done == 0 || vif1.inprogress == 1) {
if( !(psHu32(DMAC_CTRL) & 0x1) ) {
SysPrintf("vif1 dma masked\n");
return;
}
//_chainVIF1();
if(vif1.inprogress == 0)vif1SetupTransfer();
CPU_INT(1, vif1ch->qwc * BIAS);
return; return;
} }
#ifdef PCSX2_DEVBUILD
if(vif1ch->qwc > 0) SysPrintf("VIF1 Ending with %x QWC left\n");
if(vif1.cmd != 0) SysPrintf("vif1.cmd still set %x\n", vif1.cmd);
#endif
prevviftag = NULL;
prevvifcycles = 0;
vif1ch->chcr &= ~0x100;
g_vifCycles = 0;
hwDmacIrq(DMAC_VIF1);
if(vif1Regs->mskpath3 == 0 || (vif1ch->chcr & 0x1) == 0x1)vif1Regs->stat&= ~0x1F000000; // FQC=0
}
#define spr0 ((DMACh*)&PS2MEM_HW[0xD000])
void dmaVIF1()
{
VIF_LOG("dmaVIF1 chcr = %lx, madr = %lx, qwc = %lx\n"
" tadr = %lx, asr0 = %lx, asr1 = %lx\n",
vif1ch->chcr, vif1ch->madr, vif1ch->qwc,
vif1ch->tadr, vif1ch->asr0, vif1ch->asr1 );
g_vifCycles = 0;
vif1.inprogress = 0;
if (((psHu32(DMAC_CTRL) & 0xC) == 0x8)) { // VIF MFIFO
//SysPrintf("VIFMFIFO\n");
if(!(vif1ch->chcr & 0x4)) SysPrintf("MFIFO mode != Chain! %x\n", vif1ch->chcr);
/*if(vif1ch->madr != spr0->madr)*/vifMFIFOInterrupt();
//else vif1.inprogress |= 0x10;
return;
}
#ifdef PCSX2_DEVBUILD
if ((psHu32(DMAC_CTRL) & 0xC0) == 0x40) { // STD == VIF1
//SysPrintf("VIF Stall Control Source = %x, Drain = %x\n", (psHu32(0xe000) >> 4) & 0x3, (psHu32(0xe000) >> 6) & 0x3);
//return;
}
#endif
vif1Regs->stat|= 0x10000000; // FQC=16
if (!(vif1ch->chcr & 0x4) || vif1ch->qwc > 0) { // Normal Mode
if ((psHu32(DMAC_CTRL) & 0xC0) == 0x40) {
SysPrintf("DMA Stall Control on VIF1 normal\n");
}
if ((vif1ch->chcr & 0x1)) { // to Memory
/*if(_VIF1chain() == -2) {
SysPrintf("Stall on normal\n");
//vif1.vifstalled = 1;
}
CPU_INT(1, g_vifCycles);*/
vif1.dmamode = 0;
} else {
vif1.dmamode = 1;
/*int size;
u64* pMem = (u64*)dmaGetAddr(vif1ch->madr);
// VIF from gsMemory
if (pMem == NULL) { //Is vif0ptag empty?
SysPrintf("Vif1 Tag BUSERR\n");
psHu32(DMAC_STAT)|= 1<<15; //If yes, set BEIS (BUSERR) in DMAC_STAT register
vif1.done = 1;
vif1Regs->stat&= ~0x1f000000;
vif1ch->qwc = 0;
CPU_INT(1, 0);
return; //Return -1 as an error has occurred
}
// MTGS concerns: The MTGS is inherently disagreeable with the idea of downloading
// stuff from the GS. The *only* way to handle this case safely is to flush the GS
// completely and execute the transfer there-after.
FreezeXMMRegs(1);
if( GSreadFIFO2 == NULL ) {
for (size=vif1ch->qwc; size>0; --size) {
if (size > 1 ) {
mtgsWaitGS();
GSreadFIFO((u64*)&PS2MEM_HW[0x5000]);
}
pMem[0] = psHu64(0x5000);
pMem[1] = psHu64(0x5008); pMem+= 2;
}
}
else {
mtgsWaitGS();
GSreadFIFO2(pMem, vif1ch->qwc);
// set incase read
psHu64(0x5000) = pMem[2*vif1ch->qwc-2];
psHu64(0x5008) = pMem[2*vif1ch->qwc-1];
}
FreezeXMMRegs(0);
if(vif1Regs->mskpath3 == 0)vif1Regs->stat&= ~0x1f000000;
g_vifCycles += vif1ch->qwc * 2;
vif1ch->madr += vif1ch->qwc * 16; // mgs3 scene changes
vif1ch->qwc = 0;
CPU_INT(1, g_vifCycles);*/
}
/*vif1.done = 1;
return;*/
} else vif1.dmamode = 2;
// Chain Mode // Chain Mode
vif1.done = 0; vif1.done = 0;
@ -2154,6 +2231,7 @@ void vif1Write32(u32 mem, u32 value) {
psHu64(0x10005008) = 0; psHu64(0x10005008) = 0;
vif1.done = 1; vif1.done = 1;
vif1Regs->err = 0; vif1Regs->err = 0;
vif1.inprogress = 0;
vif1Regs->stat&= ~(0x1F800000|VIF1_STAT_INT|VIF1_STAT_VSS|VIF1_STAT_VIS|VIF1_STAT_VFS|VIF1_STAT_VPS); // FQC=0 vif1Regs->stat&= ~(0x1F800000|VIF1_STAT_INT|VIF1_STAT_VSS|VIF1_STAT_VIS|VIF1_STAT_VFS|VIF1_STAT_VPS); // FQC=0
} }
if (value & 0x2) { if (value & 0x2) {
@ -2192,15 +2270,18 @@ void vif1Write32(u32 mem, u32 value) {
g_vifCycles = 0; g_vifCycles = 0;
// loop necessary for spiderman // loop necessary for spiderman
if((psHu32(DMAC_CTRL) & 0xC) == 0x8){ if((psHu32(DMAC_CTRL) & 0xC) == 0x8){
//SysPrintf("MFIFO Stall\n");
CPU_INT(10, 0);
}else {
if(vif1.stallontag == 1){
//SysPrintf("Sorting VIF Stall on tag\n");
_chainVIF1();
} else _VIF1chain();
CPU_INT(1, g_vifCycles); // Gets the timing right - Flatout //SysPrintf("MFIFO Stall\n");
//CPU_INT(10, 0);
CPU_INT(10, vif1ch->qwc * BIAS);
}else {
/*if(vif1.stallontag == 1){
//SysPrintf("Sorting VIF Stall on tag\n");
vif1SetupTransfer();
} *///else _VIF1chain();
//CPU_INT(1, g_vifCycles); // Gets the timing right - Flatout
CPU_INT(1, vif1ch->qwc * BIAS);
} }
vif1ch->chcr |= 0x100; vif1ch->chcr |= 0x100;
} }
@ -2270,16 +2351,8 @@ void SaveState::vif1Freeze()
{ {
Freeze(vif1); Freeze(vif1);
if( GetVersion() >= 0x04 ) Freeze( g_vif1HasMask3 );
{ Freeze( g_vif1Masks );
Freeze( g_vif1HasMask3 ); Freeze( g_vifRow1 );
Freeze( g_vif1Masks ); Freeze( g_vifCol1 );
Freeze( g_vifRow1 );
Freeze( g_vifCol1 );
}
else if( IsLoading() )
{
SetNewMask(g_vif1Masks, g_vif1HasMask3, vif1Regs->mask, ~vif1Regs->mask);
//if(vif1ch->chcr & 0x100) vif1.done = 0;
}
} }

View File

@ -40,6 +40,8 @@ struct vifStruct {
u8 irqoffset; // 32bit offset where next vif code is u8 irqoffset; // 32bit offset where next vif code is
u32 savedtag; // need this for backwards compat with save states u32 savedtag; // need this for backwards compat with save states
u32 vifpacketsize; u32 vifpacketsize;
u8 inprogress;
u8 dmamode;
}; };
extern vifStruct vif0, vif1; extern vifStruct vif0, vif1;

View File

@ -209,10 +209,21 @@ static void number(std::string& dest, T num, int base, int size, int precision,
tmp[i++] = '0'; tmp[i++] = '0';
else else
{ {
while (num != 0) if( base == 16 )
{ {
tmp[i++] = dig[num % (uint) base]; while (num != 0)
num = num / (uint) base; {
tmp[i++] = dig[num & 0xf];
num = (uint)num >> 4;
}
}
else
{
while (num != 0)
{
tmp[i++] = dig[num % (uint) base];
num /= (uint) base;
}
} }
} }
@ -232,10 +243,16 @@ static void number(std::string& dest, T num, int base, int size, int precision,
} }
} }
if (!(type & LEFT)) while (size-- > 0) dest += c;
while (i < precision--) dest += '0'; if( !(type & LEFT) && size > 0) { dest.append( size, c ); size = 0; }
if( i < precision ) dest.append( precision-i, '0' );
while (i-- > 0) dest += tmp[i]; while (i-- > 0) dest += tmp[i];
while (size-- > 0) dest += ' '; if( size > 0 ) dest.append( size, ' ' );
//if (!(type & LEFT)) while (size-- > 0) dest += c;
//while (i < precision--) dest += '0';
//while (i-- > 0) dest += tmp[i];
//while (size-- > 0) dest += ' ';
} }
static void eaddr( std::string& dest, unsigned char *addr, int size, int precision, int type) static void eaddr( std::string& dest, unsigned char *addr, int size, int precision, int type)
@ -451,7 +468,7 @@ static void flt( std::string& dest, double num, int size, int precision, char fm
{ {
char tmp[80]; char tmp[80];
char c, sign; char c, sign;
int n, i; int n;
// Left align means no zero padding // Left align means no zero padding
if (flags & LEFT) flags &= ~ZEROPAD; if (flags & LEFT) flags &= ~ZEROPAD;
@ -498,11 +515,12 @@ static void flt( std::string& dest, double num, int size, int precision, char fm
// Output number with alignment and padding // Output number with alignment and padding
size -= n; size -= n;
if (!(flags & (ZEROPAD | LEFT))) while (size-- > 0) dest += ' ';
if (!(flags & (ZEROPAD | LEFT)) && size > 0) { dest.append( size, ' ' ); size = 0; }
if (sign) dest += sign; if (sign) dest += sign;
if (!(flags & LEFT)) while (size-- > 0) dest += c; if (!(flags & LEFT) && size > 0) { dest.append( size, c ); size = 0; }
for (i = 0; i < n; i++) dest += tmp[i]; dest.append( tmp, n );
while (size-- > 0) dest += ' '; if(size > 0) dest.append( size, ' ' );
} }
#endif #endif
@ -520,11 +538,7 @@ void vssappendf(std::string& dest, const char* format, va_list args)
int precision; // Min. # of digits for integers; max number of chars for from string int precision; // Min. # of digits for integers; max number of chars for from string
int qualifier; // 'h', 'l', or 'L' for integer fields int qualifier; // 'h', 'l', or 'L' for integer fields
// Optimization: Memory is cheap. Allocating it on the fly is not. Allocate more room for( const char* fmt = format; *fmt; ++fmt )
// than we'll likely need right upfront!
dest.reserve( strlen( format ) * 2 );
for( const char* fmt = format; *fmt; fmt++ )
{ {
if (*fmt != '%') if (*fmt != '%')
{ {
@ -607,16 +621,26 @@ repeat:
if( precision < 0 ) if( precision < 0 )
{ {
// no precision override so just copy the whole string. // no precision override so just copy the whole string.
if (!(flags & LEFT)) while (len < field_width--) dest += ' '; if (!(flags & LEFT) && (len < field_width))
{
dest.append( field_width - len, ' ' );
field_width = 0;
}
dest += *ss; dest += *ss;
} }
else else
{ {
if( len > precision ) len = precision; if( len > precision ) len = precision;
if (!(flags & LEFT)) while (len < field_width--) dest += ' '; if (!(flags & LEFT) && (len < field_width))
{
dest.append( field_width - len, ' ' );
field_width = 0;
}
dest.append( ss->begin(), ss->begin()+len ); dest.append( ss->begin(), ss->begin()+len );
} }
while (len < field_width--) dest += ' ';
if( len < field_width )
dest.append( field_width - len, ' ' );
} }
else else
{ {
@ -736,7 +760,12 @@ repeat:
void vssprintf( std::string& dest, const char* format, va_list args ) void vssprintf( std::string& dest, const char* format, va_list args )
{ {
// Optimization: Memory is cheap. Allocating it on the fly is not. Allocate more room
// than we'll likely need right upfront! Also, strlen is slow, so better to just pick an
// arbitrarily generous value to reserve instead of basing it on string length.
dest.clear(); dest.clear();
dest.reserve( 96 );
vssappendf( dest, format, args ); vssappendf( dest, format, args );
} }
@ -807,6 +836,5 @@ std::string vfmt_string( const char* fmt, va_list args )
std::string retval; std::string retval;
vssprintf( retval, fmt, args ); vssprintf( retval, fmt, args );
return retval; return retval;
} }

View File

@ -50,13 +50,7 @@ using namespace vtlb_private;
namespace vtlb_private namespace vtlb_private
{ {
s32 pmap[VTLB_PMAP_ITEMS]; //512KB PCSX2_ALIGNED( 64, MapData vtlbdata );
s32 vmap[VTLB_VMAP_ITEMS]; //4MB
// first indexer -- 8/16/32/64/128 bit tables [values 0-4]
// second indexer -- read/write [0 or 1]
// third indexer -- 128 pages of memory!
void* RWFT[5][2][128];
} }
vtlbHandler vtlbHandlerCount=0; vtlbHandler vtlbHandlerCount=0;
@ -97,11 +91,11 @@ callfunction:
// Interpreter Implementations of VTLB Memory Operations. // Interpreter Implementations of VTLB Memory Operations.
// See recVTLB.cpp for the dynarec versions. // See recVTLB.cpp for the dynarec versions.
// Interpreterd VTLB lookup for 8, 16, and 32 bit accesses // Interpreted VTLB lookup for 8, 16, and 32 bit accesses
template<int DataSize,typename DataType> template<int DataSize,typename DataType>
__forceinline DataType __fastcall MemOp_r0(u32 addr) __forceinline DataType __fastcall MemOp_r0(u32 addr)
{ {
u32 vmv=vmap[addr>>VTLB_PAGE_BITS]; u32 vmv=vtlbdata.vmap[addr>>VTLB_PAGE_BITS];
s32 ppf=addr+vmv; s32 ppf=addr+vmv;
if (!(ppf<0)) if (!(ppf<0))
@ -111,13 +105,13 @@ __forceinline DataType __fastcall MemOp_r0(u32 addr)
u32 hand=(u8)vmv; u32 hand=(u8)vmv;
u32 paddr=ppf-hand+0x80000000; u32 paddr=ppf-hand+0x80000000;
//SysPrintf("Translated 0x%08X to 0x%08X\n",addr,paddr); //SysPrintf("Translated 0x%08X to 0x%08X\n",addr,paddr);
//return reinterpret_cast<TemplateHelper<DataSize,false>::HandlerType*>(RWFT[TemplateHelper<DataSize,false>::sidx][0][hand])(paddr,data); //return reinterpret_cast<TemplateHelper<DataSize,false>::HandlerType*>(vtlbdata.RWFT[TemplateHelper<DataSize,false>::sidx][0][hand])(paddr,data);
switch( DataSize ) switch( DataSize )
{ {
case 8: return ((vtlbMemR8FP*)RWFT[0][0][hand])(paddr); case 8: return ((vtlbMemR8FP*)vtlbdata.RWFT[0][0][hand])(paddr);
case 16: return ((vtlbMemR16FP*)RWFT[1][0][hand])(paddr); case 16: return ((vtlbMemR16FP*)vtlbdata.RWFT[1][0][hand])(paddr);
case 32: return ((vtlbMemR32FP*)RWFT[2][0][hand])(paddr); case 32: return ((vtlbMemR32FP*)vtlbdata.RWFT[2][0][hand])(paddr);
jNO_DEFAULT; jNO_DEFAULT;
} }
@ -127,7 +121,7 @@ __forceinline DataType __fastcall MemOp_r0(u32 addr)
template<int DataSize,typename DataType> template<int DataSize,typename DataType>
__forceinline void __fastcall MemOp_r1(u32 addr, DataType* data) __forceinline void __fastcall MemOp_r1(u32 addr, DataType* data)
{ {
u32 vmv=vmap[addr>>VTLB_PAGE_BITS]; u32 vmv=vtlbdata.vmap[addr>>VTLB_PAGE_BITS];
s32 ppf=addr+vmv; s32 ppf=addr+vmv;
if (!(ppf<0)) if (!(ppf<0))
@ -146,8 +140,8 @@ __forceinline void __fastcall MemOp_r1(u32 addr, DataType* data)
switch( DataSize ) switch( DataSize )
{ {
case 64: ((vtlbMemR64FP*)RWFT[3][0][hand])(paddr, data); break; case 64: ((vtlbMemR64FP*)vtlbdata.RWFT[3][0][hand])(paddr, data); break;
case 128: ((vtlbMemR128FP*)RWFT[4][0][hand])(paddr, data); break; case 128: ((vtlbMemR128FP*)vtlbdata.RWFT[4][0][hand])(paddr, data); break;
jNO_DEFAULT; jNO_DEFAULT;
} }
@ -157,7 +151,7 @@ __forceinline void __fastcall MemOp_r1(u32 addr, DataType* data)
template<int DataSize,typename DataType> template<int DataSize,typename DataType>
__forceinline void __fastcall MemOp_w0(u32 addr, DataType data) __forceinline void __fastcall MemOp_w0(u32 addr, DataType data)
{ {
u32 vmv=vmap[addr>>VTLB_PAGE_BITS]; u32 vmv=vtlbdata.vmap[addr>>VTLB_PAGE_BITS];
s32 ppf=addr+vmv; s32 ppf=addr+vmv;
if (!(ppf<0)) if (!(ppf<0))
{ {
@ -172,9 +166,9 @@ __forceinline void __fastcall MemOp_w0(u32 addr, DataType data)
switch( DataSize ) switch( DataSize )
{ {
case 8: return ((vtlbMemW8FP*)RWFT[0][1][hand])(paddr, (u8)data); case 8: return ((vtlbMemW8FP*)vtlbdata.RWFT[0][1][hand])(paddr, (u8)data);
case 16: return ((vtlbMemW16FP*)RWFT[1][1][hand])(paddr, (u16)data); case 16: return ((vtlbMemW16FP*)vtlbdata.RWFT[1][1][hand])(paddr, (u16)data);
case 32: return ((vtlbMemW32FP*)RWFT[2][1][hand])(paddr, (u32)data); case 32: return ((vtlbMemW32FP*)vtlbdata.RWFT[2][1][hand])(paddr, (u32)data);
jNO_DEFAULT; jNO_DEFAULT;
} }
@ -184,7 +178,7 @@ template<int DataSize,typename DataType>
__forceinline void __fastcall MemOp_w1(u32 addr,const DataType* data) __forceinline void __fastcall MemOp_w1(u32 addr,const DataType* data)
{ {
verify(DataSize==128 || DataSize==64); verify(DataSize==128 || DataSize==64);
u32 vmv=vmap[addr>>VTLB_PAGE_BITS]; u32 vmv=vtlbdata.vmap[addr>>VTLB_PAGE_BITS];
s32 ppf=addr+vmv; s32 ppf=addr+vmv;
if (!(ppf<0)) if (!(ppf<0))
{ {
@ -200,8 +194,8 @@ __forceinline void __fastcall MemOp_w1(u32 addr,const DataType* data)
//SysPrintf("Translated 0x%08X to 0x%08X\n",addr,paddr); //SysPrintf("Translated 0x%08X to 0x%08X\n",addr,paddr);
switch( DataSize ) switch( DataSize )
{ {
case 64: return ((vtlbMemW64FP*)RWFT[3][1][hand])(paddr, data); case 64: return ((vtlbMemW64FP*)vtlbdata.RWFT[3][1][hand])(paddr, data);
case 128: return ((vtlbMemW128FP*)RWFT[4][1][hand])(paddr, data); case 128: return ((vtlbMemW128FP*)vtlbdata.RWFT[4][1][hand])(paddr, data);
jNO_DEFAULT; jNO_DEFAULT;
} }
@ -352,17 +346,17 @@ vtlbHandler vtlb_RegisterHandler( vtlbMemR8FP* r8,vtlbMemR16FP* r16,vtlbMemR32FP
//write the code :p //write the code :p
vtlbHandler rv=vtlbHandlerCount++; vtlbHandler rv=vtlbHandlerCount++;
RWFT[0][0][rv] = (r8!=0) ? r8:vtlbDefaultPhyRead8; vtlbdata.RWFT[0][0][rv] = (r8!=0) ? r8:vtlbDefaultPhyRead8;
RWFT[1][0][rv] = (r16!=0) ? r16:vtlbDefaultPhyRead16; vtlbdata.RWFT[1][0][rv] = (r16!=0) ? r16:vtlbDefaultPhyRead16;
RWFT[2][0][rv] = (r32!=0) ? r32:vtlbDefaultPhyRead32; vtlbdata.RWFT[2][0][rv] = (r32!=0) ? r32:vtlbDefaultPhyRead32;
RWFT[3][0][rv] = (r64!=0) ? r64:vtlbDefaultPhyRead64; vtlbdata.RWFT[3][0][rv] = (r64!=0) ? r64:vtlbDefaultPhyRead64;
RWFT[4][0][rv] = (r128!=0) ? r128:vtlbDefaultPhyRead128; vtlbdata.RWFT[4][0][rv] = (r128!=0) ? r128:vtlbDefaultPhyRead128;
RWFT[0][1][rv] = (w8!=0) ? w8:vtlbDefaultPhyWrite8; vtlbdata.RWFT[0][1][rv] = (w8!=0) ? w8:vtlbDefaultPhyWrite8;
RWFT[1][1][rv] = (w16!=0) ? w16:vtlbDefaultPhyWrite16; vtlbdata.RWFT[1][1][rv] = (w16!=0) ? w16:vtlbDefaultPhyWrite16;
RWFT[2][1][rv] = (w32!=0) ? w32:vtlbDefaultPhyWrite32; vtlbdata.RWFT[2][1][rv] = (w32!=0) ? w32:vtlbDefaultPhyWrite32;
RWFT[3][1][rv] = (w64!=0) ? w64:vtlbDefaultPhyWrite64; vtlbdata.RWFT[3][1][rv] = (w64!=0) ? w64:vtlbDefaultPhyWrite64;
RWFT[4][1][rv] = (w128!=0) ? w128:vtlbDefaultPhyWrite128; vtlbdata.RWFT[4][1][rv] = (w128!=0) ? w128:vtlbDefaultPhyWrite128;
return rv; return rv;
} }
@ -382,7 +376,7 @@ void vtlb_MapHandler(vtlbHandler handler,u32 start,u32 size)
while(size>0) while(size>0)
{ {
pmap[start>>VTLB_PAGE_BITS]=value; vtlbdata.pmap[start>>VTLB_PAGE_BITS]=value;
start+=VTLB_PAGE_SIZE; start+=VTLB_PAGE_SIZE;
size-=VTLB_PAGE_SIZE; size-=VTLB_PAGE_SIZE;
@ -407,7 +401,7 @@ void vtlb_MapBlock(void* base,u32 start,u32 size,u32 blocksize)
while(blocksz>0) while(blocksz>0)
{ {
pmap[start>>VTLB_PAGE_BITS]=ptr; vtlbdata.pmap[start>>VTLB_PAGE_BITS]=ptr;
start+=VTLB_PAGE_SIZE; start+=VTLB_PAGE_SIZE;
ptr+=VTLB_PAGE_SIZE; ptr+=VTLB_PAGE_SIZE;
@ -425,7 +419,7 @@ void vtlb_Mirror(u32 new_region,u32 start,u32 size)
while(size>0) while(size>0)
{ {
pmap[start>>VTLB_PAGE_BITS]=pmap[new_region>>VTLB_PAGE_BITS]; vtlbdata.pmap[start>>VTLB_PAGE_BITS]=vtlbdata.pmap[new_region>>VTLB_PAGE_BITS];
start+=VTLB_PAGE_SIZE; start+=VTLB_PAGE_SIZE;
new_region+=VTLB_PAGE_SIZE; new_region+=VTLB_PAGE_SIZE;
@ -435,10 +429,10 @@ void vtlb_Mirror(u32 new_region,u32 start,u32 size)
__forceinline void* vtlb_GetPhyPtr(u32 paddr) __forceinline void* vtlb_GetPhyPtr(u32 paddr)
{ {
if (paddr>=VTLB_PMAP_SZ || pmap[paddr>>VTLB_PAGE_BITS]<0) if (paddr>=VTLB_PMAP_SZ || vtlbdata.pmap[paddr>>VTLB_PAGE_BITS]<0)
return NULL; return NULL;
else else
return reinterpret_cast<void*>(pmap[paddr>>VTLB_PAGE_BITS]+(paddr&VTLB_PAGE_MASK)); return reinterpret_cast<void*>(vtlbdata.pmap[paddr>>VTLB_PAGE_BITS]+(paddr&VTLB_PAGE_MASK));
} }
//virtual mappings //virtual mappings
@ -462,11 +456,11 @@ void vtlb_VMap(u32 vaddr,u32 paddr,u32 sz)
} }
else else
{ {
pme=pmap[paddr>>VTLB_PAGE_BITS]; pme=vtlbdata.pmap[paddr>>VTLB_PAGE_BITS];
if (pme<0) if (pme<0)
pme|=paddr;// top bit is set anyway ... pme|=paddr;// top bit is set anyway ...
} }
vmap[vaddr>>VTLB_PAGE_BITS]=pme-vaddr; vtlbdata.vmap[vaddr>>VTLB_PAGE_BITS]=pme-vaddr;
vaddr+=VTLB_PAGE_SIZE; vaddr+=VTLB_PAGE_SIZE;
paddr+=VTLB_PAGE_SIZE; paddr+=VTLB_PAGE_SIZE;
sz-=VTLB_PAGE_SIZE; sz-=VTLB_PAGE_SIZE;
@ -480,7 +474,7 @@ void vtlb_VMapBuffer(u32 vaddr,void* buffer,u32 sz)
u32 bu8=(u32)buffer; u32 bu8=(u32)buffer;
while(sz>0) while(sz>0)
{ {
vmap[vaddr>>VTLB_PAGE_BITS]=bu8-vaddr; vtlbdata.vmap[vaddr>>VTLB_PAGE_BITS]=bu8-vaddr;
vaddr+=VTLB_PAGE_SIZE; vaddr+=VTLB_PAGE_SIZE;
bu8+=VTLB_PAGE_SIZE; bu8+=VTLB_PAGE_SIZE;
sz-=VTLB_PAGE_SIZE; sz-=VTLB_PAGE_SIZE;
@ -500,7 +494,7 @@ void vtlb_VMapUnmap(u32 vaddr,u32 sz)
} }
handl|=vaddr; // top bit is set anyway ... handl|=vaddr; // top bit is set anyway ...
handl|=0x80000000; handl|=0x80000000;
vmap[vaddr>>VTLB_PAGE_BITS]=handl-vaddr; vtlbdata.vmap[vaddr>>VTLB_PAGE_BITS]=handl-vaddr;
vaddr+=VTLB_PAGE_SIZE; vaddr+=VTLB_PAGE_SIZE;
sz-=VTLB_PAGE_SIZE; sz-=VTLB_PAGE_SIZE;
} }
@ -510,7 +504,7 @@ void vtlb_VMapUnmap(u32 vaddr,u32 sz)
void vtlb_Init() void vtlb_Init()
{ {
vtlbHandlerCount=0; vtlbHandlerCount=0;
memzero_obj(RWFT); memzero_obj(vtlbdata.RWFT);
//Register default handlers //Register default handlers
//Unmapped Virt handlers _MUST_ be registered first. //Unmapped Virt handlers _MUST_ be registered first.

View File

@ -75,9 +75,18 @@ namespace vtlb_private
static const uint VTLB_PMAP_SZ = 0x20000000; static const uint VTLB_PMAP_SZ = 0x20000000;
static const uint VTLB_VMAP_ITEMS = 0x100000000ULL / VTLB_PAGE_SIZE; static const uint VTLB_VMAP_ITEMS = 0x100000000ULL / VTLB_PAGE_SIZE;
extern void* RWFT[5][2][128]; struct MapData
extern s32 pmap[VTLB_PMAP_ITEMS]; //512KB {
extern s32 vmap[VTLB_VMAP_ITEMS]; //4MB s32 pmap[VTLB_PMAP_ITEMS]; //512KB
s32 vmap[VTLB_VMAP_ITEMS]; //4MB
// first indexer -- 8/16/32/64/128 bit tables [values 0-4]
// second indexer -- read/write [0 or 1]
// third indexer -- 128 possible handlers!
void* RWFT[5][2][128];
};
PCSX2_ALIGNED_EXTERN( 64, MapData vtlbdata );
} }
#endif #endif

View File

@ -35,8 +35,6 @@ static void InitRoundClampModes( HWND hDlg, u32 new_eeopt, u32 new_vuopt )
else if (new_vuopt & 0x1) CheckRadioButton(hDlg, IDC_VU_CLAMPMODE0, IDC_VU_CLAMPMODE3, IDC_VU_CLAMPMODE0 + 1); else if (new_vuopt & 0x1) CheckRadioButton(hDlg, IDC_VU_CLAMPMODE0, IDC_VU_CLAMPMODE3, IDC_VU_CLAMPMODE0 + 1);
else CheckRadioButton(hDlg, IDC_VU_CLAMPMODE0, IDC_VU_CLAMPMODE3, IDC_VU_CLAMPMODE0 + 0); else CheckRadioButton(hDlg, IDC_VU_CLAMPMODE0, IDC_VU_CLAMPMODE3, IDC_VU_CLAMPMODE0 + 0);
CheckDlgButton(hDlg, IDC_EE_CHECK3, (new_eeopt & 0x8) ? TRUE : FALSE);
if (new_eeopt & 0x4) CheckRadioButton(hDlg, IDC_EE_CLAMPMODE0, IDC_EE_CLAMPMODE3, IDC_EE_CLAMPMODE0 + 3); if (new_eeopt & 0x4) CheckRadioButton(hDlg, IDC_EE_CLAMPMODE0, IDC_EE_CLAMPMODE3, IDC_EE_CLAMPMODE0 + 3);
else if (new_eeopt & 0x2) CheckRadioButton(hDlg, IDC_EE_CLAMPMODE0, IDC_EE_CLAMPMODE3, IDC_EE_CLAMPMODE0 + 2); else if (new_eeopt & 0x2) CheckRadioButton(hDlg, IDC_EE_CLAMPMODE0, IDC_EE_CLAMPMODE3, IDC_EE_CLAMPMODE0 + 2);
else if (new_eeopt & 0x1) CheckRadioButton(hDlg, IDC_EE_CLAMPMODE0, IDC_EE_CLAMPMODE3, IDC_EE_CLAMPMODE0 + 1); else if (new_eeopt & 0x1) CheckRadioButton(hDlg, IDC_EE_CLAMPMODE0, IDC_EE_CLAMPMODE3, IDC_EE_CLAMPMODE0 + 1);
@ -96,8 +94,6 @@ BOOL APIENTRY AdvancedOptionsProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM
new_eeopt |= IsDlgButtonChecked(hDlg, IDC_EE_CLAMPMODE2) ? 0x3 : 0; new_eeopt |= IsDlgButtonChecked(hDlg, IDC_EE_CLAMPMODE2) ? 0x3 : 0;
new_eeopt |= IsDlgButtonChecked(hDlg, IDC_EE_CLAMPMODE3) ? 0x7 : 0; new_eeopt |= IsDlgButtonChecked(hDlg, IDC_EE_CLAMPMODE3) ? 0x7 : 0;
new_eeopt |= IsDlgButtonChecked(hDlg, IDC_EE_CHECK3) ? 0x8 : 0;
new_vuopt |= IsDlgButtonChecked(hDlg, IDC_VU_CLAMPMODE0) ? 0x0 : 0; new_vuopt |= IsDlgButtonChecked(hDlg, IDC_VU_CLAMPMODE0) ? 0x0 : 0;
new_vuopt |= IsDlgButtonChecked(hDlg, IDC_VU_CLAMPMODE1) ? 0x1 : 0; new_vuopt |= IsDlgButtonChecked(hDlg, IDC_VU_CLAMPMODE1) ? 0x1 : 0;
new_vuopt |= IsDlgButtonChecked(hDlg, IDC_VU_CLAMPMODE2) ? 0x3 : 0; new_vuopt |= IsDlgButtonChecked(hDlg, IDC_VU_CLAMPMODE2) ? 0x3 : 0;

View File

@ -106,7 +106,7 @@
UseOfMFC="0" UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false" ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2" CharacterSet="2"
WholeProgramOptimization="1" WholeProgramOptimization="0"
> >
<Tool <Tool
Name="VCPreBuildEventTool" Name="VCPreBuildEventTool"
@ -134,6 +134,9 @@
<Tool <Tool
Name="VCCLCompilerTool" Name="VCCLCompilerTool"
Optimization="3" Optimization="3"
InlineFunctionExpansion="0"
FavorSizeOrSpeed="1"
WholeProgramOptimization="false"
AdditionalIncludeDirectories="" AdditionalIncludeDirectories=""
PreprocessorDefinitions="NDEBUG" PreprocessorDefinitions="NDEBUG"
StringPooling="true" StringPooling="true"
@ -161,6 +164,7 @@
Name="VCLinkerTool" Name="VCLinkerTool"
AdditionalDependencies="zlib.lib" AdditionalDependencies="zlib.lib"
OutputFile="$(OutDir)\$(ProjectName)-dev.exe" OutputFile="$(OutDir)\$(ProjectName)-dev.exe"
LinkIncremental="2"
/> />
<Tool <Tool
Name="VCALinkTool" Name="VCALinkTool"
@ -2908,6 +2912,14 @@
RelativePath="..\..\NewGUI\frmGameFixes.h" RelativePath="..\..\NewGUI\frmGameFixes.h"
> >
</File> </File>
<File
RelativePath="..\..\NewGUI\frmLogging.cpp"
>
</File>
<File
RelativePath="..\..\NewGUI\frmLogging.h"
>
</File>
<File <File
RelativePath="..\..\NewGUI\frmMain.cpp" RelativePath="..\..\NewGUI\frmMain.cpp"
> >

View File

@ -529,7 +529,7 @@ BOOL APIENTRY GameFixes(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
case WM_INITDIALOG: case WM_INITDIALOG:
if(Config.GameFixes & 0x1) CheckDlgButton(hDlg, IDC_GAMEFIX2, TRUE);//Tri-Ace fix if(Config.GameFixes & 0x1) CheckDlgButton(hDlg, IDC_GAMEFIX2, TRUE);//Tri-Ace fix
if(Config.GameFixes & 0x4) CheckDlgButton(hDlg, IDC_GAMEFIX3, TRUE);//Digimon FPU compare fix if(Config.GameFixes & 0x4) CheckDlgButton(hDlg, IDC_GAMEFIX3, TRUE);//Digimon FPU compare fix
if(Config.GameFixes & 0x2) CheckDlgButton(hDlg, IDC_GAMEFIX4, TRUE);//GoW fix if(Config.GameFixes & 0x8) CheckDlgButton(hDlg, IDC_GAMEFIX5, TRUE);//Tales of Destiny fix
return TRUE; return TRUE;
case WM_COMMAND: case WM_COMMAND:
@ -538,7 +538,7 @@ BOOL APIENTRY GameFixes(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
uint newfixes = 0; uint newfixes = 0;
newfixes |= IsDlgButtonChecked(hDlg, IDC_GAMEFIX2) ? 0x1 : 0; newfixes |= IsDlgButtonChecked(hDlg, IDC_GAMEFIX2) ? 0x1 : 0;
newfixes |= IsDlgButtonChecked(hDlg, IDC_GAMEFIX3) ? 0x4 : 0; newfixes |= IsDlgButtonChecked(hDlg, IDC_GAMEFIX3) ? 0x4 : 0;
newfixes |= IsDlgButtonChecked(hDlg, IDC_GAMEFIX4) ? 0x2 : 0; newfixes |= IsDlgButtonChecked(hDlg, IDC_GAMEFIX5) ? 0x8 : 0;
EndDialog(hDlg, TRUE); EndDialog(hDlg, TRUE);

View File

@ -20,7 +20,6 @@
#include "Win32.h" #include "Win32.h"
#include "System.h" #include "System.h"
#include "Threading.h"
#include "ix86/ix86_types.h" #include "ix86/ix86_types.h"
#ifdef _WIN32 #ifdef _WIN32
@ -110,7 +109,7 @@ namespace Threading
__forceinline long pcsx2_InterlockedExchangeAdd( volatile long* target, long srcval ) __forceinline long pcsx2_InterlockedExchangeAdd( volatile long* target, long srcval )
{ {
long result; //long result;
// Use our own implementation... // Use our own implementation...
// Pcsx2 won't use threads unless it's a multicore cpu, so no need to use // Pcsx2 won't use threads unless it's a multicore cpu, so no need to use
@ -120,30 +119,26 @@ namespace Threading
{ {
__asm __asm
{ {
//PUSH ecx
mov ecx,dword ptr [target] mov ecx,dword ptr [target]
mov eax,dword ptr [srcval] mov eax,dword ptr [srcval]
lock xadd dword ptr [ecx],eax lock xadd dword ptr [ecx],eax
mov dword ptr [result], eax
//POP ecx // msvc smartly returns eax for us without so much as a compiler warning even...
//mov dword ptr [result], eax
} }
} }
else else
{ {
__asm __asm
{ {
//PUSH ecx
//PUSH edx
mov ecx,dword ptr [target] mov ecx,dword ptr [target]
//L1:
mov eax,dword ptr [srcval] mov eax,dword ptr [srcval]
xadd dword ptr [ecx],eax xadd dword ptr [ecx],eax
//jnz L1
mov dword ptr [result], eax // msvc smartly returns eax for us without so much as a compiler warning even...
//POP edx //mov dword ptr [result], eax
//POP ecx
} }
} }
return result; // return result;
} }
} }

View File

@ -74,21 +74,21 @@ LANGUAGE LANG_GERMAN, SUBLANG_GERMAN
// Dialog // Dialog
// //
IDD_GAMEFIXES DIALOGEX 0, 0, 278, 127 IDD_GAMEFIXES DIALOGEX 0, 0, 279, 118
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Game Special Fixes" CAPTION "Game Special Fixes"
FONT 8, "MS Shell Dlg", 400, 0, 0x1 FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN BEGIN
DEFPUSHBUTTON "OK",IDOK,85,91,50,14 DEFPUSHBUTTON "OK",IDOK,87,89,50,14
PUSHBUTTON "Cancel",IDCANCEL,139,91,50,14 PUSHBUTTON "Cancel",IDCANCEL,142,89,50,14
CTEXT "Some games need special settings.\nConfigure them here.",IDC_STATIC,7,7,264,17 CTEXT "Some games need special settings.\nConfigure them here.",IDC_STATIC,7,7,265,17
GROUPBOX "PCSX2 Gamefixes",IDC_STATIC,7,31,264,89 GROUPBOX "PCSX2 Gamefixes",IDC_STATIC,7,28,265,83
CONTROL "FPU Compare Hack - Special fix for Digimon Rumble Arena 2.",IDC_GAMEFIX3, CONTROL "FPU Compare Hack - Special fix for Digimon Rumble Arena 2.",IDC_GAMEFIX3,
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,47,249,10 "Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,43,249,10
CONTROL "VU Add / Sub Hack - Special fix for Tri-Ace games!",IDC_GAMEFIX2, CONTROL "VU Add Hack - Special fix for Tri-Ace games!",IDC_GAMEFIX2,
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,61,252,10 "Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,72,252,10
CONTROL "VU Clip Hack - Special fix for God of War",IDC_GAMEFIX4, CONTROL "FPU Mul Hack - Special fix for Tales of Destiny (possibly other games).",IDC_GAMEFIX5,
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,75,144,10 "Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,57,249,10
END END
@ -103,10 +103,11 @@ BEGIN
IDD_GAMEFIXES, DIALOG IDD_GAMEFIXES, DIALOG
BEGIN BEGIN
LEFTMARGIN, 7 LEFTMARGIN, 7
RIGHTMARGIN, 271 RIGHTMARGIN, 272
VERTGUIDE, 12 VERTGUIDE, 14
TOPMARGIN, 7 TOPMARGIN, 7
BOTTOMMARGIN, 120 BOTTOMMARGIN, 111
HORZGUIDE, 103
END END
END END
#endif // APSTUDIO_INVOKED #endif // APSTUDIO_INVOKED
@ -195,31 +196,30 @@ BEGIN
RADIOBUTTON "Chop / Zero",IDC_EE_ROUNDMODE3,156,36,54,16 RADIOBUTTON "Chop / Zero",IDC_EE_ROUNDMODE3,156,36,54,16
CONTROL " Flush to Zero",IDC_EE_CHECK1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,20,105,58,13 CONTROL " Flush to Zero",IDC_EE_CHECK1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,20,105,58,13
CONTROL " Denormals are Zero",IDC_EE_CHECK2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,111,105,79,13 CONTROL " Denormals are Zero",IDC_EE_CHECK2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,111,105,79,13
CONTROL " Flush to Zero",IDC_VU_CHECK1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,20,232,58,13 CONTROL " Flush to Zero",IDC_VU_CHECK1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,20,217,58,13
CONTROL " Denormals are Zero",IDC_VU_CHECK2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,111,232,81,13 CONTROL " Denormals are Zero",IDC_VU_CHECK2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,111,217,81,13
RADIOBUTTON "Nearest",IDC_VU_ROUNDMODE0,20,172,44,12 RADIOBUTTON "Nearest",IDC_VU_ROUNDMODE0,20,157,44,12
RADIOBUTTON "Negative",IDC_VU_ROUNDMODE1,64,172,47,12 RADIOBUTTON "Negative",IDC_VU_ROUNDMODE1,64,157,47,12
RADIOBUTTON "Positive",IDC_VU_ROUNDMODE2,111,172,45,12 RADIOBUTTON "Positive",IDC_VU_ROUNDMODE2,111,157,45,12
RADIOBUTTON "Chop / Zero",IDC_VU_ROUNDMODE3,156,172,52,12 RADIOBUTTON "Chop / Zero",IDC_VU_ROUNDMODE3,156,157,52,12
PUSHBUTTON "Defaults",IDDEFAULT,346,254,50,14 PUSHBUTTON "Defaults",IDDEFAULT,346,254,50,14
GROUPBOX "VU Recs Options",IDC_STATIC,7,146,250,122,BS_CENTER GROUPBOX "VU Recs Options",IDC_STATIC,7,133,250,118,BS_CENTER
GROUPBOX "EE Recs Options",IDC_STATIC,7,12,250,129,BS_CENTER GROUPBOX "EE Recs Options",IDC_STATIC,7,12,250,113,BS_CENTER
GROUPBOX "Round Mode",IDC_STATIC,11,159,236,32 GROUPBOX "Round Mode",IDC_STATIC,11,144,236,32
GROUPBOX "Round Mode",IDC_STATIC,11,26,236,36 GROUPBOX "Round Mode",IDC_STATIC,11,26,236,36
GROUPBOX "Help",IDC_STATIC,271,12,251,238,BS_CENTER GROUPBOX "Help",IDC_STATIC,271,12,251,239,BS_CENTER
GROUPBOX "Clamp Mode",IDC_STATIC,11,196,236,31 GROUPBOX "Clamp Mode",IDC_STATIC,11,181,236,31
RADIOBUTTON "None",IDC_VU_CLAMPMODE0,20,207,44,12 RADIOBUTTON "None",IDC_VU_CLAMPMODE0,20,192,44,12
RADIOBUTTON "Normal",IDC_VU_CLAMPMODE1,64,207,47,12 RADIOBUTTON "Normal",IDC_VU_CLAMPMODE1,64,192,47,12
RADIOBUTTON "Extra",IDC_VU_CLAMPMODE2,111,207,45,12 RADIOBUTTON "Extra",IDC_VU_CLAMPMODE2,111,192,45,12
RADIOBUTTON "Extra + Preserve Sign",IDC_VU_CLAMPMODE3,156,207,85,12 RADIOBUTTON "Extra + Preserve Sign",IDC_VU_CLAMPMODE3,156,192,85,12
CONTROL " Set O and U Flags",IDC_VU_CHECK3,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,20,250,91,13 CONTROL " Set O and U Flags",IDC_VU_CHECK3,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,20,235,91,13
CONTROL " Software Emulate DaZ",IDC_VU_CHECK4,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,111,250,116,13 CONTROL " Software Emulate DaZ",IDC_VU_CHECK4,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,111,235,116,13
GROUPBOX "Clamp Mode",IDC_STATIC,11,67,236,31 GROUPBOX "Clamp Mode",IDC_STATIC,11,67,236,31
RADIOBUTTON "None",IDC_EE_CLAMPMODE0,20,76,44,16 RADIOBUTTON "None",IDC_EE_CLAMPMODE0,20,76,44,16
RADIOBUTTON "Normal",IDC_EE_CLAMPMODE1,64,76,47,16 RADIOBUTTON "Normal",IDC_EE_CLAMPMODE1,64,76,47,16
RADIOBUTTON "Extra + Preserve Sign",IDC_EE_CLAMPMODE2,111,76,91,16 RADIOBUTTON "Extra + Preserve Sign",IDC_EE_CLAMPMODE2,111,76,91,16
RADIOBUTTON "Full",IDC_EE_CLAMPMODE3,202,76,38,16 RADIOBUTTON "Full",IDC_EE_CLAMPMODE3,202,76,38,16
CONTROL " Software Emulate MUL",IDC_EE_CHECK3,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,20,123,116,13
LTEXT "These options specify how your CPU rounds floating point values.\n\nTry changing the roundmode for EE if your game hangs, it could make it work again.",IDC_STATIC,287,33,216,35 LTEXT "These options specify how your CPU rounds floating point values.\n\nTry changing the roundmode for EE if your game hangs, it could make it work again.",IDC_STATIC,287,33,216,35
GROUPBOX "Round Mode",IDC_STATIC,281,22,235,51,BS_LEFT GROUPBOX "Round Mode",IDC_STATIC,281,22,235,51,BS_LEFT
GROUPBOX "Clamp Mode",IDC_STATIC,281,80,236,127,BS_LEFT GROUPBOX "Clamp Mode",IDC_STATIC,281,80,236,127,BS_LEFT

View File

@ -19,7 +19,7 @@
#include "PrecompiledHeader.h" #include "PrecompiledHeader.h"
#include "BaseblockEx.h" #include "BaseblockEx.h"
BASEBLOCKEX* BaseBlocks::New(u32 startpc) BASEBLOCKEX* BaseBlocks::New(u32 startpc, uptr fnptr)
{ {
if (blocks.size() == size) if (blocks.size() == size)
return 0; return 0;
@ -28,6 +28,7 @@ BASEBLOCKEX* BaseBlocks::New(u32 startpc)
std::vector<BASEBLOCKEX>::iterator iter; std::vector<BASEBLOCKEX>::iterator iter;
memset(&newblock, 0, sizeof newblock); memset(&newblock, 0, sizeof newblock);
newblock.startpc = startpc; newblock.startpc = startpc;
newblock.fnptr = fnptr;
int imin = 0, imax = blocks.size(), imid; int imin = 0, imax = blocks.size(), imid;
@ -42,10 +43,15 @@ BASEBLOCKEX* BaseBlocks::New(u32 startpc)
assert(imin == blocks.size() || blocks[imin].startpc > startpc); assert(imin == blocks.size() || blocks[imin].startpc > startpc);
iter = blocks.insert(blocks.begin() + imin, newblock); iter = blocks.insert(blocks.begin() + imin, newblock);
std::pair<linkiter_t, linkiter_t> range = links.equal_range(startpc);
for (linkiter_t i = range.first; i != range.second; ++i)
*(u32*)i->second = fnptr - (i->second + 4);
return &*iter; return &*iter;
} }
int BaseBlocks::Index(u32 startpc) const int BaseBlocks::LastIndex(u32 startpc) const
{ {
if (0 == blocks.size()) if (0 == blocks.size())
return -1; return -1;
@ -61,9 +67,21 @@ int BaseBlocks::Index(u32 startpc) const
imin = imid; imin = imid;
} }
if (startpc < blocks[imin].startpc || return imin;
startpc >= blocks[imin].startpc + blocks[imin].size*4)
return -1;
else
return imin;
} }
BASEBLOCKEX* BaseBlocks::GetByX86(uptr ip) const
{
// TODO
return 0;
}
void BaseBlocks::Link(u32 pc, uptr jumpptr)
{
BASEBLOCKEX *targetblock = Get(pc);
if (targetblock && targetblock->startpc == pc)
*(u32*)jumpptr = targetblock->fnptr - (jumpptr + 4);
else
*(u32*)jumpptr = recompiler - (jumpptr + 4);
links.insert(std::pair<u32, uptr>(pc, jumpptr));
}

View File

@ -20,6 +20,8 @@
#include "PrecompiledHeader.h" #include "PrecompiledHeader.h"
#include <vector> #include <vector>
#include <map>
#include <utility>
// used to keep block information // used to keep block information
#define BLOCKTYPE_DELAYSLOT 1 // if bit set, delay slot #define BLOCKTYPE_DELAYSLOT 1 // if bit set, delay slot
@ -38,9 +40,10 @@ struct BASEBLOCK
// extra block info (only valid for start of fn) // extra block info (only valid for start of fn)
struct BASEBLOCKEX struct BASEBLOCKEX
{ {
u16 size; // size in dwords
u16 dummy;
u32 startpc; u32 startpc;
uptr fnptr;
u16 size; // size in dwords
u16 x86size;
#ifdef PCSX2_DEVBUILD #ifdef PCSX2_DEVBUILD
u32 visited; // number of times called u32 visited; // number of times called
@ -53,18 +56,34 @@ class BaseBlocks
{ {
private: private:
std::vector<BASEBLOCKEX> blocks; std::vector<BASEBLOCKEX> blocks;
// switch to a hash map later?
std::multimap<u32, uptr> links;
typedef std::multimap<u32, uptr>::iterator linkiter_t;
unsigned long size; unsigned long size;
uptr recompiler;
public: public:
BaseBlocks(unsigned long max) : BaseBlocks(unsigned long size_, uptr recompiler_) :
size(max), size(size_),
recompiler(recompiler_),
blocks(0) blocks(0)
{ {
blocks.reserve(size); blocks.reserve(size);
} }
BASEBLOCKEX* New(u32 startpc); BASEBLOCKEX* New(u32 startpc, uptr fnptr);
int Index (u32 startpc) const; int LastIndex (u32 startpc) const;
BASEBLOCKEX* GetByX86(uptr ip) const;
inline int Index (u32 startpc) const
{
int idx = LastIndex(startpc);
if (idx == -1 || startpc < blocks[idx].startpc ||
blocks[idx].size && (startpc >= blocks[idx].startpc + blocks[idx].size * 4))
return -1;
else
return idx;
}
inline BASEBLOCKEX* operator[](int idx) inline BASEBLOCKEX* operator[](int idx)
{ {
@ -80,12 +99,20 @@ public:
inline void Remove(int idx) inline void Remove(int idx)
{ {
u32 startpc = blocks[idx].startpc;
std::pair<linkiter_t, linkiter_t> range = links.equal_range(blocks[idx].startpc);
for (linkiter_t i = range.first; i != range.second; ++i)
*(u32*)i->second = recompiler - (i->second + 4);
// TODO: remove links from this block?
blocks.erase(blocks.begin() + idx); blocks.erase(blocks.begin() + idx);
} }
void Link(u32 pc, uptr jumpptr);
inline void Reset() inline void Reset()
{ {
blocks.clear(); blocks.clear();
links.clear();
} }
}; };

View File

@ -18,11 +18,6 @@
.extern RECLUT .extern RECLUT
.extern iopRecRecompile .extern iopRecRecompile
#define BLOCKTYPE_STARTPC 4 // startpc offset
#define BLOCKTYPE_DELAYSLOT 1 // if bit set, delay slot
#define BASEBLOCK_SIZE 2 // in dwords
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// The address for all cleared blocks. It recompiles the current pc and then // The address for all cleared blocks. It recompiles the current pc and then
// dispatches to the recompiled block address. // dispatches to the recompiled block address.
@ -42,87 +37,6 @@ iopJITCompile:
iopJITCompileInBlock: iopJITCompileInBlock:
jmp iopJITCompile jmp iopJITCompile
//////////////////////////////////////////////////////////////////////////
// Recompiles the next block, and links the old block directly to it.
// This is a on-shot execution for any block which uses it. Once the block
// has been statically linked to the new block, this function will be bypassed
//
// edx - jump address to modify
.globl iopDispatcher
iopDispatcher:
# calc PC_GETBLOCK
# ((BASEBLOCK*)(reclut[((u32)(x)) >> 16] + (x)*(sizeof(BASEBLOCK)/4)))
mov eax, dword ptr [REGINFO + PCOFFSET]
mov ebx, eax
shr eax, 16
mov ecx, dword ptr [RECLUT+eax*4]
mov eax, dword ptr [ecx+ebx]
cmp eax, offset iopJITCompile
je Dispatch_notcompiled
cmp eax, offset iopJITCompileInBlock
je Dispatch_notcompiled
lea ebx, [eax-4]
sub ebx, edx
mov dword ptr [edx], ebx
jmp eax
.align 16
Dispatch_notcompiled:
mov esi, edx
lea edi, [ecx+ebx]
push ebx
call iopRecRecompile
add esp, 4
mov eax, dword ptr [edi]
lea ebx, [eax-4]
sub ebx, esi
mov dword ptr [esi], ebx
jmp eax
//////////////////////////////////////////////////////////////////////////
// edx - baseblock->startpc
// stack - x86Ptr
.globl iopDispatcherClear
iopDispatcherClear:
mov [REGINFO + PCOFFSET], edx
# calc PC_GETBLOCK
# ((BASEBLOCK*)(reclut[((u32)(x)) >> 16] + (x)*(sizeof(BASEBLOCK)/4)))
mov ebx, edx
shr edx, 16
mov ecx, dword ptr [RECLUT+edx*4]
mov eax, dword ptr [ecx+ebx]
cmp eax, offset iopJITCompile
je Clear_notcompiled
cmp eax, offset iopJITCompileInBlock
je Clear_notcompiled
add esp, 4
jmp eax
.align 16
Clear_notcompiled:
lea edi, [ecx+ebx]
push ebx
call iopRecRecompile
add esp, 4
mov eax, dword ptr [edi]
pop ecx
mov byte ptr [ecx], 0xe9 // jmp32
lea ebx, [eax-5]
sub ebx, ecx
mov dword ptr [ecx+1], ebx
jmp eax
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// called when jumping to variable pc address. // called when jumping to variable pc address.

View File

@ -165,8 +165,12 @@ void recMFC0( void )
break; break;
case 1: case 1:
CALLFunc( (uptr)COP0_UpdatePCCR );
MOV32MtoR(EAX, (uptr)&cpuRegs.PERF.n.pcr0);
break;
case 3: case 3:
CALLFunc( (uptr)COP0_UpdatePCCR ); CALLFunc( (uptr)COP0_UpdatePCCR );
MOV32MtoR(EAX, (uptr)&cpuRegs.PERF.n.pcr1);
break; break;
} }
_deleteEEreg(_Rt_, 0); _deleteEEreg(_Rt_, 0);

View File

@ -592,7 +592,7 @@ void FPU_SUB(int regd, int regt) {
// FPU_MUL (Used to approximate PS2's FPU mul behavior) // FPU_MUL (Used to approximate PS2's FPU mul behavior)
//------------------------------------------------------------------ //------------------------------------------------------------------
// PS2's multiplication uses some modification (possibly not the one used in this function) // PS2's multiplication uses some modification (possibly not the one used in this function)
// of booth multiplication with wallace trees (not used in this function) // of booth multiplication with wallace trees (not used in this function)
// it cuts of some bits, resulting in inaccurate and non-commutative results. // it cuts of some bits, resulting in inaccurate and non-commutative results.
// This function attempts to replicate this. It is currently inaccurate. But still not too bad. // This function attempts to replicate this. It is currently inaccurate. But still not too bad.
//------------------------------------------------------------------ //------------------------------------------------------------------
@ -653,7 +653,7 @@ u32 __fastcall FPU_MUL_MANTISSA(u32 s, u32 t)
void FPU_MUL(int regd, int regt) void FPU_MUL(int regd, int regt)
{ {
if (CHECK_FPU_ATTEMPT_MUL) if (CHECK_FPUMULHACK)
{ {
SSE2_MOVD_XMM_to_R(ECX, regd); SSE2_MOVD_XMM_to_R(ECX, regd);
SSE2_MOVD_XMM_to_R(EDX, regt); SSE2_MOVD_XMM_to_R(EDX, regt);

View File

@ -391,7 +391,7 @@ void FPU_ADD_SUB(int tempd, int tempt) //tempd and tempt are overwritten, they a
void FPU_MUL(int info, int regd, int sreg, int treg, bool acc) void FPU_MUL(int info, int regd, int sreg, int treg, bool acc)
{ {
if (CHECK_FPU_ATTEMPT_MUL) if (CHECK_FPUMULHACK)
{ {
SSE2_MOVD_XMM_to_R(ECX, sreg); SSE2_MOVD_XMM_to_R(ECX, sreg);
SSE2_MOVD_XMM_to_R(EDX, treg); SSE2_MOVD_XMM_to_R(EDX, treg);

View File

@ -60,7 +60,8 @@ static u8 *recMem = NULL; // the recompiled blocks will be here
static BASEBLOCK *recRAM = NULL; // and the ptr to the blocks here static BASEBLOCK *recRAM = NULL; // and the ptr to the blocks here
static BASEBLOCK *recROM = NULL; // and here static BASEBLOCK *recROM = NULL; // and here
static BASEBLOCK *recROM1 = NULL; // also here static BASEBLOCK *recROM1 = NULL; // also here
static BaseBlocks recBlocks(PSX_NUMBLOCKS); void iopJITCompile();
static BaseBlocks recBlocks(PSX_NUMBLOCKS, (uptr)iopJITCompile);
static u8 *recPtr = NULL; static u8 *recPtr = NULL;
u32 psxpc; // recompiler psxpc u32 psxpc; // recompiler psxpc
int psxbranch; // set for branch int psxbranch; // set for branch
@ -74,8 +75,8 @@ static BASEBLOCKEX* s_pCurBlockEx = NULL;
static u32 s_nEndBlock = 0; // what psxpc the current block ends static u32 s_nEndBlock = 0; // what psxpc the current block ends
static u32 s_ConstGPRreg; static u32 s_saveConstRegs[32];
static u32 s_saveConstGPRreg = 0, s_saveHasConstReg = 0, s_saveFlushedConstReg = 0; static u32 s_saveHasConstReg = 0, s_saveFlushedConstReg = 0;
static EEINST* s_psaveInstInfo = NULL; static EEINST* s_psaveInstInfo = NULL;
u32 s_psxBlockCycles = 0; // cycles of current block recompiling u32 s_psxBlockCycles = 0; // cycles of current block recompiling
@ -334,7 +335,7 @@ void _psxFlushCall(int flushtype)
void psxSaveBranchState() void psxSaveBranchState()
{ {
s_savenBlockCycles = s_psxBlockCycles; s_savenBlockCycles = s_psxBlockCycles;
s_saveConstGPRreg = 0xffffffff; // indicate searching memcpy(s_saveConstRegs, g_psxConstRegs, sizeof(g_psxConstRegs));
s_saveHasConstReg = g_psxHasConstReg; s_saveHasConstReg = g_psxHasConstReg;
s_saveFlushedConstReg = g_psxFlushedConstReg; s_saveFlushedConstReg = g_psxFlushedConstReg;
s_psaveInstInfo = g_pCurInstInfo; s_psaveInstInfo = g_pCurInstInfo;
@ -347,18 +348,7 @@ void psxLoadBranchState()
{ {
s_psxBlockCycles = s_savenBlockCycles; s_psxBlockCycles = s_savenBlockCycles;
if( s_saveConstGPRreg != 0xffffffff ) { memcpy(g_psxConstRegs, s_saveConstRegs, sizeof(g_psxConstRegs));
assert( s_saveConstGPRreg > 0 );
// make sure right GPR was saved
assert( g_psxHasConstReg == s_saveHasConstReg || (g_psxHasConstReg ^ s_saveHasConstReg) == (1<<s_saveConstGPRreg) );
// restore the GPR reg
g_psxConstRegs[s_saveConstGPRreg] = s_ConstGPRreg;
PSX_SET_CONST(s_saveConstGPRreg);
//s_saveConstGPRreg = 0;
}
g_psxHasConstReg = s_saveHasConstReg; g_psxHasConstReg = s_saveHasConstReg;
g_psxFlushedConstReg = s_saveFlushedConstReg; g_psxFlushedConstReg = s_saveFlushedConstReg;
g_pCurInstInfo = s_psaveInstInfo; g_pCurInstInfo = s_psaveInstInfo;
@ -371,23 +361,8 @@ void psxLoadBranchState()
// Code Templates // // Code Templates //
//////////////////// ////////////////////
void PSX_CHECK_SAVE_REG(int reg)
{
if( s_saveConstGPRreg == 0xffffffff ) {
if( PSX_IS_CONST1(reg) ) {
s_saveConstGPRreg = reg;
s_ConstGPRreg = g_psxConstRegs[reg];
}
}
else {
// can be non zero when double loading
//assert( s_saveConstGPRreg == 0 );
}
}
void _psxOnWriteReg(int reg) void _psxOnWriteReg(int reg)
{ {
PSX_CHECK_SAVE_REG(reg);
PSX_DEL_CONST(reg); PSX_DEL_CONST(reg);
} }
@ -397,7 +372,6 @@ void psxRecompileCodeConst0(R3000AFNPTR constcode, R3000AFNPTR_INFO constscode,
if ( ! _Rd_ ) return; if ( ! _Rd_ ) return;
// for now, don't support xmm // for now, don't support xmm
PSX_CHECK_SAVE_REG(_Rd_);
_deleteX86reg(X86TYPE_PSX, _Rs_, 1); _deleteX86reg(X86TYPE_PSX, _Rs_, 1);
_deleteX86reg(X86TYPE_PSX, _Rt_, 1); _deleteX86reg(X86TYPE_PSX, _Rt_, 1);
@ -447,7 +421,6 @@ void psxRecompileCodeConst1(R3000AFNPTR constcode, R3000AFNPTR_INFO noconstcode)
} }
// for now, don't support xmm // for now, don't support xmm
PSX_CHECK_SAVE_REG(_Rt_);
_deleteX86reg(X86TYPE_PSX, _Rs_, 1); _deleteX86reg(X86TYPE_PSX, _Rs_, 1);
_deleteX86reg(X86TYPE_PSX, _Rt_, 0); _deleteX86reg(X86TYPE_PSX, _Rt_, 0);
@ -468,7 +441,6 @@ void psxRecompileCodeConst2(R3000AFNPTR constcode, R3000AFNPTR_INFO noconstcode)
if ( ! _Rd_ ) return; if ( ! _Rd_ ) return;
// for now, don't support xmm // for now, don't support xmm
PSX_CHECK_SAVE_REG(_Rd_);
_deleteX86reg(X86TYPE_PSX, _Rt_, 1); _deleteX86reg(X86TYPE_PSX, _Rt_, 1);
_deleteX86reg(X86TYPE_PSX, _Rd_, 0); _deleteX86reg(X86TYPE_PSX, _Rd_, 0);
@ -650,77 +622,6 @@ static __declspec(naked) void iopJITCompileInBlock()
} }
} }
// jumped to when an immediate branch (EE side) hasn't been statically linked yet.
// Block is compiled if needed, and the link is made.
// EDX contains the jump addr to modify
static __declspec(naked) void iopDispatcher()
{
__asm {
mov eax, dword ptr [psxRegs.pc]
mov ebx, eax
shr eax, 16
mov ecx, dword ptr [psxRecLUT+eax*4]
mov eax, dword ptr [ecx+ebx]
cmp eax, offset iopJITCompile
je notcompiled
cmp eax, offset iopJITCompileInBlock
je notcompiled
lea ebx, [eax-4]
sub ebx, edx
mov dword ptr [edx], ebx
jmp eax
align 16
notcompiled:
mov esi, edx
lea edi, [ecx+ebx]
push ebx
call iopRecRecompile
add esp, 4
mov eax, dword ptr [edi]
lea ebx, [eax-4]
sub ebx, esi
mov dword ptr [esi], ebx
jmp eax
}
}
// edx - baseblock start pc
// stack - x86Ptr[0]
static __declspec(naked) void iopDispatcherClear()
{
__asm {
mov [psxRegs.pc], edx
mov ebx, edx
shr edx, 16
mov ecx, dword ptr [psxRecLUT+edx*4]
mov eax, dword ptr [ecx+ebx]
cmp eax, offset iopJITCompile
je notcompiled
cmp eax, offset iopJITCompileInBlock
je notcompiled
add esp, 4
jmp eax
align 16
notcompiled:
lea edi, [ecx+ebx]
push ebx
call iopRecRecompile
add esp, 4
mov eax, dword ptr [edi]
pop ecx
mov byte ptr [ecx], 0xe9 // jmp32
lea ebx, [eax-5]
sub ebx, ecx
mov dword ptr [ecx+1], ebx
jmp eax
}
}
// called when jumping to variable psxpc address // called when jumping to variable psxpc address
static __declspec(naked) void iopDispatcherReg() static __declspec(naked) void iopDispatcherReg()
{ {
@ -822,28 +723,6 @@ static __forceinline u32 psxRecClearMem(u32 pc)
if (pexblock->startpc >= upperextent) if (pexblock->startpc >= upperextent)
break; break;
pblock = PSX_GETBLOCK(pexblock->startpc);
x86Ptr[_EmitterId_] = (u8*)pblock->GetFnptr();
jASSUME((u8*)iopJITCompile != x86Ptr[_EmitterId_]);
// jASSUME((u8*)iopJITCompileInside != x86Ptr[_EmitterId_]);
// This is breaking things currently, rather than figure it out
// I'm just using DispatcherReg, it's fast enough now.
// Actually, if we want to do this at all maybe keeping a hash
// table of const jumps and modifying the jumps straight from
// here is the way to go.
#if 1
// there is a small problem: mem can be ored with 0xa<<28 or 0x8<<28, and don't know which
MOV32ItoR(EDX, pexblock->startpc);
assert((uptr)x86Ptr[_EmitterId_] <= 0xffffffff);
PUSH32I((uptr)x86Ptr[_EmitterId_]); // will be replaced by JMP32
JMP32((uptr)iopDispatcherClear - ((uptr)x86Ptr[_EmitterId_] + 5));
#else
MOV32ItoM((uptr)&psxRegs.pc, pexblock->startpc);
JMP32((uptr)iopDispatcherReg - ((uptr)x86Ptr[_EmitterId_] + 5));
#endif
lowerextent = min(lowerextent, pexblock->startpc); lowerextent = min(lowerextent, pexblock->startpc);
upperextent = max(upperextent, pexblock->startpc + pexblock->size * 4); upperextent = max(upperextent, pexblock->startpc + pexblock->size * 4);
recBlocks.Remove(blockidx); recBlocks.Remove(blockidx);
@ -907,9 +786,8 @@ void psxSetBranchImm( u32 imm )
_psxFlushCall(FLUSH_EVERYTHING); _psxFlushCall(FLUSH_EVERYTHING);
iPsxBranchTest(imm, imm <= psxpc); iPsxBranchTest(imm, imm <= psxpc);
MOV32ItoR(EDX, 0); ptr = JMP32(0);
ptr = (u32*)(x86Ptr[0]-4); recBlocks.Link(HWADDR(imm), (uptr)ptr);
*ptr = (uptr)JMP32((uptr)iopDispatcher - ( (uptr)x86Ptr[0] + 5 ));
} }
//fixme : this is all a huge hack, we base the counter advancements on the average an opcode should take (wtf?) //fixme : this is all a huge hack, we base the counter advancements on the average an opcode should take (wtf?)
@ -967,7 +845,7 @@ static void checkcodefn()
#ifdef _MSC_VER #ifdef _MSC_VER
__asm mov pctemp, eax; __asm mov pctemp, eax;
#else #else
__asm__("movl %%eax, %0" : : "m"(pctemp) ); __asm__("movl %%eax, %[pctemp]" : : [pctemp]"m"(pctemp) );
#endif #endif
SysPrintf("iop code changed! %x\n", pctemp); SysPrintf("iop code changed! %x\n", pctemp);
} }
@ -1018,24 +896,6 @@ void psxRecompileNextInstruction(int delayslot)
BASEBLOCK* pblock = PSX_GETBLOCK(psxpc); BASEBLOCK* pblock = PSX_GETBLOCK(psxpc);
// need *ppblock != s_pCurBlock because of branches
if (HWADDR(psxpc) != s_pCurBlockEx->startpc
&& pblock->GetFnptr() != (uptr)iopJITCompile
&& pblock->GetFnptr() != (uptr)iopJITCompileInBlock )
{
if(!delayslot)
{
// code already in place, so jump to it and exit recomp
assert( recBlocks.Get(HWADDR(psxpc))->startpc == HWADDR(psxpc) );
_psxFlushCall(FLUSH_EVERYTHING);
MOV32ItoM((uptr)&psxRegs.pc, psxpc);
JMP32((uptr)pblock->GetFnptr() - ((uptr)x86Ptr[0] + 5));
psxbranch = 3;
return;
}
}
#ifdef _DEBUG #ifdef _DEBUG
MOV32ItoR(EAX, psxpc); MOV32ItoR(EAX, psxpc);
#endif #endif
@ -1130,7 +990,6 @@ void iopRecRecompile(u32 startpc)
u32 i; u32 i;
u32 branchTo; u32 branchTo;
u32 willbranch3 = 0; u32 willbranch3 = 0;
u32* ptr;
#ifdef _DEBUG #ifdef _DEBUG
if( psxdump & 4 ) if( psxdump & 4 )
@ -1143,6 +1002,10 @@ void iopRecRecompile(u32 startpc)
if (((uptr)recPtr - (uptr)recMem) >= (RECMEM_SIZE - 0x10000)) if (((uptr)recPtr - (uptr)recMem) >= (RECMEM_SIZE - 0x10000))
recResetIOP(); recResetIOP();
x86SetPtr( recPtr );
x86Align(16);
recPtr = x86Ptr[_EmitterId_];
s_pCurBlock = PSX_GETBLOCK(startpc); s_pCurBlock = PSX_GETBLOCK(startpc);
assert(s_pCurBlock->GetFnptr() == (uptr)iopJITCompile assert(s_pCurBlock->GetFnptr() == (uptr)iopJITCompile
@ -1150,19 +1013,16 @@ void iopRecRecompile(u32 startpc)
s_pCurBlockEx = recBlocks.Get(HWADDR(startpc)); s_pCurBlockEx = recBlocks.Get(HWADDR(startpc));
if(!s_pCurBlockEx || s_pCurBlockEx->startpc != HWADDR(startpc)) { if(!s_pCurBlockEx || s_pCurBlockEx->startpc != HWADDR(startpc)) {
s_pCurBlockEx = recBlocks.New(HWADDR(startpc)); s_pCurBlockEx = recBlocks.New(HWADDR(startpc), (uptr)recPtr);
if( s_pCurBlockEx == NULL ) { if( s_pCurBlockEx == NULL ) {
DevCon::WriteLn("IOP Recompiler data reset"); DevCon::WriteLn("IOP Recompiler data reset");
recResetIOP(); recResetIOP();
s_pCurBlockEx = recBlocks.New(HWADDR(startpc)); x86SetPtr( recPtr );
s_pCurBlockEx = recBlocks.New(HWADDR(startpc), (uptr)recPtr);
} }
} }
x86SetPtr( recPtr );
x86Align(16);
recPtr = x86Ptr[0];
psxbranch = 0; psxbranch = 0;
s_pCurBlock->SetFnptr( (uptr)x86Ptr[0] ); s_pCurBlock->SetFnptr( (uptr)x86Ptr[0] );
@ -1170,7 +1030,6 @@ void iopRecRecompile(u32 startpc)
// reset recomp state variables // reset recomp state variables
psxpc = startpc; psxpc = startpc;
s_saveConstGPRreg = 0;
g_psxHasConstReg = g_psxFlushedConstReg = 1; g_psxHasConstReg = g_psxFlushedConstReg = 1;
_initX86regs(); _initX86regs();
@ -1304,7 +1163,6 @@ StartRecomp:
JMP32((uptr)iopDispatcherReg - ( (uptr)x86Ptr[0] + 5 )); JMP32((uptr)iopDispatcherReg - ( (uptr)x86Ptr[0] + 5 ));
} }
else { else {
assert( psxbranch != 3 );
if( psxbranch ) assert( !willbranch3 ); if( psxbranch ) assert( !willbranch3 );
else else
{ {
@ -1312,42 +1170,27 @@ StartRecomp:
SUB32ItoM((uptr)&psxCycleEE, psxScaleBlockCycles()*8 ); SUB32ItoM((uptr)&psxCycleEE, psxScaleBlockCycles()*8 );
} }
if( willbranch3 ) { if (willbranch3 || !psxbranch) {
BASEBLOCK* pblock = PSX_GETBLOCK(s_nEndBlock);
assert( psxpc == s_nEndBlock ); assert( psxpc == s_nEndBlock );
_psxFlushCall(FLUSH_EVERYTHING); _psxFlushCall(FLUSH_EVERYTHING);
MOV32ItoM((uptr)&psxRegs.pc, psxpc); MOV32ItoM((uptr)&psxRegs.pc, psxpc);
JMP32((uptr)pblock->GetFnptr() - ((uptr)x86Ptr[0] + 5)); u32 *ptr = JMP32(0);
recBlocks.Link(HWADDR(s_nEndBlock), (uptr)ptr);
psxbranch = 3; psxbranch = 3;
} }
else if( !psxbranch ) {
// didn't branch, but had to stop
MOV32ItoM( (uptr)&psxRegs.pc, psxpc );
_psxFlushCall(FLUSH_EVERYTHING);
ptr = JMP32(0);
//JMP32((uptr)psxDispatcherReg - ( (uptr)x86Ptr[0] + 5 ));
}
} }
assert( x86Ptr[0] < recMem+RECMEM_SIZE ); assert( x86Ptr[0] < recMem+RECMEM_SIZE );
assert(x86Ptr[_EmitterId_] - recPtr < 0x10000);
s_pCurBlockEx->x86size = x86Ptr[_EmitterId_] - recPtr;
recPtr = x86Ptr[0]; recPtr = x86Ptr[0];
assert( (g_psxHasConstReg&g_psxFlushedConstReg) == g_psxHasConstReg ); assert( (g_psxHasConstReg&g_psxFlushedConstReg) == g_psxHasConstReg );
if( !psxbranch ) { s_pCurBlock = NULL;
assert( ptr != NULL ); s_pCurBlockEx = NULL;
s_pCurBlock = PSX_GETBLOCK(psxpc);
if (s_pCurBlock->GetFnptr() == (uptr)iopJITCompile
|| s_pCurBlock->GetFnptr() == (uptr)iopJITCompileInBlock){
iopRecRecompile(psxpc);
}
*ptr = s_pCurBlock->GetFnptr() - ((u32)ptr + 4);
}
} }
R3000Acpu psxRec = { R3000Acpu psxRec = {

View File

@ -58,8 +58,6 @@ void _psxMoveGPRtoR(x86IntRegType to, int fromgpr);
void _psxMoveGPRtoM(u32 to, int fromgpr); void _psxMoveGPRtoM(u32 to, int fromgpr);
void _psxMoveGPRtoRm(x86IntRegType to, int fromgpr); void _psxMoveGPRtoRm(x86IntRegType to, int fromgpr);
void PSX_CHECK_SAVE_REG(int reg);
extern u32 psxpc; // recompiler pc extern u32 psxpc; // recompiler pc
extern int psxbranch; // set for branch extern int psxbranch; // set for branch
extern u32 g_iopCyclePenalty; extern u32 g_iopCyclePenalty;

View File

@ -58,8 +58,6 @@ extern u32 pc; // recompiler pc (also used by the SuperVU! .. why? (a
extern int branch; // set for branch (also used by the SuperVU! .. why? (air)) extern int branch; // set for branch (also used by the SuperVU! .. why? (air))
extern u32 target; // branch target extern u32 target; // branch target
extern u32 s_nBlockCycles; // cycles of current block recompiling extern u32 s_nBlockCycles; // cycles of current block recompiling
extern u32 s_saveConstGPRreg;
extern GPR_reg64 s_ConstGPRreg;
#define REC_FUNC( f ) \ #define REC_FUNC( f ) \
void rec##f( void ) \ void rec##f( void ) \

View File

@ -3000,23 +3000,24 @@ void VuInstruction::Recompile(list<VuInstruction>::iterator& itinst, u32 vuxyz)
if( type & INST_CLIP_WRITE ) { if( type & INST_CLIP_WRITE ) {
if( nParentPc < s_pCurBlock->startpc || nParentPc >= (int)pc ) { if( nParentPc < s_pCurBlock->startpc || nParentPc >= (int)pc ) {
if( !CHECK_VUCLIPFLAGHACK && pparentinst != NULL ) { if( pparentinst != NULL ) {
if( pparentinst->pClipWrite == 0 ) {
pparentinst->pClipWrite = (uptr)SuperVUStaticAlloc(4);
}
if( nParentCheckForExecution >= 0 ) { if( nParentCheckForExecution >= 0 ) {
if( pparentinst->pClipWrite == 0 )
pparentinst->pClipWrite = (uptr)SuperVUStaticAlloc(4);
if( s_ClipRead == 0 ) if( s_ClipRead == 0 )
s_ClipRead = (uptr)&VU->VI[REG_CLIP_FLAG]; s_ClipRead = (uptr)&VU->VI[REG_CLIP_FLAG];
CMP32ItoM((uptr)&g_nLastBlockExecuted, nParentCheckForExecution); CMP32ItoM((uptr)&g_nLastBlockExecuted, nParentCheckForExecution);
u8* jptr = JNE8(0); u8* jptr = JNE8(0);
CMP32ItoM((uptr)&s_ClipRead, (uptr)&VU->VI[REG_CLIP_FLAG]);
u8* jptr2 = JE8(0);
MOV32MtoR(EAX, pparentinst->pClipWrite); MOV32MtoR(EAX, pparentinst->pClipWrite);
MOV32RtoM(s_ClipRead, EAX); MOV32RtoM(s_ClipRead, EAX);
x86SetJ8(jptr); x86SetJ8(jptr);
x86SetJ8(jptr2);
} }
else s_ClipRead = (uptr)&VU->VI[REG_CLIP_FLAG];
} }
else s_ClipRead = (uptr)&VU->VI[REG_CLIP_FLAG]; else s_ClipRead = (uptr)&VU->VI[REG_CLIP_FLAG];
} }

View File

@ -18,11 +18,6 @@
.extern RECLUT .extern RECLUT
.extern recRecompile .extern recRecompile
#define BLOCKTYPE_STARTPC 4 // startpc offset
#define BLOCKTYPE_DELAYSLOT 1 // if bit set, delay slot
#define BASEBLOCK_SIZE 2 // in dwords
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// The address for all cleared blocks. It recompiles the current pc and then // The address for all cleared blocks. It recompiles the current pc and then
// dispatches to the recompiled block address. // dispatches to the recompiled block address.
@ -41,87 +36,6 @@ JITCompile:
.global JITCompileInBlock .global JITCompileInBlock
JITCompileInBlock: JITCompileInBlock:
jmp JITCompile jmp JITCompile
//////////////////////////////////////////////////////////////////////////
// Recompiles the next block, and links the old block directly to it.
// This is a on-shot execution for any block which uses it. Once the block
// has been statically linked to the new block, this function will be bypassed
//
// edx - jump address to modify
.globl Dispatcher
Dispatcher:
# calc PC_GETBLOCK
# ((BASEBLOCK*)(reclut[((u32)(x)) >> 16] + (x)*(sizeof(BASEBLOCK)/4)))
mov eax, dword ptr [REGINFO + PCOFFSET]
mov ebx, eax
shr eax, 16
mov ecx, dword ptr [RECLUT+eax*4]
mov eax, dword ptr [ecx+ebx]
cmp eax, offset JITCompile
je Dispatch_notcompiled
cmp eax, offset JITCompileInBlock
je Dispatch_notcompiled
lea ebx, [eax-4]
sub ebx, edx
mov dword ptr [edx], ebx
jmp eax
.align 16
Dispatch_notcompiled:
mov esi, edx
lea edi, [ecx+ebx]
push ebx
call recRecompile
add esp, 4
mov eax, dword ptr [edi]
lea ebx, [eax-4]
sub ebx, esi
mov dword ptr [esi], ebx
jmp eax
//////////////////////////////////////////////////////////////////////////
// edx - baseblock->startpc
// stack - x86Ptr
.globl DispatcherClear
DispatcherClear:
mov [REGINFO + PCOFFSET], edx
# calc PC_GETBLOCK
# ((BASEBLOCK*)(reclut[((u32)(x)) >> 16] + (x)*(sizeof(BASEBLOCK)/4)))
mov ebx, edx
shr edx, 16
mov ecx, dword ptr [RECLUT+edx*4]
mov eax, dword ptr [ecx+ebx]
cmp eax, offset JITCompile
je Clear_notcompiled
cmp eax, offset JITCompileInBlock
je Clear_notcompiled
add esp, 4
jmp eax
.align 16
Clear_notcompiled:
lea edi, [ecx+ebx]
push ebx
call recRecompile
add esp, 4
mov eax, dword ptr [edi]
pop ecx
mov byte ptr [ecx], 0xe9 // jmp32
lea ebx, [eax-5]
sub ebx, ecx
mov dword ptr [ecx+1], ebx
jmp eax
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// called when jumping to variable pc address. // called when jumping to variable pc address.

View File

@ -139,17 +139,63 @@ void _flushConstReg(int reg)
void _flushConstRegs() void _flushConstRegs()
{ {
int i; int i, j;
int zero_cnt = 0, minusone_cnt = 0;
int eaxval = 1; // 0, -1
unsigned long done[4] = {0, 0, 0, 0};
u8* rewindPtr;
// flush constants // flush constants
// flush 0 and -1 first
// ignore r0 // ignore r0
for(i = 1; i < 32; ++i) { for (i = 1, j = 0; i < 32; j++ && ++i, j %= 2) {
if( g_cpuHasConstReg & (1<<i) ) { if (!GPR_IS_CONST1(i) || g_cpuFlushedConstReg & (1<<i))
continue;
if( !(g_cpuFlushedConstReg&(1<<i)) ) { if (g_cpuConstRegs[i].SL[j] != 0)
MOV32ItoM((uptr)&cpuRegs.GPR.r[i].UL[0], g_cpuConstRegs[i].UL[0]); continue;
MOV32ItoM((uptr)&cpuRegs.GPR.r[i].UL[1], g_cpuConstRegs[i].UL[1]); if (eaxval != 0)
XOR32RtoR(EAX, EAX), eaxval = 0;
MOV32RtoM((uptr)&cpuRegs.GPR.r[i].SL[j], EAX);
done[j] |= 1<<i;
zero_cnt++;
}
rewindPtr = x86Ptr[_EmitterId_];
for (i = 1, j = 0; i < 32; j++ && ++i, j %= 2) {
if (!GPR_IS_CONST1(i) || g_cpuFlushedConstReg & (1<<i))
continue;
if (g_cpuConstRegs[i].SL[j] != -1)
continue;
#if 1
if (eaxval > 0)
XOR32RtoR(EAX, EAX), eaxval = 0;
#else
if (eaxval > 0)
MOV32ItoR(EAX, -1), eaxval = -1;
#endif
if (eaxval == 0)
NOT32R(EAX), eaxval = -1;
MOV32RtoM((uptr)&cpuRegs.GPR.r[i].SL[j], EAX);
done[j + 2] |= 1<<i;
minusone_cnt++;
}
if (minusone_cnt == 1 && !zero_cnt) { // not worth it for one byte
x86Ptr[_EmitterId_] = rewindPtr;
} else {
done[0] |= done[2];
done[1] |= done[3];
}
for (i = 1; i < 32; ++i) {
if (GPR_IS_CONST1(i)) {
if (!(g_cpuFlushedConstReg&(1<<i))) {
if (!(done[0] & (1<<i)))
MOV32ItoM((uptr)&cpuRegs.GPR.r[i].UL[0], g_cpuConstRegs[i].UL[0]);
if (!(done[1] & (1<<i)))
MOV32ItoM((uptr)&cpuRegs.GPR.r[i].UL[1], g_cpuConstRegs[i].UL[1]);
g_cpuFlushedConstReg |= 1<<i; g_cpuFlushedConstReg |= 1<<i;
} }
#if defined(_DEBUG)&&0 #if defined(_DEBUG)&&0
@ -171,8 +217,8 @@ void _flushConstRegs()
x86SetJ8( ptemp[2] ); x86SetJ8( ptemp[2] );
} }
#else #else
if( g_cpuHasConstReg == g_cpuFlushedConstReg ) if( g_cpuHasConstReg == g_cpuFlushedConstReg )
break; break;
#endif #endif
} }
} }

View File

@ -65,8 +65,6 @@ int branch; // set for branch
PCSX2_ALIGNED16(GPR_reg64 g_cpuConstRegs[32]) = {0}; PCSX2_ALIGNED16(GPR_reg64 g_cpuConstRegs[32]) = {0};
u32 g_cpuHasConstReg = 0, g_cpuFlushedConstReg = 0; u32 g_cpuHasConstReg = 0, g_cpuFlushedConstReg = 0;
u32 s_saveConstGPRreg = 0;
GPR_reg64 s_ConstGPRreg;
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
// Static Private Variables - R5900 Dynarec // Static Private Variables - R5900 Dynarec
@ -80,7 +78,9 @@ static u8* recStack = NULL; // stack mem
static BASEBLOCK *recRAM = NULL; // and the ptr to the blocks here static BASEBLOCK *recRAM = NULL; // and the ptr to the blocks here
static BASEBLOCK *recROM = NULL; // and here static BASEBLOCK *recROM = NULL; // and here
static BASEBLOCK *recROM1 = NULL; // also here static BASEBLOCK *recROM1 = NULL; // also here
static BaseBlocks recBlocks(EE_NUMBLOCKS); static u32 *recRAMCopy = NULL;
void JITCompile();
static BaseBlocks recBlocks(EE_NUMBLOCKS, (uptr)JITCompile);
static u8* recPtr = NULL, *recStackPtr = NULL; static u8* recPtr = NULL, *recStackPtr = NULL;
static EEINST* s_pInstCache = NULL; static EEINST* s_pInstCache = NULL;
static u32 s_nInstCacheSize = 0; static u32 s_nInstCacheSize = 0;
@ -91,6 +91,7 @@ static u32 s_nEndBlock = 0; // what pc the current block ends
static u32 s_nHasDelay = 0; static u32 s_nHasDelay = 0;
// save states for branches // save states for branches
GPR_reg64 s_saveConstRegs[32];
static u16 s_savex86FpuState, s_saveiCWstate; static u16 s_savex86FpuState, s_saveiCWstate;
static u32 s_saveHasConstReg = 0, s_saveFlushedConstReg = 0, s_saveRegHasLive1 = 0, s_saveRegHasSignExt = 0; static u32 s_saveHasConstReg = 0, s_saveFlushedConstReg = 0, s_saveRegHasLive1 = 0, s_saveRegHasSignExt = 0;
static EEINST* s_psaveInstInfo = NULL; static EEINST* s_psaveInstInfo = NULL;
@ -111,7 +112,7 @@ static u32 dumplog = 0;
//static const char *txt2 = "M32 = %x\n"; //static const char *txt2 = "M32 = %x\n";
#endif #endif
static void iBranchTest(u32 newpc, bool noDispatch=false); static void iBranchTest(u32 newpc = 0xffffffff, bool noDispatch=false);
static void ClearRecLUT(BASEBLOCK* base, int count); static void ClearRecLUT(BASEBLOCK* base, int count);
//////////////////////////////////////////////////// ////////////////////////////////////////////////////
@ -446,7 +447,6 @@ u32* recAllocStackMem(int size, int align)
return (u32*)(recStackPtr-size); return (u32*)(recStackPtr-size);
} }
static const int REC_CACHEMEM = 0x01000000; static const int REC_CACHEMEM = 0x01000000;
static void __fastcall dyna_block_discard(u32 start,u32 sz); static void __fastcall dyna_block_discard(u32 start,u32 sz);
@ -455,7 +455,7 @@ static u8* m_recBlockAlloc = NULL;
static const uint m_recBlockAllocSize = static const uint m_recBlockAllocSize =
(((Ps2MemSize::Base + Ps2MemSize::Rom + Ps2MemSize::Rom1) / 4) * sizeof(BASEBLOCK)) (((Ps2MemSize::Base + Ps2MemSize::Rom + Ps2MemSize::Rom1) / 4) * sizeof(BASEBLOCK))
+ RECSTACK_SIZE; // recStack + RECSTACK_SIZE + Ps2MemSize::Base;
static void recAlloc() static void recAlloc()
{ {
@ -497,7 +497,8 @@ static void recAlloc()
recRAM = (BASEBLOCK*)curpos; curpos += (Ps2MemSize::Base / 4) * sizeof(BASEBLOCK); recRAM = (BASEBLOCK*)curpos; curpos += (Ps2MemSize::Base / 4) * sizeof(BASEBLOCK);
recROM = (BASEBLOCK*)curpos; curpos += (Ps2MemSize::Rom / 4) * sizeof(BASEBLOCK); recROM = (BASEBLOCK*)curpos; curpos += (Ps2MemSize::Rom / 4) * sizeof(BASEBLOCK);
recROM1 = (BASEBLOCK*)curpos; curpos += (Ps2MemSize::Rom1 / 4) * sizeof(BASEBLOCK); recROM1 = (BASEBLOCK*)curpos; curpos += (Ps2MemSize::Rom1 / 4) * sizeof(BASEBLOCK);
recStack = (u8*)curpos; recStack = (u8*)curpos; curpos += RECSTACK_SIZE;
recRAMCopy = (u32*)curpos;
if( s_pInstCache == NULL ) if( s_pInstCache == NULL )
{ {
@ -599,6 +600,7 @@ static void recShutdown( void )
safe_aligned_free( m_recBlockAlloc ); safe_aligned_free( m_recBlockAlloc );
recRAM = recROM = recROM1 = NULL; recRAM = recROM = recROM1 = NULL;
recStack = NULL; recStack = NULL;
recRAMCopy = NULL;
safe_free( s_pInstCache ); safe_free( s_pInstCache );
s_nInstCacheSize = 0; s_nInstCacheSize = 0;
@ -661,79 +663,6 @@ static __declspec(naked) void JITCompileInBlock()
} }
} }
// jumped to when an immediate branch (EE side) hasn't been statically linked yet.
// Block is compiled if needed, and the link is made.
// EDX contains the jump addr to modify
static __naked void Dispatcher()
{
__asm {
mov eax, dword ptr [cpuRegs.pc]
mov ebx, eax
shr eax, 16
mov ecx, dword ptr [recLUT+eax*4]
mov eax, dword ptr [ecx+ebx]
cmp eax, offset JITCompile
je notcompiled
cmp eax, offset JITCompileInBlock
je notcompiled
lea ebx, [eax-4]
sub ebx, edx
mov dword ptr [edx], ebx
jmp eax
align 16
notcompiled:
mov esi, edx
lea edi, [ecx+ebx]
push ebx
call recRecompile
add esp, 4
mov eax, dword ptr [edi]
lea ebx, [eax-4]
sub ebx, esi
mov dword ptr [esi], ebx
jmp eax
}
}
// edx - block start pc
// stack - x86Ptr[0]
static __naked void DispatcherClear()
{
__asm {
mov [cpuRegs.pc], edx
mov ebx, edx
shr edx, 16
mov ecx, dword ptr [recLUT+edx*4]
mov eax, dword ptr [ecx+ebx]
cmp eax, offset JITCompile
je notcompiled
cmp eax, offset JITCompileInBlock
je notcompiled
add esp, 4
jmp eax
align 16
notcompiled:
lea edi, [ecx+ebx]
push ebx
call recRecompile
add esp, 4
mov eax, dword ptr [edi]
pop ecx
mov byte ptr [ecx], 0xe9 // jmp32
lea ebx, [eax-5]
sub ebx, ecx
mov dword ptr [ecx+1], ebx
jmp eax
}
}
// called when jumping to variable pc address // called when jumping to variable pc address
static void __naked DispatcherReg() static void __naked DispatcherReg()
{ {
@ -882,22 +811,6 @@ void recBREAK( void ) {
} } } // end namespace R5900::Dynarec::OpcodeImpl } } } // end namespace R5900::Dynarec::OpcodeImpl
////////////////////////////////////////////////////
static u32 REC_CLEARM( u32 mem )
{
if ((mem) < maxrecmem && (recLUT[(mem) >> 16] + mem))
return recClearMem(mem);
else
return 4;
}
void recClear( u32 Addr, u32 Size )
{
u32 pc = Addr;
while (pc < Addr + Size*4)
pc += REC_CLEARM(pc);
}
// Clears the recLUT table so that all blocks are mapped to the JIT recompiler by default. // Clears the recLUT table so that all blocks are mapped to the JIT recompiler by default.
static void ClearRecLUT(BASEBLOCK* base, int count) static void ClearRecLUT(BASEBLOCK* base, int count)
{ {
@ -906,7 +819,7 @@ static void ClearRecLUT(BASEBLOCK* base, int count)
} }
// Returns the offset to the next instruction after any cleared memory // Returns the offset to the next instruction after any cleared memory
u32 recClearMem(u32 pc) void recClear(u32 addr, u32 size)
{ {
BASEBLOCKEX* pexblock; BASEBLOCKEX* pexblock;
BASEBLOCK* pblock; BASEBLOCK* pblock;
@ -928,61 +841,61 @@ u32 recClearMem(u32 pc)
#endif #endif
#endif #endif
pblock = PC_GETBLOCK(pc); if ((addr) >= maxrecmem || !(recLUT[(addr) >> 16] + (addr & ~0xFFFFUL)))
if (pblock->GetFnptr() == (uptr)JITCompile) return;
return 4; addr = HWADDR(addr);
pc = HWADDR(pc); int blockidx = recBlocks.LastIndex(addr + size * 4 - 4);
u32 lowerextent = pc, upperextent = pc + 4; if (blockidx == -1)
int blockidx = recBlocks.Index(pc); return;
jASSUME(blockidx != -1); u32 lowerextent = (u32)-1, upperextent = 0, ceiling = (u32)-1;
while (pexblock = recBlocks[blockidx - 1]) { pexblock = recBlocks[blockidx + 1];
if (pexblock->startpc + pexblock->size*4 <= lowerextent) if (pexblock)
break; ceiling = pexblock->startpc;
lowerextent = min(lowerextent, pexblock->startpc);
blockidx--;
}
while (pexblock = recBlocks[blockidx]) { while (pexblock = recBlocks[blockidx]) {
if (pexblock->startpc >= upperextent) u32 blockstart = pexblock->startpc;
u32 blockend = pexblock->startpc + pexblock->size * 4;
pblock = PC_GETBLOCK(blockstart);
if (pblock == s_pCurBlock) {
blockidx--;
continue;
}
if (blockend <= addr) {
lowerextent = max(lowerextent, blockend);
break; break;
}
pblock = PC_GETBLOCK(pexblock->startpc); lowerextent = min(lowerextent, blockstart);
x86Ptr[_EmitterId_] = (u8*)pblock->GetFnptr(); upperextent = max(upperextent, blockend);
// This might end up inside a block that doesn't contain the clearing range,
jASSUME((u8*)JITCompile != x86Ptr[_EmitterId_]); // so set it to recompile now. This will become JITCompile if we clear it.
jASSUME((u8*)JITCompileInBlock != x86Ptr[_EmitterId_]); pblock->SetFnptr((uptr)JITCompileInBlock);
recBlocks.Remove(blockidx--);
// Actually, if we want to do this at all maybe keeping a hash
// table of const jumps and modifying the jumps straight from
// here is the way to go.
// there is a small problem: mem can be ored with 0xa<<28 or 0x8<<28, and don't know which
MOV32ItoR(EDX, pexblock->startpc);
assert((uptr)x86Ptr[_EmitterId_] <= 0xffffffff);
PUSH32I((uptr)x86Ptr[_EmitterId_]); // will be replaced by JMP32
JMP32((uptr)DispatcherClear - ((uptr)x86Ptr[_EmitterId_] + 5));
lowerextent = min(lowerextent, pexblock->startpc);
upperextent = max(upperextent, pexblock->startpc + pexblock->size * 4);
recBlocks.Remove(blockidx);
} }
upperextent = min(upperextent, ceiling);
#ifdef PCSX2_DEVBUILD #ifdef PCSX2_DEVBUILD
for (int i = 0; pexblock = recBlocks[i]; i++) for (int i = 0; pexblock = recBlocks[i]; i++) {
if (pc >= pexblock->startpc && pc < pexblock->startpc + pexblock->size * 4) { if (s_pCurBlock == PC_GETBLOCK(pexblock->startpc))
continue;
u32 blockend = pexblock->startpc + pexblock->size * 4;
if (pexblock->startpc >= addr && pexblock->startpc < addr + size * 4
|| pexblock->startpc < addr && blockend > addr) {
Console::Error("Impossible block clearing failure"); Console::Error("Impossible block clearing failure");
jASSUME(0); jASSUME(0);
} }
}
#endif #endif
ClearRecLUT(PC_GETBLOCK(lowerextent), (upperextent - lowerextent) / 4); if (upperextent > lowerextent)
ClearRecLUT(PC_GETBLOCK(lowerextent), (upperextent - lowerextent) / 4);
return upperextent - pc;
} }
// check for end of bios // check for end of bios
@ -1055,7 +968,7 @@ void SetBranchReg( u32 reg )
iFlushCall(FLUSH_EVERYTHING); iFlushCall(FLUSH_EVERYTHING);
iBranchTest(0xffffffff); iBranchTest();
} }
void SetBranchImm( u32 imm ) void SetBranchImm( u32 imm )
@ -1065,9 +978,7 @@ void SetBranchImm( u32 imm )
assert( imm ); assert( imm );
// end the current block // end the current block
MOV32ItoM( (uptr)&cpuRegs.pc, imm );
iFlushCall(FLUSH_EVERYTHING); iFlushCall(FLUSH_EVERYTHING);
iBranchTest(imm); iBranchTest(imm);
} }
@ -1076,7 +987,7 @@ void SaveBranchState()
s_savex86FpuState = x86FpuState; s_savex86FpuState = x86FpuState;
s_saveiCWstate = iCWstate; s_saveiCWstate = iCWstate;
s_savenBlockCycles = s_nBlockCycles; s_savenBlockCycles = s_nBlockCycles;
s_saveConstGPRreg = 0xffffffff; // indicate searching memcpy(s_saveConstRegs, g_cpuConstRegs, sizeof(g_cpuConstRegs));
s_saveHasConstReg = g_cpuHasConstReg; s_saveHasConstReg = g_cpuHasConstReg;
s_saveFlushedConstReg = g_cpuFlushedConstReg; s_saveFlushedConstReg = g_cpuFlushedConstReg;
s_psaveInstInfo = g_pCurInstInfo; s_psaveInstInfo = g_pCurInstInfo;
@ -1094,19 +1005,7 @@ void LoadBranchState()
iCWstate = s_saveiCWstate; iCWstate = s_saveiCWstate;
s_nBlockCycles = s_savenBlockCycles; s_nBlockCycles = s_savenBlockCycles;
if( s_saveConstGPRreg != 0xffffffff ) { memcpy(g_cpuConstRegs, s_saveConstRegs, sizeof(g_cpuConstRegs));
assert( s_saveConstGPRreg > 0 );
// make sure right GPR was saved
assert( g_cpuHasConstReg == s_saveHasConstReg || (g_cpuHasConstReg ^ s_saveHasConstReg) == (1<<s_saveConstGPRreg) );
// restore the GPR reg
g_cpuConstRegs[s_saveConstGPRreg] = s_ConstGPRreg;
GPR_SET_CONST(s_saveConstGPRreg);
s_saveConstGPRreg = 0;
}
g_cpuHasConstReg = s_saveHasConstReg; g_cpuHasConstReg = s_saveHasConstReg;
g_cpuFlushedConstReg = s_saveFlushedConstReg; g_cpuFlushedConstReg = s_saveFlushedConstReg;
g_pCurInstInfo = s_psaveInstInfo; g_pCurInstInfo = s_psaveInstInfo;
@ -1209,6 +1108,19 @@ u32 eeScaleBlockCycles()
return temp >> (3+2); return temp >> (3+2);
} }
static void iBranch(u32 newpc, int type)
{
u32* ptr;
MOV32ItoM((uptr)&cpuRegs.pc, newpc);
if (type == 0)
ptr = JMP32(0);
else if (type == 1)
ptr = JS32(0);
recBlocks.Link(HWADDR(newpc), (uptr)ptr);
}
// Generates dynarec code for Event tests followed by a block dispatch (branch). // Generates dynarec code for Event tests followed by a block dispatch (branch).
// Parameters: // Parameters:
// newpc - address to jump to at the end of the block. If newpc == 0xffffffff then // newpc - address to jump to at the end of the block. If newpc == 0xffffffff then
@ -1224,41 +1136,23 @@ static void iBranchTest(u32 newpc, bool noDispatch)
#ifdef _DEBUG #ifdef _DEBUG
//CALLFunc((uptr)testfpu); //CALLFunc((uptr)testfpu);
#endif #endif
u32* ptr;
if( bExecBIOS ) CheckForBIOSEnd(); if( bExecBIOS ) CheckForBIOSEnd();
MOV32MtoR(EAX, (uptr)&cpuRegs.cycle);
if( !noDispatch && newpc != 0xffffffff )
{
// Optimization note: Instructions order to pair EDX with EAX's load above.
// Load EDX with the address of the JS32 jump below.
// We do this because the the Dispatcher will use this info to modify
// the JS instruction later on with the address of the block it's jumping
// to; creating a static link of blocks that doesn't require the overhead
// of a dispatcher.
MOV32ItoR(EDX, 0);
ptr = (u32*)(x86Ptr[0]-4);
}
// Check the Event scheduler if our "cycle target" has been reached. // Check the Event scheduler if our "cycle target" has been reached.
// Equiv code to: // Equiv code to:
// cpuRegs.cycle += blockcycles; // cpuRegs.cycle += blockcycles;
// if( cpuRegs.cycle > g_nextBranchCycle ) { DoEvents(); } // if( cpuRegs.cycle > g_nextBranchCycle ) { DoEvents(); }
MOV32MtoR(EAX, (uptr)&cpuRegs.cycle);
ADD32ItoR(EAX, eeScaleBlockCycles()); ADD32ItoR(EAX, eeScaleBlockCycles());
MOV32RtoM((uptr)&cpuRegs.cycle, EAX); // update cycles MOV32RtoM((uptr)&cpuRegs.cycle, EAX); // update cycles
SUB32MtoR(EAX, (uptr)&g_nextBranchCycle); SUB32MtoR(EAX, (uptr)&g_nextBranchCycle);
if( newpc != 0xffffffff ) if (!noDispatch) {
{ if (newpc == 0xffffffff)
// This is the jump instruction which gets modified by Dispatcher. JS32((uptr)DispatcherReg - ( (uptr)x86Ptr[0] + 6 ));
*ptr = (u32)JS32((u32)Dispatcher - ( (u32)x86Ptr[0] + 6 )); else
} iBranch(newpc, 1);
else if( !noDispatch )
{
// This instruction is a dynamic link, so it's never modified.
JS32((uptr)DispatcherReg - ( (uptr)x86Ptr[0] + 6 ));
} }
RET(); RET();
@ -1271,7 +1165,7 @@ static void checkcodefn()
#ifdef _MSC_VER #ifdef _MSC_VER
__asm mov pctemp, eax; __asm mov pctemp, eax;
#else #else
__asm__("movl %%eax, %0" : "=m"(pctemp) ); __asm__("movl %%eax, %[pctemp]" : [pctemp]"=m"(pctemp) );
#endif #endif
Console::Error("code changed! %x", params pctemp); Console::Error("code changed! %x", params pctemp);
@ -1283,54 +1177,39 @@ void recompileNextInstruction(int delayslot)
static u8 s_bFlushReg = 1; static u8 s_bFlushReg = 1;
int i, count; int i, count;
BASEBLOCK* pblock = PC_GETBLOCK(pc);
// need *ppblock != s_pCurBlock because of branches
if (HWADDR(pc) != s_pCurBlockEx->startpc && pblock->GetFnptr() != (uptr)JITCompile && pblock->GetFnptr() != (uptr)JITCompileInBlock)
{
if (!delayslot)
{
// code already in place, so jump to it and exit recomp
assert( recBlocks.Get(HWADDR(pc))->startpc == HWADDR(pc) );
iFlushCall(FLUSH_EVERYTHING);
MOV32ItoM((uptr)&cpuRegs.pc, pc);
JMP32((uptr)pblock->GetFnptr() - ((uptr)x86Ptr[0] + 5));
branch = 3;
return;
}
}
s_pCode = (int *)PSM( pc ); s_pCode = (int *)PSM( pc );
assert(s_pCode); assert(s_pCode);
// why?
#ifdef _DEBUG #ifdef _DEBUG
MOV32ItoR(EAX, pc); MOV32ItoR(EAX, pc);
#endif #endif
cpuRegs.code = *(int *)s_pCode; cpuRegs.code = *(int *)s_pCode;
pc += 4; pc += 4;
//#ifdef _DEBUG #if 0
// CMP32ItoM((u32)s_pCode, cpuRegs.code); #ifdef _DEBUG
// j8Ptr[0] = JE8(0); CMP32ItoM((u32)s_pCode, cpuRegs.code);
// MOV32ItoR(EAX, pc); j8Ptr[0] = JE8(0);
// CALLFunc((uptr)checkcodefn); MOV32ItoR(EAX, pc);
// x86SetJ8( j8Ptr[ 0 ] ); CALLFunc((uptr)checkcodefn);
// x86SetJ8( j8Ptr[ 0 ] );
// if( !delayslot ) {
// CMP32ItoM((u32)&cpuRegs.pc, s_pCurBlockEx->startpc); if( !delayslot ) {
// j8Ptr[0] = JB8(0); CMP32ItoM((u32)&cpuRegs.pc, s_pCurBlockEx->startpc);
// CMP32ItoM((u32)&cpuRegs.pc, pc); j8Ptr[0] = JB8(0);
// j8Ptr[1] = JA8(0); CMP32ItoM((u32)&cpuRegs.pc, pc);
// j8Ptr[2] = JMP8(0); j8Ptr[1] = JA8(0);
// x86SetJ8( j8Ptr[ 0 ] ); j8Ptr[2] = JMP8(0);
// x86SetJ8( j8Ptr[ 1 ] ); x86SetJ8( j8Ptr[ 0 ] );
// PUSH32I(s_pCurBlockEx->startpc); x86SetJ8( j8Ptr[ 1 ] );
// ADD32ItoR(ESP, 4); PUSH32I(s_pCurBlockEx->startpc);
// x86SetJ8( j8Ptr[ 2 ] ); ADD32ItoR(ESP, 4);
// } x86SetJ8( j8Ptr[ 2 ] );
//#endif }
#endif
#endif
g_pCurInstInfo++; g_pCurInstInfo++;
@ -1476,13 +1355,12 @@ void recRecompile( const u32 startpc )
u32 i = 0; u32 i = 0;
u32 branchTo; u32 branchTo;
u32 willbranch3 = 0; u32 willbranch3 = 0;
u32* ptr;
u32 usecop2; u32 usecop2;
#ifdef _DEBUG #ifdef _DEBUG
//dumplog |= 4; //dumplog |= 4;
if( dumplog & 4 ) if( dumplog & 4 )
iDumpRegisters(startpc, 0); iDumpRegisters(startpc, 0);
#endif #endif
assert( startpc ); assert( startpc );
@ -1497,29 +1375,29 @@ void recRecompile( const u32 startpc )
recResetEE(); recResetEE();
} }
x86SetPtr( recPtr );
x86Align(16);
recPtr = x86Ptr[_EmitterId_];
s_pCurBlock = PC_GETBLOCK(startpc); s_pCurBlock = PC_GETBLOCK(startpc);
assert(s_pCurBlock->GetFnptr() == (uptr)JITCompile assert(s_pCurBlock->GetFnptr() == (uptr)JITCompile
|| s_pCurBlock->GetFnptr() == (uptr)JITCompileInBlock); || s_pCurBlock->GetFnptr() == (uptr)JITCompileInBlock);
s_pCurBlockEx = recBlocks.Get(HWADDR(startpc)); s_pCurBlockEx = recBlocks.Get(HWADDR(startpc));
if (!s_pCurBlockEx || s_pCurBlockEx->startpc != HWADDR(startpc)) { assert(!s_pCurBlockEx || s_pCurBlockEx->startpc != HWADDR(startpc));
s_pCurBlockEx = recBlocks.New(HWADDR(startpc));
if( s_pCurBlockEx == NULL ) { s_pCurBlockEx = recBlocks.New(HWADDR(startpc), (uptr)recPtr);
//SysPrintf("ee reset (blocks)\n");
recResetEE(); if( s_pCurBlockEx == NULL ) {
s_pCurBlockEx = recBlocks.New(HWADDR(startpc)); //SysPrintf("ee reset (blocks)\n");
} recResetEE();
x86SetPtr( recPtr );
s_pCurBlockEx = recBlocks.New(HWADDR(startpc), (uptr)recPtr);
} }
assert(s_pCurBlockEx); assert(s_pCurBlockEx);
x86SetPtr( recPtr );
x86Align(16);
recPtr = x86Ptr[0];
s_pCurBlock->SetFnptr( (uptr)x86Ptr[0] );
branch = 0; branch = 0;
// reset recomp state variables // reset recomp state variables
@ -1527,7 +1405,6 @@ void recRecompile( const u32 startpc )
pc = startpc; pc = startpc;
x86FpuState = FPU_STATE; x86FpuState = FPU_STATE;
iCWstate = 0; iCWstate = 0;
s_saveConstGPRreg = 0;
g_cpuHasConstReg = g_cpuFlushedConstReg = 1; g_cpuHasConstReg = g_cpuFlushedConstReg = 1;
g_cpuPrevRegHasLive1 = g_cpuRegHasLive1 = 0xffffffff; g_cpuPrevRegHasLive1 = g_cpuRegHasLive1 = 0xffffffff;
g_cpuPrevRegHasSignExt = g_cpuRegHasSignExt = 0; g_cpuPrevRegHasSignExt = g_cpuRegHasSignExt = 0;
@ -1815,40 +1692,25 @@ StartRecomp:
#endif #endif
u32 sz=(s_nEndBlock-startpc)>>2; u32 sz=(s_nEndBlock-startpc)>>2;
#ifdef lulz
/*
Block checking (ADDED BY RAZ-TEMP)
*/
MOV32ItoR(ECX,startpc);
MOV32ItoR(EDX,sz);
#endif
u32 inpage_offs=startpc&0xFFF;
u32 inpage_ptr=startpc; u32 inpage_ptr=startpc;
u32 inpage_sz=sz*4; u32 inpage_sz=sz*4;
MOV32ItoR(ECX,startpc);
MOV32ItoR(EDX,sz);
while(inpage_sz) while(inpage_sz)
{ {
int PageType=mmap_GetRamPageInfo((u32*)PSM(inpage_ptr)); int PageType = mmap_GetRamPageInfo((u32*)PSM(inpage_ptr));
u32 pgsz=std::min(0x1000-inpage_offs,inpage_sz); u32 inpage_offs = inpage_ptr & 0xFFF;
u32 pgsz = std::min(0x1000 - inpage_offs, inpage_sz);
if(PageType!=-1) if(PageType!=-1)
{ {
if (PageType==0) if (PageType==0)
{
//MOV32ItoR(EAX,*pageVer);
//CMP32MtoR(EAX,(uptr)pageVer);
//JNE32(((u32)dyna_block_discard_recmem)- ( (u32)x86Ptr[0] + 6 ));
mmap_MarkCountedRamPage(PSM(inpage_ptr),inpage_ptr&~0xFFF); mmap_MarkCountedRamPage(PSM(inpage_ptr),inpage_ptr&~0xFFF);
}
else else
{ {
MOV32ItoR(ECX, startpc);
MOV32ItoR(EDX, sz);
u32 lpc=inpage_ptr; u32 lpc=inpage_ptr;
u32 stg=pgsz; u32 stg=pgsz;
while(stg>0) while(stg>0)
@ -1866,7 +1728,6 @@ StartRecomp:
} }
inpage_ptr+=pgsz; inpage_ptr+=pgsz;
inpage_sz-=pgsz; inpage_sz-=pgsz;
inpage_offs=inpage_ptr&0xFFF;
} }
// finally recompile // // finally recompile //
@ -1883,6 +1744,32 @@ StartRecomp:
assert( (pc-startpc)>>2 <= 0xffff ); assert( (pc-startpc)>>2 <= 0xffff );
s_pCurBlockEx->size = (pc-startpc)>>2; s_pCurBlockEx->size = (pc-startpc)>>2;
if (HWADDR(pc) <= Ps2MemSize::Base) {
BASEBLOCKEX *oldBlock;
int i;
i = recBlocks.LastIndex(HWADDR(pc) - 4);
while (oldBlock = recBlocks[i--]) {
if (oldBlock == s_pCurBlockEx)
continue;
if (oldBlock->startpc >= HWADDR(pc))
continue;
if (oldBlock->startpc + oldBlock->size * 4 <= HWADDR(startpc))
break;
if (memcmp(&recRAMCopy[oldBlock->startpc / 4], PSM(oldBlock->startpc),
oldBlock->size * 4)) {
recClear(startpc, (pc - startpc) / 4);
s_pCurBlockEx = recBlocks.Get(HWADDR(startpc));
assert(s_pCurBlockEx->startpc == HWADDR(startpc));
break;
}
}
memcpy(&recRAMCopy[HWADDR(startpc) / 4], PSM(startpc), pc - startpc);
}
s_pCurBlock->SetFnptr((uptr)recPtr);
for(i = 1; i < (u32)s_pCurBlockEx->size; i++) { for(i = 1; i < (u32)s_pCurBlockEx->size; i++) {
if ((uptr)JITCompile == s_pCurBlock[i].GetFnptr()) if ((uptr)JITCompile == s_pCurBlock[i].GetFnptr())
s_pCurBlock[i].SetFnptr((uptr)JITCompileInBlock); s_pCurBlock[i].SetFnptr((uptr)JITCompileInBlock);
@ -1910,21 +1797,9 @@ StartRecomp:
else else
ADD32ItoM((int)&cpuRegs.cycle, eeScaleBlockCycles() ); ADD32ItoM((int)&cpuRegs.cycle, eeScaleBlockCycles() );
if( willbranch3 ) { if( willbranch3 || !branch) {
BASEBLOCK* pblock = PC_GETBLOCK(s_nEndBlock);
assert( pc == s_nEndBlock );
iFlushCall(FLUSH_EVERYTHING); iFlushCall(FLUSH_EVERYTHING);
MOV32ItoM((uptr)&cpuRegs.pc, pc); iBranch(pc, 0);
JMP32((uptr)pblock->GetFnptr() - ((uptr)x86Ptr[0] + 5));
branch = 3;
}
else if( !branch ) {
// didn't branch, but had to stop
MOV32ItoM( (uptr)&cpuRegs.pc, pc );
iFlushCall(FLUSH_EVERYTHING);
ptr = JMP32(0);
} }
} }
@ -1932,20 +1807,15 @@ StartRecomp:
assert( recStackPtr < recStack+RECSTACK_SIZE ); assert( recStackPtr < recStack+RECSTACK_SIZE );
assert( x86FpuState == 0 ); assert( x86FpuState == 0 );
assert(x86Ptr[_EmitterId_] - recPtr < 0x10000);
s_pCurBlockEx->x86size = x86Ptr[_EmitterId_] - recPtr;
recPtr = x86Ptr[0]; recPtr = x86Ptr[0];
assert( (g_cpuHasConstReg&g_cpuFlushedConstReg) == g_cpuHasConstReg ); assert( (g_cpuHasConstReg&g_cpuFlushedConstReg) == g_cpuHasConstReg );
if( !branch ) { s_pCurBlock = NULL;
assert( ptr != NULL ); s_pCurBlockEx = NULL;
s_pCurBlock = PC_GETBLOCK(pc);
if (s_pCurBlock->GetFnptr() == (uptr)JITCompile
|| s_pCurBlock->GetFnptr() == (uptr)JITCompileInBlock)
recRecompile(pc);
*ptr = s_pCurBlock->GetFnptr() - ((u32)ptr + 4);
}
} }
R5900cpu recCpu = { R5900cpu recCpu = {

View File

@ -2077,13 +2077,6 @@ void recLoad64( u32 bits, bool sign )
//no int 3? i love to get my hands dirty ;p - Raz //no int 3? i love to get my hands dirty ;p - Raz
//write8(0xCC); //write8(0xCC);
_deleteEEreg(_Rs_, 1);
_eeOnLoadWrite(_Rt_);
EEINST_RESETSIGNEXT(_Rt_); // remove the sign extension
_deleteEEreg(_Rt_, 0);
// Load EDX with the destination. // Load EDX with the destination.
// 64/128 bit modes load the result directly into the cpuRegs.GPR struct. // 64/128 bit modes load the result directly into the cpuRegs.GPR struct.
@ -2092,16 +2085,23 @@ void recLoad64( u32 bits, bool sign )
else else
MOV32ItoR(EDX, (uptr)&dummyValue[0] ); MOV32ItoR(EDX, (uptr)&dummyValue[0] );
if( IS_EECONSTREG( _Rs_ ) ) if( GPR_IS_CONST1( _Rs_ ) )
{ {
_eeOnLoadWrite(_Rt_);
EEINST_RESETSIGNEXT(_Rt_); // remove the sign extension
_deleteEEreg(_Rt_, 0);
u32 srcadr = g_cpuConstRegs[_Rs_].UL[0] + _Imm_; u32 srcadr = g_cpuConstRegs[_Rs_].UL[0] + _Imm_;
if( bits == 128 ) srcadr &= ~0x0f; if( bits == 128 ) srcadr &= ~0x0f;
vtlb_DynGenRead64_Const( bits, srcadr ); vtlb_DynGenRead64_Const( bits, srcadr );
} }
else else
{ {
_deleteEEreg(_Rs_, 1);
// Load ECX with the source memory address that we're reading from. // Load ECX with the source memory address that we're reading from.
MOV32MtoR( ECX, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); MOV32MtoR( ECX, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] );
_eeOnLoadWrite(_Rt_);
EEINST_RESETSIGNEXT(_Rt_); // remove the sign extension
_deleteEEreg(_Rt_, 0);
if ( _Imm_ != 0 ) if ( _Imm_ != 0 )
ADD32ItoR( ECX, _Imm_ ); ADD32ItoR( ECX, _Imm_ );
@ -2119,21 +2119,23 @@ void recLoad32(u32 bits,bool sign)
//no int 3? i love to get my hands dirty ;p - Raz //no int 3? i love to get my hands dirty ;p - Raz
//write8(0xCC); //write8(0xCC);
_deleteEEreg(_Rs_, 1);
_eeOnLoadWrite(_Rt_);
_deleteEEreg(_Rt_, 0);
// 8/16/32 bit modes return the loaded value in EAX. // 8/16/32 bit modes return the loaded value in EAX.
if( IS_EECONSTREG( _Rs_ ) ) if( GPR_IS_CONST1( _Rs_ ) )
{ {
_eeOnLoadWrite(_Rt_);
_deleteEEreg(_Rt_, 0);
u32 srcadr = g_cpuConstRegs[_Rs_].UL[0] + _Imm_; u32 srcadr = g_cpuConstRegs[_Rs_].UL[0] + _Imm_;
vtlb_DynGenRead32_Const( bits, sign, srcadr ); vtlb_DynGenRead32_Const( bits, sign, srcadr );
} }
else else
{ {
_deleteEEreg(_Rs_, 1);
// Load ECX with the source memory address that we're reading from. // Load ECX with the source memory address that we're reading from.
MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] );
_eeOnLoadWrite(_Rt_);
_deleteEEreg(_Rt_, 0);
if ( _Imm_ != 0 ) if ( _Imm_ != 0 )
ADD32ItoR( ECX, _Imm_ ); ADD32ItoR( ECX, _Imm_ );
@ -2463,7 +2465,6 @@ void recStore(u32 sz)
//no int 3? i love to get my hands dirty ;p - Raz //no int 3? i love to get my hands dirty ;p - Raz
//write8(0xCC); //write8(0xCC);
_deleteEEreg(_Rs_, 1);
_deleteEEreg(_Rt_, 1); _deleteEEreg(_Rt_, 1);
// Performance note: Const prop for the store address is good, always. // Performance note: Const prop for the store address is good, always.
@ -2498,6 +2499,7 @@ void recStore(u32 sz)
} }
else else
{ {
_deleteEEreg(_Rs_, 1);
MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] );
if ( _Imm_ != 0 ) if ( _Imm_ != 0 )
ADD32ItoR(ECX, _Imm_); ADD32ItoR(ECX, _Imm_);

View File

@ -425,13 +425,7 @@ void recMTLO1( void )
//// MOVZ //// MOVZ
void recMOVZtemp_const() void recMOVZtemp_const()
{ {
GPR_DEL_CONST(_Rd_); g_cpuConstRegs[_Rd_].UD[0] = g_cpuConstRegs[_Rs_].UD[0];
_deleteEEreg(_Rd_, 1);
_eeOnWriteReg(_Rd_, 0);
if (g_cpuConstRegs[_Rt_].UD[0] == 0) {
MOV32ItoM((uptr)&cpuRegs.GPR.r[_Rd_].UL[0], g_cpuConstRegs[_Rs_].UL[0]);
MOV32ItoM((uptr)&cpuRegs.GPR.r[_Rd_].UL[1], g_cpuConstRegs[_Rs_].UL[1]);
}
} }
//static PCSX2_ALIGNED16(u32 s_zero[4]) = {0,0,0xffffffff, 0xffffffff}; //static PCSX2_ALIGNED16(u32 s_zero[4]) = {0,0,0xffffffff, 0xffffffff};
@ -475,24 +469,22 @@ void recMOVZtemp_consts(int info)
void recMOVZtemp_constt(int info) void recMOVZtemp_constt(int info)
{ {
if (g_cpuConstRegs[_Rt_].UD[0] == 0) { if( info & PROCESS_EE_MMX ) {
if( info & PROCESS_EE_MMX ) { if( EEREC_D != EEREC_S ) MOVQRtoR(EEREC_D, EEREC_S);
if( EEREC_D != EEREC_S ) MOVQRtoR(EEREC_D, EEREC_S); return;
return; }
}
if( _hasFreeXMMreg() ) {
if( _hasFreeXMMreg() ) { int t0reg = _allocMMXreg(-1, MMX_TEMP, 0);
int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); MOVQMtoR(t0reg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]);
MOVQMtoR(t0reg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); MOVQRtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], t0reg);
MOVQRtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], t0reg); _freeMMXreg(t0reg);
_freeMMXreg(t0reg); }
} else {
else { MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]);
MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); MOV32MtoR(EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ]);
MOV32MtoR(EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ]); MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX);
MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX); MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX);
MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX);
}
} }
} }
@ -546,22 +538,11 @@ void recMOVZ()
if( _Rs_ == _Rd_ ) if( _Rs_ == _Rd_ )
return; return;
if( GPR_IS_CONST1(_Rd_) ) { if(GPR_IS_CONST1(_Rt_)) {
if (g_cpuConstRegs[_Rt_].UD[0] != 0)
if( !GPR_IS_CONST2(_Rs_, _Rt_) ) {
// remove the const, since move is conditional
_deleteEEreg(_Rd_, 0);
MOV32ItoM((uptr)&cpuRegs.GPR.r[_Rd_].UL[0], g_cpuConstRegs[_Rd_].UL[0]);
MOV32ItoM((uptr)&cpuRegs.GPR.r[_Rd_].UL[1], g_cpuConstRegs[_Rd_].UL[1]);
}
else {
if (g_cpuConstRegs[_Rt_].UD[0] == 0) {
g_cpuConstRegs[_Rd_].UL[0] = g_cpuConstRegs[_Rs_].UL[0];
g_cpuConstRegs[_Rd_].UL[1] = g_cpuConstRegs[_Rs_].UL[1];
}
return; return;
} } else if (GPR_IS_CONST1(_Rd_))
} _deleteEEreg(_Rd_, 1);
recMOVZtemp(); recMOVZtemp();
} }
@ -569,13 +550,7 @@ void recMOVZ()
//// MOVN //// MOVN
void recMOVNtemp_const() void recMOVNtemp_const()
{ {
GPR_DEL_CONST(_Rd_); g_cpuConstRegs[_Rd_].UD[0] = g_cpuConstRegs[_Rs_].UD[0];
_deleteEEreg(_Rd_, 1);
_eeOnWriteReg(_Rd_, 0);
if (g_cpuConstRegs[_Rt_].UD[0] != 0) {
MOV32ItoM((uptr)&cpuRegs.GPR.r[_Rd_].UL[0], g_cpuConstRegs[_Rs_].UL[0]);
MOV32ItoM((uptr)&cpuRegs.GPR.r[_Rd_].UL[1], g_cpuConstRegs[_Rs_].UL[1]);
}
} }
void recMOVNtemp_consts(int info) void recMOVNtemp_consts(int info)
@ -618,19 +593,17 @@ void recMOVNtemp_consts(int info)
void recMOVNtemp_constt(int info) void recMOVNtemp_constt(int info)
{ {
if (g_cpuConstRegs[_Rt_].UD[0] != 0) { if( _hasFreeXMMreg() ) {
if( _hasFreeXMMreg() ) { int t0reg = _allocMMXreg(-1, MMX_TEMP, 0);
int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); MOVQMtoR(t0reg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]);
MOVQMtoR(t0reg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); MOVQRtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], t0reg);
MOVQRtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], t0reg); _freeMMXreg(t0reg);
_freeMMXreg(t0reg); }
} else {
else { MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]);
MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); MOV32MtoR(EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ]);
MOV32MtoR(EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ]); MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX);
MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX); MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX);
MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX);
}
} }
} }
@ -685,22 +658,11 @@ void recMOVN()
if( _Rs_ == _Rd_ ) if( _Rs_ == _Rd_ )
return; return;
if( GPR_IS_CONST1(_Rd_) ) { if (GPR_IS_CONST1(_Rt_)) {
if (g_cpuConstRegs[_Rt_].UD[0] == 0)
if( !GPR_IS_CONST2(_Rs_, _Rt_) ) {
// remove the const, since move is conditional
_deleteEEreg(_Rd_, 0);
MOV32ItoM((uptr)&cpuRegs.GPR.r[_Rd_].UL[0], g_cpuConstRegs[_Rd_].UL[0]);
MOV32ItoM((uptr)&cpuRegs.GPR.r[_Rd_].UL[1], g_cpuConstRegs[_Rd_].UL[1]);
}
else {
if (g_cpuConstRegs[_Rt_].UD[0] != 0) {
g_cpuConstRegs[_Rd_].UL[0] = g_cpuConstRegs[_Rs_].UL[0];
g_cpuConstRegs[_Rd_].UL[1] = g_cpuConstRegs[_Rs_].UL[1];
}
return; return;
} } else if (GPR_IS_CONST1(_Rd_))
} _deleteEEreg(_Rd_, 1);
recMOVNtemp(); recMOVNtemp();
} }

View File

@ -38,19 +38,6 @@
// Code Templates // // Code Templates //
//////////////////// ////////////////////
void CHECK_SAVE_REG(int reg)
{
if( s_saveConstGPRreg == 0xffffffff ) {
if( GPR_IS_CONST1(reg) ) {
s_saveConstGPRreg = reg;
s_ConstGPRreg = g_cpuConstRegs[reg];
}
}
else {
assert( s_saveConstGPRreg == 0 || s_saveConstGPRreg == reg );
}
}
void _eeProcessHasLive(int reg, int signext) void _eeProcessHasLive(int reg, int signext)
{ {
g_cpuPrevRegHasLive1 = g_cpuRegHasLive1; g_cpuPrevRegHasLive1 = g_cpuRegHasLive1;
@ -68,7 +55,6 @@ void _eeProcessHasLive(int reg, int signext)
void _eeOnWriteReg(int reg, int signext) void _eeOnWriteReg(int reg, int signext)
{ {
CHECK_SAVE_REG(reg);
GPR_DEL_CONST(reg); GPR_DEL_CONST(reg);
_eeProcessHasLive(reg, signext); _eeProcessHasLive(reg, signext);
} }
@ -109,7 +95,6 @@ void eeRecompileCode0(R5900FNPTR constcode, R5900FNPTR_INFO constscode, R5900FNP
if ( ! _Rd_ && (xmminfo&XMMINFO_WRITED) ) return; if ( ! _Rd_ && (xmminfo&XMMINFO_WRITED) ) return;
if( xmminfo&XMMINFO_WRITED) { if( xmminfo&XMMINFO_WRITED) {
CHECK_SAVE_REG(_Rd_);
_eeProcessHasLive(_Rd_, 0); _eeProcessHasLive(_Rd_, 0);
EEINST_RESETSIGNEXT(_Rd_); EEINST_RESETSIGNEXT(_Rd_);
} }
@ -421,7 +406,6 @@ void eeRecompileCode1(R5900FNPTR constcode, R5900FNPTR_INFO noconstcode)
int mmreg1, mmreg2; int mmreg1, mmreg2;
if ( ! _Rt_ ) return; if ( ! _Rt_ ) return;
CHECK_SAVE_REG(_Rt_);
_eeProcessHasLive(_Rt_, 0); _eeProcessHasLive(_Rt_, 0);
EEINST_RESETSIGNEXT(_Rt_); EEINST_RESETSIGNEXT(_Rt_);
@ -522,7 +506,6 @@ void eeRecompileCode2(R5900FNPTR constcode, R5900FNPTR_INFO noconstcode)
int mmreg1, mmreg2; int mmreg1, mmreg2;
if ( ! _Rd_ ) return; if ( ! _Rd_ ) return;
CHECK_SAVE_REG(_Rd_);
_eeProcessHasLive(_Rd_, 0); _eeProcessHasLive(_Rd_, 0);
EEINST_RESETSIGNEXT(_Rd_); EEINST_RESETSIGNEXT(_Rd_);
@ -651,7 +634,6 @@ void eeRecompileCodeConst0(R5900FNPTR constcode, R5900FNPTR_INFO constscode, R59
if ( ! _Rd_ ) return; if ( ! _Rd_ ) return;
// for now, don't support xmm // for now, don't support xmm
CHECK_SAVE_REG(_Rd_);
_deleteGPRtoXMMreg(_Rs_, 1); _deleteGPRtoXMMreg(_Rs_, 1);
_deleteGPRtoXMMreg(_Rt_, 1); _deleteGPRtoXMMreg(_Rt_, 1);
@ -689,7 +671,6 @@ void eeRecompileCodeConst1(R5900FNPTR constcode, R5900FNPTR_INFO noconstcode)
return; return;
// for now, don't support xmm // for now, don't support xmm
CHECK_SAVE_REG(_Rt_);
_deleteGPRtoXMMreg(_Rs_, 1); _deleteGPRtoXMMreg(_Rs_, 1);
_deleteGPRtoXMMreg(_Rt_, 0); _deleteGPRtoXMMreg(_Rt_, 0);
@ -710,7 +691,6 @@ void eeRecompileCodeConst2(R5900FNPTR constcode, R5900FNPTR_INFO noconstcode)
if ( ! _Rd_ ) return; if ( ! _Rd_ ) return;
// for now, don't support xmm // for now, don't support xmm
CHECK_SAVE_REG(_Rd_);
_deleteGPRtoXMMreg(_Rt_, 1); _deleteGPRtoXMMreg(_Rt_, 1);
_deleteGPRtoXMMreg(_Rd_, 0); _deleteGPRtoXMMreg(_Rd_, 0);
@ -731,7 +711,6 @@ void eeRecompileCodeConstSPECIAL(R5900FNPTR constcode, R5900FNPTR_INFO multicode
assert(0); assert(0);
// for now, don't support xmm // for now, don't support xmm
if( MULT ) { if( MULT ) {
CHECK_SAVE_REG(_Rd_);
_deleteGPRtoXMMreg(_Rd_, 0); _deleteGPRtoXMMreg(_Rd_, 0);
} }
@ -767,7 +746,6 @@ int eeRecompileCodeXMM(int xmminfo)
// save state // save state
if( xmminfo & XMMINFO_WRITED ) { if( xmminfo & XMMINFO_WRITED ) {
CHECK_SAVE_REG(_Rd_);
_eeProcessHasLive(_Rd_, 0); _eeProcessHasLive(_Rd_, 0);
EEINST_RESETSIGNEXT(_Rd_); EEINST_RESETSIGNEXT(_Rd_);
} }

View File

@ -173,7 +173,7 @@ static void _vtlb_DynGen_IndirectRead( u32 bits )
MOVZX32R8toR(EAX,EAX); MOVZX32R8toR(EAX,EAX);
SUB32RtoR(ECX,EAX); SUB32RtoR(ECX,EAX);
//eax=[funct+eax] //eax=[funct+eax]
MOV32RmSOffsettoR(EAX,EAX,(int)RWFT[szidx][0],2); MOV32RmSOffsettoR(EAX,EAX,(int)vtlbdata.RWFT[szidx][0],2);
SUB32ItoR(ECX,0x80000000); SUB32ItoR(ECX,0x80000000);
CALL32R(EAX); CALL32R(EAX);
} }
@ -187,7 +187,7 @@ void vtlb_DynGenRead64(u32 bits)
MOV32RtoR(EAX,ECX); MOV32RtoR(EAX,ECX);
SHR32ItoR(EAX,VTLB_PAGE_BITS); SHR32ItoR(EAX,VTLB_PAGE_BITS);
MOV32RmSOffsettoR(EAX,EAX,(int)vmap,2); MOV32RmSOffsettoR(EAX,EAX,(int)vtlbdata.vmap,2);
ADD32RtoR(ECX,EAX); ADD32RtoR(ECX,EAX);
u8* _fullread = JS8(0); u8* _fullread = JS8(0);
@ -209,7 +209,7 @@ void vtlb_DynGenRead32(u32 bits, bool sign)
MOV32RtoR(EAX,ECX); MOV32RtoR(EAX,ECX);
SHR32ItoR(EAX,VTLB_PAGE_BITS); SHR32ItoR(EAX,VTLB_PAGE_BITS);
MOV32RmSOffsettoR(EAX,EAX,(int)vmap,2); MOV32RmSOffsettoR(EAX,EAX,(int)vtlbdata.vmap,2);
ADD32RtoR(ECX,EAX); ADD32RtoR(ECX,EAX);
u8* _fullread = JS8(0); u8* _fullread = JS8(0);
@ -243,7 +243,7 @@ void vtlb_DynGenRead64_Const( u32 bits, u32 addr_const )
{ {
jASSUME( bits == 64 || bits == 128 ); jASSUME( bits == 64 || bits == 128 );
void* vmv_ptr = &vmap[addr_const>>VTLB_PAGE_BITS]; void* vmv_ptr = &vtlbdata.vmap[addr_const>>VTLB_PAGE_BITS];
MOV32MtoR(EAX,(uptr)vmv_ptr); MOV32MtoR(EAX,(uptr)vmv_ptr);
MOV32ItoR(ECX,addr_const); MOV32ItoR(ECX,addr_const);
@ -266,7 +266,7 @@ void vtlb_DynGenRead32_Const( u32 bits, bool sign, u32 addr_const )
{ {
jASSUME( bits <= 32 ); jASSUME( bits <= 32 );
void* vmv_ptr = &vmap[addr_const>>VTLB_PAGE_BITS]; void* vmv_ptr = &vtlbdata.vmap[addr_const>>VTLB_PAGE_BITS];
MOV32MtoR(EAX,(uptr)vmv_ptr); MOV32MtoR(EAX,(uptr)vmv_ptr);
MOV32ItoR(ECX,addr_const); MOV32ItoR(ECX,addr_const);
@ -368,7 +368,7 @@ static void _vtlb_DynGen_IndirectWrite( u32 bits )
MOVZX32R8toR(EAX,EAX); MOVZX32R8toR(EAX,EAX);
SUB32RtoR(ECX,EAX); SUB32RtoR(ECX,EAX);
//eax=[funct+eax] //eax=[funct+eax]
MOV32RmSOffsettoR(EAX,EAX,(int)RWFT[szidx][1],2); MOV32RmSOffsettoR(EAX,EAX,(int)vtlbdata.RWFT[szidx][1],2);
SUB32ItoR(ECX,0x80000000); SUB32ItoR(ECX,0x80000000);
CALL32R(EAX); CALL32R(EAX);
} }
@ -377,7 +377,7 @@ void vtlb_DynGenWrite(u32 sz)
{ {
MOV32RtoR(EAX,ECX); MOV32RtoR(EAX,ECX);
SHR32ItoR(EAX,VTLB_PAGE_BITS); SHR32ItoR(EAX,VTLB_PAGE_BITS);
MOV32RmSOffsettoR(EAX,EAX,(int)vmap,2); MOV32RmSOffsettoR(EAX,EAX,(int)vtlbdata.vmap,2);
ADD32RtoR(ECX,EAX); ADD32RtoR(ECX,EAX);
u8* _full=JS8(0); u8* _full=JS8(0);
@ -398,7 +398,7 @@ void vtlb_DynGenWrite_Const( u32 bits, u32 addr_const )
// the VTLB could feasibly be remapped by other recompiled code at any time. // the VTLB could feasibly be remapped by other recompiled code at any time.
// So we're limited in exactly how much we can pre-calcuate. // So we're limited in exactly how much we can pre-calcuate.
void* vmv_ptr = &vmap[addr_const>>VTLB_PAGE_BITS]; void* vmv_ptr = &vtlbdata.vmap[addr_const>>VTLB_PAGE_BITS];
MOV32MtoR(EAX,(uptr)vmv_ptr); MOV32MtoR(EAX,(uptr)vmv_ptr);
MOV32ItoR(ECX,addr_const); MOV32ItoR(ECX,addr_const);

View File

@ -41,7 +41,7 @@ emitterT void WriteRmOffset(x86IntRegType to, s32 offset)
ModRM<I>( 0, 0, 4 ); ModRM<I>( 0, 0, 4 );
SibSB<I>( 0, ESP, 4 ); SibSB<I>( 0, ESP, 4 );
} }
else if( offset < 128 && offset >= -128 ) { else if( offset <= 127 && offset >= -128 ) {
ModRM<I>( 1, 0, 4 ); ModRM<I>( 1, 0, 4 );
SibSB<I>( 0, ESP, 4 ); SibSB<I>( 0, ESP, 4 );
write8<I>(offset); write8<I>(offset);
@ -56,7 +56,7 @@ emitterT void WriteRmOffset(x86IntRegType to, s32 offset)
if( offset == 0 ) { if( offset == 0 ) {
ModRM<I>( 0, 0, to ); ModRM<I>( 0, 0, to );
} }
else if( offset < 128 && offset >= -128 ) { else if( offset <= 127 && offset >= -128 ) {
ModRM<I>( 1, 0, to ); ModRM<I>( 1, 0, to );
write8<I>(offset); write8<I>(offset);
} }
@ -74,7 +74,7 @@ emitterT void WriteRmOffsetFrom(x86IntRegType to, x86IntRegType from, int offset
ModRM<I>( 0, to, 0x4 ); ModRM<I>( 0, to, 0x4 );
SibSB<I>( 0, 0x4, 0x4 ); SibSB<I>( 0, 0x4, 0x4 );
} }
else if( offset < 128 && offset >= -128 ) { else if( offset <= 127 && offset >= -128 ) {
ModRM<I>( 1, to, 0x4 ); ModRM<I>( 1, to, 0x4 );
SibSB<I>( 0, 0x4, 0x4 ); SibSB<I>( 0, 0x4, 0x4 );
write8<I>(offset); write8<I>(offset);
@ -89,7 +89,7 @@ emitterT void WriteRmOffsetFrom(x86IntRegType to, x86IntRegType from, int offset
if( offset == 0 ) { if( offset == 0 ) {
ModRM<I>( 0, to, from ); ModRM<I>( 0, to, from );
} }
else if( offset < 128 && offset >= -128 ) { else if( offset <= 127 && offset >= -128 ) {
ModRM<I>( 1, to, from ); ModRM<I>( 1, to, from );
write8<I>(offset); write8<I>(offset);
} }
@ -401,8 +401,12 @@ emitterT void eMOV32RtoR( x86IntRegType to, x86IntRegType from )
emitterT void eMOV32RtoM( uptr to, x86IntRegType from ) emitterT void eMOV32RtoM( uptr to, x86IntRegType from )
{ {
RexR(0, from); RexR(0, from);
write8<I>( 0x89 ); if (from == EAX) {
ModRM<I>( 0, from, DISP32 ); write8<I>(0xA3);
} else {
write8<I>( 0x89 );
ModRM<I>( 0, from, DISP32 );
}
write32<I>( MEMADDR(to, 4) ); write32<I>( MEMADDR(to, 4) );
} }
@ -410,8 +414,12 @@ emitterT void eMOV32RtoM( uptr to, x86IntRegType from )
emitterT void eMOV32MtoR( x86IntRegType to, uptr from ) emitterT void eMOV32MtoR( x86IntRegType to, uptr from )
{ {
RexR(0, to); RexR(0, to);
write8<I>( 0x8B ); if (to == EAX) {
ModRM<I>( 0, to, DISP32 ); write8<I>(0xA1);
} else {
write8<I>( 0x8B );
ModRM<I>( 0, to, DISP32 );
}
write32<I>( MEMADDR(from, 4) ); write32<I>( MEMADDR(from, 4) );
} }
@ -1038,69 +1046,69 @@ emitterT void eADD64RtoR( x86IntRegType to, x86IntRegType from )
} }
/* add imm32 to EAX */ /* add imm32 to EAX */
emitterT void eADD32ItoEAX( u32 from ) emitterT void eADD32ItoEAX( s32 imm )
{ {
write8<I>( 0x05 ); write8<I>( 0x05 );
write32<I>( from ); write32<I>( imm );
} }
/* add imm32 to r32 */ /* add imm32 to r32 */
emitterT void eADD32ItoR( x86IntRegType to, u32 from ) emitterT void eADD32ItoR( x86IntRegType to, s32 imm )
{ {
RexB(0, to); RexB(0, to);
if(from < 0x80) if (imm <= 127 && imm >= -128)
{ {
write8<I>( 0x83 ); write8<I>( 0x83 );
ModRM<I>( 3, 0, to ); ModRM<I>( 3, 0, to );
write8<I>( from ); write8<I>( (s8)imm );
} }
else else
{ {
if ( to == EAX ) { if ( to == EAX ) {
eADD32ItoEAX<I>(from); eADD32ItoEAX<I>(imm);
} }
else { else {
write8<I>( 0x81 ); write8<I>( 0x81 );
ModRM<I>( 3, 0, to ); ModRM<I>( 3, 0, to );
write32<I>( from ); write32<I>( imm );
} }
} }
} }
/* add imm32 to m32 */ /* add imm32 to m32 */
emitterT void eADD32ItoM( uptr to, u32 from ) emitterT void eADD32ItoM( uptr to, s32 imm )
{ {
/*if(from < 0x80) // crashes games in 64bit build; TODO: figure out why. if(imm <= 127 && imm >= -128)
{ {
write8<I>( 0x83 ); write8<I>( 0x83 );
ModRM<I>( 0, 0, DISP32 ); ModRM<I>( 0, 0, DISP32 );
write32<I>( MEMADDR(to, 8) ); write32<I>( MEMADDR(to, 8) );
write8<I>( from ); write8<I>( imm );
} }
else*/ else
{ {
write8<I>( 0x81 ); write8<I>( 0x81 );
ModRM<I>( 0, 0, DISP32 ); ModRM<I>( 0, 0, DISP32 );
write32<I>( MEMADDR(to, 8) ); write32<I>( MEMADDR(to, 8) );
write32<I>( from ); write32<I>( imm );
} }
} }
// add imm32 to [r32+off] // add imm32 to [r32+off]
emitterT void eADD32ItoRmOffset( x86IntRegType to, u32 from, s32 offset) emitterT void eADD32ItoRmOffset( x86IntRegType to, s32 imm, s32 offset)
{ {
RexB(0,to); RexB(0,to);
if(from < 0x80) if(imm <= 127 && imm >= -128)
{ {
write8<I>( 0x83 ); write8<I>( 0x83 );
WriteRmOffset<I>(to,offset); WriteRmOffset<I>(to,offset);
write8<I>(from); write8<I>(imm);
} }
else else
{ {
write8<I>( 0x81 ); write8<I>( 0x81 );
WriteRmOffset<I>(to,offset); WriteRmOffset<I>(to,offset);
write32<I>(from); write32<I>(imm);
} }
} }
@ -1140,7 +1148,7 @@ emitterT void eADD16RtoR( x86IntRegType to , x86IntRegType from )
} }
/* add imm16 to r16 */ /* add imm16 to r16 */
emitterT void eADD16ItoR( x86IntRegType to, u16 from ) emitterT void eADD16ItoR( x86IntRegType to, s16 imm )
{ {
write8<I>( 0x66 ); write8<I>( 0x66 );
RexB(0,to); RexB(0,to);
@ -1148,39 +1156,39 @@ emitterT void eADD16ItoR( x86IntRegType to, u16 from )
if ( to == EAX) if ( to == EAX)
{ {
write8<I>( 0x05 ); write8<I>( 0x05 );
write16<I>( from ); write16<I>( imm );
} }
else if(from < 0x80) else if(imm <= 127 && imm >= -128)
{ {
write8<I>( 0x83 ); write8<I>( 0x83 );
ModRM<I>( 3, 0, to ); ModRM<I>( 3, 0, to );
write8<I>((u8)from ); write8<I>((u8)imm );
} }
else else
{ {
write8<I>( 0x81 ); write8<I>( 0x81 );
ModRM<I>( 3, 0, to ); ModRM<I>( 3, 0, to );
write16<I>( from ); write16<I>( imm );
} }
} }
/* add imm16 to m16 */ /* add imm16 to m16 */
emitterT void eADD16ItoM( uptr to, u16 from ) emitterT void eADD16ItoM( uptr to, s16 imm )
{ {
write8<I>( 0x66 ); write8<I>( 0x66 );
if(from < 0x80) if(imm <= 127 && imm >= -128)
{ {
write8<I>( 0x83 ); write8<I>( 0x83 );
ModRM<I>( 0, 0, DISP32 ); ModRM<I>( 0, 0, DISP32 );
write32<I>( MEMADDR(to, 6) ); write32<I>( MEMADDR(to, 6) );
write8<I>((u8)from ); write8<I>((u8)imm );
} }
else else
{ {
write8<I>( 0x81 ); write8<I>( 0x81 );
ModRM<I>( 0, 0, DISP32 ); ModRM<I>( 0, 0, DISP32 );
write32<I>( MEMADDR(to, 6) ); write32<I>( MEMADDR(to, 6) );
write16<I>( from ); write16<I>( imm );
} }
} }
@ -3250,7 +3258,7 @@ emitterT void eLEA16RtoR(x86IntRegType to, x86IntRegType from, u16 offset)
eLEA32RtoR<I>(to, from, offset); eLEA32RtoR<I>(to, from, offset);
} }
emitterT void eLEA32RtoR(x86IntRegType to, x86IntRegType from, u32 offset) emitterT void eLEA32RtoR(x86IntRegType to, x86IntRegType from, s32 offset)
{ {
RexRB(0,to,from); RexRB(0,to,from);
write8<I>(0x8d); write8<I>(0x8d);
@ -3260,7 +3268,7 @@ emitterT void eLEA32RtoR(x86IntRegType to, x86IntRegType from, u32 offset)
ModRM<I>(1, to, from); ModRM<I>(1, to, from);
write8<I>(0x24); write8<I>(0x24);
} }
else if( offset < 128 ) { else if( offset <= 127 && offset >= -128 ) {
ModRM<I>(1, to, from); ModRM<I>(1, to, from);
write8<I>(0x24); write8<I>(0x24);
write8<I>(offset); write8<I>(offset);
@ -3275,7 +3283,7 @@ emitterT void eLEA32RtoR(x86IntRegType to, x86IntRegType from, u32 offset)
if( offset == 0 && from != EBP && from!=ESP ) { if( offset == 0 && from != EBP && from!=ESP ) {
ModRM<I>(0, to, from); ModRM<I>(0, to, from);
} }
else if( offset < 128 ) { else if( offset <= 127 && offset >= -128 ) {
ModRM<I>(1, to, from); ModRM<I>(1, to, from);
write8<I>(offset); write8<I>(offset);
} }

View File

@ -115,7 +115,7 @@ extern s32 iCpuId( u32 cmd, u32 *regs )
"pushf\n" "pushf\n"
"pop %%eax\n" "pop %%eax\n"
"xor %%edx, %%eax\n" "xor %%edx, %%eax\n"
"mov %%eax, %0\n" "mov %%eax, %[flag]\n"
"add $0x18, %%esp\n" "add $0x18, %%esp\n"
"cmpl $0x0,%%eax\n" "cmpl $0x0,%%eax\n"
"jne 1f\n" "jne 1f\n"
@ -123,7 +123,7 @@ extern s32 iCpuId( u32 cmd, u32 *regs )
"leave\n" "leave\n"
"ret\n" "ret\n"
"1:\n" "1:\n"
: "=r"(flag) : : [flag]"=r"(flag) :
); );
cpuid(cmd, regs[0], regs[1], regs[2], regs[3]); cpuid(cmd, regs[0], regs[1], regs[2], regs[3]);

View File

@ -61,7 +61,7 @@ void SetCPUState(u32 sseMXCSR, u32 sseVUMXCSR)
#ifdef _MSC_VER #ifdef _MSC_VER
__asm ldmxcsr g_sseMXCSR; // set the new sse control __asm ldmxcsr g_sseMXCSR; // set the new sse control
#else #else
__asm__("ldmxcsr %0" : : "m"(g_sseMXCSR) ); __asm__("ldmxcsr %[g_sseMXCSR]" : : [g_sseMXCSR]"m"(g_sseMXCSR) );
#endif #endif
//g_sseVUMXCSR = g_sseMXCSR|0x6000; //g_sseVUMXCSR = g_sseMXCSR|0x6000;
} }
@ -108,16 +108,16 @@ __forceinline void FreezeMMXRegs_(int save)
#else #else
__asm__( __asm__(
".intel_syntax noprefix\n" ".intel_syntax noprefix\n"
"movq [%0+0x00], mm0\n" "movq [%[g_globalMMXData]+0x00], mm0\n"
"movq [%0+0x08], mm1\n" "movq [%[g_globalMMXData]+0x08], mm1\n"
"movq [%0+0x10], mm2\n" "movq [%[g_globalMMXData]+0x10], mm2\n"
"movq [%0+0x18], mm3\n" "movq [%[g_globalMMXData]+0x18], mm3\n"
"movq [%0+0x20], mm4\n" "movq [%[g_globalMMXData]+0x20], mm4\n"
"movq [%0+0x28], mm5\n" "movq [%[g_globalMMXData]+0x28], mm5\n"
"movq [%0+0x30], mm6\n" "movq [%[g_globalMMXData]+0x30], mm6\n"
"movq [%0+0x38], mm7\n" "movq [%[g_globalMMXData]+0x38], mm7\n"
"emms\n" "emms\n"
".att_syntax\n" : : "r"(g_globalMMXData) ".att_syntax\n" : : [g_globalMMXData]"r"(g_globalMMXData)
); );
#endif #endif
@ -148,16 +148,16 @@ __forceinline void FreezeMMXRegs_(int save)
#else #else
__asm__( __asm__(
".intel_syntax noprefix\n" ".intel_syntax noprefix\n"
"movq mm0, [%0+0x00]\n" "movq mm0, [%[g_globalMMXData]+0x00]\n"
"movq mm1, [%0+0x08]\n" "movq mm1, [%[g_globalMMXData]+0x08]\n"
"movq mm2, [%0+0x10]\n" "movq mm2, [%[g_globalMMXData]+0x10]\n"
"movq mm3, [%0+0x18]\n" "movq mm3, [%[g_globalMMXData]+0x18]\n"
"movq mm4, [%0+0x20]\n" "movq mm4, [%[g_globalMMXData]+0x20]\n"
"movq mm5, [%0+0x28]\n" "movq mm5, [%[g_globalMMXData]+0x28]\n"
"movq mm6, [%0+0x30]\n" "movq mm6, [%[g_globalMMXData]+0x30]\n"
"movq mm7, [%0+0x38]\n" "movq mm7, [%[g_globalMMXData]+0x38]\n"
"emms\n" "emms\n"
".att_syntax\n" : : "r"(g_globalMMXData) ".att_syntax\n" : : [g_globalMMXData]"r"(g_globalMMXData)
); );
#endif #endif
} }
@ -195,15 +195,15 @@ __forceinline void FreezeXMMRegs_(int save)
#else #else
__asm__( __asm__(
".intel_syntax noprefix\n" ".intel_syntax noprefix\n"
"movaps [%0+0x00], xmm0\n" "movaps [%[g_globalXMMData]+0x00], xmm0\n"
"movaps [%0+0x10], xmm1\n" "movaps [%[g_globalXMMData]+0x10], xmm1\n"
"movaps [%0+0x20], xmm2\n" "movaps [%[g_globalXMMData]+0x20], xmm2\n"
"movaps [%0+0x30], xmm3\n" "movaps [%[g_globalXMMData]+0x30], xmm3\n"
"movaps [%0+0x40], xmm4\n" "movaps [%[g_globalXMMData]+0x40], xmm4\n"
"movaps [%0+0x50], xmm5\n" "movaps [%[g_globalXMMData]+0x50], xmm5\n"
"movaps [%0+0x60], xmm6\n" "movaps [%[g_globalXMMData]+0x60], xmm6\n"
"movaps [%0+0x70], xmm7\n" "movaps [%[g_globalXMMData]+0x70], xmm7\n"
".att_syntax\n" : : "r"(g_globalXMMData) ".att_syntax\n" : : [g_globalXMMData]"r"(g_globalXMMData)
); );
#endif // _MSC_VER #endif // _MSC_VER
@ -237,15 +237,15 @@ __forceinline void FreezeXMMRegs_(int save)
#else #else
__asm__( __asm__(
".intel_syntax noprefix\n" ".intel_syntax noprefix\n"
"movaps xmm0, [%0+0x00]\n" "movaps xmm0, [%[g_globalXMMData]+0x00]\n"
"movaps xmm1, [%0+0x10]\n" "movaps xmm1, [%[g_globalXMMData]+0x10]\n"
"movaps xmm2, [%0+0x20]\n" "movaps xmm2, [%[g_globalXMMData]+0x20]\n"
"movaps xmm3, [%0+0x30]\n" "movaps xmm3, [%[g_globalXMMData]+0x30]\n"
"movaps xmm4, [%0+0x40]\n" "movaps xmm4, [%[g_globalXMMData]+0x40]\n"
"movaps xmm5, [%0+0x50]\n" "movaps xmm5, [%[g_globalXMMData]+0x50]\n"
"movaps xmm6, [%0+0x60]\n" "movaps xmm6, [%[g_globalXMMData]+0x60]\n"
"movaps xmm7, [%0+0x70]\n" "movaps xmm7, [%[g_globalXMMData]+0x70]\n"
".att_syntax\n" : : "r"(g_globalXMMData) ".att_syntax\n" : : [g_globalXMMData]"r"(g_globalXMMData)
); );
#endif // _MSC_VER #endif // _MSC_VER

View File

@ -29,42 +29,12 @@
PCSX2_ALIGNED16(microVU microVU0); PCSX2_ALIGNED16(microVU microVU0);
PCSX2_ALIGNED16(microVU microVU1); PCSX2_ALIGNED16(microVU microVU1);
PCSX2_ALIGNED16(const u32 mVU_absclip[4]) = {0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff}; declareAllVariables // Declares All Global Variables :D
PCSX2_ALIGNED16(const u32 mVU_signbit[4]) = {0x80000000, 0x80000000, 0x80000000, 0x80000000};
PCSX2_ALIGNED16(const u32 mVU_minvals[4]) = {0xff7fffff, 0xff7fffff, 0xff7fffff, 0xff7fffff};
PCSX2_ALIGNED16(const u32 mVU_maxvals[4]) = {0x7f7fffff, 0x7f7fffff, 0x7f7fffff, 0x7f7fffff};
PCSX2_ALIGNED16(const u32 mVU_one[4]) = {0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000};
PCSX2_ALIGNED16(const u32 mVU_T1[4]) = {0x3f7ffff5, 0x3f7ffff5, 0x3f7ffff5, 0x3f7ffff5};
PCSX2_ALIGNED16(const u32 mVU_T2[4]) = {0xbeaaa61c, 0xbeaaa61c, 0xbeaaa61c, 0xbeaaa61c};
PCSX2_ALIGNED16(const u32 mVU_T3[4]) = {0x3e4c40a6, 0x3e4c40a6, 0x3e4c40a6, 0x3e4c40a6};
PCSX2_ALIGNED16(const u32 mVU_T4[4]) = {0xbe0e6c63, 0xbe0e6c63, 0xbe0e6c63, 0xbe0e6c63};
PCSX2_ALIGNED16(const u32 mVU_T5[4]) = {0x3dc577df, 0x3dc577df, 0x3dc577df, 0x3dc577df};
PCSX2_ALIGNED16(const u32 mVU_T6[4]) = {0xbd6501c4, 0xbd6501c4, 0xbd6501c4, 0xbd6501c4};
PCSX2_ALIGNED16(const u32 mVU_T7[4]) = {0x3cb31652, 0x3cb31652, 0x3cb31652, 0x3cb31652};
PCSX2_ALIGNED16(const u32 mVU_T8[4]) = {0xbb84d7e7, 0xbb84d7e7, 0xbb84d7e7, 0xbb84d7e7};
PCSX2_ALIGNED16(const u32 mVU_Pi4[4]) = {0x3f490fdb, 0x3f490fdb, 0x3f490fdb, 0x3f490fdb};
PCSX2_ALIGNED16(const u32 mVU_S2[4]) = {0xbe2aaaa4, 0xbe2aaaa4, 0xbe2aaaa4, 0xbe2aaaa4};
PCSX2_ALIGNED16(const u32 mVU_S3[4]) = {0x3c08873e, 0x3c08873e, 0x3c08873e, 0x3c08873e};
PCSX2_ALIGNED16(const u32 mVU_S4[4]) = {0xb94fb21f, 0xb94fb21f, 0xb94fb21f, 0xb94fb21f};
PCSX2_ALIGNED16(const u32 mVU_S5[4]) = {0x362e9c14, 0x362e9c14, 0x362e9c14, 0x362e9c14};
PCSX2_ALIGNED16(const u32 mVU_E1[4]) = {0x3e7fffa8, 0x3e7fffa8, 0x3e7fffa8, 0x3e7fffa8};
PCSX2_ALIGNED16(const u32 mVU_E2[4]) = {0x3d0007f4, 0x3d0007f4, 0x3d0007f4, 0x3d0007f4};
PCSX2_ALIGNED16(const u32 mVU_E3[4]) = {0x3b29d3ff, 0x3b29d3ff, 0x3b29d3ff, 0x3b29d3ff};
PCSX2_ALIGNED16(const u32 mVU_E4[4]) = {0x3933e553, 0x3933e553, 0x3933e553, 0x3933e553};
PCSX2_ALIGNED16(const u32 mVU_E5[4]) = {0x36b63510, 0x36b63510, 0x36b63510, 0x36b63510};
PCSX2_ALIGNED16(const u32 mVU_E6[4]) = {0x353961ac, 0x353961ac, 0x353961ac, 0x353961ac};
PCSX2_ALIGNED16(const float mVU_FTOI_4[4]) = {16.0, 16.0, 16.0, 16.0};
PCSX2_ALIGNED16(const float mVU_FTOI_12[4]) = {4096.0, 4096.0, 4096.0, 4096.0};
PCSX2_ALIGNED16(const float mVU_FTOI_15[4]) = {32768.0, 32768.0, 32768.0, 32768.0};
PCSX2_ALIGNED16(const float mVU_ITOF_4[4]) = {0.0625f, 0.0625f, 0.0625f, 0.0625f};
PCSX2_ALIGNED16(const float mVU_ITOF_12[4]) = {0.000244140625, 0.000244140625, 0.000244140625, 0.000244140625};
PCSX2_ALIGNED16(const float mVU_ITOF_15[4]) = {0.000030517578125, 0.000030517578125, 0.000030517578125, 0.000030517578125};
//------------------------------------------------------------------ //------------------------------------------------------------------
// Micro VU - Main Functions // Micro VU - Main Functions
//------------------------------------------------------------------ //------------------------------------------------------------------
// Only run this once! ;) // Only run this once per VU! ;)
microVUt(void) mVUinit(VURegs* vuRegsPtr) { microVUt(void) mVUinit(VURegs* vuRegsPtr) {
microVU* mVU = mVUx; microVU* mVU = mVUx;
@ -86,7 +56,7 @@ microVUt(void) mVUreset() {
// Create Block Managers // Create Block Managers
for (int i; i <= mVU->prog.max; i++) { for (int i; i <= mVU->prog.max; i++) {
for (u32 j; j < mVU->progSize; j++) { for (u32 j; j < (mVU->progSize / 2); j++) {
mVU->prog.prog[i].block[j] = new microBlockManager(); mVU->prog.prog[i].block[j] = new microBlockManager();
} }
} }
@ -112,7 +82,7 @@ microVUt(void) mVUclose() {
// Delete Block Managers // Delete Block Managers
for (int i; i <= mVU->prog.max; i++) { for (int i; i <= mVU->prog.max; i++) {
for (u32 j; j < mVU->progSize; j++) { for (u32 j; j < (mVU->progSize / 2); j++) {
if (mVU->prog.prog[i].block[j]) delete mVU->prog.prog[i].block[j]; if (mVU->prog.prog[i].block[j]) delete mVU->prog.prog[i].block[j];
} }
} }
@ -142,8 +112,8 @@ microVUt(void*) __fastcall mVUexecute(u32 startPC, u32 cycles) {
*/ */
microVU* mVU = mVUx; microVU* mVU = mVUx;
if ( mVUsearchProg(mVU) ) { // Found Program if ( mVUsearchProg(mVU) ) { // Found Program
microBlock* block = mVU->prog.prog[mVU->prog.cur].block[startPC]->search(mVU->prog.lastPipelineState); //microBlock* block = mVU->prog.prog[mVU->prog.cur].block[startPC]->search(mVU->prog.lastPipelineState);
if (block) return block->x86ptrStart; // Found Block //if (block) return block->x86ptrStart; // Found Block
} }
// Recompile code // Recompile code
return NULL; return NULL;
@ -163,7 +133,7 @@ void* __fastcall mVUexecuteVU1(u32 startPC, u32 cycles) {
// Clears program data (Sets used to 1 because calling this function implies the program will be used at least once) // Clears program data (Sets used to 1 because calling this function implies the program will be used at least once)
__forceinline void mVUclearProg(microVU* mVU, int progIndex) { __forceinline void mVUclearProg(microVU* mVU, int progIndex) {
mVU->prog.prog[progIndex].used = 1; mVU->prog.prog[progIndex].used = 1;
for (u32 i = 0; i < mVU->progSize; i++) { for (u32 i = 0; i < (mVU->progSize / 2); i++) {
mVU->prog.prog[progIndex].block[i]->reset(); mVU->prog.prog[progIndex].block[i]->reset();
} }
} }

View File

@ -17,18 +17,21 @@
*/ */
#pragma once #pragma once
#define mVUdebug // Prints Extra Info to Console
#define _EmitterId_ (vuIndex+1) #define _EmitterId_ (vuIndex+1)
#include "Common.h" #include "Common.h"
#include "VU.h" #include "VU.h"
#include "GS.h"
#include "ix86/ix86.h" #include "ix86/ix86.h"
#include "microVU_Alloc.h" #include "microVU_Alloc.h"
struct microBlock { struct microBlock {
u32 pipelineState; // FMACx|y|z|w | FDiv | EFU | IALU | BRANCH // Still thinking of how I'm going to do this microRegInfo pState; // Detailed State of Pipeline
u8* x86ptrStart; u32 pipelineState; // | FDiv x 4 | EFU x 6 | Needs pState Info? x 1 | // Simple State of Pipeline
u8* x86ptrEnd; u8* x86ptrStart; // Start of code
u8* x86ptrBranch; u8* x86ptrEnd; // End of code (first byte outside of block)
//u32 size; u8* x86ptrBranch; //
u32 size; // Number of 64bit VU Instructions in Block
}; };
#define mMaxBlocks 32 // Max Blocks With Different Pipeline States (For n = 1, 2, 4, 8, 16, etc...) #define mMaxBlocks 32 // Max Blocks With Different Pipeline States (For n = 1, 2, 4, 8, 16, etc...)
@ -53,17 +56,24 @@ public:
} }
void reset() { init(); }; void reset() { init(); };
void close() {}; // Can be Omitted? void close() {}; // Can be Omitted?
void add(u32 pipelineState, u8* x86ptrStart) { /*void add(u32 pipelineState, u8* x86ptrStart) {
if (!search(pipelineState)) { if (!search(pipelineState)) {
listSize++; listSize++;
listSize &= MaxBlocks; listSize &= MaxBlocks;
blockList[listSize].pipelineState = pipelineState; blockList[listSize].pipelineState = pipelineState;
blockList[listSize].x86ptrStart = x86ptrStart; blockList[listSize].x86ptrStart = x86ptrStart;
} }
} }*/
microBlock* search(u32 pipelineState) { microBlock* search(u32 pipelineState, microRegInfo* pState) {
for (int i = 0; i < listSize; i++) { if (pipelineState & 1) { // Needs Detailed Search (Exact Match of Pipeline State)
if (blockList[i].pipelineState == pipelineState) return &blockList[i]; for (int i = 0; i < listSize; i++) {
if (!memcmp(pState, &blockList[i].pState, sizeof(microRegInfo))) return &blockList[i];
}
}
else { // Can do Simple Search (Only Matches the Important Pipeline Stuff)
for (int i = 0; i < listSize; i++) {
if (blockList[i].pipelineState == pipelineState) return &blockList[i];
}
} }
return NULL; return NULL;
} }
@ -81,9 +91,9 @@ public:
template<u32 progSize> template<u32 progSize>
struct microProgram { struct microProgram {
u8 data[progSize]; u32 data[progSize];
u32 used; // Number of times its been used u32 used; // Number of times its been used
microBlockManager* block[progSize]; microBlockManager* block[progSize / 2];
microAllocInfo<progSize> allocInfo; microAllocInfo<progSize> allocInfo;
}; };
@ -104,15 +114,16 @@ struct microVU {
u32 microSize; // VU Micro Memory Size u32 microSize; // VU Micro Memory Size
u32 progSize; // VU Micro Program Size (microSize/8) u32 progSize; // VU Micro Program Size (microSize/8)
u32 cacheAddr; // VU Cache Start Address u32 cacheAddr; // VU Cache Start Address
static const u32 cacheSize = 0x400000; // VU Cache Size static const u32 cacheSize = 0x500000; // VU Cache Size
microProgManager<0x800> prog; // Micro Program Data microProgManager<0x1000> prog; // Micro Program Data
VURegs* regs; // VU Regs Struct VURegs* regs; // VU Regs Struct
u8* cache; // Dynarec Cache Start (where we will start writing the recompiled code to) u8* cache; // Dynarec Cache Start (where we will start writing the recompiled code to)
u8* ptr; // Pointer to next place to write recompiled code to u8* ptr; // Pointer to next place to write recompiled code to
u32 code; // Contains the current Instruction u32 code; // Contains the current Instruction
u32 iReg; // iReg u32 iReg; // iReg (only used in recompilation, not execution)
u32 clipFlag[4]; // 4 instances of clip flag (used in execution)
/* /*
uptr x86eax; // Accumulator register. Used in arithmetic operations. uptr x86eax; // Accumulator register. Used in arithmetic operations.
@ -147,3 +158,4 @@ microVUt(void) mVUclose();
#include "microVU_Misc.h" #include "microVU_Misc.h"
#include "microVU_Alloc.inl" #include "microVU_Alloc.inl"
#include "microVU_Tables.inl" #include "microVU_Tables.inl"
#include "microVU_Compile.inl"

View File

@ -28,8 +28,7 @@ union regInfo {
}; };
}; };
template<u32 pSize> struct microRegInfo {
struct microAllocInfo {
regInfo VF[32]; regInfo VF[32];
regInfo Acc; regInfo Acc;
u8 VI[32]; u8 VI[32];
@ -37,22 +36,34 @@ struct microAllocInfo {
u8 q; u8 q;
u8 p; u8 p;
u8 r; u8 r;
u16 info[pSize];// bit 0 = NOP?
// bit 1 = Used with bit 2 to make a 2-bit key for ACC write instance
// bit 2 = (00 = instance #0, 01 = instance #1, 10 = instance #2, 11 = instance #3)
// bit 3 = Used with bit 4 to make a 2-bit key for ACC read instance
// bit 4 = (00 = instance #0, 01 = instance #1, 10 = instance #2, 11 = instance #3)
// bit 5 = Write to Q1 or Q2?
// bit 6 = Read Q1 or Q2?
// bit 7 = Read/Write to P1 or P2?
// bit 8 = Update Mac Flags?
// bit 9 = Update Status Flags?
// bit 10 = Used with bit 11 to make a 2-bit key for mac flag instance
// bit 11 = (00 = instance #0, 01 = instance #1, 10 = instance #2, 11 = instance #3)
// bit 12 = Used with bit 13 to make a 2-bit key for status flag instance
// bit 13 = (00 = instance #0, 01 = instance #1, 10 = instance #2, 11 = instance #3)
// bit 14 = Read VI(Fs) from backup memory?
// bit 15 = Read VI(Ft) from backup memory?
u32 curPC;
}; };
template<u32 pSize>
struct microAllocInfo {
microRegInfo regs;
u8 branch; // 0 = No Branch, 1 = Branch, 2 = Conditional Branch, 3 = Jump (JALR/JR)
u32 curPC; // Current PC
u32 cycles; // Cycles for current block
u32 info[pSize];// bit 00 = Lower Instruction is NOP
// bit 01
// bit 02
// bit 03
// bit 04
// bit 05 = Write to Q1 or Q2?
// bit 06 = Read Q1 or Q2?
// bit 07 = Read/Write to P1 or P2?
// bit 08 = Update Mac Flags?
// bit 09 = Update Status Flags?
// bit 10 = Used with bit 11 to make a 2-bit key for mac flag instance
// bit 11
// bit 12 = Used with bit 13 to make a 2-bit key for status flag instance
// bit 13
// bit 14 = Used with bit 15 to make a 2-bit key for clip flag instance
// bit 15
// bit 16 = Used with bit 17 to make a 2-bit key for mac flag instance
// bit 17
// bit 18 = Used with bit 19 to make a 2-bit key for status flag instance
// bit 19
// bit 20 = Read VI(Fs) from backup memory?
// bit 21 = Read VI(Ft) from backup memory?
};

View File

@ -146,18 +146,18 @@ microVUt(void) mVUallocFMAC3b(int& Fd) {
if (_W) { mVUloadReg<vuIndex>(reg, (uptr)&mVU->regs->VF[0].UL[0], _xyzw_ACC); } \ if (_W) { mVUloadReg<vuIndex>(reg, (uptr)&mVU->regs->VF[0].UL[0], _xyzw_ACC); } \
else { SSE_XORPS_XMM_to_XMM(reg, reg); } \ else { SSE_XORPS_XMM_to_XMM(reg, reg); } \
} }
/*
#define getACC(reg) { \ #define getACC(reg) { \
reg = xmmACC0 + writeACC; \ reg = xmmACC0 + writeACC; \
if (_X_Y_Z_W != 15) { SSE_MOVAPS_XMM_to_XMM(reg, (xmmACC0 + prevACC)); } \ if (_X_Y_Z_W != 15) { SSE_MOVAPS_XMM_to_XMM(reg, (xmmACC0 + prevACC)); } \
} }
*/
microVUt(void) mVUallocFMAC4a(int& ACC, int& Fs, int& Ft) { microVUt(void) mVUallocFMAC4a(int& ACC, int& Fs, int& Ft) {
microVU* mVU = mVUx; microVU* mVU = mVUx;
Fs = xmmFs; ACC = xmmACC;
Fs = (_X_Y_Z_W == 15) ? xmmACC : xmmFs;
Ft = xmmFt; Ft = xmmFt;
getACC(ACC); if (_X_Y_Z_W == 8) {
if (_XYZW_SS && _X) {
getReg6(Fs, _Fs_); getReg6(Fs, _Fs_);
if (_Ft_ == _Fs_) { Ft = Fs; } if (_Ft_ == _Fs_) { Ft = Fs; }
else { getReg6(Ft, _Ft_); } else { getReg6(Ft, _Ft_); }
@ -184,10 +184,10 @@ microVUt(void) mVUallocFMAC4b(int& ACC, int& Fs) {
microVUt(void) mVUallocFMAC5a(int& ACC, int& Fs, int& Ft) { microVUt(void) mVUallocFMAC5a(int& ACC, int& Fs, int& Ft) {
microVU* mVU = mVUx; microVU* mVU = mVUx;
Fs = xmmFs; ACC = xmmACC;
Fs = (_X_Y_Z_W == 15) ? xmmACC : xmmFs;
Ft = xmmFt; Ft = xmmFt;
getACC(ACC); if (_X_Y_Z_W == 8) {
if (_XYZW_SS && _X) {
getReg6(Fs, _Fs_); getReg6(Fs, _Fs_);
if ((_Ft_ == _Fs_) && _bc_x) { Ft = Fs; } if ((_Ft_ == _Fs_) && _bc_x) { Ft = Fs; }
else if (!_Ft_) { getZero3SS(Ft); } else if (!_Ft_) { getZero3SS(Ft); }
@ -236,11 +236,11 @@ microVUt(void) mVUallocFMAC6b(int& Fd) {
microVUt(void) mVUallocFMAC7a(int& ACC, int& Fs, int& Ft) { microVUt(void) mVUallocFMAC7a(int& ACC, int& Fs, int& Ft) {
microVU* mVU = mVUx; microVU* mVU = mVUx;
Fs = xmmFs; ACC = xmmACC;
Fs = (_X_Y_Z_W == 15) ? xmmACC : xmmFs;
Ft = xmmFt; Ft = xmmFt;
getACC(ACC);
getIreg(Ft); getIreg(Ft);
if (_XYZW_SS && _X) { getReg6(Fs, _Fs_); } if (_X_Y_Z_W == 8) { getReg6(Fs, _Fs_); }
else if (!_Fs_) { getZero4(Fs); } else if (!_Fs_) { getZero4(Fs); }
else { getReg4(Fs, _Fs_); } else { getReg4(Fs, _Fs_); }
} }
@ -253,13 +253,13 @@ microVUt(void) mVUallocFMAC7b(int& ACC, int& Fs) {
// FMAC8 - MADD FMAC Opcode Storing Result to Fd // FMAC8 - MADD FMAC Opcode Storing Result to Fd
//------------------------------------------------------------------ //------------------------------------------------------------------
microVUt(void) mVUallocFMAC8a(int& Fd, int&ACC, int& Fs, int& Ft) { microVUt(void) mVUallocFMAC8a(int& Fd, int& ACC, int& Fs, int& Ft) {
microVU* mVU = mVUx; microVU* mVU = mVUx;
Fs = xmmFs; Fs = xmmFs;
Ft = xmmFt; Ft = xmmFt;
Fd = xmmFs; Fd = xmmFs;
ACC = xmmACC0 + readACC; ACC = xmmACC;
if (_XYZW_SS && _X) { if (_X_Y_Z_W == 8) {
getReg6(Fs, _Fs_); getReg6(Fs, _Fs_);
if (_Ft_ == _Fs_) { Ft = Fs; } if (_Ft_ == _Fs_) { Ft = Fs; }
else { getReg6(Ft, _Ft_); } else { getReg6(Ft, _Ft_); }
@ -285,14 +285,14 @@ microVUt(void) mVUallocFMAC8b(int& Fd) {
// FMAC9 - MSUB FMAC Opcode Storing Result to Fd // FMAC9 - MSUB FMAC Opcode Storing Result to Fd
//------------------------------------------------------------------ //------------------------------------------------------------------
microVUt(void) mVUallocFMAC9a(int& Fd, int&ACC, int& Fs, int& Ft) { microVUt(void) mVUallocFMAC9a(int& Fd, int& ACC, int& Fs, int& Ft) {
microVU* mVU = mVUx; microVU* mVU = mVUx;
Fs = xmmFs; Fs = xmmFs;
Ft = xmmFt; Ft = xmmFt;
Fd = xmmT1; Fd = xmmT1;
ACC = xmmT1; ACC = xmmT1;
SSE_MOVAPS_XMM_to_XMM(ACC, xmmACC0 + readACC); SSE_MOVAPS_XMM_to_XMM(ACC, xmmACC);
if (_XYZW_SS && _X) { if (_X_Y_Z_W == 8) {
getReg6(Fs, _Fs_); getReg6(Fs, _Fs_);
if (_Ft_ == _Fs_) { Ft = Fs; } if (_Ft_ == _Fs_) { Ft = Fs; }
else { getReg6(Ft, _Ft_); } else { getReg6(Ft, _Ft_); }
@ -323,8 +323,8 @@ microVUt(void) mVUallocFMAC10a(int& Fd, int& ACC, int& Fs, int& Ft) {
Fs = xmmFs; Fs = xmmFs;
Ft = xmmFt; Ft = xmmFt;
Fd = xmmFs; Fd = xmmFs;
ACC = xmmACC0 + readACC; ACC = xmmACC;
if (_XYZW_SS && _X) { if (_X_Y_Z_W == 8) {
getReg6(Fs, _Fs_); getReg6(Fs, _Fs_);
if ( (_Ft_ == _Fs_) && _bc_x) { Ft = Fs; } if ( (_Ft_ == _Fs_) && _bc_x) { Ft = Fs; }
else if (!_Ft_) { getZero3SS(Ft); } else if (!_Ft_) { getZero3SS(Ft); }
@ -353,8 +353,8 @@ microVUt(void) mVUallocFMAC11a(int& Fd, int& ACC, int& Fs, int& Ft) {
Ft = xmmFt; Ft = xmmFt;
Fd = xmmT1; Fd = xmmT1;
ACC = xmmT1; ACC = xmmT1;
SSE_MOVAPS_XMM_to_XMM(ACC, xmmACC0 + readACC); SSE_MOVAPS_XMM_to_XMM(ACC, xmmACC);
if (_XYZW_SS && _X) { if (_X_Y_Z_W == 8) {
getReg6(Fs, _Fs_); getReg6(Fs, _Fs_);
if ( (_Ft_ == _Fs_) && _bc_x) { Ft = Fs; } if ( (_Ft_ == _Fs_) && _bc_x) { Ft = Fs; }
else if (!_Ft_) { getZero3SS(Ft); } else if (!_Ft_) { getZero3SS(Ft); }
@ -377,14 +377,14 @@ microVUt(void) mVUallocFMAC11b(int& Fd) {
// FMAC12 - MADD FMAC Opcode Storing Result to Fd (I Reg) // FMAC12 - MADD FMAC Opcode Storing Result to Fd (I Reg)
//------------------------------------------------------------------ //------------------------------------------------------------------
microVUt(void) mVUallocFMAC12a(int& Fd, int&ACC, int& Fs, int& Ft) { microVUt(void) mVUallocFMAC12a(int& Fd, int& ACC, int& Fs, int& Ft) {
microVU* mVU = mVUx; microVU* mVU = mVUx;
Fs = xmmFs; Fs = xmmFs;
Ft = xmmFt; Ft = xmmFt;
Fd = xmmFs; Fd = xmmFs;
ACC = xmmACC0 + readACC; ACC = xmmACC;
getIreg(Ft); getIreg(Ft);
if (_XYZW_SS && _X) { getReg6(Fs, _Fs_); } if (_X_Y_Z_W == 8) { getReg6(Fs, _Fs_); }
else if (!_Fs_) { getZero4(Fs); } else if (!_Fs_) { getZero4(Fs); }
else { getReg4(Fs, _Fs_); } else { getReg4(Fs, _Fs_); }
} }
@ -397,15 +397,15 @@ microVUt(void) mVUallocFMAC12b(int& Fd) {
// FMAC13 - MSUB FMAC Opcode Storing Result to Fd (I Reg) // FMAC13 - MSUB FMAC Opcode Storing Result to Fd (I Reg)
//------------------------------------------------------------------ //------------------------------------------------------------------
microVUt(void) mVUallocFMAC13a(int& Fd, int&ACC, int& Fs, int& Ft) { microVUt(void) mVUallocFMAC13a(int& Fd, int& ACC, int& Fs, int& Ft) {
microVU* mVU = mVUx; microVU* mVU = mVUx;
Fs = xmmFs; Fs = xmmFs;
Ft = xmmFt; Ft = xmmFt;
Fd = xmmT1; Fd = xmmT1;
ACC = xmmT1; ACC = xmmT1;
SSE_MOVAPS_XMM_to_XMM(ACC, xmmACC0 + readACC); SSE_MOVAPS_XMM_to_XMM(ACC, xmmACC);
getIreg(Ft); getIreg(Ft);
if (_XYZW_SS && _X) { getReg6(Fs, _Fs_); } if (_X_Y_Z_W == 8) { getReg6(Fs, _Fs_); }
else if (!_Fs_) { getZero4(Fs); } else if (!_Fs_) { getZero4(Fs); }
else { getReg4(Fs, _Fs_); } else { getReg4(Fs, _Fs_); }
} }
@ -415,16 +415,18 @@ microVUt(void) mVUallocFMAC13b(int& Fd) {
} }
//------------------------------------------------------------------ //------------------------------------------------------------------
// FMAC14 - MADDA FMAC Opcode // FMAC14 - MADDA/MSUBA FMAC Opcodes
//------------------------------------------------------------------ //------------------------------------------------------------------
microVUt(void) mVUallocFMAC14a(int& ACCw, int&ACCr, int& Fs, int& Ft) { microVUt(void) mVUallocFMAC14a(int& ACCw, int& ACCr, int& Fs, int& Ft) {
microVU* mVU = mVUx; microVU* mVU = mVUx;
getACC(ACCw); Fs = xmmFs;
Fs = (_X_Y_Z_W == 15) ? ACCw : xmmFs;
Ft = xmmFt; Ft = xmmFt;
ACCr = xmmACC0 + readACC; ACCw = xmmACC;
if (_XYZW_SS && _X) { ACCr = ((_X_Y_Z_W == 15) || (_X_Y_Z_W == 8)) ? xmmACC : xmmT1;
SSE_MOVAPS_XMM_to_XMM(ACCr, xmmACC);
if (_X_Y_Z_W == 8) {
getReg6(Fs, _Fs_); getReg6(Fs, _Fs_);
if (_Ft_ == _Fs_) { Ft = Fs; } if (_Ft_ == _Fs_) { Ft = Fs; }
else { getReg6(Ft, _Ft_); } else { getReg6(Ft, _Ft_); }
@ -439,39 +441,25 @@ microVUt(void) mVUallocFMAC14a(int& ACCw, int&ACCr, int& Fs, int& Ft) {
} }
} }
microVUt(void) mVUallocFMAC14b(int& ACCw, int& Fs) { microVUt(void) mVUallocFMAC14b(int& ACCw, int& ACCr) {
microVU* mVU = mVUx;
if (CHECK_VU_OVERFLOW) mVUclamp1<vuIndex>(Fs, xmmT1, _xyzw_ACC);
mVUmergeRegs<vuIndex>(ACCw, Fs, _X_Y_Z_W);
}
//------------------------------------------------------------------
// FMAC15 - MSUBA FMAC Opcode
//------------------------------------------------------------------
microVUt(void) mVUallocFMAC15a(int& ACCw, int&ACCr, int& Fs, int& Ft) {
mVUallocFMAC14a<vuIndex>(ACCw, ACCr, Fs, Ft);
SSE_MOVAPS_XMM_to_XMM(xmmT1, ACCr);
ACCr = xmmT1;
}
microVUt(void) mVUallocFMAC15b(int& ACCw, int& ACCr) {
microVU* mVU = mVUx; microVU* mVU = mVUx;
if (CHECK_VU_OVERFLOW) mVUclamp1<vuIndex>(ACCr, xmmFt, _xyzw_ACC); if (CHECK_VU_OVERFLOW) mVUclamp1<vuIndex>(ACCr, xmmFt, _xyzw_ACC);
mVUmergeRegs<vuIndex>(ACCw, ACCr, _X_Y_Z_W); mVUmergeRegs<vuIndex>(ACCw, ACCr, _X_Y_Z_W);
} }
//------------------------------------------------------------------ //------------------------------------------------------------------
// FMAC16 - MADDA BC(xyzw) FMAC Opcode // FMAC15 - MADDA/MSUBA BC(xyzw) FMAC Opcode
//------------------------------------------------------------------ //------------------------------------------------------------------
microVUt(void) mVUallocFMAC16a(int& ACCw, int&ACCr, int& Fs, int& Ft) { microVUt(void) mVUallocFMAC15a(int& ACCw, int& ACCr, int& Fs, int& Ft) {
microVU* mVU = mVUx; microVU* mVU = mVUx;
getACC(ACCw); Fs = xmmFs;
Fs = (_X_Y_Z_W == 15) ? ACCw : xmmFs;
Ft = xmmFt; Ft = xmmFt;
ACCr = xmmACC0 + readACC; ACCw = xmmACC;
if (_XYZW_SS && _X) { ACCr = ((_X_Y_Z_W == 15) || (_X_Y_Z_W == 8)) ? xmmACC : xmmT1;
SSE_MOVAPS_XMM_to_XMM(ACCr, xmmACC);
if (_X_Y_Z_W == 8) {
getReg6(Fs, _Fs_); getReg6(Fs, _Fs_);
if ((_Ft_ == _Fs_) && _bc_x) { Ft = Fs; } if ((_Ft_ == _Fs_) && _bc_x) { Ft = Fs; }
else if (!_Ft_) { getZero3SS(Ft); } else if (!_Ft_) { getZero3SS(Ft); }
@ -486,22 +474,29 @@ microVUt(void) mVUallocFMAC16a(int& ACCw, int&ACCr, int& Fs, int& Ft) {
} }
} }
microVUt(void) mVUallocFMAC16b(int& ACCw, int& Fs) { microVUt(void) mVUallocFMAC15b(int& ACCw, int& ACCr) {
mVUallocFMAC14b<vuIndex>(ACCw, Fs); mVUallocFMAC14b<vuIndex>(ACCw, ACCr);
} }
//------------------------------------------------------------------ //------------------------------------------------------------------
// FMAC17 - MSUBA BC(xyzw) FMAC Opcode // FMAC16 - MADDA/MSUBA FMAC Opcode (I Reg)
//------------------------------------------------------------------ //------------------------------------------------------------------
microVUt(void) mVUallocFMAC17a(int& ACCw, int&ACCr, int& Fs, int& Ft) { microVUt(void) mVUallocFMAC16a(int& ACCw, int& ACCr, int& Fs, int& Ft) {
mVUallocFMAC16a<vuIndex>(ACCw, ACCr, Fs, Ft); microVU* mVU = mVUx;
SSE_MOVAPS_XMM_to_XMM(xmmT1, ACCr); Fs = xmmFs;
ACCr = xmmT1; Ft = xmmFt;
ACCw = xmmACC;
ACCr = ((_X_Y_Z_W == 15) || (_X_Y_Z_W == 8)) ? xmmACC : xmmT1;
SSE_MOVAPS_XMM_to_XMM(ACCr, xmmACC);
getIreg(Ft);
if (_X_Y_Z_W == 8) { getReg6(Fs, _Fs_); }
else if (!_Fs_) { getZero4(Fs); }
else { getReg4(Fs, _Fs_); }
} }
microVUt(void) mVUallocFMAC17b(int& ACCw, int& ACCr) { microVUt(void) mVUallocFMAC16b(int& ACCw, int& ACCr) {
mVUallocFMAC15b<vuIndex>(ACCw, ACCr); mVUallocFMAC14b<vuIndex>(ACCw, ACCr);
} }
//------------------------------------------------------------------ //------------------------------------------------------------------
@ -512,7 +507,7 @@ microVUt(void) mVUallocFMAC18a(int& ACC, int& Fs, int& Ft) {
microVU* mVU = mVUx; microVU* mVU = mVUx;
Fs = xmmFs; Fs = xmmFs;
Ft = xmmFt; Ft = xmmFt;
getACC(ACC); ACC = xmmACC;
if (!_Fs_) { getZero4(Fs); } if (!_Fs_) { getZero4(Fs); }
else { getReg4(Fs, _Fs_); } else { getReg4(Fs, _Fs_); }
@ -532,13 +527,13 @@ microVUt(void) mVUallocFMAC18b(int& ACC, int& Fs) {
// FMAC19 - OPMULA FMAC Opcode // FMAC19 - OPMULA FMAC Opcode
//------------------------------------------------------------------ //------------------------------------------------------------------
microVUt(void) mVUallocFMAC19a(int& Fd, int&ACC, int& Fs, int& Ft) { microVUt(void) mVUallocFMAC19a(int& Fd, int& ACC, int& Fs, int& Ft) {
microVU* mVU = mVUx; microVU* mVU = mVUx;
Fs = xmmFs; Fs = xmmFs;
Ft = xmmFt; Ft = xmmFt;
Fd = xmmT1; Fd = xmmT1;
ACC = xmmT1; ACC = xmmT1;
SSE_MOVAPS_XMM_to_XMM(ACC, xmmACC0 + readACC); SSE_MOVAPS_XMM_to_XMM(ACC, xmmACC);
if (!_Fs_) { getZero4(Fs); } if (!_Fs_) { getZero4(Fs); }
else { getReg4(Fs, _Fs_); } else { getReg4(Fs, _Fs_); }
@ -554,40 +549,6 @@ microVUt(void) mVUallocFMAC19b(int& Fd) {
mVUallocFMAC9b<vuIndex>(Fd); mVUallocFMAC9b<vuIndex>(Fd);
} }
//------------------------------------------------------------------
// FMAC20 - MADDA FMAC Opcode (I Reg)
//------------------------------------------------------------------
microVUt(void) mVUallocFMAC20a(int& ACCw, int&ACCr, int& Fs, int& Ft) {
microVU* mVU = mVUx;
getACC(ACCw);
Fs = (_X_Y_Z_W == 15) ? ACCw : xmmFs;
Ft = xmmFt;
ACCr = xmmACC0 + readACC;
getIreg(Ft);
if (_XYZW_SS && _X) { getReg6(Fs, _Fs_); }
else if (!_Fs_) { getZero4(Fs); }
else { getReg4(Fs, _Fs_); }
}
microVUt(void) mVUallocFMAC20b(int& ACCw, int& Fs) {
mVUallocFMAC14b<vuIndex>(ACCw, Fs);
}
//------------------------------------------------------------------
// FMAC21 - MSUBA FMAC Opcode (I Reg)
//------------------------------------------------------------------
microVUt(void) mVUallocFMAC21a(int& ACCw, int&ACCr, int& Fs, int& Ft) {
mVUallocFMAC20a<vuIndex>(ACCw, ACCr, Fs, Ft);
SSE_MOVAPS_XMM_to_XMM(xmmT1, ACCr);
ACCr = xmmT1;
}
microVUt(void) mVUallocFMAC21b(int& ACCw, int& ACCr) {
mVUallocFMAC15b<vuIndex>(ACCw, ACCr);
}
//------------------------------------------------------------------ //------------------------------------------------------------------
// FMAC22 - Normal FMAC Opcodes (Q Reg) // FMAC22 - Normal FMAC Opcodes (Q Reg)
//------------------------------------------------------------------ //------------------------------------------------------------------
@ -616,11 +577,11 @@ microVUt(void) mVUallocFMAC22b(int& Fd) {
microVUt(void) mVUallocFMAC23a(int& ACC, int& Fs, int& Ft) { microVUt(void) mVUallocFMAC23a(int& ACC, int& Fs, int& Ft) {
microVU* mVU = mVUx; microVU* mVU = mVUx;
Fs = xmmFs; ACC = xmmACC;
Fs = (_X_Y_Z_W == 15) ? xmmACC : xmmFs;
Ft = xmmFt; Ft = xmmFt;
getACC(ACC);
getQreg(Ft); getQreg(Ft);
if (_XYZW_SS && _X) { getReg6(Fs, _Fs_); } if (_X_Y_Z_W == 8) { getReg6(Fs, _Fs_); }
else if (!_Fs_) { getZero4(Fs); } else if (!_Fs_) { getZero4(Fs); }
else { getReg4(Fs, _Fs_); } else { getReg4(Fs, _Fs_); }
} }
@ -633,14 +594,14 @@ microVUt(void) mVUallocFMAC23b(int& ACC, int& Fs) {
// FMAC24 - MADD FMAC Opcode Storing Result to Fd (Q Reg) // FMAC24 - MADD FMAC Opcode Storing Result to Fd (Q Reg)
//------------------------------------------------------------------ //------------------------------------------------------------------
microVUt(void) mVUallocFMAC24a(int& Fd, int&ACC, int& Fs, int& Ft) { microVUt(void) mVUallocFMAC24a(int& Fd, int& ACC, int& Fs, int& Ft) {
microVU* mVU = mVUx; microVU* mVU = mVUx;
Fs = xmmFs; Fs = xmmFs;
Ft = xmmFt; Ft = xmmFt;
Fd = xmmFs; Fd = xmmFs;
ACC = xmmACC0 + readACC; ACC = xmmACC;
getQreg(Ft); getQreg(Ft);
if (_XYZW_SS && _X) { getReg6(Fs, _Fs_); } if (_X_Y_Z_W == 8) { getReg6(Fs, _Fs_); }
else if (!_Fs_) { getZero4(Fs); } else if (!_Fs_) { getZero4(Fs); }
else { getReg4(Fs, _Fs_); } else { getReg4(Fs, _Fs_); }
} }
@ -653,15 +614,15 @@ microVUt(void) mVUallocFMAC24b(int& Fd) {
// FMAC25 - MSUB FMAC Opcode Storing Result to Fd (Q Reg) // FMAC25 - MSUB FMAC Opcode Storing Result to Fd (Q Reg)
//------------------------------------------------------------------ //------------------------------------------------------------------
microVUt(void) mVUallocFMAC25a(int& Fd, int&ACC, int& Fs, int& Ft) { microVUt(void) mVUallocFMAC25a(int& Fd, int& ACC, int& Fs, int& Ft) {
microVU* mVU = mVUx; microVU* mVU = mVUx;
Fs = xmmFs; Fs = xmmFs;
Ft = xmmFt; Ft = xmmFt;
Fd = xmmT1; Fd = xmmT1;
ACC = xmmT1; ACC = xmmT1;
SSE_MOVAPS_XMM_to_XMM(ACC, xmmACC0 + readACC); SSE_MOVAPS_XMM_to_XMM(ACC, xmmACC);
getQreg(Ft); getQreg(Ft);
if (_XYZW_SS && _X) { getReg6(Fs, _Fs_); } if (_X_Y_Z_W == 8) { getReg6(Fs, _Fs_); }
else if (!_Fs_) { getZero4(Fs); } else if (!_Fs_) { getZero4(Fs); }
else { getReg4(Fs, _Fs_); } else { getReg4(Fs, _Fs_); }
} }
@ -671,37 +632,24 @@ microVUt(void) mVUallocFMAC25b(int& Fd) {
} }
//------------------------------------------------------------------ //------------------------------------------------------------------
// FMAC26 - MADDA FMAC Opcode (Q Reg) // FMAC26 - MADDA/MSUBA FMAC Opcode (Q Reg)
//------------------------------------------------------------------ //------------------------------------------------------------------
microVUt(void) mVUallocFMAC26a(int& ACCw, int&ACCr, int& Fs, int& Ft) { microVUt(void) mVUallocFMAC26a(int& ACCw, int& ACCr, int& Fs, int& Ft) {
microVU* mVU = mVUx; microVU* mVU = mVUx;
getACC(ACCw); Fs = xmmFs;
Fs = (_X_Y_Z_W == 15) ? ACCw : xmmFs;
Ft = xmmFt; Ft = xmmFt;
ACCr = xmmACC0 + readACC; ACCw = xmmACC;
ACCr = ((_X_Y_Z_W == 15) || (_X_Y_Z_W == 8)) ? xmmACC : xmmT1;
SSE_MOVAPS_XMM_to_XMM(ACCr, xmmACC);
getQreg(Ft); getQreg(Ft);
if (_XYZW_SS && _X) { getReg6(Fs, _Fs_); } if (_X_Y_Z_W == 8) { getReg6(Fs, _Fs_); }
else if (!_Fs_) { getZero4(Fs); } else if (!_Fs_) { getZero4(Fs); }
else { getReg4(Fs, _Fs_); } else { getReg4(Fs, _Fs_); }
} }
microVUt(void) mVUallocFMAC26b(int& ACCw, int& Fs) { microVUt(void) mVUallocFMAC26b(int& ACCw, int& ACCr) {
mVUallocFMAC14b<vuIndex>(ACCw, Fs); mVUallocFMAC14b<vuIndex>(ACCw, ACCr);
}
//------------------------------------------------------------------
// FMAC27 - MSUBA FMAC Opcode (Q Reg)
//------------------------------------------------------------------
microVUt(void) mVUallocFMAC27a(int& ACCw, int&ACCr, int& Fs, int& Ft) {
mVUallocFMAC26a<vuIndex>(ACCw, ACCr, Fs, Ft);
SSE_MOVAPS_XMM_to_XMM(xmmT1, ACCr);
ACCr = xmmT1;
}
microVUt(void) mVUallocFMAC27b(int& ACCw, int& ACCr) {
mVUallocFMAC15b<vuIndex>(ACCw, ACCr);
} }
//------------------------------------------------------------------ //------------------------------------------------------------------
@ -741,6 +689,16 @@ microVUt(void) mVUallocMFLAGb(int reg, int fInstance) {
OR32RtoR(fInstance, reg); OR32RtoR(fInstance, reg);
} }
microVUt(void) mVUallocCFLAGa(int reg, int fInstance) {
microVU* mVU = mVUx;
MOV32MtoR(reg, mVU->clipFlag[fInstance]);
}
microVUt(void) mVUallocCFLAGb(int reg, int fInstance) {
microVU* mVU = mVUx;
MOV32RtoM(mVU->clipFlag[fInstance], reg);
}
//------------------------------------------------------------------ //------------------------------------------------------------------
// VI Reg Allocators // VI Reg Allocators
//------------------------------------------------------------------ //------------------------------------------------------------------
@ -788,4 +746,10 @@ microVUt(void) mVUallocVIb(int GPRreg, int _reg_) {
if (!_reg_) { getZero(reg); } \ if (!_reg_) { getZero(reg); } \
else { mVUloadReg<vuIndex>(reg, (uptr)&mVU->regs->VF[_reg_].UL[0], _X_Y_Z_W); } \ else { mVUloadReg<vuIndex>(reg, (uptr)&mVU->regs->VF[_reg_].UL[0], _X_Y_Z_W); } \
} }
// VF to GPR
#define getReg8(GPRreg, _reg_, _fxf_) { \
if (!_reg_ && (_fxf_ < 3)) { XOR32RtoR(GPRreg, GPRreg); } \
else { MOV32MtoR(GPRreg, (uptr)&mVU->regs->VF[_reg_].UL[0]); } \
}
#endif //PCSX2_MICROVU #endif //PCSX2_MICROVU

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