mirror of https://github.com/PCSX2/pcsx2.git
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:
commit
6ce8ac189c
|
@ -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"
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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=""$(ProjectDir)";"$(ProjectDir)\include""
|
AdditionalIncludeDirectories=""$(ProjectDir)";"$(ProjectDir)\include""
|
||||||
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"
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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];
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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__
|
|
@ -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!!! ---------------
|
||||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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__
|
|
@ -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__
|
|
@ -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__
|
|
@ -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__
|
|
@ -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__
|
|
@ -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__
|
|
@ -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__
|
|
@ -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
|
|
@ -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__
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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() )
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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.
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 )
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
720
pcsx2/IopMem.cpp
720
pcsx2/IopMem.cpp
|
@ -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
|
|
||||||
|
|
|
@ -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])
|
||||||
|
|
|
@ -203,6 +203,7 @@ u8 sio2_fifoOut(){
|
||||||
|
|
||||||
void SaveState::sio2Freeze()
|
void SaveState::sio2Freeze()
|
||||||
{
|
{
|
||||||
|
FreezeTag( "sio2" );
|
||||||
Freeze(sio2);
|
Freeze(sio2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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"
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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 );
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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 );
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 )
|
||||||
{
|
{
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 );
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 );
|
||||||
|
|
|
@ -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 );
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
541
pcsx2/VifDma.cpp
541
pcsx2/VifDma.cpp
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
||||||
|
|
15
pcsx2/vtlb.h
15
pcsx2/vtlb.h
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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"
|
||||||
>
|
>
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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));
|
||||||
|
}
|
|
@ -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();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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 = {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 ) \
|
||||||
|
|
|
@ -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];
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 = {
|
||||||
|
|
|
@ -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_);
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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_);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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]);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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?
|
||||||
|
};
|
||||||
|
|
|
@ -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
Loading…
Reference in New Issue