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++"
|
||||
Version="8.00"
|
||||
Name="3rdparty"
|
||||
OutputDirectory="$(ProjectDir)..\..\deps\$(PlatformName)\$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ProjectDir)\$(PlatformName)\$(ConfigurationName)"
|
||||
OutputDirectory="..\..\deps\$(PlatformName)\$(ConfigurationName)"
|
||||
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
|
|
|
@ -142,7 +142,7 @@
|
|||
ConfigurationType="4"
|
||||
InheritedPropertySheets="..\3rdparty.vsprops"
|
||||
CharacterSet="2"
|
||||
WholeProgramOptimization="1"
|
||||
WholeProgramOptimization="0"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
|
@ -166,6 +166,7 @@
|
|||
EnableIntrinsicFunctions="true"
|
||||
FavorSizeOrSpeed="1"
|
||||
OmitFramePointers="true"
|
||||
WholeProgramOptimization="false"
|
||||
StringPooling="true"
|
||||
RuntimeLibrary="0"
|
||||
BufferSecurityCheck="false"
|
||||
|
|
|
@ -157,7 +157,7 @@
|
|||
ConfigurationType="4"
|
||||
InheritedPropertySheets="..\3rdparty.vsprops"
|
||||
CharacterSet="2"
|
||||
WholeProgramOptimization="1"
|
||||
WholeProgramOptimization="0"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
|
@ -181,6 +181,7 @@
|
|||
EnableIntrinsicFunctions="true"
|
||||
FavorSizeOrSpeed="1"
|
||||
EnableFiberSafeOptimizations="true"
|
||||
WholeProgramOptimization="false"
|
||||
AdditionalIncludeDirectories=""$(ProjectDir)";"$(ProjectDir)\include""
|
||||
PreprocessorDefinitions="PTW32_STATIC_LIB;PTW32_BUILD_INLINED;__CLEANUP_SEH;WIN32;NDEBUG;_LIB"
|
||||
StringPooling="true"
|
||||
|
|
|
@ -168,8 +168,6 @@ ptw32_InterlockedExchange (volatile PTW32_INTERLOCKED_LPLONG location,
|
|||
#pragma disable_message (200)
|
||||
#endif
|
||||
|
||||
LONG result;
|
||||
|
||||
/*
|
||||
* The XCHG instruction always locks the bus with or without the
|
||||
* 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))
|
||||
#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 {
|
||||
//PUSH ecx
|
||||
MOV ecx,dword ptr [location]
|
||||
MOV eax,dword ptr [value]
|
||||
XCHG dword ptr [ecx],eax
|
||||
MOV dword ptr [result], eax
|
||||
//POP ecx
|
||||
MOV ecx,dword ptr [location]
|
||||
MOV eax,dword ptr [value]
|
||||
XCHG dword ptr [ecx],eax
|
||||
//MOV dword ptr [result], eax
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -215,22 +214,20 @@ ptw32_InterlockedExchange (volatile PTW32_INTERLOCKED_LPLONG location,
|
|||
* Can we do without the PUSH/POP instructions?
|
||||
*/
|
||||
_asm {
|
||||
//PUSH ecx
|
||||
//PUSH edx
|
||||
MOV ecx,dword ptr [location]
|
||||
MOV edx,dword ptr [value]
|
||||
L1: MOV eax,dword ptr [ecx]
|
||||
CMPXCHG dword ptr [ecx],edx
|
||||
JNZ L1
|
||||
MOV dword ptr [result], eax
|
||||
//POP edx
|
||||
//POP ecx
|
||||
MOV ecx,dword ptr [location]
|
||||
MOV edx,dword ptr [value]
|
||||
L1: MOV eax,dword ptr [ecx]
|
||||
CMPXCHG dword ptr [ecx],edx
|
||||
JNZ L1
|
||||
//MOV dword ptr [result], eax
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(__GNUC__)
|
||||
#define HAVE_INLINABLE_INTERLOCKED_XCHG
|
||||
|
||||
LONG result;
|
||||
|
||||
{
|
||||
__asm__ __volatile__
|
||||
(
|
||||
|
@ -264,6 +261,8 @@ L1: MOV eax,dword ptr [ecx]
|
|||
:"m" (*location), "r" (value));
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
@ -279,8 +278,6 @@ L1: MOV eax,dword ptr [ecx]
|
|||
|
||||
/* *INDENT-ON* */
|
||||
|
||||
return result;
|
||||
|
||||
#if defined(__WATCOMC__)
|
||||
#pragma enable_message (200)
|
||||
#endif
|
||||
|
|
|
@ -179,7 +179,7 @@
|
|||
InheritedPropertySheets="..\..\..\3rdparty.vsprops"
|
||||
UseOfMFC="0"
|
||||
ATLMinimizesCRunTimeLibraryUsage="false"
|
||||
WholeProgramOptimization="1"
|
||||
WholeProgramOptimization="0"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
|
@ -202,7 +202,7 @@
|
|||
Optimization="3"
|
||||
InlineFunctionExpansion="1"
|
||||
FavorSizeOrSpeed="2"
|
||||
WholeProgramOptimization="true"
|
||||
WholeProgramOptimization="false"
|
||||
AdditionalIncludeDirectories="..\..\Include;..\..\Include\msvc;..\..\..\zlib"
|
||||
PreprocessorDefinitions="WIN32;_LIB;__WXMSW__;wxUSE_GUI=0;wxUSE_BASE=1;_CRT_SECURE_NO_WARNINGS"
|
||||
StringPooling="true"
|
||||
|
@ -5732,6 +5732,10 @@
|
|||
<Filter
|
||||
Name="Setup Headers"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\..\include\wx\univ\setup.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\include\wx\msw\setup.h"
|
||||
>
|
||||
|
@ -5796,10 +5800,6 @@
|
|||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\include\wx\univ\setup.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="MSW Headers"
|
||||
|
|
|
@ -178,7 +178,7 @@
|
|||
InheritedPropertySheets="..\..\..\3rdparty.vsprops"
|
||||
UseOfMFC="0"
|
||||
ATLMinimizesCRunTimeLibraryUsage="false"
|
||||
WholeProgramOptimization="1"
|
||||
WholeProgramOptimization="0"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
|
@ -201,7 +201,7 @@
|
|||
Optimization="3"
|
||||
InlineFunctionExpansion="1"
|
||||
FavorSizeOrSpeed="2"
|
||||
WholeProgramOptimization="true"
|
||||
WholeProgramOptimization="false"
|
||||
AdditionalIncludeDirectories="..\..\Include;..\..\Include\msvc;..\..\..\zlib;..\..\src\png"
|
||||
PreprocessorDefinitions="WIN32;_LIB;__WXMSW__;wxUSE_BASE=0;_CRT_SECURE_NO_WARNINGS"
|
||||
StringPooling="true"
|
||||
|
@ -16948,10 +16948,6 @@
|
|||
<Filter
|
||||
Name="Setup Headers"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\..\include\wx\univ\setup.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\include\wx\msw\setup.h"
|
||||
>
|
||||
|
@ -17016,6 +17012,10 @@
|
|||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\include\wx\univ\setup.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="MSW Headers"
|
||||
|
|
|
@ -140,7 +140,7 @@
|
|||
ConfigurationType="4"
|
||||
InheritedPropertySheets="..\3rdparty.vsprops"
|
||||
CharacterSet="2"
|
||||
WholeProgramOptimization="1"
|
||||
WholeProgramOptimization="0"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
|
@ -164,6 +164,7 @@
|
|||
EnableIntrinsicFunctions="true"
|
||||
FavorSizeOrSpeed="1"
|
||||
OmitFramePointers="true"
|
||||
WholeProgramOptimization="false"
|
||||
StringPooling="true"
|
||||
RuntimeLibrary="0"
|
||||
WarningLevel="3"
|
||||
|
|
|
@ -548,6 +548,7 @@ typedef void (CALLBACK* _PADgsDriverInfo)(GSdriverInfo *info);
|
|||
typedef void (CALLBACK* _PADconfigure)();
|
||||
typedef s32 (CALLBACK* _PADtest)();
|
||||
typedef void (CALLBACK* _PADabout)();
|
||||
typedef int (CALLBACK* _PADfreeze)(int mode, freezeData *data);
|
||||
|
||||
// SIO
|
||||
typedef s32 (CALLBACK* _SIOinit)(u32 port, u32 slot, SIOchangeSlotCB f);
|
||||
|
@ -732,6 +733,7 @@ extern _PADgsDriverInfo PAD1gsDriverInfo;
|
|||
extern _PADconfigure PAD1configure;
|
||||
extern _PADtest PAD1test;
|
||||
extern _PADabout PAD1about;
|
||||
extern _PADfreeze PAD1freeze;
|
||||
|
||||
// PAD2
|
||||
extern _PADinit PAD2init;
|
||||
|
@ -748,6 +750,7 @@ extern _PADgsDriverInfo PAD2gsDriverInfo;
|
|||
extern _PADconfigure PAD2configure;
|
||||
extern _PADtest PAD2test;
|
||||
extern _PADabout PAD2about;
|
||||
extern _PADfreeze PAD2freeze;
|
||||
|
||||
// SIO[2]
|
||||
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.
|
||||
|
||||
#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_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
|
||||
// above instead for both definitions (implementations) and declarations (includes)? -- air
|
||||
|
||||
#define PCSX2_ALIGNED_EXTERN(alig,x) extern x
|
||||
#define PCSX2_ALIGNED16_EXTERN(x) extern x
|
||||
#define PCSX2_ALIGNED_EXTERN(alig,x) extern x __attribute((aligned(alig)))
|
||||
#define PCSX2_ALIGNED16_EXTERN(x) extern x __attribute((aligned(16)))
|
||||
|
||||
#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!!! ---------------
|
||||
#define CHECK_VUADDSUBHACK (Config.GameFixes & 0x1) // Special Fix for Tri-ace games, they use an encryption algorithm that requires VU addi opcode to be bit-accurate.
|
||||
#define CHECK_FPUCOMPAREHACK (Config.GameFixes & 0x4) // Special Fix for Digimon Rumble Arena 2, fixes spinning/hanging on intro-menu.
|
||||
#define CHECK_VUCLIPFLAGHACK (Config.GameFixes & 0x2) // Special Fix for God of War, fixes SPS.
|
||||
#define CHECK_FPUMULHACK (Config.GameFixes & 0x8) // Special Fix for Tales of Destiny hangs.
|
||||
//------------ Advanced Options!!! ---------------
|
||||
#define CHECK_VU_OVERFLOW (Config.vuOptions & 0x1)
|
||||
#define CHECK_VU_EXTRA_OVERFLOW (Config.vuOptions & 0x2) // If enabled, Operands are clamped before being used in the VU recs
|
||||
|
@ -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_FLAGS 1 // Always enabled now // Sets D/I flags on FPU instructions
|
||||
#define CHECK_FPU_FULL (Config.eeOptions & 0x4)
|
||||
#define CHECK_FPU_ATTEMPT_MUL (Config.eeOptions & 0x8)
|
||||
#define DEFAULT_eeOptions 0x01
|
||||
#define DEFAULT_vuOptions 0x01
|
||||
//------------ 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.
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// -- 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
|
||||
// a different read speed from inner rings). But for our purposes an average is good
|
||||
// enough, since all of Pcsx2's instruction cycle counting is hardly accurate anyway.
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Cdvd Block Read Cycle Timings
|
||||
//
|
||||
// The PS2 CDVD effectively has two seek modes -- the normal/slow one (est. avg seeks being
|
||||
// around 120-160ms), and a faster seek which has an estimated seek time of about 35-40ms.
|
||||
// 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
|
||||
// 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_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"};
|
||||
|
||||
|
@ -768,6 +786,7 @@ struct Freeze_v10Compat
|
|||
|
||||
void SaveState::cdvdFreeze()
|
||||
{
|
||||
FreezeTag( "cdvd" );
|
||||
Freeze( cdvd );
|
||||
|
||||
if( IsLoading() )
|
||||
|
@ -941,8 +960,8 @@ __forceinline void cdvdActionInterrupt()
|
|||
}
|
||||
|
||||
// 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);
|
||||
|
||||
cdvd.Ready = 0x00;
|
||||
|
@ -1265,7 +1284,7 @@ u8 cdvdRead3A(void) { // DEC_SET
|
|||
|
||||
|
||||
// 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;
|
||||
|
||||
|
@ -1283,10 +1302,21 @@ static uint cdvdStartSeek( uint newsector )
|
|||
seektime = PSXCLK / 3; // 333ms delay
|
||||
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 );
|
||||
seektime = Cdvd_Avg_SeekCycles;
|
||||
// Select either Full or Fast seek depending on delta:
|
||||
|
||||
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
|
||||
{
|
||||
|
@ -1332,7 +1362,7 @@ void cdvdWrite04(u8 rt) { // NCOMMAND
|
|||
DevCon::Notice( "CdStandby : %d", params rt );
|
||||
cdvd.Action = cdvdAction_Standby;
|
||||
cdvd.ReadTime = cdvdBlockReadTime( MODE_DVDROM );
|
||||
CDVD_INT( cdvdStartSeek( 0 ) );
|
||||
CDVD_INT( cdvdStartSeek( 0, MODE_DVDROM ) );
|
||||
break;
|
||||
|
||||
case 0x03: // CdStop
|
||||
|
@ -1349,7 +1379,7 @@ void cdvdWrite04(u8 rt) { // NCOMMAND
|
|||
case 0x05: // CdSeek
|
||||
cdvd.Action = cdvdAction_Seek;
|
||||
cdvd.ReadTime = cdvdBlockReadTime( MODE_DVDROM );
|
||||
CDVD_INT( cdvdStartSeek( *(uint*)(cdvd.Param+0) ) );
|
||||
CDVD_INT( cdvdStartSeek( *(uint*)(cdvd.Param+0), MODE_DVDROM ) );
|
||||
break;
|
||||
|
||||
case 0x06: // CdRead
|
||||
|
@ -1372,7 +1402,7 @@ void cdvdWrite04(u8 rt) { // NCOMMAND
|
|||
params cdvd.Sector, cdvd.nSectors,cdvd.BlockSize,cdvd.Speed);
|
||||
|
||||
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.
|
||||
// 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);
|
||||
|
||||
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.
|
||||
// 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);
|
||||
|
||||
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.
|
||||
// This helps improve performance on actual from-cd emulation
|
||||
|
|
|
@ -84,6 +84,7 @@
|
|||
* 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 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
|
||||
|
@ -95,7 +96,6 @@
|
|||
#define SCECdDETCT 0x01 // DETCT (Detecting) Disc distinction action
|
||||
#define SCECdNODISC 0x00 // NODISC (No disc) No disc entered
|
||||
|
||||
|
||||
/*
|
||||
* Media mode
|
||||
*/
|
||||
|
|
|
@ -27,6 +27,7 @@ namespace R5900{
|
|||
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
|
||||
int getFreeCache(u32 mem, int mode, int * way) {
|
||||
u8 * out;
|
||||
|
|
|
@ -944,15 +944,9 @@ void cdrReset() {
|
|||
cdReadTime = (PSXCLK / 1757) * BIAS;
|
||||
}
|
||||
|
||||
void SaveState::cdrFreeze() {
|
||||
void SaveState::cdrFreeze()
|
||||
{
|
||||
FreezeTag( "cdrom" );
|
||||
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 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()
|
||||
s32 nextCounter; // delta from nextsCounter, in cycles, until the next rcntUpdate()
|
||||
|
@ -101,7 +103,7 @@ static __forceinline void cpuRcntSet()
|
|||
int i;
|
||||
|
||||
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++)
|
||||
_rcntSet( i );
|
||||
|
@ -124,10 +126,10 @@ void rcntInit() {
|
|||
counters[2].interrupt = 11;
|
||||
counters[3].interrupt = 12;
|
||||
|
||||
counters[4].modeval = MODE_HRENDER;
|
||||
counters[4].sCycle = cpuRegs.cycle;
|
||||
counters[5].modeval = MODE_VRENDER;
|
||||
counters[5].sCycle = cpuRegs.cycle;
|
||||
hsyncCounter.Mode = MODE_HRENDER;
|
||||
hsyncCounter.sCycle = cpuRegs.cycle;
|
||||
vsyncCounter.Mode = MODE_VRENDER;
|
||||
vsyncCounter.sCycle = cpuRegs.cycle;
|
||||
|
||||
UpdateVSyncRate();
|
||||
|
||||
|
@ -136,7 +138,7 @@ void rcntInit() {
|
|||
}
|
||||
|
||||
// debug code, used for stats
|
||||
int g_nCounters[4];
|
||||
int g_nhsyncCounter;
|
||||
static uint iFrame = 0;
|
||||
|
||||
#ifndef _WIN32
|
||||
|
@ -235,8 +237,8 @@ u32 UpdateVSyncRate()
|
|||
vSyncInfoCalc( &vSyncInfo, FRAMERATE_NTSC, SCANLINES_TOTAL_NTSC );
|
||||
}
|
||||
|
||||
counters[4].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
|
||||
hsyncCounter.CycleT = vSyncInfo.hRender; // 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)
|
||||
{
|
||||
|
@ -393,28 +395,28 @@ static int vblankinc = 0;
|
|||
|
||||
__forceinline void rcntUpdate_hScanline()
|
||||
{
|
||||
if( !cpuTestCycle( counters[4].sCycle, counters[4].CycleT ) ) return;
|
||||
if( !cpuTestCycle( hsyncCounter.sCycle, hsyncCounter.CycleT ) ) return;
|
||||
|
||||
//iopBranchAction = 1;
|
||||
if (counters[4].modeval & MODE_HBLANK) { //HBLANK Start
|
||||
rcntStartGate(false, counters[4].sCycle);
|
||||
if (hsyncCounter.Mode & MODE_HBLANK) { //HBLANK Start
|
||||
rcntStartGate(false, hsyncCounter.sCycle);
|
||||
psxCheckStartGate16(0);
|
||||
|
||||
// Setup the hRender's start and end cycle information:
|
||||
counters[4].sCycle += vSyncInfo.hBlank; // start (absolute cycle value)
|
||||
counters[4].CycleT = vSyncInfo.hRender; // endpoint (delta from start value)
|
||||
counters[4].modeval = MODE_HRENDER;
|
||||
hsyncCounter.sCycle += vSyncInfo.hBlank; // start (absolute cycle value)
|
||||
hsyncCounter.CycleT = vSyncInfo.hRender; // endpoint (delta from start value)
|
||||
hsyncCounter.Mode = MODE_HRENDER;
|
||||
}
|
||||
else { //HBLANK END / HRENDER Begin
|
||||
if (CSRw & 0x4) GSCSRr |= 4; // signal
|
||||
if (!(GSIMR&0x400)) gsIrq();
|
||||
if (gates) rcntEndGate(false, counters[4].sCycle);
|
||||
if (gates) rcntEndGate(false, hsyncCounter.sCycle);
|
||||
if (psxhblankgate) psxCheckEndGate16(0);
|
||||
|
||||
// set up the hblank's start and end cycle information:
|
||||
counters[4].sCycle += vSyncInfo.hRender; // start (absolute cycle value)
|
||||
counters[4].CycleT = vSyncInfo.hBlank; // endpoint (delta from start value)
|
||||
counters[4].modeval = MODE_HBLANK;
|
||||
hsyncCounter.sCycle += vSyncInfo.hRender; // start (absolute cycle value)
|
||||
hsyncCounter.CycleT = vSyncInfo.hBlank; // endpoint (delta from start value)
|
||||
hsyncCounter.Mode = MODE_HBLANK;
|
||||
|
||||
# ifdef VSYNC_DEBUG
|
||||
hsc++;
|
||||
|
@ -424,30 +426,30 @@ __forceinline void rcntUpdate_hScanline()
|
|||
|
||||
__forceinline bool rcntUpdate_vSync()
|
||||
{
|
||||
s32 diff = (cpuRegs.cycle - counters[5].sCycle);
|
||||
if( diff < counters[5].CycleT ) return false;
|
||||
s32 diff = (cpuRegs.cycle - vsyncCounter.sCycle);
|
||||
if( diff < vsyncCounter.CycleT ) return false;
|
||||
|
||||
//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;
|
||||
counters[5].CycleT = vSyncInfo.Render;
|
||||
counters[5].modeval = MODE_VRENDER;
|
||||
vsyncCounter.sCycle += vSyncInfo.Blank;
|
||||
vsyncCounter.CycleT = vSyncInfo.Render;
|
||||
vsyncCounter.Mode = MODE_VRENDER;
|
||||
|
||||
return true;
|
||||
}
|
||||
else // VSYNC end / VRENDER begin
|
||||
{
|
||||
VSyncStart(counters[5].sCycle);
|
||||
VSyncStart(vsyncCounter.sCycle);
|
||||
|
||||
counters[5].sCycle += vSyncInfo.Render;
|
||||
counters[5].CycleT = vSyncInfo.Blank;
|
||||
counters[5].modeval = MODE_VSYNC;
|
||||
vsyncCounter.sCycle += vSyncInfo.Render;
|
||||
vsyncCounter.CycleT = vSyncInfo.Blank;
|
||||
vsyncCounter.Mode = MODE_VSYNC;
|
||||
|
||||
// Accumulate hsync rounding errors:
|
||||
counters[4].sCycle += vSyncInfo.hSyncError;
|
||||
hsyncCounter.sCycle += vSyncInfo.hSyncError;
|
||||
|
||||
# ifdef VSYNC_DEBUG
|
||||
vblankinc++;
|
||||
|
@ -766,15 +768,12 @@ u32 __fastcall rcntCycle(int index)
|
|||
|
||||
void SaveState::rcntFreeze()
|
||||
{
|
||||
Freeze(counters);
|
||||
Freeze(nextCounter);
|
||||
Freeze(nextsCounter);
|
||||
|
||||
// New in version 1 -- save the PAL/NTSC info!
|
||||
if( GetVersion() >= 0x1 )
|
||||
{
|
||||
Freeze( Config.PsxType );
|
||||
}
|
||||
Freeze( counters );
|
||||
Freeze( hsyncCounter );
|
||||
Freeze( vsyncCounter );
|
||||
Freeze( nextCounter );
|
||||
Freeze( nextsCounter );
|
||||
Freeze( Config.PsxType );
|
||||
|
||||
if( IsLoading() )
|
||||
{
|
||||
|
|
|
@ -66,7 +66,8 @@ struct EECNT_MODE
|
|||
|
||||
// fixme: Cycle and sCycleT members are unused.
|
||||
// But they can't be removed without making a new savestate version.
|
||||
struct Counter {
|
||||
struct Counter
|
||||
{
|
||||
u32 count;
|
||||
union
|
||||
{
|
||||
|
@ -75,10 +76,14 @@ struct Counter {
|
|||
};
|
||||
u32 target, hold;
|
||||
u32 rate, interrupt;
|
||||
u32 Cycle;
|
||||
u32 sCycleT; // delta values should be signed.
|
||||
};
|
||||
|
||||
struct SyncCounter
|
||||
{
|
||||
u32 Mode;
|
||||
u32 sCycle; // start cycle of timer
|
||||
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
|
||||
|
||||
|
||||
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 u32 nextsCounter;
|
||||
|
||||
|
|
|
@ -250,6 +250,13 @@ void GIFdma()
|
|||
GIFchain(); //Transfers the data set by the switch
|
||||
FreezeRegs(0);
|
||||
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;
|
||||
}
|
||||
else {
|
||||
|
@ -308,15 +315,28 @@ void GIFdma()
|
|||
|
||||
prevcycles = 0;
|
||||
if (!(vif1Regs->mskpath3 || (psHu32(GIF_MODE) & 0x1))) {
|
||||
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
|
||||
gif->chcr = ( gif->chcr & 0xFFFF ) | ( (*ptag) & 0xFFFF0000 ); //Transfer upper part of tag to CHCR bits 31-15
|
||||
CPU_INT(2, gif->qwc * BIAS);
|
||||
gif->qwc = 0;
|
||||
return;
|
||||
if(gspath3done == 0)
|
||||
{
|
||||
if((psHu32(GIF_MODE) & 0x4) && gif->qwc != 0)
|
||||
{
|
||||
CPU_INT(2, min( 8, (int)gif->qwc )/** BIAS*/);
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -348,7 +368,14 @@ void dmaGIF() {
|
|||
ptag = (u32*)dmaGetAddr(gif->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
|
||||
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;
|
||||
return;
|
||||
}
|
||||
|
@ -356,15 +383,28 @@ void dmaGIF() {
|
|||
if(gif->qwc > 0 && (gif->chcr & 0x4) == 0x4) {
|
||||
//SysPrintf("HL Hack\n");
|
||||
gspath3done = 1; //Halflife sets a QWC amount in chain mode, no tadr set.
|
||||
CPU_INT(2, gif->qwc * BIAS);
|
||||
GIFdma();
|
||||
if((psHu32(GIF_MODE) & 0x4) && gif->qwc != 0)
|
||||
{
|
||||
CPU_INT(2, min( 8, (int)gif->qwc ) /** BIAS*/);
|
||||
}
|
||||
else
|
||||
{
|
||||
CPU_INT(2, gif->qwc /** BIAS*/);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//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()
|
||||
{
|
||||
if( GetVersion() >= 0x04 )
|
||||
{
|
||||
Freeze( gifstate );
|
||||
Freeze( gifqwc );
|
||||
Freeze( gspath3done );
|
||||
Freeze( gscycles );
|
||||
FreezeTag( "GIFdma" );
|
||||
|
||||
// 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,7 +36,10 @@ using namespace R5900;
|
|||
|
||||
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
|
||||
// implementation above (none known that break yet)
|
||||
|
|
|
@ -163,14 +163,14 @@ void ipuShutdown()
|
|||
|
||||
// fixme - ipuFreeze looks fairly broken. Should probably take a closer look at some point.
|
||||
|
||||
void SaveState::ipuFreeze() {
|
||||
void SaveState::ipuFreeze()
|
||||
{
|
||||
IPUProcessInterrupt();
|
||||
|
||||
if( GetVersion() < 0x04 )
|
||||
{
|
||||
// old versions saved the IPU regs, but they're already saved as part of HW!
|
||||
FreezeMem(ipuRegs, sizeof(IPUregisters));
|
||||
}
|
||||
FreezeTag( "IPU" );
|
||||
|
||||
// old versions saved the IPU regs, but they're already saved as part of HW!
|
||||
//FreezeMem(ipuRegs, sizeof(IPUregisters));
|
||||
|
||||
Freeze(g_nDMATransfer);
|
||||
Freeze(FIreadpos);
|
||||
|
|
|
@ -215,7 +215,7 @@ ihatemsvc:
|
|||
jne tworows
|
||||
}
|
||||
#elif defined(__GNUC__)
|
||||
asm(
|
||||
__asm__(
|
||||
".intel_syntax noprefix\n"
|
||||
"mov eax, 1\n"
|
||||
"xor esi, esi\n"
|
||||
|
|
|
@ -751,6 +751,8 @@ void psxRcntSetGates()
|
|||
|
||||
void SaveState::psxRcntFreeze()
|
||||
{
|
||||
FreezeTag( "iopCounters" );
|
||||
|
||||
Freeze(psxCounters);
|
||||
Freeze(psxNextCounter);
|
||||
Freeze(psxNextsCounter);
|
||||
|
|
|
@ -19,14 +19,10 @@
|
|||
#ifndef __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 {
|
||||
u64 count, target;
|
||||
u32 mode;
|
||||
u32 rate, interrupt, otarget;
|
||||
u32 sCycle, Cycle;
|
||||
u32 rate, interrupt;
|
||||
u32 sCycleT;
|
||||
s32 CycleT;
|
||||
};
|
||||
|
|
716
pcsx2/IopMem.cpp
716
pcsx2/IopMem.cpp
|
@ -17,319 +17,12 @@
|
|||
*/
|
||||
|
||||
#include "PrecompiledHeader.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 *psxP = NULL;
|
||||
u8 *psxH = NULL;
|
||||
u8 *psxS = NULL;
|
||||
u8 *psxH = NULL; // standard hardware registers (0x000->0x3ff is the scratchpad)
|
||||
u8 *psxS = NULL; // 'undocumented' SIF communication registers
|
||||
|
||||
uptr *psxMemWLUT = NULL;
|
||||
const uptr *psxMemRLUT = NULL;
|
||||
|
@ -339,7 +32,7 @@ static const uint m_psxMemSize =
|
|||
Ps2MemSize::IopRam +
|
||||
Ps2MemSize::IopHardware +
|
||||
0x00010000 + // psxP
|
||||
0x00010000 ; // psxS
|
||||
0x00000100 ; // psxS
|
||||
|
||||
void psxMemAlloc()
|
||||
{
|
||||
|
@ -355,8 +48,8 @@ void psxMemAlloc()
|
|||
psxH = curpos; curpos += Ps2MemSize::IopHardware;
|
||||
psxS = curpos; //curpos += 0x00010000;
|
||||
|
||||
psxMemWLUT = (uptr*)_aligned_malloc(0x10000 * sizeof(uptr) * 2, 16);
|
||||
psxMemRLUT = psxMemWLUT + 0x10000; //(uptr*)_aligned_malloc(0x10000 * sizeof(uptr),16);
|
||||
psxMemWLUT = (uptr*)_aligned_malloc(0x2000 * sizeof(uptr) * 2, 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,
|
||||
|
@ -368,53 +61,53 @@ void psxMemReset()
|
|||
|
||||
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 );
|
||||
|
||||
// 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
|
||||
// at 0x0, 0x8000, and 0xa000:
|
||||
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];
|
||||
//psxMemWLUT[i + 0x8000] = (uptr)&psxM[(i & 0x1f) << 16];
|
||||
//psxMemWLUT[i + 0xa000] = (uptr)&psxM[(i & 0x1f) << 16];
|
||||
|
||||
// RLUTs, accessed through WLUT.
|
||||
psxMemWLUT[i + 0x10000] = (uptr)&psxM[(i & 0x1f) << 16];
|
||||
psxMemWLUT[i + 0x18000] = (uptr)&psxM[(i & 0x1f) << 16];
|
||||
psxMemWLUT[i + 0x1a000] = (uptr)&psxM[(i & 0x1f) << 16];
|
||||
psxMemWLUT[i + 0x2000] = (uptr)&psxM[(i & 0x1f) << 16];
|
||||
//psxMemWLUT[i + 0x18000] = (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.
|
||||
psxMemWLUT[0x11f00] = (uptr)psxP;
|
||||
psxMemWLUT[0x11f80] = (uptr)psxH;
|
||||
psxMemWLUT[0x1bf80] = (uptr)psxH;
|
||||
psxMemWLUT[0x2000 + 0x1f00] = (uptr)psxP;
|
||||
psxMemWLUT[0x2000 + 0x1f80] = (uptr)psxH;
|
||||
//psxMemWLUT[0x1bf80] = (uptr)psxH;
|
||||
|
||||
psxMemWLUT[0x1f00] = (uptr)psxP;
|
||||
psxMemWLUT[0x1f80] = (uptr)psxH;
|
||||
psxMemWLUT[0xbf80] = (uptr)psxH;
|
||||
//psxMemWLUT[0xbf80] = (uptr)psxH;
|
||||
|
||||
// Read-only memory areas, so don't map WLUT for these...
|
||||
for (int i=0; i<0x0040; i++)
|
||||
{
|
||||
psxMemWLUT[i + 0x11fc0] = (uptr)&PS2MEM_ROM[i << 16];
|
||||
psxMemWLUT[i + 0x19fc0] = (uptr)&PS2MEM_ROM[i << 16];
|
||||
psxMemWLUT[i + 0x1bfc0] = (uptr)&PS2MEM_ROM[i << 16];
|
||||
psxMemWLUT[i + 0x2000 + 0x1fc0] = (uptr)&PS2MEM_ROM[i << 16];
|
||||
//psxMemWLUT[i + 0x19fc0] = (uptr)&PS2MEM_ROM[i << 16];
|
||||
//psxMemWLUT[i + 0x1bfc0] = (uptr)&PS2MEM_ROM[i << 16];
|
||||
}
|
||||
|
||||
for (int i=0; i<0x0004; i++)
|
||||
{
|
||||
psxMemWLUT[i + 0x11e00] = (uptr)&PS2MEM_ROM1[i << 16];
|
||||
psxMemWLUT[i + 0x19e00] = (uptr)&PS2MEM_ROM1[i << 16];
|
||||
psxMemWLUT[i + 0x1be00] = (uptr)&PS2MEM_ROM1[i << 16];
|
||||
psxMemWLUT[i + 0x2000 + 0x1e00] = (uptr)&PS2MEM_ROM1[i << 16];
|
||||
//psxMemWLUT[i + 0x19e00] = (uptr)&PS2MEM_ROM1[i << 16];
|
||||
//psxMemWLUT[i + 0x1be00] = (uptr)&PS2MEM_ROM1[i << 16];
|
||||
}
|
||||
|
||||
// Scratchpad! (which is read only? (air))
|
||||
psxMemWLUT[0x11d00] = (uptr)psxS;
|
||||
psxMemWLUT[0x1bd00] = (uptr)psxS;
|
||||
// sif!! (which is read only? (air))
|
||||
psxMemWLUT[0x2000 + 0x1d00] = (uptr)psxS;
|
||||
//psxMemWLUT[0x1bd00] = (uptr)psxS;
|
||||
|
||||
// why isn't scratchpad read/write? (air)
|
||||
//for (i=0; i<0x0001; i++) psxMemWLUT[i + 0x1d00] = (uptr)&psxS[i << 16];
|
||||
|
@ -436,48 +129,58 @@ void psxMemShutdown()
|
|||
psxMemRLUT = NULL;
|
||||
}
|
||||
|
||||
u8 iopMemRead8(u32 mem) {
|
||||
const u8* p;
|
||||
u32 t;
|
||||
u8 iopMemRead8(u32 mem)
|
||||
{
|
||||
mem &= 0x1fffffff;
|
||||
u32 t = mem >> 16;
|
||||
|
||||
t = (mem >> 16) & 0x1fff;
|
||||
if (t == 0x1f80) {
|
||||
mem&= 0x1fffffff;
|
||||
if (t == 0x1f80)
|
||||
{
|
||||
if (mem < 0x1f801000)
|
||||
return psxHu8(mem);
|
||||
else
|
||||
return psxHwRead8(mem);
|
||||
} else
|
||||
if (t == 0x1f40) {
|
||||
mem&= 0x1fffffff;
|
||||
}
|
||||
else if (t == 0x1f40)
|
||||
{
|
||||
return psxHw4Read8(mem);
|
||||
} else {
|
||||
p = (const u8*)(psxMemRLUT[mem >> 16]);
|
||||
if (p != NULL) {
|
||||
}
|
||||
else
|
||||
{
|
||||
const u8* p = (const u8*)(psxMemRLUT[mem >> 16]);
|
||||
if (p != NULL)
|
||||
{
|
||||
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);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
u16 iopMemRead16(u32 mem) {
|
||||
const u8* p;
|
||||
u32 t;
|
||||
u16 iopMemRead16(u32 mem)
|
||||
{
|
||||
mem &= 0x1fffffff;
|
||||
u32 t = mem >> 16;
|
||||
|
||||
t = (mem >> 16) & 0x1fff;
|
||||
if (t == 0x1f80) {
|
||||
mem&= 0x1fffffff;
|
||||
if (t == 0x1f80)
|
||||
{
|
||||
if (mem < 0x1f801000)
|
||||
return psxHu16(mem);
|
||||
else
|
||||
return psxHwRead16(mem);
|
||||
} else {
|
||||
p = (const u8*)(psxMemRLUT[mem >> 16]);
|
||||
if (p != NULL) {
|
||||
if (t == 0x1d00) {
|
||||
}
|
||||
else
|
||||
{
|
||||
const u8* p = (const u8*)(psxMemRLUT[mem >> 16]);
|
||||
if (p != NULL)
|
||||
{
|
||||
if (t == 0x1d00)
|
||||
{
|
||||
u16 ret;
|
||||
switch(mem & 0xF0)
|
||||
{
|
||||
|
@ -501,31 +204,38 @@ u16 iopMemRead16(u32 mem) {
|
|||
return ret;
|
||||
}
|
||||
return *(const u16 *)(p + (mem & 0xffff));
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
if (t == 0x1F90)
|
||||
return SPU2read(mem & 0x1FFFFFFF);
|
||||
if (t == 0x1000) return DEV9read16(mem & 0x1FFFFFFF);
|
||||
return SPU2read(mem);
|
||||
if (t == 0x1000)
|
||||
return DEV9read16(mem);
|
||||
PSXMEM_LOG("err lh %8.8lx\n", mem);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
u32 iopMemRead32(u32 mem) {
|
||||
const u8* p;
|
||||
u32 t;
|
||||
t = (mem >> 16) & 0x1fff;
|
||||
if (t == 0x1f80) {
|
||||
mem&= 0x1fffffff;
|
||||
u32 iopMemRead32(u32 mem)
|
||||
{
|
||||
mem &= 0x1fffffff;
|
||||
u32 t = mem >> 16;
|
||||
|
||||
if (t == 0x1f80)
|
||||
{
|
||||
if (mem < 0x1f801000)
|
||||
return psxHu32(mem);
|
||||
else
|
||||
return psxHwRead32(mem);
|
||||
} else {
|
||||
} else
|
||||
{
|
||||
//see also Hw.c
|
||||
p = (const u8*)(psxMemRLUT[mem >> 16]);
|
||||
if (p != NULL) {
|
||||
if (t == 0x1d00) {
|
||||
const u8* p = (const u8*)(psxMemRLUT[mem >> 16]);
|
||||
if (p != NULL)
|
||||
{
|
||||
if (t == 0x1d00)
|
||||
{
|
||||
u32 ret;
|
||||
switch(mem & 0xF0)
|
||||
{
|
||||
|
@ -555,215 +265,191 @@ u32 iopMemRead32(u32 mem) {
|
|||
return ret;
|
||||
}
|
||||
return *(const u32 *)(p + (mem & 0xffff));
|
||||
} else {
|
||||
if (t == 0x1000) return DEV9read32(mem & 0x1FFFFFFF);
|
||||
|
||||
if (mem != 0xfffe0130) {
|
||||
if (g_psxWriteOk) PSXMEM_LOG("err lw %8.8lx\n", mem);
|
||||
} else {
|
||||
return writectrl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (t == 0x1000)
|
||||
return DEV9read32(mem);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void iopMemWrite8(u32 mem, u8 value) {
|
||||
char *p;
|
||||
u32 t;
|
||||
void iopMemWrite8(u32 mem, u8 value)
|
||||
{
|
||||
mem &= 0x1fffffff;
|
||||
u32 t = mem >> 16;
|
||||
|
||||
t = (mem >> 16) & 0x1fff;
|
||||
if (t == 0x1f80) {
|
||||
mem&= 0x1fffffff;
|
||||
if (t == 0x1f80)
|
||||
{
|
||||
if (mem < 0x1f801000)
|
||||
psxHu8(mem) = value;
|
||||
else
|
||||
psxHwWrite8(mem, value);
|
||||
} else
|
||||
if (t == 0x1f40) {
|
||||
mem&= 0x1fffffff;
|
||||
}
|
||||
else if (t == 0x1f40)
|
||||
{
|
||||
psxHw4Write8(mem, value);
|
||||
} else {
|
||||
p = (char *)(psxMemWLUT[mem >> 16]);
|
||||
if (p != NULL) {
|
||||
}
|
||||
else
|
||||
{
|
||||
u8* p = (u8 *)(psxMemWLUT[mem >> 16]);
|
||||
if (p != NULL && !(psxRegs.CP0.n.Status & 0x10000) )
|
||||
{
|
||||
*(u8 *)(p + (mem & 0xffff)) = value;
|
||||
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) {
|
||||
psxSu8(mem) = value; return;
|
||||
}
|
||||
if (t == 0x1000) {
|
||||
DEV9write8(mem & 0x1fffffff, value); return;
|
||||
DEV9write8(mem, value); return;
|
||||
}
|
||||
PSXMEM_LOG("err sb %8.8lx = %x\n", mem, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void iopMemWrite16(u32 mem, u16 value) {
|
||||
char *p;
|
||||
u32 t;
|
||||
void iopMemWrite16(u32 mem, u16 value)
|
||||
{
|
||||
mem &= 0x1fffffff;
|
||||
u32 t = mem >> 16;
|
||||
|
||||
t = (mem >> 16) & 0x1fff;
|
||||
if (t == 0x1f80) {
|
||||
mem&= 0x1fffffff;
|
||||
if (t == 0x1f80)
|
||||
{
|
||||
if (mem < 0x1f801000)
|
||||
psxHu16(mem) = value;
|
||||
else
|
||||
psxHwWrite16(mem, value);
|
||||
} else {
|
||||
p = (char *)(psxMemWLUT[mem >> 16]);
|
||||
if (p != NULL) {
|
||||
if ((t & 0x1FFF)==0x1D00) SysPrintf("sw16 [0x%08X]=0x%08X\n", mem, value);
|
||||
} else
|
||||
{
|
||||
u8* p = (u8 *)(psxMemWLUT[mem >> 16]);
|
||||
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;
|
||||
psxCpu->Clear(mem&~3, 1);
|
||||
} else {
|
||||
if (t == 0x1d00) {
|
||||
switch (mem & 0xf0) {
|
||||
case 0x10:
|
||||
// write to ps2 mem
|
||||
psHu16(0x1000F210) = value;
|
||||
return;
|
||||
case 0x40:
|
||||
}
|
||||
else
|
||||
{
|
||||
if (t == 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)
|
||||
{
|
||||
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;
|
||||
psHu16(0x1000F240) &= ~0xF000;
|
||||
psHu16(0x1000F240) |= 0x2000;
|
||||
}
|
||||
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;
|
||||
}
|
||||
if (t == 0x1F90) {
|
||||
SPU2write(mem & 0x1FFFFFFF, value); return;
|
||||
SPU2write(mem, value); return;
|
||||
}
|
||||
if (t == 0x1000) {
|
||||
DEV9write16(mem & 0x1fffffff, value); return;
|
||||
DEV9write16(mem, value); return;
|
||||
}
|
||||
PSXMEM_LOG("err sh %8.8lx = %x\n", mem, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void iopMemWrite32(u32 mem, u32 value) {
|
||||
char *p;
|
||||
u32 t;
|
||||
void iopMemWrite32(u32 mem, u32 value)
|
||||
{
|
||||
mem &= 0x1fffffff;
|
||||
u32 t = mem >> 16;
|
||||
|
||||
t = (mem >> 16) & 0x1fff;
|
||||
if (t == 0x1f80) {
|
||||
mem&= 0x1fffffff;
|
||||
if (t == 0x1f80)
|
||||
{
|
||||
if (mem < 0x1f801000)
|
||||
psxHu32(mem) = value;
|
||||
else
|
||||
psxHwWrite32(mem, value);
|
||||
} else {
|
||||
} else
|
||||
{
|
||||
//see also Hw.c
|
||||
p = (char *)(psxMemWLUT[mem >> 16]);
|
||||
if (p != NULL) {
|
||||
u8* p = (u8 *)(psxMemWLUT[mem >> 16]);
|
||||
if( p != NULL && !(psxRegs.CP0.n.Status & 0x10000) )
|
||||
{
|
||||
*(u32 *)(p + (mem & 0xffff)) = value;
|
||||
psxCpu->Clear(mem&~3, 1);
|
||||
} else {
|
||||
if (mem != 0xfffe0130) {
|
||||
if (t == 0x1d00) {
|
||||
}
|
||||
else
|
||||
{
|
||||
if (t == 0x1d00)
|
||||
{
|
||||
MEM_LOG("iop Sif reg write %x value %x\n", mem, value);
|
||||
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:
|
||||
switch (mem & 0xf0)
|
||||
{
|
||||
case 0x00: // EE write path (EE/IOP readable)
|
||||
return; // this is the IOP, so read-only (do nothing)
|
||||
|
||||
case 0x10: // IOP write path (EE/IOP readable)
|
||||
psHu32(0x1000F210) = value;
|
||||
return;
|
||||
|
||||
case 0x20: // Bits cleared when written from IOP.
|
||||
psHu32(0x1000F220) &= ~value;
|
||||
return;
|
||||
|
||||
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;
|
||||
// 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;
|
||||
psHu32(0x1000F240) &= ~0xF000;
|
||||
psHu32(0x1000F240) |= 0x2000;
|
||||
}
|
||||
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
|
||||
if( (mem & 0xf0) != 0x60 )
|
||||
*(u32*)(PS2MEM_HW+0xf200+(mem&0xf0)) = value;
|
||||
case 0x60:
|
||||
psHu32(0x1000F260) = 0;
|
||||
return;
|
||||
}
|
||||
if (t == 0x1000) {
|
||||
DEV9write32(mem & 0x1fffffff, value); return;
|
||||
}
|
||||
psxSu32(mem) = value;
|
||||
|
||||
//if (!g_psxWriteOk) psxCpu->Clear(mem&~3, 1);
|
||||
if (g_psxWriteOk) { PSXMEM_LOG("err sw %8.8lx = %x\n", mem, value); }
|
||||
} else {
|
||||
writectrl = value;
|
||||
switch (value) {
|
||||
case 0x800: case 0x804:
|
||||
case 0xc00: case 0xc04:
|
||||
case 0xcc0: case 0xcc4:
|
||||
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;
|
||||
}
|
||||
// wtf? why were we writing to the EE's sif space? Commenting this out doesn't
|
||||
// break any of my games, and should be more correct, but I guess we'll see. --air
|
||||
//*(u32*)(PS2MEM_HW+0xf200+(mem&0xf0)) = value;
|
||||
return;
|
||||
}
|
||||
else if (t == 0x1000)
|
||||
{
|
||||
DEV9write32(mem, value); return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -46,7 +46,8 @@ static __forceinline T* iopVirtMemW( u32 mem )
|
|||
template<typename T>
|
||||
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)
|
||||
|
@ -56,11 +57,11 @@ static __forceinline u8* iopPhysMem( u32 addr )
|
|||
}
|
||||
|
||||
#define psxSs8(mem) psxS[(mem) & 0xffff]
|
||||
#define psxSs16(mem) (*(s16*)&psxS[(mem) & 0xffff])
|
||||
#define psxSs32(mem) (*(s32*)&psxS[(mem) & 0xffff])
|
||||
#define psxSu8(mem) (*(u8*) &psxS[(mem) & 0xffff])
|
||||
#define psxSu16(mem) (*(u16*)&psxS[(mem) & 0xffff])
|
||||
#define psxSu32(mem) (*(u32*)&psxS[(mem) & 0xffff])
|
||||
#define psxSs16(mem) (*(s16*)&psxS[(mem) & 0x00ff])
|
||||
#define psxSs32(mem) (*(s32*)&psxS[(mem) & 0x00ff])
|
||||
#define psxSu8(mem) (*(u8*) &psxS[(mem) & 0x00ff])
|
||||
#define psxSu16(mem) (*(u16*)&psxS[(mem) & 0x00ff])
|
||||
#define psxSu32(mem) (*(u32*)&psxS[(mem) & 0x00ff])
|
||||
|
||||
#define psxPs8(mem) psxP[(mem) & 0xffff]
|
||||
#define psxPs16(mem) (*(s16*)&psxP[(mem) & 0xffff])
|
||||
|
|
|
@ -203,6 +203,7 @@ u8 sio2_fifoOut(){
|
|||
|
||||
void SaveState::sio2Freeze()
|
||||
{
|
||||
FreezeTag( "sio2" );
|
||||
Freeze(sio2);
|
||||
}
|
||||
|
||||
|
|
|
@ -24,9 +24,9 @@ GtkWidget *GameFixDlg, *SpeedHacksDlg;
|
|||
{
|
||||
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_Clip", (Config.GameFixes & FLAG_VU_CLIP));
|
||||
set_checked(GameFixDlg, "check_FPU_Clamp", (Config.GameFixes & FLAG_FPU_CLAMP));
|
||||
set_checked(GameFixDlg, "check_FPU_Mul", (Config.GameFixes & FLAG_FPU_MUL));
|
||||
|
||||
gtk_widget_show_all(GameFixDlg);
|
||||
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 |= 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_Clip") ? FLAG_VU_CLIP : 0;
|
||||
Config.GameFixes |= is_checked(GameFixDlg, "check_FPU_Clamp") ? FLAG_FPU_CLAMP : 0;
|
||||
Config.GameFixes |= is_checked(GameFixDlg, "check_FPU_Mul") ? FLAG_FPU_MUL : 0;
|
||||
|
||||
SaveConfig();
|
||||
gtk_widget_destroy(GameFixDlg);
|
||||
|
|
|
@ -100,12 +100,12 @@ char iop_log_names[9][32] =
|
|||
"Cdr Log",
|
||||
"GPU Log"
|
||||
};
|
||||
|
||||
//Tri-Ace - IDC_GAMEFIX2
|
||||
#define FLAG_VU_ADD_SUB 0x1
|
||||
#define FLAG_VU_CLIP 0x2
|
||||
#define FLAG_FPU_CLAMP 0x4
|
||||
#define FLAG_VU_FCOR_HACK 0x8
|
||||
#define FLAG_AVOID_DELAY_HANDLING 0x10
|
||||
// Digimon Rumble Arena - IDC_GAMEFIX3
|
||||
#define FLAG_FPU_Compare 0x4
|
||||
//Tales of Destiny - IDC_GAMEFIX5
|
||||
#define FLAG_FPU_MUL 0x8
|
||||
|
||||
#define FLAG_VU_NO_OVERFLOW 0x2
|
||||
#define FLAG_VU_EXTRA_OVERFLOW 0x40
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include "Threading.h"
|
||||
#include "Linux.h"
|
||||
#include "../x86/ix86/ix86.h"
|
||||
|
||||
|
|
|
@ -109,30 +109,6 @@ void
|
|||
OnDebug_memWrite32 (GtkButton *button,
|
||||
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
|
||||
OnConfButton (GtkButton *button,
|
||||
gpointer user_data);
|
||||
|
|
|
@ -888,9 +888,9 @@ create_GameFixDlg (void)
|
|||
GtkWidget *GameSettings;
|
||||
GtkWidget *alignment5;
|
||||
GtkWidget *vbox30;
|
||||
GtkWidget *check_FPU_Clamp;
|
||||
GtkWidget *check_FPU_Compare;
|
||||
GtkWidget *check_VU_Add_Sub;
|
||||
GtkWidget *check_VU_Clip;
|
||||
GtkWidget *check_FPU_Mul;
|
||||
GtkWidget *label42;
|
||||
GtkWidget *dialog_action_area1;
|
||||
GtkWidget *cancelbutton1;
|
||||
|
@ -922,20 +922,20 @@ create_GameFixDlg (void)
|
|||
gtk_widget_show (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."));
|
||||
gtk_widget_set_name (check_FPU_Clamp, "check_FPU_Clamp");
|
||||
gtk_widget_show (check_FPU_Clamp);
|
||||
gtk_box_pack_start (GTK_BOX (vbox30), check_FPU_Clamp, FALSE, FALSE, 0);
|
||||
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_Compare, "check_FPU_Compare");
|
||||
gtk_widget_show (check_FPU_Compare);
|
||||
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!"));
|
||||
gtk_widget_set_name (check_VU_Add_Sub, "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);
|
||||
|
||||
check_VU_Clip = gtk_check_button_new_with_mnemonic (_("VU Clip Hack - Special fix for God of War"));
|
||||
gtk_widget_set_name (check_VU_Clip, "check_VU_Clip");
|
||||
gtk_widget_show (check_VU_Clip);
|
||||
gtk_box_pack_start (GTK_BOX (vbox30), check_VU_Clip, FALSE, TRUE, 0);
|
||||
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_FPU_Mul, "check_FPU_Mul");
|
||||
gtk_widget_show (check_FPU_Mul);
|
||||
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>"));
|
||||
gtk_widget_set_name (label42, "label42");
|
||||
|
@ -973,9 +973,9 @@ create_GameFixDlg (void)
|
|||
GLADE_HOOKUP_OBJECT (GameFixDlg, GameSettings, "GameSettings");
|
||||
GLADE_HOOKUP_OBJECT (GameFixDlg, alignment5, "alignment5");
|
||||
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_Clip, "check_VU_Clip");
|
||||
GLADE_HOOKUP_OBJECT (GameFixDlg, check_FPU_Mul, "check_FPU_Mul");
|
||||
GLADE_HOOKUP_OBJECT (GameFixDlg, label42, "label42");
|
||||
GLADE_HOOKUP_OBJECT_NO_REF (GameFixDlg, dialog_action_area1, "dialog_action_area1");
|
||||
GLADE_HOOKUP_OBJECT (GameFixDlg, cancelbutton1, "cancelbutton1");
|
||||
|
@ -3425,8 +3425,11 @@ create_PatchFinderWindow (void)
|
|||
GtkWidget *radiobutton6;
|
||||
GSList *radiobutton6_group = NULL;
|
||||
GtkWidget *radiobutton5;
|
||||
GSList *radiobutton5_group = NULL;
|
||||
GtkWidget *radiobutton4;
|
||||
GSList *radiobutton4_group = NULL;
|
||||
GtkWidget *radiobutton3;
|
||||
GSList *radiobutton3_group = NULL;
|
||||
GtkWidget *label56;
|
||||
GtkWidget *frame21;
|
||||
GtkWidget *alignment16;
|
||||
|
@ -3553,8 +3556,8 @@ create_PatchFinderWindow (void)
|
|||
gtk_table_attach (GTK_TABLE (table6), radiobutton5, 0, 1, 1, 2,
|
||||
(GtkAttachOptions) (0),
|
||||
(GtkAttachOptions) (0), 0, 0);
|
||||
gtk_radio_button_set_group (GTK_RADIO_BUTTON (radiobutton5), radiobutton6_group);
|
||||
radiobutton6_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radiobutton5));
|
||||
gtk_radio_button_set_group (GTK_RADIO_BUTTON (radiobutton5), radiobutton5_group);
|
||||
radiobutton5_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radiobutton5));
|
||||
|
||||
radiobutton4 = gtk_radio_button_new_with_mnemonic (NULL, _("16 bits"));
|
||||
gtk_widget_set_name (radiobutton4, "radiobutton4");
|
||||
|
@ -3562,8 +3565,8 @@ create_PatchFinderWindow (void)
|
|||
gtk_table_attach (GTK_TABLE (table6), radiobutton4, 1, 2, 0, 1,
|
||||
(GtkAttachOptions) (0),
|
||||
(GtkAttachOptions) (0), 0, 0);
|
||||
gtk_radio_button_set_group (GTK_RADIO_BUTTON (radiobutton4), radiobutton6_group);
|
||||
radiobutton6_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radiobutton4));
|
||||
gtk_radio_button_set_group (GTK_RADIO_BUTTON (radiobutton4), radiobutton4_group);
|
||||
radiobutton4_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radiobutton4));
|
||||
|
||||
radiobutton3 = gtk_radio_button_new_with_mnemonic (NULL, _("8 bits"));
|
||||
gtk_widget_set_name (radiobutton3, "radiobutton3");
|
||||
|
@ -3571,8 +3574,8 @@ create_PatchFinderWindow (void)
|
|||
gtk_table_attach (GTK_TABLE (table6), radiobutton3, 0, 1, 0, 1,
|
||||
(GtkAttachOptions) (0),
|
||||
(GtkAttachOptions) (0), 0, 0);
|
||||
gtk_radio_button_set_group (GTK_RADIO_BUTTON (radiobutton3), radiobutton6_group);
|
||||
radiobutton6_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radiobutton3));
|
||||
gtk_radio_button_set_group (GTK_RADIO_BUTTON (radiobutton3), radiobutton3_group);
|
||||
radiobutton3_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radiobutton3));
|
||||
|
||||
label56 = gtk_label_new (_("<b>Values of Size</b>"));
|
||||
gtk_widget_set_name (label56, "label56");
|
||||
|
|
|
@ -109,14 +109,14 @@ static __forceinline void memset_8( void *dest )
|
|||
(
|
||||
".intel_syntax noprefix\n"
|
||||
"cld\n"
|
||||
// "mov edi, %0\n"
|
||||
// "mov eax, %1\n"
|
||||
// "mov edi, %[dest]\n"
|
||||
// "mov eax, %[data32]\n"
|
||||
"stosd\n"
|
||||
"stosd\n"
|
||||
"stosd\n"
|
||||
".att_syntax\n"
|
||||
:
|
||||
: "D"(dest), "a"(data32)
|
||||
: [dest]"D"(dest), [data32]"a"(data32)
|
||||
// D - edi, a -- eax, c ecx
|
||||
:
|
||||
);
|
||||
|
@ -127,15 +127,15 @@ static __forceinline void memset_8( void *dest )
|
|||
(
|
||||
".intel_syntax noprefix\n"
|
||||
"cld\n"
|
||||
// "mov edi, %0\n"
|
||||
// "mov eax, %1\n"
|
||||
// "mov edi, %[dest]\n"
|
||||
// "mov eax, %[data32]\n"
|
||||
"stosd\n"
|
||||
"stosd\n"
|
||||
"stosd\n"
|
||||
"stosd\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"
|
||||
"cld\n"
|
||||
// "mov edi, %0\n"
|
||||
// "mov eax, %1\n"
|
||||
// "mov edi, %[dest]\n"
|
||||
// "mov eax, %[data32]\n"
|
||||
"stosd\n"
|
||||
"stosd\n"
|
||||
"stosd\n"
|
||||
|
@ -155,7 +155,7 @@ static __forceinline void memset_8( void *dest )
|
|||
"stosd\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"
|
||||
"cld\n"
|
||||
// "mov ecx, %0\n"
|
||||
// "mov edi, %1\n"
|
||||
// "mov eax, %2\n"
|
||||
// "mov ecx, %[remdat]\n"
|
||||
// "mov edi, %[dest]\n"
|
||||
// "mov eax, %\[data32]n"
|
||||
"rep stosd\n"
|
||||
".att_syntax\n"
|
||||
:
|
||||
: "c"(remdat), "D"(dest), "a"(data32)
|
||||
: [remdat]"c"(remdat), [dest]"D"(dest), [data32]"a"(data32)
|
||||
:
|
||||
);
|
||||
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>
|
||||
|
||||
<child>
|
||||
<widget class="GtkCheckButton" id="check_FPU_Clamp">
|
||||
<widget class="GtkCheckButton" id="check_FPU_Compare">
|
||||
<property name="visible">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="relief">GTK_RELIEF_NORMAL</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>
|
||||
<widget class="GtkCheckButton" id="check_VU_Clip">
|
||||
<widget class="GtkCheckButton" id="check_FPU_Mul">
|
||||
<property name="visible">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="relief">GTK_RELIEF_NORMAL</property>
|
||||
<property name="focus_on_click">True</property>
|
||||
|
@ -5063,7 +5063,7 @@ Version x.x</property>
|
|||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">_Graphics</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>
|
||||
</child>
|
||||
|
||||
|
@ -5072,7 +5072,7 @@ Version x.x</property>
|
|||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">C_ontrollers</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>
|
||||
</child>
|
||||
|
||||
|
@ -5081,7 +5081,7 @@ Version x.x</property>
|
|||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">_Sound</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>
|
||||
</child>
|
||||
|
||||
|
@ -5090,7 +5090,7 @@ Version x.x</property>
|
|||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">_Cdvdrom</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>
|
||||
</child>
|
||||
|
||||
|
@ -5099,7 +5099,7 @@ Version x.x</property>
|
|||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">D_ev9</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>
|
||||
</child>
|
||||
|
||||
|
@ -5108,7 +5108,7 @@ Version x.x</property>
|
|||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">U_SB</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>
|
||||
</child>
|
||||
|
||||
|
@ -5117,7 +5117,7 @@ Version x.x</property>
|
|||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Fire_Wire</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>
|
||||
</child>
|
||||
|
||||
|
@ -5774,7 +5774,6 @@ Version x.x</property>
|
|||
<property name="active">False</property>
|
||||
<property name="inconsistent">False</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
<property name="group">radiobutton6</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
|
@ -5797,7 +5796,6 @@ Version x.x</property>
|
|||
<property name="active">False</property>
|
||||
<property name="inconsistent">False</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
<property name="group">radiobutton6</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
|
@ -5820,7 +5818,6 @@ Version x.x</property>
|
|||
<property name="active">False</property>
|
||||
<property name="inconsistent">False</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
<property name="group">radiobutton6</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
|
|
|
@ -116,6 +116,8 @@ static void _mtgsFreezeGIF( SaveState& state, GIFPath (&paths)[3] )
|
|||
|
||||
void SaveState::mtgsFreeze()
|
||||
{
|
||||
FreezeTag( "mtgs" );
|
||||
|
||||
if( mtgsThread != NULL )
|
||||
{
|
||||
mtgsThread->Freeze( *this );
|
||||
|
|
|
@ -104,11 +104,7 @@ void loadBiosRom( const char *ext, u8 *dest, long maxSize )
|
|||
Bios1 = Path::Combine( Config.BiosDir, ext ) + ".bin";
|
||||
if( (filesize=Path::getFileSize( Bios1 ) ) <= 0 )
|
||||
{
|
||||
Console::Error( "\n\n\n"
|
||||
"**************\n"
|
||||
"%s NOT FOUND\n"
|
||||
"**************\n\n\n", params ext
|
||||
);
|
||||
Console::Notice( "Bios Warning > %s not found.", params ext );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -853,7 +849,7 @@ void mmap_ClearCpuBlock( uint offset )
|
|||
|
||||
for (u32 i=0;i<psMPWVA[offset].size();i++)
|
||||
{
|
||||
Cpu->Clear(psMPWVA[offset][i],0x1000);
|
||||
Cpu->Clear(psMPWVA[offset][i],0x400);
|
||||
}
|
||||
psMPWVA[offset].clear();
|
||||
}
|
|
@ -141,9 +141,9 @@ u32 GetBiosVersion() {
|
|||
}
|
||||
|
||||
//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;
|
||||
unsigned int fileOffset=0, found=FALSE;
|
||||
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
|
||||
}
|
||||
|
||||
while(strlen(rd.fileName) > 0){
|
||||
if (strcmp(rd.fileName, "ROMVER") == 0){ // found romver
|
||||
unsigned int filepos=ftell(fp);
|
||||
while(strlen(rd.fileName) > 0)
|
||||
{
|
||||
if (strcmp(rd.fileName, "ROMVER") == 0) // found romver
|
||||
{
|
||||
uint filepos = ftell(fp);
|
||||
fseek(fp, fileOffset, SEEK_SET);
|
||||
if (fread(&ROMVER, 14, 1, fp) == 0) break;
|
||||
fseek(fp, filepos, SEEK_SET);//go back
|
||||
|
||||
switch(ROMVER[4]){
|
||||
case 'T':sprintf(zone, "T10K "); break;
|
||||
case 'X':sprintf(zone, "Test ");break;
|
||||
case 'J':sprintf(zone, "Japan "); break;
|
||||
case 'A':sprintf(zone, "USA "); break;
|
||||
case 'E':sprintf(zone, "Europe"); break;
|
||||
case 'H':sprintf(zone, "HK "); break;
|
||||
case 'P':sprintf(zone, "Free "); break;
|
||||
case 'C':sprintf(zone, "China "); break;
|
||||
default: sprintf(zone, "%c ",ROMVER[4]); break;//shoudn't show
|
||||
const char zonefail[2] = { ROMVER[4], '\0' }; // the default "zone" (unknown code)
|
||||
const char* zone = zonefail;
|
||||
|
||||
switch(ROMVER[4])
|
||||
{
|
||||
case 'T': zone = "T10K "; break;
|
||||
case 'X': zone = "Test "; break;
|
||||
case 'J': zone = "Japan "; break;
|
||||
case 'A': zone = "USA "; break;
|
||||
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":"");
|
||||
strncpy(description+ 8, ROMVER+ 0, 2);//ver major
|
||||
strncpy(description+11, ROMVER+ 2, 2);//ver minor
|
||||
strncpy(description+14, ROMVER+12, 2);//day
|
||||
strncpy(description+17, ROMVER+10, 2);//month
|
||||
strncpy(description+20, ROMVER+ 6, 4);//year
|
||||
|
||||
sprintf(description, "%s v%c%c.%c%c(%c%c/%c%c/%c%c%c%c) %s", zone,
|
||||
ROMVER[0], ROMVER[1], // ver major
|
||||
ROMVER[2], ROMVER[3], // ver minor
|
||||
ROMVER[12], ROMVER[13], // day
|
||||
ROMVER[10], ROMVER[11], // month
|
||||
ROMVER[6], ROMVER[7], ROMVER[8], ROMVER[9], // year!
|
||||
(ROMVER[5]=='C') ? "Console" : (ROMVER[5]=='D') ? "Devel" : ""
|
||||
);
|
||||
found = TRUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -73,8 +73,9 @@ extern u64 GetCPUTicks();
|
|||
extern u64 GetTickFrequency();
|
||||
|
||||
// Used in Misc,and Windows/Linux files.
|
||||
void ProcessFKeys(int fkey, int shift); // processes fkey related commands value 1-12
|
||||
int IsBIOS(char *filename, char *description);
|
||||
extern void ProcessFKeys(int fkey, int shift); // processes fkey related commands value 1-12
|
||||
extern int IsBIOS(const char *filename, char *description);
|
||||
|
||||
extern const char *LabelAuthors;
|
||||
extern const char *LabelGreets;
|
||||
void CycleFrameLimit(int dir);
|
||||
|
|
|
@ -54,15 +54,11 @@ void svudispfn();
|
|||
// aR3000A.S
|
||||
void iopJITCompile();
|
||||
void iopJITCompileInBlock();
|
||||
void iopDispatcher();
|
||||
void iopDispatcherClear();
|
||||
void iopDispatcherReg();
|
||||
|
||||
// aR5900-32.S
|
||||
void JITCompile();
|
||||
void JITCompileInBlock();
|
||||
void Dispatcher();
|
||||
void DispatcherClear();
|
||||
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.
|
||||
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;
|
||||
_PADtest PAD1test;
|
||||
_PADabout PAD1about;
|
||||
_PADfreeze PAD1freeze;
|
||||
|
||||
// PAD2
|
||||
_PADinit PAD2init;
|
||||
|
@ -87,6 +88,7 @@ _PADgsDriverInfo PAD2gsDriverInfo;
|
|||
_PADconfigure PAD2configure;
|
||||
_PADtest PAD2test;
|
||||
_PADabout PAD2about;
|
||||
_PADfreeze PAD2freeze;
|
||||
|
||||
// SIO[2]
|
||||
_SIOinit SIOinit[2][9];
|
||||
|
@ -330,6 +332,7 @@ void *PAD1plugin;
|
|||
void CALLBACK PAD1_configure() {}
|
||||
void CALLBACK PAD1_about() {}
|
||||
s32 CALLBACK PAD1_test() { return 0; }
|
||||
s32 CALLBACK PAD1_freeze(int mode, freezeData *data) { data->size = 0; return 0; }
|
||||
|
||||
int LoadPAD1plugin(const string& filename) {
|
||||
void *drv;
|
||||
|
@ -352,6 +355,7 @@ int LoadPAD1plugin(const string& filename) {
|
|||
MapSymbolPAD_Fallback(PAD1,PAD,configure);
|
||||
MapSymbolPAD_Fallback(PAD1,PAD,about);
|
||||
MapSymbolPAD_Fallback(PAD1,PAD,test);
|
||||
MapSymbolPAD_Fallback(PAD1,PAD,freeze);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -361,6 +365,7 @@ void *PAD2plugin;
|
|||
void CALLBACK PAD2_configure() {}
|
||||
void CALLBACK PAD2_about() {}
|
||||
s32 CALLBACK PAD2_test() { return 0; }
|
||||
s32 CALLBACK PAD2_freeze(int mode, freezeData *data) { data->size = 0; return 0; }
|
||||
|
||||
int LoadPAD2plugin(const string& filename) {
|
||||
void *drv;
|
||||
|
@ -383,6 +388,7 @@ int LoadPAD2plugin(const string& filename) {
|
|||
MapSymbolPAD_Fallback(PAD2,PAD,configure);
|
||||
MapSymbolPAD_Fallback(PAD2,PAD,about);
|
||||
MapSymbolPAD_Fallback(PAD2,PAD,test);
|
||||
MapSymbolPAD_Fallback(PAD2,PAD,freeze);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -112,10 +112,10 @@ struct psxRegisters {
|
|||
u32 code; /* The instruction */
|
||||
u32 cycle;
|
||||
u32 interrupt;
|
||||
u32 sCycle[64]; // start cycle for signaled ints
|
||||
s32 eCycle[64]; // cycle delta for signaled ints (sCycle + eCycle == branch cycle)
|
||||
u32 _msflag[32];
|
||||
u32 _smflag[32];
|
||||
u32 sCycle[32]; // start cycle for signaled ints
|
||||
s32 eCycle[32]; // cycle delta for signaled ints (sCycle + eCycle == branch cycle)
|
||||
//u32 _msflag[32];
|
||||
//u32 _smflag[32];
|
||||
};
|
||||
|
||||
PCSX2_ALIGNED16_EXTERN(psxRegisters psxRegs);
|
||||
|
|
|
@ -522,7 +522,7 @@ __forceinline bool _cpuBranchTest_Shared()
|
|||
cpuSetNextBranchDelta( ((g_psxNextBranchCycle-psxRegs.cycle)*8) - EEsCycle );
|
||||
|
||||
// Apply the hsync counter's nextCycle
|
||||
cpuSetNextBranch( counters[4].sCycle, counters[4].CycleT );
|
||||
cpuSetNextBranch( hsyncCounter.sCycle, hsyncCounter.CycleT );
|
||||
|
||||
// Apply vsync and other counter nextCycles
|
||||
cpuSetNextBranch( nextsCounter, nextCounter );
|
||||
|
|
|
@ -26,8 +26,6 @@
|
|||
#include "deci2_netmp.h"
|
||||
#include "deci2_ttyp.h"
|
||||
|
||||
#include "Threading.h"
|
||||
|
||||
#define PROTO_DCMP 0x0001
|
||||
#define PROTO_ITTYP 0x0110
|
||||
#define PROTO_IDBGP 0x0130
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
#include "VUmicro.h"
|
||||
#include "deci2.h"
|
||||
|
||||
#include "Threading.h"
|
||||
using namespace Threading;
|
||||
|
||||
using namespace R5900;
|
||||
|
|
|
@ -454,11 +454,9 @@ void SPRTOinterrupt()
|
|||
|
||||
void SaveState::sprFreeze()
|
||||
{
|
||||
// Gotta save the weird ref-style DMA timing vars!
|
||||
if( GetVersion() >= 0x05 )
|
||||
{
|
||||
Freeze(spr0finished);
|
||||
Freeze(spr1finished);
|
||||
Freeze(mfifotransferred);
|
||||
}
|
||||
FreezeTag( "SPRdma" );
|
||||
|
||||
Freeze(spr0finished);
|
||||
Freeze(spr1finished);
|
||||
Freeze(mfifotransferred);
|
||||
}
|
|
@ -33,7 +33,6 @@
|
|||
|
||||
using namespace R5900;
|
||||
|
||||
extern int g_psxWriteOk;
|
||||
extern void recResetEE();
|
||||
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 ) );
|
||||
}
|
||||
|
||||
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 );
|
||||
}
|
||||
|
@ -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()
|
||||
{
|
||||
if( IsLoading() )
|
||||
PreLoadPrep();
|
||||
|
||||
FreezeMem(PS2MEM_BASE, Ps2MemSize::Base); // 32 MB main memory
|
||||
FreezeMem(PS2MEM_ROM, Ps2MemSize::Rom); // 4 mb rom memory
|
||||
FreezeMem(PS2MEM_ROM1, Ps2MemSize::Rom1); // 256kb rom1 memory
|
||||
FreezeMem(PS2MEM_SCRATCH, Ps2MemSize::Scratch); // scratch pad
|
||||
FreezeMem(PS2MEM_HW, Ps2MemSize::Hardware); // hardware memory
|
||||
// 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).
|
||||
|
||||
char descout[128], descin[128];
|
||||
memzero_obj( descout );
|
||||
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_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(psxRegs); // iop regs
|
||||
if (GetVersion() >= 0x6)
|
||||
Freeze(fpuRegs);
|
||||
else
|
||||
{
|
||||
// Old versiosn didn't save the ACCflags...
|
||||
FreezeLegacy(fpuRegs, sizeof(u32)); // fpu regs
|
||||
fpuRegs.ACCflag = 0;
|
||||
}
|
||||
Freeze(fpuRegs);
|
||||
Freeze(tlb); // tlbs
|
||||
|
||||
// Third Block - Cycle Timers and Events
|
||||
// -------------------------------------
|
||||
FreezeTag( "Cycles" );
|
||||
Freeze(EEsCycle);
|
||||
Freeze(EEoCycle);
|
||||
Freeze(psxRegs.cycle); // used to be IOPoCycle. This retains compatibility.
|
||||
Freeze(g_nextBranchCycle);
|
||||
Freeze(g_psxNextBranchCycle);
|
||||
|
||||
Freeze(s_iLastCOP0Cycle);
|
||||
Freeze(s_iLastPERFCycle);
|
||||
|
||||
Freeze(g_psxWriteOk);
|
||||
|
||||
//hope didn't forgot any cpu....
|
||||
|
||||
// Fourth Block - EE-related systems
|
||||
// ---------------------------------
|
||||
rcntFreeze();
|
||||
gsFreeze();
|
||||
vuMicroFreeze();
|
||||
|
@ -124,38 +159,27 @@ void SaveState::FreezeAll()
|
|||
gifFreeze();
|
||||
sprFreeze();
|
||||
|
||||
// iop now
|
||||
FreezeMem(psxM, Ps2MemSize::IopRam); // 2 MB main memory
|
||||
FreezeMem(psxH, Ps2MemSize::IopHardware); // hardware memory
|
||||
//FreezeMem(psxS, 0x00010000); // sif memory
|
||||
|
||||
// Fifth Block - iop-related systems
|
||||
// ---------------------------------
|
||||
psxRcntFreeze();
|
||||
sioFreeze();
|
||||
sio2Freeze();
|
||||
cdrFreeze();
|
||||
cdvdFreeze();
|
||||
psxRcntFreeze();
|
||||
sio2Freeze();
|
||||
|
||||
// Sixth Block - Plugins Galore!
|
||||
// -----------------------------
|
||||
FreezePlugin( "GS", gsSafeFreeze );
|
||||
FreezePlugin( "SPU2", SPU2freeze );
|
||||
FreezePlugin( "DEV9", DEV9freeze );
|
||||
FreezePlugin( "USB", USBfreeze );
|
||||
FreezePlugin( "PAD1", PAD1freeze );
|
||||
FreezePlugin( "PAD2", PAD2freeze );
|
||||
|
||||
if( IsLoading() )
|
||||
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
|
||||
|
||||
|
@ -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!" );
|
||||
throw Exception::UnsupportedStateVersion( m_version );
|
||||
}
|
||||
|
||||
_testCdvdCrc();
|
||||
}
|
||||
|
||||
gzLoadingState::~gzLoadingState() { }
|
||||
|
@ -226,34 +248,30 @@ void gzSavingState::FreezeMem( void* data, int size )
|
|||
|
||||
void gzLoadingState::FreezeMem( void* data, int size )
|
||||
{
|
||||
gzread( m_file, data, size );
|
||||
if( gzeof( m_file ) )
|
||||
if( gzread( m_file, data, size ) != size )
|
||||
throw Exception::BadSavedState( m_filename );
|
||||
}
|
||||
|
||||
void gzSavingState::FreezePlugin( const char* name, s32 (CALLBACK *freezer)(int mode, freezeData *data) )
|
||||
{
|
||||
Console::WriteLn( "\tSaving %s", params name );
|
||||
freezeData fP = { 0, NULL };
|
||||
Console::WriteLn( "\tSaving %s", params name );
|
||||
|
||||
FreezeTag( name );
|
||||
|
||||
if (freezer(FREEZE_SIZE, &fP) == -1)
|
||||
throw Exception::FreezePluginFailure( name, "saving" );
|
||||
|
||||
gzwrite(m_file, &fP.size, sizeof(fP.size));
|
||||
Freeze( fP.size );
|
||||
if( fP.size == 0 ) return;
|
||||
|
||||
fP.data = (s8*)malloc(fP.size);
|
||||
if (fP.data == NULL)
|
||||
throw Exception::OutOfMemory();
|
||||
SafeArray<s8> buffer( fP.size );
|
||||
fP.data = buffer.GetPtr();
|
||||
|
||||
if(freezer(FREEZE_SAVE, &fP) == -1)
|
||||
throw Exception::FreezePluginFailure( name, "saving" );
|
||||
|
||||
if (fP.size)
|
||||
{
|
||||
gzwrite(m_file, fP.data, fP.size);
|
||||
free(fP.data);
|
||||
}
|
||||
FreezeMem( fP.data, fP.size );
|
||||
}
|
||||
|
||||
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 };
|
||||
Console::WriteLn( "\tLoading %s", params name );
|
||||
|
||||
gzread(m_file, &fP.size, sizeof(fP.size));
|
||||
FreezeTag( name );
|
||||
Freeze( fP.size );
|
||||
if( fP.size == 0 ) return;
|
||||
|
||||
fP.data = (s8*)malloc(fP.size);
|
||||
if (fP.data == NULL)
|
||||
throw Exception::OutOfMemory();
|
||||
gzread(m_file, fP.data, fP.size);
|
||||
SafeArray<s8> buffer( fP.size );
|
||||
fP.data = buffer.GetPtr();
|
||||
|
||||
if( gzeof( m_file ) )
|
||||
throw Exception::BadSavedState( m_filename );
|
||||
FreezeMem( fP.data, fP.size );
|
||||
|
||||
if(freezer(FREEZE_LOAD, &fP) == -1)
|
||||
throw Exception::FreezePluginFailure( name, "loading" );
|
||||
|
||||
if (fP.size) free(fP.data);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -24,10 +24,14 @@
|
|||
#include "PS2Edefs.h"
|
||||
#endif
|
||||
#include "System.h"
|
||||
|
||||
// Savestate Versioning!
|
||||
// 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
|
||||
// between the GS saving function and the MTGS's needs. :)
|
||||
|
@ -41,6 +45,7 @@ class SaveState
|
|||
{
|
||||
protected:
|
||||
u32 m_version; // version of the savestate being loaded.
|
||||
SafeArray<char> m_tagspace;
|
||||
|
||||
public:
|
||||
SaveState( const char* msg, const string& destination );
|
||||
|
@ -76,6 +81,12 @@ public:
|
|||
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.
|
||||
virtual void FreezePlugin( const char* name, s32 (CALLBACK* freezer)(int mode, freezeData *data) )=0;
|
||||
|
||||
|
@ -95,11 +106,6 @@ public:
|
|||
|
||||
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!
|
||||
|
||||
void rcntFreeze();
|
||||
|
|
|
@ -586,22 +586,13 @@ __forceinline void dmaSIF2() {
|
|||
}
|
||||
|
||||
|
||||
void SaveState::sifFreeze() {
|
||||
void SaveState::sifFreeze()
|
||||
{
|
||||
FreezeTag( "SIFdma" );
|
||||
|
||||
Freeze(sif0);
|
||||
Freeze(sif1);
|
||||
|
||||
if( GetVersion() >= 0x0002 )
|
||||
{
|
||||
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;
|
||||
}
|
||||
Freeze(eesifbusy);
|
||||
Freeze(iopsifbusy);
|
||||
}
|
||||
|
|
|
@ -566,22 +566,15 @@ void SaveState::sioFreeze()
|
|||
// CRCs for memory cards.
|
||||
u64 m_mcdCRCs[2];
|
||||
|
||||
FreezeTag( "sio" );
|
||||
Freeze( sio );
|
||||
|
||||
// versions prior to 3 didn't have CRCs.
|
||||
if( GetVersion() >= 0x03 )
|
||||
if( IsSaving() )
|
||||
{
|
||||
if( IsSaving() )
|
||||
{
|
||||
for( int i=0; i<2; ++i )
|
||||
m_mcdCRCs[i] = MemoryCard::GetCRC( i );
|
||||
}
|
||||
Freeze( m_mcdCRCs );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_mcdCRCs[0] = m_mcdCRCs[1] = 0;
|
||||
for( int i=0; i<2; ++i )
|
||||
m_mcdCRCs[i] = MemoryCard::GetCRC( i );
|
||||
}
|
||||
Freeze( m_mcdCRCs );
|
||||
|
||||
if( IsLoading() && Config.McdEnableEject )
|
||||
{
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
#include "PrecompiledHeader.h"
|
||||
|
||||
#include "Common.h"
|
||||
#include "Threading.h"
|
||||
#include "HostGui.h"
|
||||
|
||||
#include "VUmicro.h"
|
||||
|
@ -92,6 +91,7 @@ static void trim( string& line )
|
|||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// This function should be called once during program execution.
|
||||
void SysDetect()
|
||||
{
|
||||
|
@ -160,6 +160,7 @@ void SysDetect()
|
|||
Console::ClearColor();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Allocates memory for all PS2 systems.
|
||||
bool SysAllocateMem()
|
||||
{
|
||||
|
@ -187,10 +188,12 @@ bool SysAllocateMem()
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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
|
||||
// to have those resources at specific address ranges. The sooner memory is allocated, the better.
|
||||
// This should be done asap, since the recompilers tend to demand a lot of system resources,
|
||||
// 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).
|
||||
void SysAllocateDynarecs()
|
||||
{
|
||||
|
@ -259,6 +262,7 @@ void SysAllocateDynarecs()
|
|||
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// This should be called last thing before Pcsx2 exits.
|
||||
void SysShutdownMem()
|
||||
{
|
||||
|
@ -269,6 +273,7 @@ void SysShutdownMem()
|
|||
memShutdown();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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
|
||||
// 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_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.
|
||||
// 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
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "MemcpyFast.h"
|
||||
#include "SafeArray.h"
|
||||
#include "Misc.h"
|
||||
#include "Threading.h" // to use threading stuff, include the Threading namespace in your file.
|
||||
|
||||
|
||||
enum PageProtectionMode
|
||||
|
|
|
@ -44,6 +44,7 @@ namespace Threading
|
|||
|
||||
void Thread::Close()
|
||||
{
|
||||
if( m_terminated ) return;
|
||||
pthread_cancel( m_thread );
|
||||
pthread_join( m_thread, NULL );
|
||||
}
|
||||
|
|
|
@ -67,8 +67,7 @@ namespace Threading
|
|||
void Unlock();
|
||||
};
|
||||
|
||||
// Returns the number of available logical CPUs (cores plus
|
||||
// hyperthreaded cpus)
|
||||
// Returns the number of available logical CPUs (cores plus hyperthreaded cpus)
|
||||
extern void CountLogicalCores( int LogicalCoresPerPhysicalCPU, int PhysicalCoresPerPhysicalCPU );
|
||||
|
||||
// Releases a timeslice to other threads.
|
||||
|
@ -80,6 +79,24 @@ namespace Threading
|
|||
// sleeps the current thread for the given number of milliseconds.
|
||||
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
|
||||
{
|
||||
protected:
|
||||
|
@ -106,12 +123,135 @@ namespace Threading
|
|||
// on linux).
|
||||
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;
|
||||
};
|
||||
|
||||
// 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_InterlockedCompareExchange( volatile long* target, long srcval, long comp );
|
||||
|
|
|
@ -160,6 +160,8 @@ void vuMicroMemReset()
|
|||
|
||||
void SaveState::vuMicroFreeze()
|
||||
{
|
||||
FreezeTag( "vuMicro" );
|
||||
|
||||
jASSUME( VU0.Mem != NULL );
|
||||
jASSUME( VU1.Mem != NULL );
|
||||
|
||||
|
@ -169,15 +171,7 @@ void SaveState::vuMicroFreeze()
|
|||
FreezeMem(VU0.Micro, 4*1024);
|
||||
|
||||
Freeze(VU0.VF);
|
||||
if( GetVersion() >= 0x02 )
|
||||
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(VU0.VI);
|
||||
|
||||
Freeze(VU1.ACC);
|
||||
Freeze(VU1.code);
|
||||
|
@ -185,14 +179,5 @@ void SaveState::vuMicroFreeze()
|
|||
FreezeMem(VU1.Micro, 16*1024);
|
||||
|
||||
Freeze(VU1.VF);
|
||||
if( GetVersion() >= 0x02 )
|
||||
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 );
|
||||
}
|
||||
|
||||
Freeze(VU1.VI);
|
||||
}
|
||||
|
|
|
@ -452,7 +452,10 @@ static __forceinline int mfifoVIF1chain() {
|
|||
int ret;
|
||||
|
||||
/* 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) &&
|
||||
|
@ -485,16 +488,30 @@ void mfifoVIF1transfer(int qwc) {
|
|||
|
||||
g_vifCycles = 0;
|
||||
|
||||
mfifodmairq = 0; //Clear any previous TIE interrupt
|
||||
|
||||
|
||||
if(qwc > 0){
|
||||
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);
|
||||
|
||||
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){
|
||||
ptag = (u32*)dmaGetAddr(vif1ch->tadr);
|
||||
|
||||
|
@ -505,7 +522,7 @@ void mfifoVIF1transfer(int qwc) {
|
|||
VIF_LOG("MFIFO Stallon tag\n");
|
||||
|
||||
vif1.stallontag = 1;
|
||||
CPU_INT(10,cycles+g_vifCycles);
|
||||
//CPU_INT(10,cycles+g_vifCycles);
|
||||
return; //IRQ set by VIFTransfer
|
||||
}
|
||||
}
|
||||
|
@ -524,7 +541,7 @@ void mfifoVIF1transfer(int qwc) {
|
|||
switch (id) {
|
||||
case 0: // Refe - Transfer Packet According to ADDR field
|
||||
vif1ch->tadr = psHu32(DMAC_RBOR) + ((vif1ch->tadr + 16) & psHu32(DMAC_RBSR));
|
||||
vif1.done = 2; //End Transfer
|
||||
vif1.done = 1; //End Transfer
|
||||
break;
|
||||
|
||||
case 1: // CNT - Transfer QWC following the tag.
|
||||
|
@ -550,31 +567,33 @@ void mfifoVIF1transfer(int qwc) {
|
|||
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->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;
|
||||
}
|
||||
|
||||
if ((vif1ch->chcr & 0x80) && (ptag[0] >> 31)) {
|
||||
VIF_LOG("dmaIrq Set\n");
|
||||
vif1.done = 2;
|
||||
mfifodmairq = 1; //Let the handler know we have prematurely ended MFIFO
|
||||
}
|
||||
if ((vif1ch->chcr & 0x80) && (ptag[0] >> 31))
|
||||
{
|
||||
VIF_LOG("dmaIrq Set\n");
|
||||
vif1.done = 1;
|
||||
mfifodmairq = 1; //Let the handler know we have prematurely ended MFIFO
|
||||
}
|
||||
}
|
||||
ret = mfifoVIF1chain();
|
||||
if (ret == -1) {
|
||||
vif1.inprogress |= 1;
|
||||
|
||||
/*if (ret == -1) {
|
||||
SysPrintf("VIF dmaChain error size=%d, madr=%lx, tadr=%lx\n",
|
||||
vif1ch->qwc, vif1ch->madr, vif1ch->tadr);
|
||||
vif1.done = 1;
|
||||
CPU_INT(10,g_vifCycles);
|
||||
//CPU_INT(10,g_vifCycles);
|
||||
}
|
||||
if(ret == -2){
|
||||
VIF_LOG("MFIFO Stall\n");
|
||||
CPU_INT(10,g_vifCycles);
|
||||
//CPU_INT(10,g_vifCycles);
|
||||
return;
|
||||
}
|
||||
}*/
|
||||
|
||||
if(vif1.done == 2 && vif1ch->qwc == 0) vif1.done = 1;
|
||||
CPU_INT(10,g_vifCycles);
|
||||
//if(vif1.done == 2 && vif1ch->qwc == 0) vif1.done = 1;
|
||||
//CPU_INT(10,g_vifCycles);
|
||||
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;
|
||||
|
||||
|
||||
|
||||
if(vif1.inprogress == 1) mfifoVIF1chain();
|
||||
|
||||
if(vif1.irq && vif1.tag.size == 0) {
|
||||
vif1Regs->stat|= VIF1_STAT_INT;
|
||||
hwIntcIrq(INTC_VIF1);
|
||||
|
@ -594,15 +617,35 @@ void vifMFIFOInterrupt()
|
|||
}
|
||||
}
|
||||
|
||||
if(vif1.done != 1) {
|
||||
|
||||
|
||||
if(vif1.done != 1 || vif1.inprogress & 1) {
|
||||
|
||||
if(vifqwc <= 0){
|
||||
//SysPrintf("Empty\n");
|
||||
vif1.inprogress |= 0x10;
|
||||
hwDmacIrq(14);
|
||||
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;
|
||||
}
|
||||
} 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)
|
||||
//If we dont clear it on MFIFO end, Tekken Tag breaks, understandably (Refraction)
|
||||
|
|
537
pcsx2/VifDma.cpp
537
pcsx2/VifDma.cpp
|
@ -505,15 +505,15 @@ static void VIFunpack(u32 *data, vifCode *v, int size, const unsigned int VIFdma
|
|||
#else
|
||||
if( VIFdmanum ) {
|
||||
__asm__(".intel_syntax noprefix\n"
|
||||
"movaps xmm6, xmmword ptr [%0]\n"
|
||||
"movaps xmm7, xmmword ptr [%1]\n"
|
||||
".att_syntax\n" : :"r"(g_vifRow1), "r"(g_vifCol1) );
|
||||
"movaps xmm6, xmmword ptr [%[g_vifRow1]]\n"
|
||||
"movaps xmm7, xmmword ptr [%[g_vifCol1]]\n"
|
||||
".att_syntax\n" : :[g_vifRow1]"r"(g_vifRow1), [g_vifCol1]"r"(g_vifCol1) );
|
||||
}
|
||||
else {
|
||||
__asm__(".intel_syntax noprefix\n"
|
||||
"movaps xmm6, xmmword ptr [%0]\n"
|
||||
"movaps xmm7, xmmword ptr [%1]\n"
|
||||
".att_syntax\n" : : "r"(g_vifRow0), "r"(g_vifCol0) );
|
||||
"movaps xmm6, xmmword ptr [%[g_vifRow0]]\n"
|
||||
"movaps xmm7, xmmword ptr [%[g_vifCol0]]\n"
|
||||
".att_syntax\n" : : [g_vifRow0]"r"(g_vifRow0), [g_vifCol0]"r"(g_vifCol0) );
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1344,23 +1344,17 @@ void vif0Reset() {
|
|||
|
||||
void SaveState::vif0Freeze()
|
||||
{
|
||||
FreezeTag( "VIFdma" );
|
||||
|
||||
// Dunno if this one is needed, but whatever, it's small. :)
|
||||
if( GetVersion() >= 0x04 )
|
||||
Freeze( g_vifCycles );
|
||||
Freeze( g_vifCycles );
|
||||
|
||||
Freeze( vif0 );
|
||||
if( GetVersion() >= 0x04 )
|
||||
{
|
||||
Freeze( g_vif0HasMask3 );
|
||||
Freeze( g_vif0Masks );
|
||||
Freeze( g_vifRow0 );
|
||||
Freeze( g_vifCol0 );
|
||||
}
|
||||
else if( IsLoading() )
|
||||
{
|
||||
// Hack to "help" old savestates recover...
|
||||
SetNewMask(g_vif0Masks, g_vif0HasMask3, vif0Regs->mask, ~vif0Regs->mask);
|
||||
}
|
||||
|
||||
Freeze( g_vif0HasMask3 );
|
||||
Freeze( g_vif0Masks );
|
||||
Freeze( g_vifRow0 );
|
||||
Freeze( g_vifCol0 );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1856,15 +1850,14 @@ int VIF1transfer(u32 *data, int size, int istag) {
|
|||
transferred += size - vif1.vifpacketsize;
|
||||
g_vifCycles+= (transferred>>2)*BIAS; /* guessing */
|
||||
|
||||
vif1.irqoffset = transferred%4; // cannot lose the offset
|
||||
|
||||
if (vif1.irq && vif1.cmd == 0) {
|
||||
vif1.vifstalled = 1;
|
||||
|
||||
|
||||
|
||||
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
|
||||
vif1.irqoffset = transferred%4; // cannot lose the offset
|
||||
|
||||
if( istag ) {
|
||||
return -2;
|
||||
|
@ -1873,6 +1866,7 @@ int VIF1transfer(u32 *data, int size, int istag) {
|
|||
transferred = transferred >> 2;
|
||||
vif1ch->madr+= (transferred << 4);
|
||||
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));
|
||||
return -2;
|
||||
}
|
||||
|
@ -1885,198 +1879,13 @@ int VIF1transfer(u32 *data, int size, int istag) {
|
|||
transferred = transferred >> 2;
|
||||
vif1ch->madr+= (transferred << 4);
|
||||
vif1ch->qwc-= transferred;
|
||||
if(vif1ch->qwc == 0 && vif1.irqoffset == 0) vif1.inprogress = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _VIF1chain() {
|
||||
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 {
|
||||
|
||||
void vif1TransferFromMemory(){
|
||||
int size;
|
||||
u64* pMem = (u64*)dmaGetAddr(vif1ch->madr);
|
||||
|
||||
|
@ -2122,11 +1931,279 @@ void dmaVIF1()
|
|||
g_vifCycles += vif1ch->qwc * 2;
|
||||
vif1ch->madr += vif1ch->qwc * 16; // mgs3 scene changes
|
||||
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;
|
||||
}
|
||||
vif1.done = 1;
|
||||
else if(vif1ch->qwc > 0 || vif1.irqoffset > 0)
|
||||
{
|
||||
if(vif1.stallontag == 1)
|
||||
{
|
||||
vif1SetupTransfer();
|
||||
}
|
||||
else _VIF1chain();//CPU_INT(13, vif1ch->qwc * BIAS);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
#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
|
||||
vif1.done = 0;
|
||||
|
@ -2154,6 +2231,7 @@ void vif1Write32(u32 mem, u32 value) {
|
|||
psHu64(0x10005008) = 0;
|
||||
vif1.done = 1;
|
||||
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
|
||||
}
|
||||
if (value & 0x2) {
|
||||
|
@ -2192,15 +2270,18 @@ void vif1Write32(u32 mem, u32 value) {
|
|||
g_vifCycles = 0;
|
||||
// loop necessary for spiderman
|
||||
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;
|
||||
}
|
||||
|
@ -2270,16 +2351,8 @@ void SaveState::vif1Freeze()
|
|||
{
|
||||
Freeze(vif1);
|
||||
|
||||
if( GetVersion() >= 0x04 )
|
||||
{
|
||||
Freeze( g_vif1HasMask3 );
|
||||
Freeze( g_vif1Masks );
|
||||
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;
|
||||
}
|
||||
Freeze( g_vif1HasMask3 );
|
||||
Freeze( g_vif1Masks );
|
||||
Freeze( g_vifRow1 );
|
||||
Freeze( g_vifCol1 );
|
||||
}
|
||||
|
|
|
@ -40,6 +40,8 @@ struct vifStruct {
|
|||
u8 irqoffset; // 32bit offset where next vif code is
|
||||
u32 savedtag; // need this for backwards compat with save states
|
||||
u32 vifpacketsize;
|
||||
u8 inprogress;
|
||||
u8 dmamode;
|
||||
};
|
||||
|
||||
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';
|
||||
else
|
||||
{
|
||||
while (num != 0)
|
||||
if( base == 16 )
|
||||
{
|
||||
tmp[i++] = dig[num % (uint) base];
|
||||
num = num / (uint) base;
|
||||
while (num != 0)
|
||||
{
|
||||
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 (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)
|
||||
|
@ -451,7 +468,7 @@ static void flt( std::string& dest, double num, int size, int precision, char fm
|
|||
{
|
||||
char tmp[80];
|
||||
char c, sign;
|
||||
int n, i;
|
||||
int n;
|
||||
|
||||
// Left align means no zero padding
|
||||
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
|
||||
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 (!(flags & LEFT)) while (size-- > 0) dest += c;
|
||||
for (i = 0; i < n; i++) dest += tmp[i];
|
||||
while (size-- > 0) dest += ' ';
|
||||
if (!(flags & LEFT) && size > 0) { dest.append( size, c ); size = 0; }
|
||||
dest.append( tmp, n );
|
||||
if(size > 0) dest.append( size, ' ' );
|
||||
}
|
||||
|
||||
#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 qualifier; // 'h', 'l', or 'L' for integer fields
|
||||
|
||||
// Optimization: Memory is cheap. Allocating it on the fly is not. Allocate more room
|
||||
// than we'll likely need right upfront!
|
||||
dest.reserve( strlen( format ) * 2 );
|
||||
|
||||
for( const char* fmt = format; *fmt; fmt++ )
|
||||
for( const char* fmt = format; *fmt; ++fmt )
|
||||
{
|
||||
if (*fmt != '%')
|
||||
{
|
||||
|
@ -607,16 +621,26 @@ repeat:
|
|||
if( precision < 0 )
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
else
|
||||
{
|
||||
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 );
|
||||
}
|
||||
while (len < field_width--) dest += ' ';
|
||||
|
||||
if( len < field_width )
|
||||
dest.append( field_width - len, ' ' );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -736,7 +760,12 @@ repeat:
|
|||
|
||||
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.reserve( 96 );
|
||||
vssappendf( dest, format, args );
|
||||
}
|
||||
|
||||
|
@ -807,6 +836,5 @@ std::string vfmt_string( const char* fmt, va_list args )
|
|||
|
||||
std::string retval;
|
||||
vssprintf( retval, fmt, args );
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
|
|
@ -50,13 +50,7 @@ using namespace vtlb_private;
|
|||
|
||||
namespace vtlb_private
|
||||
{
|
||||
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 pages of memory!
|
||||
void* RWFT[5][2][128];
|
||||
PCSX2_ALIGNED( 64, MapData vtlbdata );
|
||||
}
|
||||
|
||||
vtlbHandler vtlbHandlerCount=0;
|
||||
|
@ -97,11 +91,11 @@ callfunction:
|
|||
// Interpreter Implementations of VTLB Memory Operations.
|
||||
// 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>
|
||||
__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;
|
||||
|
||||
if (!(ppf<0))
|
||||
|
@ -111,13 +105,13 @@ __forceinline DataType __fastcall MemOp_r0(u32 addr)
|
|||
u32 hand=(u8)vmv;
|
||||
u32 paddr=ppf-hand+0x80000000;
|
||||
//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 )
|
||||
{
|
||||
case 8: return ((vtlbMemR8FP*)RWFT[0][0][hand])(paddr);
|
||||
case 16: return ((vtlbMemR16FP*)RWFT[1][0][hand])(paddr);
|
||||
case 32: return ((vtlbMemR32FP*)RWFT[2][0][hand])(paddr);
|
||||
case 8: return ((vtlbMemR8FP*)vtlbdata.RWFT[0][0][hand])(paddr);
|
||||
case 16: return ((vtlbMemR16FP*)vtlbdata.RWFT[1][0][hand])(paddr);
|
||||
case 32: return ((vtlbMemR32FP*)vtlbdata.RWFT[2][0][hand])(paddr);
|
||||
|
||||
jNO_DEFAULT;
|
||||
}
|
||||
|
@ -127,7 +121,7 @@ __forceinline DataType __fastcall MemOp_r0(u32 addr)
|
|||
template<int DataSize,typename DataType>
|
||||
__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;
|
||||
|
||||
if (!(ppf<0))
|
||||
|
@ -146,8 +140,8 @@ __forceinline void __fastcall MemOp_r1(u32 addr, DataType* data)
|
|||
|
||||
switch( DataSize )
|
||||
{
|
||||
case 64: ((vtlbMemR64FP*)RWFT[3][0][hand])(paddr, data); break;
|
||||
case 128: ((vtlbMemR128FP*)RWFT[4][0][hand])(paddr, data); break;
|
||||
case 64: ((vtlbMemR64FP*)vtlbdata.RWFT[3][0][hand])(paddr, data); break;
|
||||
case 128: ((vtlbMemR128FP*)vtlbdata.RWFT[4][0][hand])(paddr, data); break;
|
||||
|
||||
jNO_DEFAULT;
|
||||
}
|
||||
|
@ -157,7 +151,7 @@ __forceinline void __fastcall MemOp_r1(u32 addr, DataType* data)
|
|||
template<int DataSize,typename DataType>
|
||||
__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;
|
||||
if (!(ppf<0))
|
||||
{
|
||||
|
@ -172,9 +166,9 @@ __forceinline void __fastcall MemOp_w0(u32 addr, DataType data)
|
|||
|
||||
switch( DataSize )
|
||||
{
|
||||
case 8: return ((vtlbMemW8FP*)RWFT[0][1][hand])(paddr, (u8)data);
|
||||
case 16: return ((vtlbMemW16FP*)RWFT[1][1][hand])(paddr, (u16)data);
|
||||
case 32: return ((vtlbMemW32FP*)RWFT[2][1][hand])(paddr, (u32)data);
|
||||
case 8: return ((vtlbMemW8FP*)vtlbdata.RWFT[0][1][hand])(paddr, (u8)data);
|
||||
case 16: return ((vtlbMemW16FP*)vtlbdata.RWFT[1][1][hand])(paddr, (u16)data);
|
||||
case 32: return ((vtlbMemW32FP*)vtlbdata.RWFT[2][1][hand])(paddr, (u32)data);
|
||||
|
||||
jNO_DEFAULT;
|
||||
}
|
||||
|
@ -184,7 +178,7 @@ template<int DataSize,typename DataType>
|
|||
__forceinline void __fastcall MemOp_w1(u32 addr,const DataType* data)
|
||||
{
|
||||
verify(DataSize==128 || DataSize==64);
|
||||
u32 vmv=vmap[addr>>VTLB_PAGE_BITS];
|
||||
u32 vmv=vtlbdata.vmap[addr>>VTLB_PAGE_BITS];
|
||||
s32 ppf=addr+vmv;
|
||||
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);
|
||||
switch( DataSize )
|
||||
{
|
||||
case 64: return ((vtlbMemW64FP*)RWFT[3][1][hand])(paddr, data);
|
||||
case 128: return ((vtlbMemW128FP*)RWFT[4][1][hand])(paddr, data);
|
||||
case 64: return ((vtlbMemW64FP*)vtlbdata.RWFT[3][1][hand])(paddr, data);
|
||||
case 128: return ((vtlbMemW128FP*)vtlbdata.RWFT[4][1][hand])(paddr, data);
|
||||
|
||||
jNO_DEFAULT;
|
||||
}
|
||||
|
@ -352,17 +346,17 @@ vtlbHandler vtlb_RegisterHandler( vtlbMemR8FP* r8,vtlbMemR16FP* r16,vtlbMemR32FP
|
|||
//write the code :p
|
||||
vtlbHandler rv=vtlbHandlerCount++;
|
||||
|
||||
RWFT[0][0][rv] = (r8!=0) ? r8:vtlbDefaultPhyRead8;
|
||||
RWFT[1][0][rv] = (r16!=0) ? r16:vtlbDefaultPhyRead16;
|
||||
RWFT[2][0][rv] = (r32!=0) ? r32:vtlbDefaultPhyRead32;
|
||||
RWFT[3][0][rv] = (r64!=0) ? r64:vtlbDefaultPhyRead64;
|
||||
RWFT[4][0][rv] = (r128!=0) ? r128:vtlbDefaultPhyRead128;
|
||||
vtlbdata.RWFT[0][0][rv] = (r8!=0) ? r8:vtlbDefaultPhyRead8;
|
||||
vtlbdata.RWFT[1][0][rv] = (r16!=0) ? r16:vtlbDefaultPhyRead16;
|
||||
vtlbdata.RWFT[2][0][rv] = (r32!=0) ? r32:vtlbDefaultPhyRead32;
|
||||
vtlbdata.RWFT[3][0][rv] = (r64!=0) ? r64:vtlbDefaultPhyRead64;
|
||||
vtlbdata.RWFT[4][0][rv] = (r128!=0) ? r128:vtlbDefaultPhyRead128;
|
||||
|
||||
RWFT[0][1][rv] = (w8!=0) ? w8:vtlbDefaultPhyWrite8;
|
||||
RWFT[1][1][rv] = (w16!=0) ? w16:vtlbDefaultPhyWrite16;
|
||||
RWFT[2][1][rv] = (w32!=0) ? w32:vtlbDefaultPhyWrite32;
|
||||
RWFT[3][1][rv] = (w64!=0) ? w64:vtlbDefaultPhyWrite64;
|
||||
RWFT[4][1][rv] = (w128!=0) ? w128:vtlbDefaultPhyWrite128;
|
||||
vtlbdata.RWFT[0][1][rv] = (w8!=0) ? w8:vtlbDefaultPhyWrite8;
|
||||
vtlbdata.RWFT[1][1][rv] = (w16!=0) ? w16:vtlbDefaultPhyWrite16;
|
||||
vtlbdata.RWFT[2][1][rv] = (w32!=0) ? w32:vtlbDefaultPhyWrite32;
|
||||
vtlbdata.RWFT[3][1][rv] = (w64!=0) ? w64:vtlbDefaultPhyWrite64;
|
||||
vtlbdata.RWFT[4][1][rv] = (w128!=0) ? w128:vtlbDefaultPhyWrite128;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
@ -382,7 +376,7 @@ void vtlb_MapHandler(vtlbHandler handler,u32 start,u32 size)
|
|||
|
||||
while(size>0)
|
||||
{
|
||||
pmap[start>>VTLB_PAGE_BITS]=value;
|
||||
vtlbdata.pmap[start>>VTLB_PAGE_BITS]=value;
|
||||
|
||||
start+=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)
|
||||
{
|
||||
pmap[start>>VTLB_PAGE_BITS]=ptr;
|
||||
vtlbdata.pmap[start>>VTLB_PAGE_BITS]=ptr;
|
||||
|
||||
start+=VTLB_PAGE_SIZE;
|
||||
ptr+=VTLB_PAGE_SIZE;
|
||||
|
@ -425,7 +419,7 @@ void vtlb_Mirror(u32 new_region,u32 start,u32 size)
|
|||
|
||||
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;
|
||||
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)
|
||||
{
|
||||
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;
|
||||
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
|
||||
|
@ -462,11 +456,11 @@ void vtlb_VMap(u32 vaddr,u32 paddr,u32 sz)
|
|||
}
|
||||
else
|
||||
{
|
||||
pme=pmap[paddr>>VTLB_PAGE_BITS];
|
||||
pme=vtlbdata.pmap[paddr>>VTLB_PAGE_BITS];
|
||||
if (pme<0)
|
||||
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;
|
||||
paddr+=VTLB_PAGE_SIZE;
|
||||
sz-=VTLB_PAGE_SIZE;
|
||||
|
@ -480,7 +474,7 @@ void vtlb_VMapBuffer(u32 vaddr,void* buffer,u32 sz)
|
|||
u32 bu8=(u32)buffer;
|
||||
while(sz>0)
|
||||
{
|
||||
vmap[vaddr>>VTLB_PAGE_BITS]=bu8-vaddr;
|
||||
vtlbdata.vmap[vaddr>>VTLB_PAGE_BITS]=bu8-vaddr;
|
||||
vaddr+=VTLB_PAGE_SIZE;
|
||||
bu8+=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|=0x80000000;
|
||||
vmap[vaddr>>VTLB_PAGE_BITS]=handl-vaddr;
|
||||
vtlbdata.vmap[vaddr>>VTLB_PAGE_BITS]=handl-vaddr;
|
||||
vaddr+=VTLB_PAGE_SIZE;
|
||||
sz-=VTLB_PAGE_SIZE;
|
||||
}
|
||||
|
@ -510,7 +504,7 @@ void vtlb_VMapUnmap(u32 vaddr,u32 sz)
|
|||
void vtlb_Init()
|
||||
{
|
||||
vtlbHandlerCount=0;
|
||||
memzero_obj(RWFT);
|
||||
memzero_obj(vtlbdata.RWFT);
|
||||
|
||||
//Register default handlers
|
||||
//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_VMAP_ITEMS = 0x100000000ULL / VTLB_PAGE_SIZE;
|
||||
|
||||
extern void* RWFT[5][2][128];
|
||||
extern s32 pmap[VTLB_PMAP_ITEMS]; //512KB
|
||||
extern s32 vmap[VTLB_VMAP_ITEMS]; //4MB
|
||||
struct MapData
|
||||
{
|
||||
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
|
||||
|
|
|
@ -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 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);
|
||||
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);
|
||||
|
@ -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_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_CLAMPMODE1) ? 0x1 : 0;
|
||||
new_vuopt |= IsDlgButtonChecked(hDlg, IDC_VU_CLAMPMODE2) ? 0x3 : 0;
|
||||
|
|
|
@ -106,7 +106,7 @@
|
|||
UseOfMFC="0"
|
||||
ATLMinimizesCRunTimeLibraryUsage="false"
|
||||
CharacterSet="2"
|
||||
WholeProgramOptimization="1"
|
||||
WholeProgramOptimization="0"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
|
@ -134,6 +134,9 @@
|
|||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="3"
|
||||
InlineFunctionExpansion="0"
|
||||
FavorSizeOrSpeed="1"
|
||||
WholeProgramOptimization="false"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions="NDEBUG"
|
||||
StringPooling="true"
|
||||
|
@ -161,6 +164,7 @@
|
|||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="zlib.lib"
|
||||
OutputFile="$(OutDir)\$(ProjectName)-dev.exe"
|
||||
LinkIncremental="2"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
|
@ -2908,6 +2912,14 @@
|
|||
RelativePath="..\..\NewGUI\frmGameFixes.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\NewGUI\frmLogging.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\NewGUI\frmLogging.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\NewGUI\frmMain.cpp"
|
||||
>
|
||||
|
|
|
@ -529,7 +529,7 @@ BOOL APIENTRY GameFixes(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
|||
case WM_INITDIALOG:
|
||||
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 & 0x2) CheckDlgButton(hDlg, IDC_GAMEFIX4, TRUE);//GoW fix
|
||||
if(Config.GameFixes & 0x8) CheckDlgButton(hDlg, IDC_GAMEFIX5, TRUE);//Tales of Destiny fix
|
||||
return TRUE;
|
||||
|
||||
case WM_COMMAND:
|
||||
|
@ -538,7 +538,7 @@ BOOL APIENTRY GameFixes(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
|||
uint newfixes = 0;
|
||||
newfixes |= IsDlgButtonChecked(hDlg, IDC_GAMEFIX2) ? 0x1 : 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);
|
||||
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
#include "Win32.h"
|
||||
|
||||
#include "System.h"
|
||||
#include "Threading.h"
|
||||
#include "ix86/ix86_types.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
|
@ -110,7 +109,7 @@ namespace Threading
|
|||
|
||||
__forceinline long pcsx2_InterlockedExchangeAdd( volatile long* target, long srcval )
|
||||
{
|
||||
long result;
|
||||
//long result;
|
||||
|
||||
// Use our own implementation...
|
||||
// Pcsx2 won't use threads unless it's a multicore cpu, so no need to use
|
||||
|
@ -120,30 +119,26 @@ namespace Threading
|
|||
{
|
||||
__asm
|
||||
{
|
||||
//PUSH ecx
|
||||
mov ecx,dword ptr [target]
|
||||
mov eax,dword ptr [srcval]
|
||||
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
|
||||
{
|
||||
__asm
|
||||
{
|
||||
//PUSH ecx
|
||||
//PUSH edx
|
||||
mov ecx,dword ptr [target]
|
||||
//L1:
|
||||
mov eax,dword ptr [srcval]
|
||||
xadd dword ptr [ecx],eax
|
||||
//jnz L1
|
||||
mov dword ptr [result], eax
|
||||
//POP edx
|
||||
//POP ecx
|
||||
|
||||
// msvc smartly returns eax for us without so much as a compiler warning even...
|
||||
//mov dword ptr [result], eax
|
||||
}
|
||||
}
|
||||
return result;
|
||||
// return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -74,21 +74,21 @@ LANGUAGE LANG_GERMAN, SUBLANG_GERMAN
|
|||
// 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
|
||||
CAPTION "Game Special Fixes"
|
||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||
BEGIN
|
||||
DEFPUSHBUTTON "OK",IDOK,85,91,50,14
|
||||
PUSHBUTTON "Cancel",IDCANCEL,139,91,50,14
|
||||
CTEXT "Some games need special settings.\nConfigure them here.",IDC_STATIC,7,7,264,17
|
||||
GROUPBOX "PCSX2 Gamefixes",IDC_STATIC,7,31,264,89
|
||||
DEFPUSHBUTTON "OK",IDOK,87,89,50,14
|
||||
PUSHBUTTON "Cancel",IDCANCEL,142,89,50,14
|
||||
CTEXT "Some games need special settings.\nConfigure them here.",IDC_STATIC,7,7,265,17
|
||||
GROUPBOX "PCSX2 Gamefixes",IDC_STATIC,7,28,265,83
|
||||
CONTROL "FPU Compare Hack - Special fix for Digimon Rumble Arena 2.",IDC_GAMEFIX3,
|
||||
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,47,249,10
|
||||
CONTROL "VU Add / Sub Hack - Special fix for Tri-Ace games!",IDC_GAMEFIX2,
|
||||
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,61,252,10
|
||||
CONTROL "VU Clip Hack - Special fix for God of War",IDC_GAMEFIX4,
|
||||
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,75,144,10
|
||||
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,43,249,10
|
||||
CONTROL "VU Add Hack - Special fix for Tri-Ace games!",IDC_GAMEFIX2,
|
||||
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,72,252,10
|
||||
CONTROL "FPU Mul Hack - Special fix for Tales of Destiny (possibly other games).",IDC_GAMEFIX5,
|
||||
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,57,249,10
|
||||
END
|
||||
|
||||
|
||||
|
@ -103,10 +103,11 @@ BEGIN
|
|||
IDD_GAMEFIXES, DIALOG
|
||||
BEGIN
|
||||
LEFTMARGIN, 7
|
||||
RIGHTMARGIN, 271
|
||||
VERTGUIDE, 12
|
||||
RIGHTMARGIN, 272
|
||||
VERTGUIDE, 14
|
||||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 120
|
||||
BOTTOMMARGIN, 111
|
||||
HORZGUIDE, 103
|
||||
END
|
||||
END
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
@ -195,31 +196,30 @@ BEGIN
|
|||
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 " 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 " Denormals are Zero",IDC_VU_CHECK2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,111,232,81,13
|
||||
RADIOBUTTON "Nearest",IDC_VU_ROUNDMODE0,20,172,44,12
|
||||
RADIOBUTTON "Negative",IDC_VU_ROUNDMODE1,64,172,47,12
|
||||
RADIOBUTTON "Positive",IDC_VU_ROUNDMODE2,111,172,45,12
|
||||
RADIOBUTTON "Chop / Zero",IDC_VU_ROUNDMODE3,156,172,52,12
|
||||
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,217,81,13
|
||||
RADIOBUTTON "Nearest",IDC_VU_ROUNDMODE0,20,157,44,12
|
||||
RADIOBUTTON "Negative",IDC_VU_ROUNDMODE1,64,157,47,12
|
||||
RADIOBUTTON "Positive",IDC_VU_ROUNDMODE2,111,157,45,12
|
||||
RADIOBUTTON "Chop / Zero",IDC_VU_ROUNDMODE3,156,157,52,12
|
||||
PUSHBUTTON "Defaults",IDDEFAULT,346,254,50,14
|
||||
GROUPBOX "VU Recs Options",IDC_STATIC,7,146,250,122,BS_CENTER
|
||||
GROUPBOX "EE Recs Options",IDC_STATIC,7,12,250,129,BS_CENTER
|
||||
GROUPBOX "Round Mode",IDC_STATIC,11,159,236,32
|
||||
GROUPBOX "VU Recs Options",IDC_STATIC,7,133,250,118,BS_CENTER
|
||||
GROUPBOX "EE Recs Options",IDC_STATIC,7,12,250,113,BS_CENTER
|
||||
GROUPBOX "Round Mode",IDC_STATIC,11,144,236,32
|
||||
GROUPBOX "Round Mode",IDC_STATIC,11,26,236,36
|
||||
GROUPBOX "Help",IDC_STATIC,271,12,251,238,BS_CENTER
|
||||
GROUPBOX "Clamp Mode",IDC_STATIC,11,196,236,31
|
||||
RADIOBUTTON "None",IDC_VU_CLAMPMODE0,20,207,44,12
|
||||
RADIOBUTTON "Normal",IDC_VU_CLAMPMODE1,64,207,47,12
|
||||
RADIOBUTTON "Extra",IDC_VU_CLAMPMODE2,111,207,45,12
|
||||
RADIOBUTTON "Extra + Preserve Sign",IDC_VU_CLAMPMODE3,156,207,85,12
|
||||
CONTROL " Set O and U Flags",IDC_VU_CHECK3,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,20,250,91,13
|
||||
CONTROL " Software Emulate DaZ",IDC_VU_CHECK4,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,111,250,116,13
|
||||
GROUPBOX "Help",IDC_STATIC,271,12,251,239,BS_CENTER
|
||||
GROUPBOX "Clamp Mode",IDC_STATIC,11,181,236,31
|
||||
RADIOBUTTON "None",IDC_VU_CLAMPMODE0,20,192,44,12
|
||||
RADIOBUTTON "Normal",IDC_VU_CLAMPMODE1,64,192,47,12
|
||||
RADIOBUTTON "Extra",IDC_VU_CLAMPMODE2,111,192,45,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,235,91,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
|
||||
RADIOBUTTON "None",IDC_EE_CLAMPMODE0,20,76,44,16
|
||||
RADIOBUTTON "Normal",IDC_EE_CLAMPMODE1,64,76,47,16
|
||||
RADIOBUTTON "Extra + Preserve Sign",IDC_EE_CLAMPMODE2,111,76,91,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
|
||||
GROUPBOX "Round Mode",IDC_STATIC,281,22,235,51,BS_LEFT
|
||||
GROUPBOX "Clamp Mode",IDC_STATIC,281,80,236,127,BS_LEFT
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
#include "PrecompiledHeader.h"
|
||||
#include "BaseblockEx.h"
|
||||
|
||||
BASEBLOCKEX* BaseBlocks::New(u32 startpc)
|
||||
BASEBLOCKEX* BaseBlocks::New(u32 startpc, uptr fnptr)
|
||||
{
|
||||
if (blocks.size() == size)
|
||||
return 0;
|
||||
|
@ -28,6 +28,7 @@ BASEBLOCKEX* BaseBlocks::New(u32 startpc)
|
|||
std::vector<BASEBLOCKEX>::iterator iter;
|
||||
memset(&newblock, 0, sizeof newblock);
|
||||
newblock.startpc = startpc;
|
||||
newblock.fnptr = fnptr;
|
||||
|
||||
int imin = 0, imax = blocks.size(), imid;
|
||||
|
||||
|
@ -42,10 +43,15 @@ BASEBLOCKEX* BaseBlocks::New(u32 startpc)
|
|||
|
||||
assert(imin == blocks.size() || blocks[imin].startpc > startpc);
|
||||
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;
|
||||
}
|
||||
|
||||
int BaseBlocks::Index(u32 startpc) const
|
||||
int BaseBlocks::LastIndex(u32 startpc) const
|
||||
{
|
||||
if (0 == blocks.size())
|
||||
return -1;
|
||||
|
@ -61,9 +67,21 @@ int BaseBlocks::Index(u32 startpc) const
|
|||
imin = imid;
|
||||
}
|
||||
|
||||
if (startpc < blocks[imin].startpc ||
|
||||
startpc >= blocks[imin].startpc + blocks[imin].size*4)
|
||||
return -1;
|
||||
else
|
||||
return imin;
|
||||
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 <vector>
|
||||
#include <map>
|
||||
#include <utility>
|
||||
|
||||
// used to keep block information
|
||||
#define BLOCKTYPE_DELAYSLOT 1 // if bit set, delay slot
|
||||
|
@ -38,9 +40,10 @@ struct BASEBLOCK
|
|||
// extra block info (only valid for start of fn)
|
||||
struct BASEBLOCKEX
|
||||
{
|
||||
u16 size; // size in dwords
|
||||
u16 dummy;
|
||||
u32 startpc;
|
||||
uptr fnptr;
|
||||
u16 size; // size in dwords
|
||||
u16 x86size;
|
||||
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
u32 visited; // number of times called
|
||||
|
@ -53,18 +56,34 @@ class BaseBlocks
|
|||
{
|
||||
private:
|
||||
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;
|
||||
uptr recompiler;
|
||||
|
||||
public:
|
||||
BaseBlocks(unsigned long max) :
|
||||
size(max),
|
||||
BaseBlocks(unsigned long size_, uptr recompiler_) :
|
||||
size(size_),
|
||||
recompiler(recompiler_),
|
||||
blocks(0)
|
||||
{
|
||||
blocks.reserve(size);
|
||||
}
|
||||
|
||||
BASEBLOCKEX* New(u32 startpc);
|
||||
int Index (u32 startpc) const;
|
||||
BASEBLOCKEX* New(u32 startpc, uptr fnptr);
|
||||
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)
|
||||
{
|
||||
|
@ -80,12 +99,20 @@ public:
|
|||
|
||||
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);
|
||||
}
|
||||
|
||||
void Link(u32 pc, uptr jumpptr);
|
||||
|
||||
inline void Reset()
|
||||
{
|
||||
blocks.clear();
|
||||
links.clear();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -18,11 +18,6 @@
|
|||
.extern RECLUT
|
||||
.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
|
||||
// dispatches to the recompiled block address.
|
||||
|
@ -43,87 +38,6 @@ iopJITCompileInBlock:
|
|||
|
||||
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.
|
||||
|
||||
|
|
|
@ -165,8 +165,12 @@ void recMFC0( void )
|
|||
break;
|
||||
|
||||
case 1:
|
||||
CALLFunc( (uptr)COP0_UpdatePCCR );
|
||||
MOV32MtoR(EAX, (uptr)&cpuRegs.PERF.n.pcr0);
|
||||
break;
|
||||
case 3:
|
||||
CALLFunc( (uptr)COP0_UpdatePCCR );
|
||||
MOV32MtoR(EAX, (uptr)&cpuRegs.PERF.n.pcr1);
|
||||
break;
|
||||
}
|
||||
_deleteEEreg(_Rt_, 0);
|
||||
|
|
|
@ -592,7 +592,7 @@ void FPU_SUB(int regd, int regt) {
|
|||
// FPU_MUL (Used to approximate PS2's FPU mul behavior)
|
||||
//------------------------------------------------------------------
|
||||
// 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.
|
||||
// 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)
|
||||
{
|
||||
if (CHECK_FPU_ATTEMPT_MUL)
|
||||
if (CHECK_FPUMULHACK)
|
||||
{
|
||||
SSE2_MOVD_XMM_to_R(ECX, regd);
|
||||
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)
|
||||
{
|
||||
if (CHECK_FPU_ATTEMPT_MUL)
|
||||
if (CHECK_FPUMULHACK)
|
||||
{
|
||||
SSE2_MOVD_XMM_to_R(ECX, sreg);
|
||||
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 *recROM = NULL; // and 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;
|
||||
u32 psxpc; // recompiler psxpc
|
||||
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_ConstGPRreg;
|
||||
static u32 s_saveConstGPRreg = 0, s_saveHasConstReg = 0, s_saveFlushedConstReg = 0;
|
||||
static u32 s_saveConstRegs[32];
|
||||
static u32 s_saveHasConstReg = 0, s_saveFlushedConstReg = 0;
|
||||
static EEINST* s_psaveInstInfo = NULL;
|
||||
|
||||
u32 s_psxBlockCycles = 0; // cycles of current block recompiling
|
||||
|
@ -334,7 +335,7 @@ void _psxFlushCall(int flushtype)
|
|||
void psxSaveBranchState()
|
||||
{
|
||||
s_savenBlockCycles = s_psxBlockCycles;
|
||||
s_saveConstGPRreg = 0xffffffff; // indicate searching
|
||||
memcpy(s_saveConstRegs, g_psxConstRegs, sizeof(g_psxConstRegs));
|
||||
s_saveHasConstReg = g_psxHasConstReg;
|
||||
s_saveFlushedConstReg = g_psxFlushedConstReg;
|
||||
s_psaveInstInfo = g_pCurInstInfo;
|
||||
|
@ -347,18 +348,7 @@ void psxLoadBranchState()
|
|||
{
|
||||
s_psxBlockCycles = s_savenBlockCycles;
|
||||
|
||||
if( s_saveConstGPRreg != 0xffffffff ) {
|
||||
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;
|
||||
}
|
||||
|
||||
memcpy(g_psxConstRegs, s_saveConstRegs, sizeof(g_psxConstRegs));
|
||||
g_psxHasConstReg = s_saveHasConstReg;
|
||||
g_psxFlushedConstReg = s_saveFlushedConstReg;
|
||||
g_pCurInstInfo = s_psaveInstInfo;
|
||||
|
@ -371,23 +361,8 @@ void psxLoadBranchState()
|
|||
// 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)
|
||||
{
|
||||
PSX_CHECK_SAVE_REG(reg);
|
||||
PSX_DEL_CONST(reg);
|
||||
}
|
||||
|
||||
|
@ -397,7 +372,6 @@ void psxRecompileCodeConst0(R3000AFNPTR constcode, R3000AFNPTR_INFO constscode,
|
|||
if ( ! _Rd_ ) return;
|
||||
|
||||
// for now, don't support xmm
|
||||
PSX_CHECK_SAVE_REG(_Rd_);
|
||||
|
||||
_deleteX86reg(X86TYPE_PSX, _Rs_, 1);
|
||||
_deleteX86reg(X86TYPE_PSX, _Rt_, 1);
|
||||
|
@ -447,7 +421,6 @@ void psxRecompileCodeConst1(R3000AFNPTR constcode, R3000AFNPTR_INFO noconstcode)
|
|||
}
|
||||
|
||||
// for now, don't support xmm
|
||||
PSX_CHECK_SAVE_REG(_Rt_);
|
||||
|
||||
_deleteX86reg(X86TYPE_PSX, _Rs_, 1);
|
||||
_deleteX86reg(X86TYPE_PSX, _Rt_, 0);
|
||||
|
@ -468,7 +441,6 @@ void psxRecompileCodeConst2(R3000AFNPTR constcode, R3000AFNPTR_INFO noconstcode)
|
|||
if ( ! _Rd_ ) return;
|
||||
|
||||
// for now, don't support xmm
|
||||
PSX_CHECK_SAVE_REG(_Rd_);
|
||||
|
||||
_deleteX86reg(X86TYPE_PSX, _Rt_, 1);
|
||||
_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
|
||||
static __declspec(naked) void iopDispatcherReg()
|
||||
{
|
||||
|
@ -822,28 +723,6 @@ static __forceinline u32 psxRecClearMem(u32 pc)
|
|||
if (pexblock->startpc >= upperextent)
|
||||
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);
|
||||
upperextent = max(upperextent, pexblock->startpc + pexblock->size * 4);
|
||||
recBlocks.Remove(blockidx);
|
||||
|
@ -907,9 +786,8 @@ void psxSetBranchImm( u32 imm )
|
|||
_psxFlushCall(FLUSH_EVERYTHING);
|
||||
iPsxBranchTest(imm, imm <= psxpc);
|
||||
|
||||
MOV32ItoR(EDX, 0);
|
||||
ptr = (u32*)(x86Ptr[0]-4);
|
||||
*ptr = (uptr)JMP32((uptr)iopDispatcher - ( (uptr)x86Ptr[0] + 5 ));
|
||||
ptr = JMP32(0);
|
||||
recBlocks.Link(HWADDR(imm), (uptr)ptr);
|
||||
}
|
||||
|
||||
//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
|
||||
__asm mov pctemp, eax;
|
||||
#else
|
||||
__asm__("movl %%eax, %0" : : "m"(pctemp) );
|
||||
__asm__("movl %%eax, %[pctemp]" : : [pctemp]"m"(pctemp) );
|
||||
#endif
|
||||
SysPrintf("iop code changed! %x\n", pctemp);
|
||||
}
|
||||
|
@ -1018,24 +896,6 @@ void psxRecompileNextInstruction(int delayslot)
|
|||
|
||||
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
|
||||
MOV32ItoR(EAX, psxpc);
|
||||
#endif
|
||||
|
@ -1130,7 +990,6 @@ void iopRecRecompile(u32 startpc)
|
|||
u32 i;
|
||||
u32 branchTo;
|
||||
u32 willbranch3 = 0;
|
||||
u32* ptr;
|
||||
|
||||
#ifdef _DEBUG
|
||||
if( psxdump & 4 )
|
||||
|
@ -1143,6 +1002,10 @@ void iopRecRecompile(u32 startpc)
|
|||
if (((uptr)recPtr - (uptr)recMem) >= (RECMEM_SIZE - 0x10000))
|
||||
recResetIOP();
|
||||
|
||||
x86SetPtr( recPtr );
|
||||
x86Align(16);
|
||||
recPtr = x86Ptr[_EmitterId_];
|
||||
|
||||
s_pCurBlock = PSX_GETBLOCK(startpc);
|
||||
|
||||
assert(s_pCurBlock->GetFnptr() == (uptr)iopJITCompile
|
||||
|
@ -1150,19 +1013,16 @@ void iopRecRecompile(u32 startpc)
|
|||
|
||||
s_pCurBlockEx = recBlocks.Get(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 ) {
|
||||
DevCon::WriteLn("IOP Recompiler data reset");
|
||||
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;
|
||||
|
||||
s_pCurBlock->SetFnptr( (uptr)x86Ptr[0] );
|
||||
|
@ -1170,7 +1030,6 @@ void iopRecRecompile(u32 startpc)
|
|||
|
||||
// reset recomp state variables
|
||||
psxpc = startpc;
|
||||
s_saveConstGPRreg = 0;
|
||||
g_psxHasConstReg = g_psxFlushedConstReg = 1;
|
||||
|
||||
_initX86regs();
|
||||
|
@ -1304,7 +1163,6 @@ StartRecomp:
|
|||
JMP32((uptr)iopDispatcherReg - ( (uptr)x86Ptr[0] + 5 ));
|
||||
}
|
||||
else {
|
||||
assert( psxbranch != 3 );
|
||||
if( psxbranch ) assert( !willbranch3 );
|
||||
else
|
||||
{
|
||||
|
@ -1312,42 +1170,27 @@ StartRecomp:
|
|||
SUB32ItoM((uptr)&psxCycleEE, psxScaleBlockCycles()*8 );
|
||||
}
|
||||
|
||||
if( willbranch3 ) {
|
||||
BASEBLOCK* pblock = PSX_GETBLOCK(s_nEndBlock);
|
||||
if (willbranch3 || !psxbranch) {
|
||||
assert( psxpc == s_nEndBlock );
|
||||
_psxFlushCall(FLUSH_EVERYTHING);
|
||||
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;
|
||||
}
|
||||
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[_EmitterId_] - recPtr < 0x10000);
|
||||
s_pCurBlockEx->x86size = x86Ptr[_EmitterId_] - recPtr;
|
||||
|
||||
recPtr = x86Ptr[0];
|
||||
|
||||
assert( (g_psxHasConstReg&g_psxFlushedConstReg) == g_psxHasConstReg );
|
||||
|
||||
if( !psxbranch ) {
|
||||
assert( ptr != 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);
|
||||
}
|
||||
s_pCurBlock = NULL;
|
||||
s_pCurBlockEx = NULL;
|
||||
}
|
||||
|
||||
R3000Acpu psxRec = {
|
||||
|
|
|
@ -58,8 +58,6 @@ void _psxMoveGPRtoR(x86IntRegType to, int fromgpr);
|
|||
void _psxMoveGPRtoM(u32 to, int fromgpr);
|
||||
void _psxMoveGPRtoRm(x86IntRegType to, int fromgpr);
|
||||
|
||||
void PSX_CHECK_SAVE_REG(int reg);
|
||||
|
||||
extern u32 psxpc; // recompiler pc
|
||||
extern int psxbranch; // set for branch
|
||||
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 u32 target; // branch target
|
||||
extern u32 s_nBlockCycles; // cycles of current block recompiling
|
||||
extern u32 s_saveConstGPRreg;
|
||||
extern GPR_reg64 s_ConstGPRreg;
|
||||
|
||||
#define REC_FUNC( f ) \
|
||||
void rec##f( void ) \
|
||||
|
|
|
@ -3000,23 +3000,24 @@ void VuInstruction::Recompile(list<VuInstruction>::iterator& itinst, u32 vuxyz)
|
|||
if( type & INST_CLIP_WRITE ) {
|
||||
if( nParentPc < s_pCurBlock->startpc || nParentPc >= (int)pc ) {
|
||||
|
||||
if( !CHECK_VUCLIPFLAGHACK && pparentinst != NULL ) {
|
||||
|
||||
if( pparentinst->pClipWrite == 0 ) {
|
||||
pparentinst->pClipWrite = (uptr)SuperVUStaticAlloc(4);
|
||||
}
|
||||
if( pparentinst != NULL ) {
|
||||
|
||||
if( nParentCheckForExecution >= 0 ) {
|
||||
if( pparentinst->pClipWrite == 0 )
|
||||
pparentinst->pClipWrite = (uptr)SuperVUStaticAlloc(4);
|
||||
|
||||
if( s_ClipRead == 0 )
|
||||
s_ClipRead = (uptr)&VU->VI[REG_CLIP_FLAG];
|
||||
|
||||
CMP32ItoM((uptr)&g_nLastBlockExecuted, nParentCheckForExecution);
|
||||
u8* jptr = JNE8(0);
|
||||
CMP32ItoM((uptr)&s_ClipRead, (uptr)&VU->VI[REG_CLIP_FLAG]);
|
||||
u8* jptr2 = JE8(0);
|
||||
MOV32MtoR(EAX, pparentinst->pClipWrite);
|
||||
MOV32RtoM(s_ClipRead, EAX);
|
||||
x86SetJ8(jptr);
|
||||
x86SetJ8(jptr2);
|
||||
}
|
||||
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 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
|
||||
// dispatches to the recompiled block address.
|
||||
|
@ -42,87 +37,6 @@ JITCompile:
|
|||
JITCompileInBlock:
|
||||
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.
|
||||
|
||||
|
|
|
@ -139,17 +139,63 @@ void _flushConstReg(int reg)
|
|||
|
||||
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 0 and -1 first
|
||||
// ignore r0
|
||||
for(i = 1; i < 32; ++i) {
|
||||
if( g_cpuHasConstReg & (1<<i) ) {
|
||||
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] != 0)
|
||||
continue;
|
||||
if (eaxval != 0)
|
||||
XOR32RtoR(EAX, EAX), eaxval = 0;
|
||||
MOV32RtoM((uptr)&cpuRegs.GPR.r[i].SL[j], EAX);
|
||||
done[j] |= 1<<i;
|
||||
zero_cnt++;
|
||||
}
|
||||
|
||||
if( !(g_cpuFlushedConstReg&(1<<i)) ) {
|
||||
MOV32ItoM((uptr)&cpuRegs.GPR.r[i].UL[0], g_cpuConstRegs[i].UL[0]);
|
||||
MOV32ItoM((uptr)&cpuRegs.GPR.r[i].UL[1], g_cpuConstRegs[i].UL[1]);
|
||||
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;
|
||||
}
|
||||
#if defined(_DEBUG)&&0
|
||||
|
@ -171,8 +217,8 @@ void _flushConstRegs()
|
|||
x86SetJ8( ptemp[2] );
|
||||
}
|
||||
#else
|
||||
if( g_cpuHasConstReg == g_cpuFlushedConstReg )
|
||||
break;
|
||||
if( g_cpuHasConstReg == g_cpuFlushedConstReg )
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
|
@ -65,8 +65,6 @@ int branch; // set for branch
|
|||
|
||||
PCSX2_ALIGNED16(GPR_reg64 g_cpuConstRegs[32]) = {0};
|
||||
u32 g_cpuHasConstReg = 0, g_cpuFlushedConstReg = 0;
|
||||
u32 s_saveConstGPRreg = 0;
|
||||
GPR_reg64 s_ConstGPRreg;
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// 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 *recROM = NULL; // and 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 EEINST* s_pInstCache = NULL;
|
||||
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;
|
||||
|
||||
// save states for branches
|
||||
GPR_reg64 s_saveConstRegs[32];
|
||||
static u16 s_savex86FpuState, s_saveiCWstate;
|
||||
static u32 s_saveHasConstReg = 0, s_saveFlushedConstReg = 0, s_saveRegHasLive1 = 0, s_saveRegHasSignExt = 0;
|
||||
static EEINST* s_psaveInstInfo = NULL;
|
||||
|
@ -111,7 +112,7 @@ static u32 dumplog = 0;
|
|||
//static const char *txt2 = "M32 = %x\n";
|
||||
#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);
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
|
@ -446,7 +447,6 @@ u32* recAllocStackMem(int size, int align)
|
|||
return (u32*)(recStackPtr-size);
|
||||
}
|
||||
|
||||
|
||||
static const int REC_CACHEMEM = 0x01000000;
|
||||
static void __fastcall dyna_block_discard(u32 start,u32 sz);
|
||||
|
||||
|
@ -455,7 +455,7 @@ static u8* m_recBlockAlloc = NULL;
|
|||
|
||||
static const uint m_recBlockAllocSize =
|
||||
(((Ps2MemSize::Base + Ps2MemSize::Rom + Ps2MemSize::Rom1) / 4) * sizeof(BASEBLOCK))
|
||||
+ RECSTACK_SIZE; // recStack
|
||||
+ RECSTACK_SIZE + Ps2MemSize::Base;
|
||||
|
||||
static void recAlloc()
|
||||
{
|
||||
|
@ -497,7 +497,8 @@ static void recAlloc()
|
|||
recRAM = (BASEBLOCK*)curpos; curpos += (Ps2MemSize::Base / 4) * sizeof(BASEBLOCK);
|
||||
recROM = (BASEBLOCK*)curpos; curpos += (Ps2MemSize::Rom / 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 )
|
||||
{
|
||||
|
@ -599,6 +600,7 @@ static void recShutdown( void )
|
|||
safe_aligned_free( m_recBlockAlloc );
|
||||
recRAM = recROM = recROM1 = NULL;
|
||||
recStack = NULL;
|
||||
recRAMCopy = NULL;
|
||||
|
||||
safe_free( s_pInstCache );
|
||||
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
|
||||
static void __naked DispatcherReg()
|
||||
{
|
||||
|
@ -882,22 +811,6 @@ void recBREAK( void ) {
|
|||
|
||||
} } } // 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.
|
||||
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
|
||||
u32 recClearMem(u32 pc)
|
||||
void recClear(u32 addr, u32 size)
|
||||
{
|
||||
BASEBLOCKEX* pexblock;
|
||||
BASEBLOCK* pblock;
|
||||
|
@ -928,61 +841,61 @@ u32 recClearMem(u32 pc)
|
|||
#endif
|
||||
#endif
|
||||
|
||||
pblock = PC_GETBLOCK(pc);
|
||||
if (pblock->GetFnptr() == (uptr)JITCompile)
|
||||
return 4;
|
||||
if ((addr) >= maxrecmem || !(recLUT[(addr) >> 16] + (addr & ~0xFFFFUL)))
|
||||
return;
|
||||
addr = HWADDR(addr);
|
||||
|
||||
pc = HWADDR(pc);
|
||||
int blockidx = recBlocks.LastIndex(addr + size * 4 - 4);
|
||||
|
||||
u32 lowerextent = pc, upperextent = pc + 4;
|
||||
int blockidx = recBlocks.Index(pc);
|
||||
if (blockidx == -1)
|
||||
return;
|
||||
|
||||
jASSUME(blockidx != -1);
|
||||
u32 lowerextent = (u32)-1, upperextent = 0, ceiling = (u32)-1;
|
||||
|
||||
while (pexblock = recBlocks[blockidx - 1]) {
|
||||
if (pexblock->startpc + pexblock->size*4 <= lowerextent)
|
||||
break;
|
||||
|
||||
lowerextent = min(lowerextent, pexblock->startpc);
|
||||
blockidx--;
|
||||
}
|
||||
pexblock = recBlocks[blockidx + 1];
|
||||
if (pexblock)
|
||||
ceiling = pexblock->startpc;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
pblock = PC_GETBLOCK(pexblock->startpc);
|
||||
x86Ptr[_EmitterId_] = (u8*)pblock->GetFnptr();
|
||||
|
||||
jASSUME((u8*)JITCompile != x86Ptr[_EmitterId_]);
|
||||
jASSUME((u8*)JITCompileInBlock != x86Ptr[_EmitterId_]);
|
||||
|
||||
// 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);
|
||||
lowerextent = min(lowerextent, blockstart);
|
||||
upperextent = max(upperextent, blockend);
|
||||
// This might end up inside a block that doesn't contain the clearing range,
|
||||
// so set it to recompile now. This will become JITCompile if we clear it.
|
||||
pblock->SetFnptr((uptr)JITCompileInBlock);
|
||||
recBlocks.Remove(blockidx--);
|
||||
}
|
||||
|
||||
upperextent = min(upperextent, ceiling);
|
||||
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
for (int i = 0; pexblock = recBlocks[i]; i++)
|
||||
if (pc >= pexblock->startpc && pc < pexblock->startpc + pexblock->size * 4) {
|
||||
for (int i = 0; pexblock = recBlocks[i]; i++) {
|
||||
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");
|
||||
jASSUME(0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
ClearRecLUT(PC_GETBLOCK(lowerextent), (upperextent - lowerextent) / 4);
|
||||
|
||||
return upperextent - pc;
|
||||
if (upperextent > lowerextent)
|
||||
ClearRecLUT(PC_GETBLOCK(lowerextent), (upperextent - lowerextent) / 4);
|
||||
}
|
||||
|
||||
// check for end of bios
|
||||
|
@ -1055,7 +968,7 @@ void SetBranchReg( u32 reg )
|
|||
|
||||
iFlushCall(FLUSH_EVERYTHING);
|
||||
|
||||
iBranchTest(0xffffffff);
|
||||
iBranchTest();
|
||||
}
|
||||
|
||||
void SetBranchImm( u32 imm )
|
||||
|
@ -1065,9 +978,7 @@ void SetBranchImm( u32 imm )
|
|||
assert( imm );
|
||||
|
||||
// end the current block
|
||||
MOV32ItoM( (uptr)&cpuRegs.pc, imm );
|
||||
iFlushCall(FLUSH_EVERYTHING);
|
||||
|
||||
iBranchTest(imm);
|
||||
}
|
||||
|
||||
|
@ -1076,7 +987,7 @@ void SaveBranchState()
|
|||
s_savex86FpuState = x86FpuState;
|
||||
s_saveiCWstate = iCWstate;
|
||||
s_savenBlockCycles = s_nBlockCycles;
|
||||
s_saveConstGPRreg = 0xffffffff; // indicate searching
|
||||
memcpy(s_saveConstRegs, g_cpuConstRegs, sizeof(g_cpuConstRegs));
|
||||
s_saveHasConstReg = g_cpuHasConstReg;
|
||||
s_saveFlushedConstReg = g_cpuFlushedConstReg;
|
||||
s_psaveInstInfo = g_pCurInstInfo;
|
||||
|
@ -1094,19 +1005,7 @@ void LoadBranchState()
|
|||
iCWstate = s_saveiCWstate;
|
||||
s_nBlockCycles = s_savenBlockCycles;
|
||||
|
||||
if( s_saveConstGPRreg != 0xffffffff ) {
|
||||
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;
|
||||
}
|
||||
|
||||
memcpy(g_cpuConstRegs, s_saveConstRegs, sizeof(g_cpuConstRegs));
|
||||
g_cpuHasConstReg = s_saveHasConstReg;
|
||||
g_cpuFlushedConstReg = s_saveFlushedConstReg;
|
||||
g_pCurInstInfo = s_psaveInstInfo;
|
||||
|
@ -1209,6 +1108,19 @@ u32 eeScaleBlockCycles()
|
|||
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).
|
||||
// Parameters:
|
||||
// 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
|
||||
//CALLFunc((uptr)testfpu);
|
||||
#endif
|
||||
u32* ptr;
|
||||
|
||||
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.
|
||||
// Equiv code to:
|
||||
// cpuRegs.cycle += blockcycles;
|
||||
// if( cpuRegs.cycle > g_nextBranchCycle ) { DoEvents(); }
|
||||
MOV32MtoR(EAX, (uptr)&cpuRegs.cycle);
|
||||
ADD32ItoR(EAX, eeScaleBlockCycles());
|
||||
MOV32RtoM((uptr)&cpuRegs.cycle, EAX); // update cycles
|
||||
SUB32MtoR(EAX, (uptr)&g_nextBranchCycle);
|
||||
|
||||
if( newpc != 0xffffffff )
|
||||
{
|
||||
// This is the jump instruction which gets modified by Dispatcher.
|
||||
*ptr = (u32)JS32((u32)Dispatcher - ( (u32)x86Ptr[0] + 6 ));
|
||||
}
|
||||
else if( !noDispatch )
|
||||
{
|
||||
// This instruction is a dynamic link, so it's never modified.
|
||||
JS32((uptr)DispatcherReg - ( (uptr)x86Ptr[0] + 6 ));
|
||||
if (!noDispatch) {
|
||||
if (newpc == 0xffffffff)
|
||||
JS32((uptr)DispatcherReg - ( (uptr)x86Ptr[0] + 6 ));
|
||||
else
|
||||
iBranch(newpc, 1);
|
||||
}
|
||||
|
||||
RET();
|
||||
|
@ -1271,7 +1165,7 @@ static void checkcodefn()
|
|||
#ifdef _MSC_VER
|
||||
__asm mov pctemp, eax;
|
||||
#else
|
||||
__asm__("movl %%eax, %0" : "=m"(pctemp) );
|
||||
__asm__("movl %%eax, %[pctemp]" : [pctemp]"=m"(pctemp) );
|
||||
#endif
|
||||
|
||||
Console::Error("code changed! %x", params pctemp);
|
||||
|
@ -1283,27 +1177,10 @@ void recompileNextInstruction(int delayslot)
|
|||
static u8 s_bFlushReg = 1;
|
||||
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 );
|
||||
assert(s_pCode);
|
||||
|
||||
// why?
|
||||
#ifdef _DEBUG
|
||||
MOV32ItoR(EAX, pc);
|
||||
#endif
|
||||
|
@ -1311,26 +1188,28 @@ void recompileNextInstruction(int delayslot)
|
|||
cpuRegs.code = *(int *)s_pCode;
|
||||
pc += 4;
|
||||
|
||||
//#ifdef _DEBUG
|
||||
// CMP32ItoM((u32)s_pCode, cpuRegs.code);
|
||||
// j8Ptr[0] = JE8(0);
|
||||
// MOV32ItoR(EAX, pc);
|
||||
// CALLFunc((uptr)checkcodefn);
|
||||
// x86SetJ8( j8Ptr[ 0 ] );
|
||||
//
|
||||
// if( !delayslot ) {
|
||||
// CMP32ItoM((u32)&cpuRegs.pc, s_pCurBlockEx->startpc);
|
||||
// j8Ptr[0] = JB8(0);
|
||||
// CMP32ItoM((u32)&cpuRegs.pc, pc);
|
||||
// j8Ptr[1] = JA8(0);
|
||||
// j8Ptr[2] = JMP8(0);
|
||||
// x86SetJ8( j8Ptr[ 0 ] );
|
||||
// x86SetJ8( j8Ptr[ 1 ] );
|
||||
// PUSH32I(s_pCurBlockEx->startpc);
|
||||
// ADD32ItoR(ESP, 4);
|
||||
// x86SetJ8( j8Ptr[ 2 ] );
|
||||
// }
|
||||
//#endif
|
||||
#if 0
|
||||
#ifdef _DEBUG
|
||||
CMP32ItoM((u32)s_pCode, cpuRegs.code);
|
||||
j8Ptr[0] = JE8(0);
|
||||
MOV32ItoR(EAX, pc);
|
||||
CALLFunc((uptr)checkcodefn);
|
||||
x86SetJ8( j8Ptr[ 0 ] );
|
||||
|
||||
if( !delayslot ) {
|
||||
CMP32ItoM((u32)&cpuRegs.pc, s_pCurBlockEx->startpc);
|
||||
j8Ptr[0] = JB8(0);
|
||||
CMP32ItoM((u32)&cpuRegs.pc, pc);
|
||||
j8Ptr[1] = JA8(0);
|
||||
j8Ptr[2] = JMP8(0);
|
||||
x86SetJ8( j8Ptr[ 0 ] );
|
||||
x86SetJ8( j8Ptr[ 1 ] );
|
||||
PUSH32I(s_pCurBlockEx->startpc);
|
||||
ADD32ItoR(ESP, 4);
|
||||
x86SetJ8( j8Ptr[ 2 ] );
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
g_pCurInstInfo++;
|
||||
|
||||
|
@ -1476,7 +1355,6 @@ void recRecompile( const u32 startpc )
|
|||
u32 i = 0;
|
||||
u32 branchTo;
|
||||
u32 willbranch3 = 0;
|
||||
u32* ptr;
|
||||
u32 usecop2;
|
||||
|
||||
#ifdef _DEBUG
|
||||
|
@ -1497,29 +1375,29 @@ void recRecompile( const u32 startpc )
|
|||
recResetEE();
|
||||
}
|
||||
|
||||
x86SetPtr( recPtr );
|
||||
x86Align(16);
|
||||
recPtr = x86Ptr[_EmitterId_];
|
||||
|
||||
s_pCurBlock = PC_GETBLOCK(startpc);
|
||||
|
||||
assert(s_pCurBlock->GetFnptr() == (uptr)JITCompile
|
||||
|| s_pCurBlock->GetFnptr() == (uptr)JITCompileInBlock);
|
||||
|
||||
s_pCurBlockEx = recBlocks.Get(HWADDR(startpc));
|
||||
if (!s_pCurBlockEx || s_pCurBlockEx->startpc != HWADDR(startpc)) {
|
||||
s_pCurBlockEx = recBlocks.New(HWADDR(startpc));
|
||||
assert(!s_pCurBlockEx || s_pCurBlockEx->startpc != HWADDR(startpc));
|
||||
|
||||
if( s_pCurBlockEx == NULL ) {
|
||||
//SysPrintf("ee reset (blocks)\n");
|
||||
recResetEE();
|
||||
s_pCurBlockEx = recBlocks.New(HWADDR(startpc));
|
||||
}
|
||||
s_pCurBlockEx = recBlocks.New(HWADDR(startpc), (uptr)recPtr);
|
||||
|
||||
if( s_pCurBlockEx == NULL ) {
|
||||
//SysPrintf("ee reset (blocks)\n");
|
||||
recResetEE();
|
||||
x86SetPtr( recPtr );
|
||||
s_pCurBlockEx = recBlocks.New(HWADDR(startpc), (uptr)recPtr);
|
||||
}
|
||||
|
||||
assert(s_pCurBlockEx);
|
||||
|
||||
x86SetPtr( recPtr );
|
||||
x86Align(16);
|
||||
recPtr = x86Ptr[0];
|
||||
s_pCurBlock->SetFnptr( (uptr)x86Ptr[0] );
|
||||
|
||||
branch = 0;
|
||||
|
||||
// reset recomp state variables
|
||||
|
@ -1527,7 +1405,6 @@ void recRecompile( const u32 startpc )
|
|||
pc = startpc;
|
||||
x86FpuState = FPU_STATE;
|
||||
iCWstate = 0;
|
||||
s_saveConstGPRreg = 0;
|
||||
g_cpuHasConstReg = g_cpuFlushedConstReg = 1;
|
||||
g_cpuPrevRegHasLive1 = g_cpuRegHasLive1 = 0xffffffff;
|
||||
g_cpuPrevRegHasSignExt = g_cpuRegHasSignExt = 0;
|
||||
|
@ -1815,40 +1692,25 @@ StartRecomp:
|
|||
#endif
|
||||
|
||||
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_sz=sz*4;
|
||||
|
||||
MOV32ItoR(ECX,startpc);
|
||||
MOV32ItoR(EDX,sz);
|
||||
|
||||
while(inpage_sz)
|
||||
{
|
||||
int PageType=mmap_GetRamPageInfo((u32*)PSM(inpage_ptr));
|
||||
u32 pgsz=std::min(0x1000-inpage_offs,inpage_sz);
|
||||
int PageType = mmap_GetRamPageInfo((u32*)PSM(inpage_ptr));
|
||||
u32 inpage_offs = inpage_ptr & 0xFFF;
|
||||
u32 pgsz = std::min(0x1000 - inpage_offs, inpage_sz);
|
||||
|
||||
if(PageType!=-1)
|
||||
{
|
||||
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);
|
||||
}
|
||||
else
|
||||
{
|
||||
MOV32ItoR(ECX, startpc);
|
||||
MOV32ItoR(EDX, sz);
|
||||
|
||||
u32 lpc=inpage_ptr;
|
||||
u32 stg=pgsz;
|
||||
while(stg>0)
|
||||
|
@ -1866,7 +1728,6 @@ StartRecomp:
|
|||
}
|
||||
inpage_ptr+=pgsz;
|
||||
inpage_sz-=pgsz;
|
||||
inpage_offs=inpage_ptr&0xFFF;
|
||||
}
|
||||
|
||||
// finally recompile //
|
||||
|
@ -1883,6 +1744,32 @@ StartRecomp:
|
|||
assert( (pc-startpc)>>2 <= 0xffff );
|
||||
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++) {
|
||||
if ((uptr)JITCompile == s_pCurBlock[i].GetFnptr())
|
||||
s_pCurBlock[i].SetFnptr((uptr)JITCompileInBlock);
|
||||
|
@ -1910,21 +1797,9 @@ StartRecomp:
|
|||
else
|
||||
ADD32ItoM((int)&cpuRegs.cycle, eeScaleBlockCycles() );
|
||||
|
||||
if( willbranch3 ) {
|
||||
BASEBLOCK* pblock = PC_GETBLOCK(s_nEndBlock);
|
||||
assert( pc == s_nEndBlock );
|
||||
if( willbranch3 || !branch) {
|
||||
iFlushCall(FLUSH_EVERYTHING);
|
||||
MOV32ItoM((uptr)&cpuRegs.pc, pc);
|
||||
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);
|
||||
iBranch(pc, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1932,20 +1807,15 @@ StartRecomp:
|
|||
assert( recStackPtr < recStack+RECSTACK_SIZE );
|
||||
assert( x86FpuState == 0 );
|
||||
|
||||
assert(x86Ptr[_EmitterId_] - recPtr < 0x10000);
|
||||
s_pCurBlockEx->x86size = x86Ptr[_EmitterId_] - recPtr;
|
||||
|
||||
recPtr = x86Ptr[0];
|
||||
|
||||
assert( (g_cpuHasConstReg&g_cpuFlushedConstReg) == g_cpuHasConstReg );
|
||||
|
||||
if( !branch ) {
|
||||
assert( ptr != 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);
|
||||
}
|
||||
s_pCurBlock = NULL;
|
||||
s_pCurBlockEx = NULL;
|
||||
}
|
||||
|
||||
R5900cpu recCpu = {
|
||||
|
|
|
@ -2077,13 +2077,6 @@ void recLoad64( u32 bits, bool sign )
|
|||
//no int 3? i love to get my hands dirty ;p - Raz
|
||||
//write8(0xCC);
|
||||
|
||||
_deleteEEreg(_Rs_, 1);
|
||||
_eeOnLoadWrite(_Rt_);
|
||||
|
||||
EEINST_RESETSIGNEXT(_Rt_); // remove the sign extension
|
||||
|
||||
_deleteEEreg(_Rt_, 0);
|
||||
|
||||
// Load EDX with the destination.
|
||||
// 64/128 bit modes load the result directly into the cpuRegs.GPR struct.
|
||||
|
||||
|
@ -2092,16 +2085,23 @@ void recLoad64( u32 bits, bool sign )
|
|||
else
|
||||
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_;
|
||||
if( bits == 128 ) srcadr &= ~0x0f;
|
||||
vtlb_DynGenRead64_Const( bits, srcadr );
|
||||
}
|
||||
else
|
||||
{
|
||||
_deleteEEreg(_Rs_, 1);
|
||||
// Load ECX with the source memory address that we're reading from.
|
||||
MOV32MtoR( ECX, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] );
|
||||
_eeOnLoadWrite(_Rt_);
|
||||
EEINST_RESETSIGNEXT(_Rt_); // remove the sign extension
|
||||
_deleteEEreg(_Rt_, 0);
|
||||
if ( _Imm_ != 0 )
|
||||
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
|
||||
//write8(0xCC);
|
||||
|
||||
_deleteEEreg(_Rs_, 1);
|
||||
_eeOnLoadWrite(_Rt_);
|
||||
_deleteEEreg(_Rt_, 0);
|
||||
|
||||
// 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_;
|
||||
vtlb_DynGenRead32_Const( bits, sign, srcadr );
|
||||
}
|
||||
else
|
||||
{
|
||||
_deleteEEreg(_Rs_, 1);
|
||||
// Load ECX with the source memory address that we're reading from.
|
||||
MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] );
|
||||
_eeOnLoadWrite(_Rt_);
|
||||
_deleteEEreg(_Rt_, 0);
|
||||
if ( _Imm_ != 0 )
|
||||
ADD32ItoR( ECX, _Imm_ );
|
||||
|
||||
|
@ -2463,7 +2465,6 @@ void recStore(u32 sz)
|
|||
//no int 3? i love to get my hands dirty ;p - Raz
|
||||
//write8(0xCC);
|
||||
|
||||
_deleteEEreg(_Rs_, 1);
|
||||
_deleteEEreg(_Rt_, 1);
|
||||
|
||||
// Performance note: Const prop for the store address is good, always.
|
||||
|
@ -2498,6 +2499,7 @@ void recStore(u32 sz)
|
|||
}
|
||||
else
|
||||
{
|
||||
_deleteEEreg(_Rs_, 1);
|
||||
MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] );
|
||||
if ( _Imm_ != 0 )
|
||||
ADD32ItoR(ECX, _Imm_);
|
||||
|
|
|
@ -425,13 +425,7 @@ void recMTLO1( void )
|
|||
//// MOVZ
|
||||
void recMOVZtemp_const()
|
||||
{
|
||||
GPR_DEL_CONST(_Rd_);
|
||||
_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]);
|
||||
}
|
||||
g_cpuConstRegs[_Rd_].UD[0] = g_cpuConstRegs[_Rs_].UD[0];
|
||||
}
|
||||
|
||||
//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)
|
||||
{
|
||||
if (g_cpuConstRegs[_Rt_].UD[0] == 0) {
|
||||
if( info & PROCESS_EE_MMX ) {
|
||||
if( EEREC_D != EEREC_S ) MOVQRtoR(EEREC_D, EEREC_S);
|
||||
return;
|
||||
}
|
||||
if( info & PROCESS_EE_MMX ) {
|
||||
if( EEREC_D != EEREC_S ) MOVQRtoR(EEREC_D, EEREC_S);
|
||||
return;
|
||||
}
|
||||
|
||||
if( _hasFreeXMMreg() ) {
|
||||
int t0reg = _allocMMXreg(-1, MMX_TEMP, 0);
|
||||
MOVQMtoR(t0reg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]);
|
||||
MOVQRtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], t0reg);
|
||||
_freeMMXreg(t0reg);
|
||||
}
|
||||
else {
|
||||
MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]);
|
||||
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[ 1 ], EDX);
|
||||
}
|
||||
if( _hasFreeXMMreg() ) {
|
||||
int t0reg = _allocMMXreg(-1, MMX_TEMP, 0);
|
||||
MOVQMtoR(t0reg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]);
|
||||
MOVQRtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], t0reg);
|
||||
_freeMMXreg(t0reg);
|
||||
}
|
||||
else {
|
||||
MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]);
|
||||
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[ 1 ], EDX);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -546,22 +538,11 @@ void recMOVZ()
|
|||
if( _Rs_ == _Rd_ )
|
||||
return;
|
||||
|
||||
if( GPR_IS_CONST1(_Rd_) ) {
|
||||
|
||||
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];
|
||||
}
|
||||
if(GPR_IS_CONST1(_Rt_)) {
|
||||
if (g_cpuConstRegs[_Rt_].UD[0] != 0)
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else if (GPR_IS_CONST1(_Rd_))
|
||||
_deleteEEreg(_Rd_, 1);
|
||||
|
||||
recMOVZtemp();
|
||||
}
|
||||
|
@ -569,13 +550,7 @@ void recMOVZ()
|
|||
//// MOVN
|
||||
void recMOVNtemp_const()
|
||||
{
|
||||
GPR_DEL_CONST(_Rd_);
|
||||
_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]);
|
||||
}
|
||||
g_cpuConstRegs[_Rd_].UD[0] = g_cpuConstRegs[_Rs_].UD[0];
|
||||
}
|
||||
|
||||
void recMOVNtemp_consts(int info)
|
||||
|
@ -618,19 +593,17 @@ void recMOVNtemp_consts(int info)
|
|||
|
||||
void recMOVNtemp_constt(int info)
|
||||
{
|
||||
if (g_cpuConstRegs[_Rt_].UD[0] != 0) {
|
||||
if( _hasFreeXMMreg() ) {
|
||||
int t0reg = _allocMMXreg(-1, MMX_TEMP, 0);
|
||||
MOVQMtoR(t0reg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]);
|
||||
MOVQRtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], t0reg);
|
||||
_freeMMXreg(t0reg);
|
||||
}
|
||||
else {
|
||||
MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]);
|
||||
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[ 1 ], EDX);
|
||||
}
|
||||
if( _hasFreeXMMreg() ) {
|
||||
int t0reg = _allocMMXreg(-1, MMX_TEMP, 0);
|
||||
MOVQMtoR(t0reg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]);
|
||||
MOVQRtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], t0reg);
|
||||
_freeMMXreg(t0reg);
|
||||
}
|
||||
else {
|
||||
MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]);
|
||||
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[ 1 ], EDX);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -685,22 +658,11 @@ void recMOVN()
|
|||
if( _Rs_ == _Rd_ )
|
||||
return;
|
||||
|
||||
if( GPR_IS_CONST1(_Rd_) ) {
|
||||
|
||||
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];
|
||||
}
|
||||
if (GPR_IS_CONST1(_Rt_)) {
|
||||
if (g_cpuConstRegs[_Rt_].UD[0] == 0)
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else if (GPR_IS_CONST1(_Rd_))
|
||||
_deleteEEreg(_Rd_, 1);
|
||||
|
||||
recMOVNtemp();
|
||||
}
|
||||
|
|
|
@ -38,19 +38,6 @@
|
|||
// 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)
|
||||
{
|
||||
g_cpuPrevRegHasLive1 = g_cpuRegHasLive1;
|
||||
|
@ -68,7 +55,6 @@ void _eeProcessHasLive(int reg, int signext)
|
|||
|
||||
void _eeOnWriteReg(int reg, int signext)
|
||||
{
|
||||
CHECK_SAVE_REG(reg);
|
||||
GPR_DEL_CONST(reg);
|
||||
_eeProcessHasLive(reg, signext);
|
||||
}
|
||||
|
@ -109,7 +95,6 @@ void eeRecompileCode0(R5900FNPTR constcode, R5900FNPTR_INFO constscode, R5900FNP
|
|||
if ( ! _Rd_ && (xmminfo&XMMINFO_WRITED) ) return;
|
||||
|
||||
if( xmminfo&XMMINFO_WRITED) {
|
||||
CHECK_SAVE_REG(_Rd_);
|
||||
_eeProcessHasLive(_Rd_, 0);
|
||||
EEINST_RESETSIGNEXT(_Rd_);
|
||||
}
|
||||
|
@ -421,7 +406,6 @@ void eeRecompileCode1(R5900FNPTR constcode, R5900FNPTR_INFO noconstcode)
|
|||
int mmreg1, mmreg2;
|
||||
if ( ! _Rt_ ) return;
|
||||
|
||||
CHECK_SAVE_REG(_Rt_);
|
||||
_eeProcessHasLive(_Rt_, 0);
|
||||
EEINST_RESETSIGNEXT(_Rt_);
|
||||
|
||||
|
@ -522,7 +506,6 @@ void eeRecompileCode2(R5900FNPTR constcode, R5900FNPTR_INFO noconstcode)
|
|||
int mmreg1, mmreg2;
|
||||
if ( ! _Rd_ ) return;
|
||||
|
||||
CHECK_SAVE_REG(_Rd_);
|
||||
_eeProcessHasLive(_Rd_, 0);
|
||||
EEINST_RESETSIGNEXT(_Rd_);
|
||||
|
||||
|
@ -651,7 +634,6 @@ void eeRecompileCodeConst0(R5900FNPTR constcode, R5900FNPTR_INFO constscode, R59
|
|||
if ( ! _Rd_ ) return;
|
||||
|
||||
// for now, don't support xmm
|
||||
CHECK_SAVE_REG(_Rd_);
|
||||
|
||||
_deleteGPRtoXMMreg(_Rs_, 1);
|
||||
_deleteGPRtoXMMreg(_Rt_, 1);
|
||||
|
@ -689,7 +671,6 @@ void eeRecompileCodeConst1(R5900FNPTR constcode, R5900FNPTR_INFO noconstcode)
|
|||
return;
|
||||
|
||||
// for now, don't support xmm
|
||||
CHECK_SAVE_REG(_Rt_);
|
||||
|
||||
_deleteGPRtoXMMreg(_Rs_, 1);
|
||||
_deleteGPRtoXMMreg(_Rt_, 0);
|
||||
|
@ -710,7 +691,6 @@ void eeRecompileCodeConst2(R5900FNPTR constcode, R5900FNPTR_INFO noconstcode)
|
|||
if ( ! _Rd_ ) return;
|
||||
|
||||
// for now, don't support xmm
|
||||
CHECK_SAVE_REG(_Rd_);
|
||||
|
||||
_deleteGPRtoXMMreg(_Rt_, 1);
|
||||
_deleteGPRtoXMMreg(_Rd_, 0);
|
||||
|
@ -731,7 +711,6 @@ void eeRecompileCodeConstSPECIAL(R5900FNPTR constcode, R5900FNPTR_INFO multicode
|
|||
assert(0);
|
||||
// for now, don't support xmm
|
||||
if( MULT ) {
|
||||
CHECK_SAVE_REG(_Rd_);
|
||||
_deleteGPRtoXMMreg(_Rd_, 0);
|
||||
}
|
||||
|
||||
|
@ -767,7 +746,6 @@ int eeRecompileCodeXMM(int xmminfo)
|
|||
|
||||
// save state
|
||||
if( xmminfo & XMMINFO_WRITED ) {
|
||||
CHECK_SAVE_REG(_Rd_);
|
||||
_eeProcessHasLive(_Rd_, 0);
|
||||
EEINST_RESETSIGNEXT(_Rd_);
|
||||
}
|
||||
|
|
|
@ -173,7 +173,7 @@ static void _vtlb_DynGen_IndirectRead( u32 bits )
|
|||
MOVZX32R8toR(EAX,EAX);
|
||||
SUB32RtoR(ECX,EAX);
|
||||
//eax=[funct+eax]
|
||||
MOV32RmSOffsettoR(EAX,EAX,(int)RWFT[szidx][0],2);
|
||||
MOV32RmSOffsettoR(EAX,EAX,(int)vtlbdata.RWFT[szidx][0],2);
|
||||
SUB32ItoR(ECX,0x80000000);
|
||||
CALL32R(EAX);
|
||||
}
|
||||
|
@ -187,7 +187,7 @@ void vtlb_DynGenRead64(u32 bits)
|
|||
|
||||
MOV32RtoR(EAX,ECX);
|
||||
SHR32ItoR(EAX,VTLB_PAGE_BITS);
|
||||
MOV32RmSOffsettoR(EAX,EAX,(int)vmap,2);
|
||||
MOV32RmSOffsettoR(EAX,EAX,(int)vtlbdata.vmap,2);
|
||||
ADD32RtoR(ECX,EAX);
|
||||
u8* _fullread = JS8(0);
|
||||
|
||||
|
@ -209,7 +209,7 @@ void vtlb_DynGenRead32(u32 bits, bool sign)
|
|||
|
||||
MOV32RtoR(EAX,ECX);
|
||||
SHR32ItoR(EAX,VTLB_PAGE_BITS);
|
||||
MOV32RmSOffsettoR(EAX,EAX,(int)vmap,2);
|
||||
MOV32RmSOffsettoR(EAX,EAX,(int)vtlbdata.vmap,2);
|
||||
ADD32RtoR(ECX,EAX);
|
||||
u8* _fullread = JS8(0);
|
||||
|
||||
|
@ -243,7 +243,7 @@ void vtlb_DynGenRead64_Const( u32 bits, u32 addr_const )
|
|||
{
|
||||
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);
|
||||
MOV32ItoR(ECX,addr_const);
|
||||
|
@ -266,7 +266,7 @@ void vtlb_DynGenRead32_Const( u32 bits, bool sign, u32 addr_const )
|
|||
{
|
||||
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);
|
||||
MOV32ItoR(ECX,addr_const);
|
||||
|
@ -368,7 +368,7 @@ static void _vtlb_DynGen_IndirectWrite( u32 bits )
|
|||
MOVZX32R8toR(EAX,EAX);
|
||||
SUB32RtoR(ECX,EAX);
|
||||
//eax=[funct+eax]
|
||||
MOV32RmSOffsettoR(EAX,EAX,(int)RWFT[szidx][1],2);
|
||||
MOV32RmSOffsettoR(EAX,EAX,(int)vtlbdata.RWFT[szidx][1],2);
|
||||
SUB32ItoR(ECX,0x80000000);
|
||||
CALL32R(EAX);
|
||||
}
|
||||
|
@ -377,7 +377,7 @@ void vtlb_DynGenWrite(u32 sz)
|
|||
{
|
||||
MOV32RtoR(EAX,ECX);
|
||||
SHR32ItoR(EAX,VTLB_PAGE_BITS);
|
||||
MOV32RmSOffsettoR(EAX,EAX,(int)vmap,2);
|
||||
MOV32RmSOffsettoR(EAX,EAX,(int)vtlbdata.vmap,2);
|
||||
ADD32RtoR(ECX,EAX);
|
||||
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.
|
||||
// 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);
|
||||
MOV32ItoR(ECX,addr_const);
|
||||
|
|
|
@ -41,7 +41,7 @@ emitterT void WriteRmOffset(x86IntRegType to, s32 offset)
|
|||
ModRM<I>( 0, 0, 4 );
|
||||
SibSB<I>( 0, ESP, 4 );
|
||||
}
|
||||
else if( offset < 128 && offset >= -128 ) {
|
||||
else if( offset <= 127 && offset >= -128 ) {
|
||||
ModRM<I>( 1, 0, 4 );
|
||||
SibSB<I>( 0, ESP, 4 );
|
||||
write8<I>(offset);
|
||||
|
@ -56,7 +56,7 @@ emitterT void WriteRmOffset(x86IntRegType to, s32 offset)
|
|||
if( offset == 0 ) {
|
||||
ModRM<I>( 0, 0, to );
|
||||
}
|
||||
else if( offset < 128 && offset >= -128 ) {
|
||||
else if( offset <= 127 && offset >= -128 ) {
|
||||
ModRM<I>( 1, 0, to );
|
||||
write8<I>(offset);
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ emitterT void WriteRmOffsetFrom(x86IntRegType to, x86IntRegType from, int offset
|
|||
ModRM<I>( 0, to, 0x4 );
|
||||
SibSB<I>( 0, 0x4, 0x4 );
|
||||
}
|
||||
else if( offset < 128 && offset >= -128 ) {
|
||||
else if( offset <= 127 && offset >= -128 ) {
|
||||
ModRM<I>( 1, to, 0x4 );
|
||||
SibSB<I>( 0, 0x4, 0x4 );
|
||||
write8<I>(offset);
|
||||
|
@ -89,7 +89,7 @@ emitterT void WriteRmOffsetFrom(x86IntRegType to, x86IntRegType from, int offset
|
|||
if( offset == 0 ) {
|
||||
ModRM<I>( 0, to, from );
|
||||
}
|
||||
else if( offset < 128 && offset >= -128 ) {
|
||||
else if( offset <= 127 && offset >= -128 ) {
|
||||
ModRM<I>( 1, to, from );
|
||||
write8<I>(offset);
|
||||
}
|
||||
|
@ -401,8 +401,12 @@ emitterT void eMOV32RtoR( x86IntRegType to, x86IntRegType from )
|
|||
emitterT void eMOV32RtoM( uptr to, x86IntRegType from )
|
||||
{
|
||||
RexR(0, from);
|
||||
write8<I>( 0x89 );
|
||||
ModRM<I>( 0, from, DISP32 );
|
||||
if (from == EAX) {
|
||||
write8<I>(0xA3);
|
||||
} else {
|
||||
write8<I>( 0x89 );
|
||||
ModRM<I>( 0, from, DISP32 );
|
||||
}
|
||||
write32<I>( MEMADDR(to, 4) );
|
||||
}
|
||||
|
||||
|
@ -410,8 +414,12 @@ emitterT void eMOV32RtoM( uptr to, x86IntRegType from )
|
|||
emitterT void eMOV32MtoR( x86IntRegType to, uptr from )
|
||||
{
|
||||
RexR(0, to);
|
||||
write8<I>( 0x8B );
|
||||
ModRM<I>( 0, to, DISP32 );
|
||||
if (to == EAX) {
|
||||
write8<I>(0xA1);
|
||||
} else {
|
||||
write8<I>( 0x8B );
|
||||
ModRM<I>( 0, to, DISP32 );
|
||||
}
|
||||
write32<I>( MEMADDR(from, 4) );
|
||||
}
|
||||
|
||||
|
@ -1038,69 +1046,69 @@ emitterT void eADD64RtoR( x86IntRegType to, x86IntRegType from )
|
|||
}
|
||||
|
||||
/* add imm32 to EAX */
|
||||
emitterT void eADD32ItoEAX( u32 from )
|
||||
emitterT void eADD32ItoEAX( s32 imm )
|
||||
{
|
||||
write8<I>( 0x05 );
|
||||
write32<I>( from );
|
||||
write32<I>( imm );
|
||||
}
|
||||
|
||||
/* add imm32 to r32 */
|
||||
emitterT void eADD32ItoR( x86IntRegType to, u32 from )
|
||||
emitterT void eADD32ItoR( x86IntRegType to, s32 imm )
|
||||
{
|
||||
RexB(0, to);
|
||||
if(from < 0x80)
|
||||
if (imm <= 127 && imm >= -128)
|
||||
{
|
||||
write8<I>( 0x83 );
|
||||
ModRM<I>( 3, 0, to );
|
||||
write8<I>( from );
|
||||
write8<I>( (s8)imm );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( to == EAX ) {
|
||||
eADD32ItoEAX<I>(from);
|
||||
eADD32ItoEAX<I>(imm);
|
||||
}
|
||||
else {
|
||||
write8<I>( 0x81 );
|
||||
ModRM<I>( 3, 0, to );
|
||||
write32<I>( from );
|
||||
write32<I>( imm );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 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 );
|
||||
ModRM<I>( 0, 0, DISP32 );
|
||||
write32<I>( MEMADDR(to, 8) );
|
||||
write8<I>( from );
|
||||
write8<I>( imm );
|
||||
}
|
||||
else*/
|
||||
else
|
||||
{
|
||||
write8<I>( 0x81 );
|
||||
ModRM<I>( 0, 0, DISP32 );
|
||||
write32<I>( MEMADDR(to, 8) );
|
||||
write32<I>( from );
|
||||
write32<I>( imm );
|
||||
}
|
||||
}
|
||||
|
||||
// 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);
|
||||
if(from < 0x80)
|
||||
if(imm <= 127 && imm >= -128)
|
||||
{
|
||||
write8<I>( 0x83 );
|
||||
WriteRmOffset<I>(to,offset);
|
||||
write8<I>(from);
|
||||
write8<I>(imm);
|
||||
}
|
||||
else
|
||||
{
|
||||
write8<I>( 0x81 );
|
||||
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 */
|
||||
emitterT void eADD16ItoR( x86IntRegType to, u16 from )
|
||||
emitterT void eADD16ItoR( x86IntRegType to, s16 imm )
|
||||
{
|
||||
write8<I>( 0x66 );
|
||||
RexB(0,to);
|
||||
|
@ -1148,39 +1156,39 @@ emitterT void eADD16ItoR( x86IntRegType to, u16 from )
|
|||
if ( to == EAX)
|
||||
{
|
||||
write8<I>( 0x05 );
|
||||
write16<I>( from );
|
||||
write16<I>( imm );
|
||||
}
|
||||
else if(from < 0x80)
|
||||
else if(imm <= 127 && imm >= -128)
|
||||
{
|
||||
write8<I>( 0x83 );
|
||||
ModRM<I>( 3, 0, to );
|
||||
write8<I>((u8)from );
|
||||
write8<I>((u8)imm );
|
||||
}
|
||||
else
|
||||
{
|
||||
write8<I>( 0x81 );
|
||||
ModRM<I>( 3, 0, to );
|
||||
write16<I>( from );
|
||||
write16<I>( imm );
|
||||
}
|
||||
}
|
||||
|
||||
/* add imm16 to m16 */
|
||||
emitterT void eADD16ItoM( uptr to, u16 from )
|
||||
emitterT void eADD16ItoM( uptr to, s16 imm )
|
||||
{
|
||||
write8<I>( 0x66 );
|
||||
if(from < 0x80)
|
||||
if(imm <= 127 && imm >= -128)
|
||||
{
|
||||
write8<I>( 0x83 );
|
||||
ModRM<I>( 0, 0, DISP32 );
|
||||
write32<I>( MEMADDR(to, 6) );
|
||||
write8<I>((u8)from );
|
||||
write8<I>((u8)imm );
|
||||
}
|
||||
else
|
||||
{
|
||||
write8<I>( 0x81 );
|
||||
ModRM<I>( 0, 0, DISP32 );
|
||||
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);
|
||||
}
|
||||
|
||||
emitterT void eLEA32RtoR(x86IntRegType to, x86IntRegType from, u32 offset)
|
||||
emitterT void eLEA32RtoR(x86IntRegType to, x86IntRegType from, s32 offset)
|
||||
{
|
||||
RexRB(0,to,from);
|
||||
write8<I>(0x8d);
|
||||
|
@ -3260,7 +3268,7 @@ emitterT void eLEA32RtoR(x86IntRegType to, x86IntRegType from, u32 offset)
|
|||
ModRM<I>(1, to, from);
|
||||
write8<I>(0x24);
|
||||
}
|
||||
else if( offset < 128 ) {
|
||||
else if( offset <= 127 && offset >= -128 ) {
|
||||
ModRM<I>(1, to, from);
|
||||
write8<I>(0x24);
|
||||
write8<I>(offset);
|
||||
|
@ -3275,7 +3283,7 @@ emitterT void eLEA32RtoR(x86IntRegType to, x86IntRegType from, u32 offset)
|
|||
if( offset == 0 && from != EBP && from!=ESP ) {
|
||||
ModRM<I>(0, to, from);
|
||||
}
|
||||
else if( offset < 128 ) {
|
||||
else if( offset <= 127 && offset >= -128 ) {
|
||||
ModRM<I>(1, to, from);
|
||||
write8<I>(offset);
|
||||
}
|
||||
|
|
|
@ -115,7 +115,7 @@ extern s32 iCpuId( u32 cmd, u32 *regs )
|
|||
"pushf\n"
|
||||
"pop %%eax\n"
|
||||
"xor %%edx, %%eax\n"
|
||||
"mov %%eax, %0\n"
|
||||
"mov %%eax, %[flag]\n"
|
||||
"add $0x18, %%esp\n"
|
||||
"cmpl $0x0,%%eax\n"
|
||||
"jne 1f\n"
|
||||
|
@ -123,7 +123,7 @@ extern s32 iCpuId( u32 cmd, u32 *regs )
|
|||
"leave\n"
|
||||
"ret\n"
|
||||
"1:\n"
|
||||
: "=r"(flag) :
|
||||
: [flag]"=r"(flag) :
|
||||
);
|
||||
|
||||
cpuid(cmd, regs[0], regs[1], regs[2], regs[3]);
|
||||
|
|
|
@ -61,7 +61,7 @@ void SetCPUState(u32 sseMXCSR, u32 sseVUMXCSR)
|
|||
#ifdef _MSC_VER
|
||||
__asm ldmxcsr g_sseMXCSR; // set the new sse control
|
||||
#else
|
||||
__asm__("ldmxcsr %0" : : "m"(g_sseMXCSR) );
|
||||
__asm__("ldmxcsr %[g_sseMXCSR]" : : [g_sseMXCSR]"m"(g_sseMXCSR) );
|
||||
#endif
|
||||
//g_sseVUMXCSR = g_sseMXCSR|0x6000;
|
||||
}
|
||||
|
@ -108,16 +108,16 @@ __forceinline void FreezeMMXRegs_(int save)
|
|||
#else
|
||||
__asm__(
|
||||
".intel_syntax noprefix\n"
|
||||
"movq [%0+0x00], mm0\n"
|
||||
"movq [%0+0x08], mm1\n"
|
||||
"movq [%0+0x10], mm2\n"
|
||||
"movq [%0+0x18], mm3\n"
|
||||
"movq [%0+0x20], mm4\n"
|
||||
"movq [%0+0x28], mm5\n"
|
||||
"movq [%0+0x30], mm6\n"
|
||||
"movq [%0+0x38], mm7\n"
|
||||
"movq [%[g_globalMMXData]+0x00], mm0\n"
|
||||
"movq [%[g_globalMMXData]+0x08], mm1\n"
|
||||
"movq [%[g_globalMMXData]+0x10], mm2\n"
|
||||
"movq [%[g_globalMMXData]+0x18], mm3\n"
|
||||
"movq [%[g_globalMMXData]+0x20], mm4\n"
|
||||
"movq [%[g_globalMMXData]+0x28], mm5\n"
|
||||
"movq [%[g_globalMMXData]+0x30], mm6\n"
|
||||
"movq [%[g_globalMMXData]+0x38], mm7\n"
|
||||
"emms\n"
|
||||
".att_syntax\n" : : "r"(g_globalMMXData)
|
||||
".att_syntax\n" : : [g_globalMMXData]"r"(g_globalMMXData)
|
||||
);
|
||||
#endif
|
||||
|
||||
|
@ -148,16 +148,16 @@ __forceinline void FreezeMMXRegs_(int save)
|
|||
#else
|
||||
__asm__(
|
||||
".intel_syntax noprefix\n"
|
||||
"movq mm0, [%0+0x00]\n"
|
||||
"movq mm1, [%0+0x08]\n"
|
||||
"movq mm2, [%0+0x10]\n"
|
||||
"movq mm3, [%0+0x18]\n"
|
||||
"movq mm4, [%0+0x20]\n"
|
||||
"movq mm5, [%0+0x28]\n"
|
||||
"movq mm6, [%0+0x30]\n"
|
||||
"movq mm7, [%0+0x38]\n"
|
||||
"movq mm0, [%[g_globalMMXData]+0x00]\n"
|
||||
"movq mm1, [%[g_globalMMXData]+0x08]\n"
|
||||
"movq mm2, [%[g_globalMMXData]+0x10]\n"
|
||||
"movq mm3, [%[g_globalMMXData]+0x18]\n"
|
||||
"movq mm4, [%[g_globalMMXData]+0x20]\n"
|
||||
"movq mm5, [%[g_globalMMXData]+0x28]\n"
|
||||
"movq mm6, [%[g_globalMMXData]+0x30]\n"
|
||||
"movq mm7, [%[g_globalMMXData]+0x38]\n"
|
||||
"emms\n"
|
||||
".att_syntax\n" : : "r"(g_globalMMXData)
|
||||
".att_syntax\n" : : [g_globalMMXData]"r"(g_globalMMXData)
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
@ -195,15 +195,15 @@ __forceinline void FreezeXMMRegs_(int save)
|
|||
#else
|
||||
__asm__(
|
||||
".intel_syntax noprefix\n"
|
||||
"movaps [%0+0x00], xmm0\n"
|
||||
"movaps [%0+0x10], xmm1\n"
|
||||
"movaps [%0+0x20], xmm2\n"
|
||||
"movaps [%0+0x30], xmm3\n"
|
||||
"movaps [%0+0x40], xmm4\n"
|
||||
"movaps [%0+0x50], xmm5\n"
|
||||
"movaps [%0+0x60], xmm6\n"
|
||||
"movaps [%0+0x70], xmm7\n"
|
||||
".att_syntax\n" : : "r"(g_globalXMMData)
|
||||
"movaps [%[g_globalXMMData]+0x00], xmm0\n"
|
||||
"movaps [%[g_globalXMMData]+0x10], xmm1\n"
|
||||
"movaps [%[g_globalXMMData]+0x20], xmm2\n"
|
||||
"movaps [%[g_globalXMMData]+0x30], xmm3\n"
|
||||
"movaps [%[g_globalXMMData]+0x40], xmm4\n"
|
||||
"movaps [%[g_globalXMMData]+0x50], xmm5\n"
|
||||
"movaps [%[g_globalXMMData]+0x60], xmm6\n"
|
||||
"movaps [%[g_globalXMMData]+0x70], xmm7\n"
|
||||
".att_syntax\n" : : [g_globalXMMData]"r"(g_globalXMMData)
|
||||
);
|
||||
|
||||
#endif // _MSC_VER
|
||||
|
@ -237,15 +237,15 @@ __forceinline void FreezeXMMRegs_(int save)
|
|||
#else
|
||||
__asm__(
|
||||
".intel_syntax noprefix\n"
|
||||
"movaps xmm0, [%0+0x00]\n"
|
||||
"movaps xmm1, [%0+0x10]\n"
|
||||
"movaps xmm2, [%0+0x20]\n"
|
||||
"movaps xmm3, [%0+0x30]\n"
|
||||
"movaps xmm4, [%0+0x40]\n"
|
||||
"movaps xmm5, [%0+0x50]\n"
|
||||
"movaps xmm6, [%0+0x60]\n"
|
||||
"movaps xmm7, [%0+0x70]\n"
|
||||
".att_syntax\n" : : "r"(g_globalXMMData)
|
||||
"movaps xmm0, [%[g_globalXMMData]+0x00]\n"
|
||||
"movaps xmm1, [%[g_globalXMMData]+0x10]\n"
|
||||
"movaps xmm2, [%[g_globalXMMData]+0x20]\n"
|
||||
"movaps xmm3, [%[g_globalXMMData]+0x30]\n"
|
||||
"movaps xmm4, [%[g_globalXMMData]+0x40]\n"
|
||||
"movaps xmm5, [%[g_globalXMMData]+0x50]\n"
|
||||
"movaps xmm6, [%[g_globalXMMData]+0x60]\n"
|
||||
"movaps xmm7, [%[g_globalXMMData]+0x70]\n"
|
||||
".att_syntax\n" : : [g_globalXMMData]"r"(g_globalXMMData)
|
||||
);
|
||||
|
||||
#endif // _MSC_VER
|
||||
|
|
|
@ -29,42 +29,12 @@
|
|||
PCSX2_ALIGNED16(microVU microVU0);
|
||||
PCSX2_ALIGNED16(microVU microVU1);
|
||||
|
||||
PCSX2_ALIGNED16(const u32 mVU_absclip[4]) = {0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff};
|
||||
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};
|
||||
|
||||
declareAllVariables // Declares All Global Variables :D
|
||||
//------------------------------------------------------------------
|
||||
// Micro VU - Main Functions
|
||||
//------------------------------------------------------------------
|
||||
|
||||
// Only run this once! ;)
|
||||
// Only run this once per VU! ;)
|
||||
microVUt(void) mVUinit(VURegs* vuRegsPtr) {
|
||||
|
||||
microVU* mVU = mVUx;
|
||||
|
@ -86,7 +56,7 @@ microVUt(void) mVUreset() {
|
|||
|
||||
// Create Block Managers
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
@ -112,7 +82,7 @@ microVUt(void) mVUclose() {
|
|||
|
||||
// Delete Block Managers
|
||||
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];
|
||||
}
|
||||
}
|
||||
|
@ -142,8 +112,8 @@ microVUt(void*) __fastcall mVUexecute(u32 startPC, u32 cycles) {
|
|||
*/
|
||||
microVU* mVU = mVUx;
|
||||
if ( mVUsearchProg(mVU) ) { // Found Program
|
||||
microBlock* block = mVU->prog.prog[mVU->prog.cur].block[startPC]->search(mVU->prog.lastPipelineState);
|
||||
if (block) return block->x86ptrStart; // Found Block
|
||||
//microBlock* block = mVU->prog.prog[mVU->prog.cur].block[startPC]->search(mVU->prog.lastPipelineState);
|
||||
//if (block) return block->x86ptrStart; // Found Block
|
||||
}
|
||||
// Recompile code
|
||||
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)
|
||||
__forceinline void mVUclearProg(microVU* mVU, int progIndex) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,18 +17,21 @@
|
|||
*/
|
||||
|
||||
#pragma once
|
||||
#define mVUdebug // Prints Extra Info to Console
|
||||
#define _EmitterId_ (vuIndex+1)
|
||||
#include "Common.h"
|
||||
#include "VU.h"
|
||||
#include "GS.h"
|
||||
#include "ix86/ix86.h"
|
||||
#include "microVU_Alloc.h"
|
||||
|
||||
struct microBlock {
|
||||
u32 pipelineState; // FMACx|y|z|w | FDiv | EFU | IALU | BRANCH // Still thinking of how I'm going to do this
|
||||
u8* x86ptrStart;
|
||||
u8* x86ptrEnd;
|
||||
u8* x86ptrBranch;
|
||||
//u32 size;
|
||||
microRegInfo pState; // Detailed State of Pipeline
|
||||
u32 pipelineState; // | FDiv x 4 | EFU x 6 | Needs pState Info? x 1 | // Simple State of Pipeline
|
||||
u8* x86ptrStart; // Start of code
|
||||
u8* x86ptrEnd; // End of code (first byte outside of block)
|
||||
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...)
|
||||
|
@ -53,17 +56,24 @@ public:
|
|||
}
|
||||
void reset() { init(); };
|
||||
void close() {}; // Can be Omitted?
|
||||
void add(u32 pipelineState, u8* x86ptrStart) {
|
||||
/*void add(u32 pipelineState, u8* x86ptrStart) {
|
||||
if (!search(pipelineState)) {
|
||||
listSize++;
|
||||
listSize &= MaxBlocks;
|
||||
blockList[listSize].pipelineState = pipelineState;
|
||||
blockList[listSize].x86ptrStart = x86ptrStart;
|
||||
}
|
||||
}
|
||||
microBlock* search(u32 pipelineState) {
|
||||
for (int i = 0; i < listSize; i++) {
|
||||
if (blockList[i].pipelineState == pipelineState) return &blockList[i];
|
||||
}*/
|
||||
microBlock* search(u32 pipelineState, microRegInfo* pState) {
|
||||
if (pipelineState & 1) { // Needs Detailed Search (Exact Match of Pipeline State)
|
||||
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;
|
||||
}
|
||||
|
@ -81,9 +91,9 @@ public:
|
|||
|
||||
template<u32 progSize>
|
||||
struct microProgram {
|
||||
u8 data[progSize];
|
||||
u32 data[progSize];
|
||||
u32 used; // Number of times its been used
|
||||
microBlockManager* block[progSize];
|
||||
microBlockManager* block[progSize / 2];
|
||||
microAllocInfo<progSize> allocInfo;
|
||||
};
|
||||
|
||||
|
@ -104,15 +114,16 @@ struct microVU {
|
|||
u32 microSize; // VU Micro Memory Size
|
||||
u32 progSize; // VU Micro Program Size (microSize/8)
|
||||
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
|
||||
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
|
||||
u32 code; // Contains the current Instruction
|
||||
u32 iReg; // iReg
|
||||
VURegs* regs; // VU Regs Struct
|
||||
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
|
||||
u32 code; // Contains the current Instruction
|
||||
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.
|
||||
|
@ -147,3 +158,4 @@ microVUt(void) mVUclose();
|
|||
#include "microVU_Misc.h"
|
||||
#include "microVU_Alloc.inl"
|
||||
#include "microVU_Tables.inl"
|
||||
#include "microVU_Compile.inl"
|
||||
|
|
|
@ -28,8 +28,7 @@ union regInfo {
|
|||
};
|
||||
};
|
||||
|
||||
template<u32 pSize>
|
||||
struct microAllocInfo {
|
||||
struct microRegInfo {
|
||||
regInfo VF[32];
|
||||
regInfo Acc;
|
||||
u8 VI[32];
|
||||
|
@ -37,22 +36,34 @@ struct microAllocInfo {
|
|||
u8 q;
|
||||
u8 p;
|
||||
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); } \
|
||||
else { SSE_XORPS_XMM_to_XMM(reg, reg); } \
|
||||
}
|
||||
|
||||
/*
|
||||
#define getACC(reg) { \
|
||||
reg = xmmACC0 + writeACC; \
|
||||
if (_X_Y_Z_W != 15) { SSE_MOVAPS_XMM_to_XMM(reg, (xmmACC0 + prevACC)); } \
|
||||
}
|
||||
|
||||
*/
|
||||
microVUt(void) mVUallocFMAC4a(int& ACC, int& Fs, int& Ft) {
|
||||
microVU* mVU = mVUx;
|
||||
Fs = xmmFs;
|
||||
ACC = xmmACC;
|
||||
Fs = (_X_Y_Z_W == 15) ? xmmACC : xmmFs;
|
||||
Ft = xmmFt;
|
||||
getACC(ACC);
|
||||
if (_XYZW_SS && _X) {
|
||||
if (_X_Y_Z_W == 8) {
|
||||
getReg6(Fs, _Fs_);
|
||||
if (_Ft_ == _Fs_) { Ft = Fs; }
|
||||
else { getReg6(Ft, _Ft_); }
|
||||
|
@ -184,10 +184,10 @@ microVUt(void) mVUallocFMAC4b(int& ACC, int& Fs) {
|
|||
|
||||
microVUt(void) mVUallocFMAC5a(int& ACC, int& Fs, int& Ft) {
|
||||
microVU* mVU = mVUx;
|
||||
Fs = xmmFs;
|
||||
ACC = xmmACC;
|
||||
Fs = (_X_Y_Z_W == 15) ? xmmACC : xmmFs;
|
||||
Ft = xmmFt;
|
||||
getACC(ACC);
|
||||
if (_XYZW_SS && _X) {
|
||||
if (_X_Y_Z_W == 8) {
|
||||
getReg6(Fs, _Fs_);
|
||||
if ((_Ft_ == _Fs_) && _bc_x) { Ft = Fs; }
|
||||
else if (!_Ft_) { getZero3SS(Ft); }
|
||||
|
@ -236,11 +236,11 @@ microVUt(void) mVUallocFMAC6b(int& Fd) {
|
|||
|
||||
microVUt(void) mVUallocFMAC7a(int& ACC, int& Fs, int& Ft) {
|
||||
microVU* mVU = mVUx;
|
||||
Fs = xmmFs;
|
||||
ACC = xmmACC;
|
||||
Fs = (_X_Y_Z_W == 15) ? xmmACC : xmmFs;
|
||||
Ft = xmmFt;
|
||||
getACC(ACC);
|
||||
getIreg(Ft);
|
||||
if (_XYZW_SS && _X) { getReg6(Fs, _Fs_); }
|
||||
if (_X_Y_Z_W == 8) { getReg6(Fs, _Fs_); }
|
||||
else if (!_Fs_) { getZero4(Fs); }
|
||||
else { getReg4(Fs, _Fs_); }
|
||||
}
|
||||
|
@ -253,13 +253,13 @@ microVUt(void) mVUallocFMAC7b(int& ACC, int& Fs) {
|
|||
// 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;
|
||||
Fs = xmmFs;
|
||||
Ft = xmmFt;
|
||||
Fd = xmmFs;
|
||||
ACC = xmmACC0 + readACC;
|
||||
if (_XYZW_SS && _X) {
|
||||
ACC = xmmACC;
|
||||
if (_X_Y_Z_W == 8) {
|
||||
getReg6(Fs, _Fs_);
|
||||
if (_Ft_ == _Fs_) { Ft = Fs; }
|
||||
else { getReg6(Ft, _Ft_); }
|
||||
|
@ -285,14 +285,14 @@ microVUt(void) mVUallocFMAC8b(int& 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;
|
||||
Fs = xmmFs;
|
||||
Ft = xmmFt;
|
||||
Fd = xmmT1;
|
||||
ACC = xmmT1;
|
||||
SSE_MOVAPS_XMM_to_XMM(ACC, xmmACC0 + readACC);
|
||||
if (_XYZW_SS && _X) {
|
||||
SSE_MOVAPS_XMM_to_XMM(ACC, xmmACC);
|
||||
if (_X_Y_Z_W == 8) {
|
||||
getReg6(Fs, _Fs_);
|
||||
if (_Ft_ == _Fs_) { Ft = Fs; }
|
||||
else { getReg6(Ft, _Ft_); }
|
||||
|
@ -323,8 +323,8 @@ microVUt(void) mVUallocFMAC10a(int& Fd, int& ACC, int& Fs, int& Ft) {
|
|||
Fs = xmmFs;
|
||||
Ft = xmmFt;
|
||||
Fd = xmmFs;
|
||||
ACC = xmmACC0 + readACC;
|
||||
if (_XYZW_SS && _X) {
|
||||
ACC = xmmACC;
|
||||
if (_X_Y_Z_W == 8) {
|
||||
getReg6(Fs, _Fs_);
|
||||
if ( (_Ft_ == _Fs_) && _bc_x) { Ft = Fs; }
|
||||
else if (!_Ft_) { getZero3SS(Ft); }
|
||||
|
@ -353,8 +353,8 @@ microVUt(void) mVUallocFMAC11a(int& Fd, int& ACC, int& Fs, int& Ft) {
|
|||
Ft = xmmFt;
|
||||
Fd = xmmT1;
|
||||
ACC = xmmT1;
|
||||
SSE_MOVAPS_XMM_to_XMM(ACC, xmmACC0 + readACC);
|
||||
if (_XYZW_SS && _X) {
|
||||
SSE_MOVAPS_XMM_to_XMM(ACC, xmmACC);
|
||||
if (_X_Y_Z_W == 8) {
|
||||
getReg6(Fs, _Fs_);
|
||||
if ( (_Ft_ == _Fs_) && _bc_x) { Ft = Fs; }
|
||||
else if (!_Ft_) { getZero3SS(Ft); }
|
||||
|
@ -377,14 +377,14 @@ microVUt(void) mVUallocFMAC11b(int& Fd) {
|
|||
// 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;
|
||||
Fs = xmmFs;
|
||||
Ft = xmmFt;
|
||||
Fd = xmmFs;
|
||||
ACC = xmmACC0 + readACC;
|
||||
ACC = xmmACC;
|
||||
getIreg(Ft);
|
||||
if (_XYZW_SS && _X) { getReg6(Fs, _Fs_); }
|
||||
if (_X_Y_Z_W == 8) { getReg6(Fs, _Fs_); }
|
||||
else if (!_Fs_) { getZero4(Fs); }
|
||||
else { getReg4(Fs, _Fs_); }
|
||||
}
|
||||
|
@ -397,15 +397,15 @@ microVUt(void) mVUallocFMAC12b(int& Fd) {
|
|||
// 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;
|
||||
Fs = xmmFs;
|
||||
Ft = xmmFt;
|
||||
Fd = xmmT1;
|
||||
ACC = xmmT1;
|
||||
SSE_MOVAPS_XMM_to_XMM(ACC, xmmACC0 + readACC);
|
||||
SSE_MOVAPS_XMM_to_XMM(ACC, xmmACC);
|
||||
getIreg(Ft);
|
||||
if (_XYZW_SS && _X) { getReg6(Fs, _Fs_); }
|
||||
if (_X_Y_Z_W == 8) { getReg6(Fs, _Fs_); }
|
||||
else if (!_Fs_) { getZero4(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;
|
||||
getACC(ACCw);
|
||||
Fs = (_X_Y_Z_W == 15) ? ACCw : xmmFs;
|
||||
Fs = xmmFs;
|
||||
Ft = xmmFt;
|
||||
ACCr = xmmACC0 + readACC;
|
||||
if (_XYZW_SS && _X) {
|
||||
ACCw = xmmACC;
|
||||
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_);
|
||||
if (_Ft_ == _Fs_) { Ft = Fs; }
|
||||
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) {
|
||||
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) {
|
||||
microVUt(void) mVUallocFMAC14b(int& ACCw, int& ACCr) {
|
||||
microVU* mVU = mVUx;
|
||||
if (CHECK_VU_OVERFLOW) mVUclamp1<vuIndex>(ACCr, xmmFt, _xyzw_ACC);
|
||||
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;
|
||||
getACC(ACCw);
|
||||
Fs = (_X_Y_Z_W == 15) ? ACCw : xmmFs;
|
||||
Fs = xmmFs;
|
||||
Ft = xmmFt;
|
||||
ACCr = xmmACC0 + readACC;
|
||||
if (_XYZW_SS && _X) {
|
||||
ACCw = xmmACC;
|
||||
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_);
|
||||
if ((_Ft_ == _Fs_) && _bc_x) { Ft = Fs; }
|
||||
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) {
|
||||
mVUallocFMAC14b<vuIndex>(ACCw, Fs);
|
||||
microVUt(void) mVUallocFMAC15b(int& ACCw, int& ACCr) {
|
||||
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) {
|
||||
mVUallocFMAC16a<vuIndex>(ACCw, ACCr, Fs, Ft);
|
||||
SSE_MOVAPS_XMM_to_XMM(xmmT1, ACCr);
|
||||
ACCr = xmmT1;
|
||||
microVUt(void) mVUallocFMAC16a(int& ACCw, int& ACCr, int& Fs, int& Ft) {
|
||||
microVU* mVU = mVUx;
|
||||
Fs = xmmFs;
|
||||
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) {
|
||||
mVUallocFMAC15b<vuIndex>(ACCw, ACCr);
|
||||
microVUt(void) mVUallocFMAC16b(int& ACCw, int& ACCr) {
|
||||
mVUallocFMAC14b<vuIndex>(ACCw, ACCr);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
|
@ -512,7 +507,7 @@ microVUt(void) mVUallocFMAC18a(int& ACC, int& Fs, int& Ft) {
|
|||
microVU* mVU = mVUx;
|
||||
Fs = xmmFs;
|
||||
Ft = xmmFt;
|
||||
getACC(ACC);
|
||||
ACC = xmmACC;
|
||||
|
||||
if (!_Fs_) { getZero4(Fs); }
|
||||
else { getReg4(Fs, _Fs_); }
|
||||
|
@ -532,13 +527,13 @@ microVUt(void) mVUallocFMAC18b(int& ACC, int& Fs) {
|
|||
// 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;
|
||||
Fs = xmmFs;
|
||||
Ft = xmmFt;
|
||||
Fd = xmmT1;
|
||||
ACC = xmmT1;
|
||||
SSE_MOVAPS_XMM_to_XMM(ACC, xmmACC0 + readACC);
|
||||
SSE_MOVAPS_XMM_to_XMM(ACC, xmmACC);
|
||||
|
||||
if (!_Fs_) { getZero4(Fs); }
|
||||
else { getReg4(Fs, _Fs_); }
|
||||
|
@ -554,40 +549,6 @@ microVUt(void) mVUallocFMAC19b(int& 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)
|
||||
//------------------------------------------------------------------
|
||||
|
@ -616,11 +577,11 @@ microVUt(void) mVUallocFMAC22b(int& Fd) {
|
|||
|
||||
microVUt(void) mVUallocFMAC23a(int& ACC, int& Fs, int& Ft) {
|
||||
microVU* mVU = mVUx;
|
||||
Fs = xmmFs;
|
||||
ACC = xmmACC;
|
||||
Fs = (_X_Y_Z_W == 15) ? xmmACC : xmmFs;
|
||||
Ft = xmmFt;
|
||||
getACC(ACC);
|
||||
getQreg(Ft);
|
||||
if (_XYZW_SS && _X) { getReg6(Fs, _Fs_); }
|
||||
if (_X_Y_Z_W == 8) { getReg6(Fs, _Fs_); }
|
||||
else if (!_Fs_) { getZero4(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)
|
||||
//------------------------------------------------------------------
|
||||
|
||||
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;
|
||||
Fs = xmmFs;
|
||||
Ft = xmmFt;
|
||||
Fd = xmmFs;
|
||||
ACC = xmmACC0 + readACC;
|
||||
ACC = xmmACC;
|
||||
getQreg(Ft);
|
||||
if (_XYZW_SS && _X) { getReg6(Fs, _Fs_); }
|
||||
if (_X_Y_Z_W == 8) { getReg6(Fs, _Fs_); }
|
||||
else if (!_Fs_) { getZero4(Fs); }
|
||||
else { getReg4(Fs, _Fs_); }
|
||||
}
|
||||
|
@ -653,15 +614,15 @@ microVUt(void) mVUallocFMAC24b(int& Fd) {
|
|||
// 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;
|
||||
Fs = xmmFs;
|
||||
Ft = xmmFt;
|
||||
Fd = xmmT1;
|
||||
ACC = xmmT1;
|
||||
SSE_MOVAPS_XMM_to_XMM(ACC, xmmACC0 + readACC);
|
||||
SSE_MOVAPS_XMM_to_XMM(ACC, xmmACC);
|
||||
getQreg(Ft);
|
||||
if (_XYZW_SS && _X) { getReg6(Fs, _Fs_); }
|
||||
if (_X_Y_Z_W == 8) { getReg6(Fs, _Fs_); }
|
||||
else if (!_Fs_) { getZero4(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;
|
||||
getACC(ACCw);
|
||||
Fs = (_X_Y_Z_W == 15) ? ACCw : xmmFs;
|
||||
Fs = xmmFs;
|
||||
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);
|
||||
if (_XYZW_SS && _X) { getReg6(Fs, _Fs_); }
|
||||
if (_X_Y_Z_W == 8) { getReg6(Fs, _Fs_); }
|
||||
else if (!_Fs_) { getZero4(Fs); }
|
||||
else { getReg4(Fs, _Fs_); }
|
||||
}
|
||||
|
||||
microVUt(void) mVUallocFMAC26b(int& ACCw, int& Fs) {
|
||||
mVUallocFMAC14b<vuIndex>(ACCw, Fs);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// 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);
|
||||
microVUt(void) mVUallocFMAC26b(int& ACCw, int& ACCr) {
|
||||
mVUallocFMAC14b<vuIndex>(ACCw, ACCr);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
|
@ -741,6 +689,16 @@ microVUt(void) mVUallocMFLAGb(int reg, int fInstance) {
|
|||
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
|
||||
//------------------------------------------------------------------
|
||||
|
@ -788,4 +746,10 @@ microVUt(void) mVUallocVIb(int GPRreg, int _reg_) {
|
|||
if (!_reg_) { getZero(reg); } \
|
||||
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
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue