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

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

View File

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

View File

@ -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"

View File

@ -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="&quot;$(ProjectDir)&quot;;&quot;$(ProjectDir)\include&quot;"
PreprocessorDefinitions="PTW32_STATIC_LIB;PTW32_BUILD_INLINED;__CLEANUP_SEH;WIN32;NDEBUG;_LIB"
StringPooling="true"

View File

@ -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

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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];

View File

@ -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

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

@ -0,0 +1,99 @@
/* Pcsx2 - Pc Ps2 Emulator
* Copyright (C) 2002-2009 Pcsx2 Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef __PCSX2API_H__
#define __PCSX2API_H__
// Note; this header is experimental, and will be a shifting target. Only use this if you are willing to repeatedly fix breakage.
/*
* Based on PS2E Definitions by
linuzappz@hotmail.com,
* shadowpcsx2@yahoo.gr,
* and florinsasu@hotmail.com
*/
#include "Pcsx2Types.h"
#include "Pcsx2Defs.h"
#include "Pcsx2Config.h"
// Indicate to use the new versions.
#define NEW_PLUGIN_APIS
#ifdef _MSC_VER
#define EXPORT_C(type) extern "C" __declspec(dllexport) type CALLBACK
#else
#define EXPORT_C(type) extern "C" type
#endif
EXPORT_C(u32) PS2EgetLibType(void);
EXPORT_C(u32) PS2EgetLibVersion2(u32 type);
EXPORT_C(char*) PS2EgetLibName(void);
// Extended functions.
// allows the plugin to see the whole configuration when started up.
// Intended for them to get the ini and plugin paths, but could allow for other things as well.
EXPORT_C_(void) PS2EpassConfig(PcsxConfig Config);
// PS2EgetLibType returns (may be OR'd)
enum {
PS2E_LT_GS = 0x01,
PS2E_LT_PAD = 0x02, // -=[ OBSOLETE ]=-
PS2E_LT_SPU2 = 0x04,
PS2E_LT_CDVD = 0x08,
PS2E_LT_DEV9 = 0x10,
PS2E_LT_USB = 0x20,
PS2E_LT_FW = 0x40,
PS2E_LT_SIO = 0x80
} PluginLibType;
// PS2EgetLibVersion2 (high 16 bits)
enum {
PS2E_GS_VERSION = 0x0006,
PS2E_PAD_VERSION = 0x0002, // -=[ OBSOLETE ]=-
PS2E_SPU2_VERSION = 0x0005,
PS2E_CDVD_VERSION = 0x0005,
PS2E_DEV9_VERSION = 0x0003,
PS2E_USB_VERSION = 0x0003,
PS2E_FW_VERSION = 0x0002,
PS2E_SIO_VERSION = 0x0001
} PluginLibVersion;
// freeze modes:
enum {
FREEZE_LOAD = 0,
FREEZE_SAVE = 1,
FREEZE_SIZE = 2
} FreezeModes;
typedef struct _GSdriverInfo {
char name[8];
void *common;
} GSdriverInfo;
#ifdef _MSC_VER
typedef struct _winInfo { // unsupported values must be set to zero
HWND hWnd;
HMENU hMenu;
HWND hStatusWnd;
} winInfo;
#endif
#endif // __PCSX2API_H__

View File

@ -66,7 +66,7 @@ extern SessionOverrideFlags g_Session;
//------------ SPECIAL GAME FIXES!!! ---------------
#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!!! ---------------

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

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

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

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

View File

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

View File

@ -0,0 +1,135 @@
/* Pcsx2 - Pc Ps2 Emulator
* Copyright (C) 2002-2009 Pcsx2 Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef __CDVDAPI_H__
#define __CDVDAPI_H__
// Note; this header is experimental, and will be a shifting target. Only use this if you are willing to repeatedly fix breakage.
/*
* Based on PS2E Definitions by
linuzappz@hotmail.com,
* shadowpcsx2@yahoo.gr,
* and florinsasu@hotmail.com
*/
#include "Pcsx2Api.h"
/* CDVD plugin API */
// Basic functions.
EXPORT_C_(s32) CDVDinit();
EXPORT_C_(s32) CDVDopen(void *pDisplay, const char* pTitleFilename);
EXPORT_C_(void) CDVDclose();
EXPORT_C_(void) CDVDshutdown();
EXPORT_C_(s32) CDVDreadTrack(u32 lsn, int mode);
// return can be NULL (for async modes)
EXPORT_C_(u8*) CDVDgetBuffer();
EXPORT_C_(s32) CDVDreadSubQ(u32 lsn, cdvdSubQ* subq);//read subq from disc (only cds have subq data)
EXPORT_C_(s32) CDVDgetTN(cdvdTN *Buffer); //disk information
EXPORT_C_(s32) CDVDgetTD(u8 Track, cdvdTD *Buffer); //track info: min,sec,frame,type
EXPORT_C_(s32) CDVDgetTOC(void* toc); //gets ps2 style toc from disc
EXPORT_C_(s32) CDVDgetDiskType(); //CDVD_TYPE_xxxx
EXPORT_C_(s32) CDVDgetTrayStatus(); //CDVD_TRAY_xxxx
EXPORT_C_(s32) CDVDctrlTrayOpen(); //open disc tray
EXPORT_C_(s32) CDVDctrlTrayClose(); //close disc tray
// Extended functions
EXPORT_C_(void) CDVDkeyEvent(keyEvent *ev);
EXPORT_C_(void) CDVDconfigure();
EXPORT_C_(s32) CDVDfreeze(u8 mode, freezeData *data);
EXPORT_C_(void) CDVDabout();
EXPORT_C_(s32) CDVDtest();
EXPORT_C_(void) CDVDnewDiskCB(void (*callback)());
typedef struct _cdvdSubQ {
u8 ctrl:4; // control and mode bits
u8 mode:4; // control and mode bits
u8 trackNum; // current track number (1 to 99)
u8 trackIndex; // current index within track (0 to 99)
u8 trackM; // current minute location on the disc (BCD encoded)
u8 trackS; // current sector location on the disc (BCD encoded)
u8 trackF; // current frame location on the disc (BCD encoded)
u8 pad; // unused
u8 discM; // current minute offset from first track (BCD encoded)
u8 discS; // current sector offset from first track (BCD encoded)
u8 discF; // current frame offset from first track (BCD encoded)
} cdvdSubQ;
typedef struct _cdvdTD { // NOT bcd coded
u32 lsn;
u8 type;
} cdvdTD;
typedef struct _cdvdTN {
u8 strack; //number of the first track (usually 1)
u8 etrack; //number of the last track
} cdvdTN;
// CDVDreadTrack mode values:
enum {
CDVD_MODE_2352 0, // full 2352 bytes
CDVD_MODE_2340 1, // skip sync (12) bytes
CDVD_MODE_2328 2, // skip sync+head+sub (24) bytes
CDVD_MODE_2048 3, // skip sync+head+sub (24) bytes
CDVD_MODE_2368 4 // full 2352 bytes + 16 subq
} TrackModes
// CDVDgetDiskType returns:
enum {
CDVD_TYPE_ILLEGAL = 0xff, // Illegal Disc
CDVD_TYPE_DVDV = 0xfe, // DVD Video
CDVD_TYPE_CDDA = 0xfd, // Audio CD
CDVD_TYPE_PS2DVD = 0x14, // PS2 DVD
CDVD_TYPE_PS2CDDA = 0x13, // PS2 CD (with audio)
CDVD_TYPE_PS2CD = 0x12, // PS2 CD
CDVD_TYPE_PSCDDA = 0x11, // PS CD (with audio)
CDVD_TYPE_PSCD = 0x10, // PS CD
CDVD_TYPE_UNKNOWN = 0x05, // Unknown
CDVD_TYPE_DETCTDVDD = 0x04, // Detecting Dvd Dual Sided
CDVD_TYPE_DETCTDVDS = 0x03, // Detecting Dvd Single Sided
CDVD_TYPE_DETCTCD = 0x02, // Detecting Cd
CDVD_TYPE_DETCT = 0x01, // Detecting
CDVD_TYPE_NODISC = 0x00 // No Disc
} DiskType;
// CDVDgetTrayStatus returns:
enum {
CDVD_TRAY_CLOSE = 0x00,
CDVD_TRAY_OPEN = 0x01
} TrayStatus;
// cdvdTD.type (track types for cds)
enum {
CDVD_AUDIO_TRACK = 0x01,
CDVD_MODE1_TRACK = 0x41,
CDVD_MODE2_TRACK = 0x61
} CDVDTDType;
enum {
CDVD_AUDIO_MASK = 0x00,
CDVD_DATA_MASK = 0x40
// CDROM_DATA_TRACK 0x04 //do not enable this! (from linux kernel)
} CDVD_Masks;
#endif // __CDVDAPI_H__

View File

@ -0,0 +1,68 @@
/* Pcsx2 - Pc Ps2 Emulator
* Copyright (C) 2002-2009 Pcsx2 Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef __DEV9API_H__
#define __DEV9API_H__
// Note; this header is experimental, and will be a shifting target. Only use this if you are willing to repeatedly fix breakage.
/*
* Based on PS2E Definitions by
* linuzappz@hotmail.com,
* shadowpcsx2@yahoo.gr,
* and florinsasu@hotmail.com
*/
#include "Pcsx2Api.h"
typedef void (*DEV9callback)(int cycles);
typedef int (*DEV9handler)(void);
// Basic functions.
// NOTE: The read/write functions CANNOT use XMM/MMX regs
// If you want to use them, need to save and restore current ones
EXPORT_C_(s32) DEV9init();
// pDisplay normally is passed a handle to the GS plugins window.
EXPORT_C_(s32) DEV9open(void *pDisplay);
EXPORT_C_(void) DEV9close();
EXPORT_C_(void) DEV9shutdown();
EXPORT_C_(u8) DEV9read8(u32 addr);
EXPORT_C_(u16) DEV9read16(u32 addr);
EXPORT_C_(u32) DEV9read32(u32 addr);
EXPORT_C_(void) DEV9write8(u32 addr, u8 value);
EXPORT_C_(void) DEV9write16(u32 addr, u16 value);
EXPORT_C_(void) DEV9write32(u32 addr, u32 value);
EXPORT_C_(void) DEV9readDMA8Mem(u32 *pMem, int size);
EXPORT_C_(void) DEV9writeDMA8Mem(u32 *pMem, int size);
// cycles = IOP cycles before calling callback,
// if callback returns 1 the irq is triggered, else not
EXPORT_C_(void) DEV9irqCallback(DEV9callback callback);
EXPORT_C_(DEV9handler) DEV9irqHandler(void);
// Extended functions
EXPORT_C_(void) DEV9keyEvent(keyEvent *ev);
EXPORT_C_(s32) DEV9freeze(u8 mode, freezeData *data);
EXPORT_C_(void) DEV9configure();
EXPORT_C_(void) DEV9about();
EXPORT_C_(s32) DEV9test();
#endif // __DEV9API_H__

View File

@ -0,0 +1,58 @@
/* Pcsx2 - Pc Ps2 Emulator
* Copyright (C) 2002-2009 Pcsx2 Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef __FWAPI_H__
#define __FWAPI_H__
// Note; this header is experimental, and will be a shifting target. Only use this if you are willing to repeatedly fix breakage.
/*
* Based on PS2E Definitions by
linuzappz@hotmail.com,
* shadowpcsx2@yahoo.gr,
* and florinsasu@hotmail.com
*/
#include "Pcsx2Api.h"
/* FW plugin API */
// Basic functions.
// NOTE: The read/write functions CANNOT use XMM/MMX regs
// If you want to use them, need to save and restore current ones
EXPORT_C_(s32) FWinit();
// pDisplay normally is passed a handle to the GS plugins window.
EXPORT_C_(s32) FWopen(void *pDisplay);
EXPORT_C_(void) FWclose();
EXPORT_C_(void) FWshutdown();
EXPORT_C_(u32) FWread32(u32 addr);
EXPORT_C_(void) FWwrite32(u32 addr, u32 value);
EXPORT_C_(void) FWirqCallback(void (*callback)());
// Extended functions
EXPORT_C_(void) FWkeyEvent(keyEvent *ev);
EXPORT_C_(s32) FWfreeze(u8 mode, freezeData *data);
EXPORT_C_(void) FWconfigure();
EXPORT_C_(void) FWabout();
EXPORT_C_(s32) FWtest();
#endif
#endif // __USBAPI_H__

View File

@ -0,0 +1,85 @@
/* Pcsx2 - Pc Ps2 Emulator
* Copyright (C) 2002-2009 Pcsx2 Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef __GSAPI_H__
#define __GSAPI_H__
// Note; this header is experimental, and will be a shifting target. Only use this if you are willing to repeatedly fix breakage.
/*
* Based on PS2E Definitions by
linuzappz@hotmail.com,
* shadowpcsx2@yahoo.gr,
* and florinsasu@hotmail.com
*/
#include "Pcsx2Api.h"
typedef struct _GSdriverInfo {
char name[8];
void *common;
} GSdriverInfo;
// Basic functions.
EXPORT_C_(s32) GSinit();
// pDisplay normally is passed a handle to the GS plugins window.
EXPORT_C_(s32) GSopen(void *pDisplay, char *Title, bool multithread);
EXPORT_C_(void) GSclose();
EXPORT_C_(void) GSshutdown();
EXPORT_C_(void) GSvsync(int field);
EXPORT_C_(void) GSgifTransfer1(u32 *pMem, u32 addr);
EXPORT_C_(void) GSgifTransfer2(u32 *pMem, u32 size);
EXPORT_C_(void) GSgifTransfer3(u32 *pMem, u32 size);
EXPORT_C_(void) GSgetLastTag(u64* ptag); // returns the last tag processed (64 bits)
EXPORT_C_(void) GSgifSoftReset(u32 mask);
EXPORT_C_(void) GSreadFIFO(u64 *mem);
EXPORT_C_(void) GSreadFIFO2(u64 *mem, int qwc);
// Extended functions
// GSkeyEvent gets called when there is a keyEvent from the PAD plugin
EXPORT_C_(void) GSkeyEvent(keyEvent *ev);
EXPORT_C_(void) GSchangeSaveState(s32 state, const char* filename);
EXPORT_C_(void) GSmakeSnapshot(char *path);
EXPORT_C_(void) GSmakeSnapshot2(char *pathname, int* snapdone, int savejpg);
EXPORT_C_(void) GSirqCallback(void (*callback)());
EXPORT_C_(void) CALLBACK GSprintf(s32 timeout, char *fmt, ...);
EXPORT_C_(void) GSsetBaseMem(void*);
EXPORT_C_(void) GSsetGameCRC(s32 crc, s32 gameoptions);
// controls frame skipping in the GS, if this routine isn't present, frame skipping won't be done
EXPORT_C_(void) GSsetFrameSkip(int frameskip);
// if start is true, starts recording spu2 data, else stops
// returns true if successful
// for now, pData is not used
EXPORT_C_(bool) GSsetupRecording(bool start);
EXPORT_C_(void) GSreset();
EXPORT_C_(void) GSwriteCSR(u32 value);
EXPORT_C_(void ) GSgetDriverInfo(GSdriverInfo *info);
#ifdef _WIN32
EXPORT_C_(s32) CALLBACK GSsetWindowInfo(winInfo *info);
#endif
EXPORT_C_(s32) GSfreeze(u8 mode, freezeData *data);
EXPORT_C_(void) GSconfigure();
EXPORT_C_(void) GSabout();
EXPORT_C_(s32) GStest();
#endif // __GSAPI_H__

View File

@ -0,0 +1,68 @@
/* Pcsx2 - Pc Ps2 Emulator
* Copyright (C) 2002-2009 Pcsx2 Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef __PADAPI_H__
#define __PADAPI_H__
// Note; this header is experimental, and will be a shifting target. Only use this if you are willing to repeatedly fix breakage.
/*
* Based on PS2E Definitions by
linuzappz@hotmail.com,
* shadowpcsx2@yahoo.gr,
* and florinsasu@hotmail.com
*/
#include "Pcsx2Api.h"
/* PAD plugin API */
/* So obsolete that everyone uses it. */
// Basic functions.
EXPORT_C_(s32) PADinit(u32 flags);
// pDisplay normally is passed a handle to the GS plugins window.
EXPORT_C_(s32) PADopen(void *pDisplay);
EXPORT_C_(void) PADclose();
EXPORT_C_(void) PADshutdown();
// PADkeyEvent is called every vsync (return NULL if no event)
EXPORT_C_(keyEvent*) PADkeyEvent();
EXPORT_C_(u8) PADstartPoll(u8 pad);
EXPORT_C_(u8) PADpoll(u8 value);
// returns: 1 if supported pad1
// 2 if supported pad2
// 3 if both are supported
EXPORT_C_(u8) PADquery();
// call to give a hint to the PAD plugin to query for the keyboard state. A
// good plugin will query the OS for keyboard state ONLY in this function.
// This function is necessary when multithreading because otherwise
// the PAD plugin can get into deadlocks with the thread that really owns
// the window (and input). Note that PADupdate can be called from a different
// thread than the other functions, so mutex or other multithreading primitives
// have to be added to maintain data integrity.
EXPORT_C_(void) PADupdate(u8 pad);
// Extended functions
EXPORT_C_(void) PADgsDriverInfo(GSdriverInfo *info);
EXPORT_C_(s32) PADfreeze(u8 mode, freezeData *data);
EXPORT_C_(void) PADconfigure();
EXPORT_C_(void) PADabout();
EXPORT_C_(s32) PADtest();
#endif // __PADAPI_H__

View File

@ -0,0 +1,86 @@
/* Pcsx2 - Pc Ps2 Emulator
* Copyright (C) 2002-2009 Pcsx2 Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef __SIOAPI_H__
#define __SIOAPI_H__
// Note; this header is experimental, and will be a shifting target. Only use this if you are willing to repeatedly fix breakage.
/*
* Based on PS2E Definitions by
linuzappz@hotmail.com,
* shadowpcsx2@yahoo.gr,
* and florinsasu@hotmail.com
*/
#include "Pcsx2Api.h"
/* SIO plugin API */
// Called by SIO_TYPE_MTAP plugins to change the slot.
// Slot is then passed to memcard and pad plugins on SIOstartPoll.
// MTAP SIO plugins should ignore slot values on startPoll, as should RMs (probably).
// Port isn't strictly necessary, but doesn't hurt.
typedef int (CALLBACK * SIOchangeSlotCB)(int port, int slot);
// Basic functions.
// Types is an or-ed combination of SioTypes to initialize. It'd probably be simplest
// just to make each SIO plugin support only one type, for simplicity.
// SIOchangeSlotCB should *only* be called by MTAP plugins.
EXPORT_C_(s32) SIOinit(int types, SIOchangeSlotCB f);
// Single plugin can only be PAD, MTAP, RM, or MC. Only load one plugin of each type,
// but not both a PAD and MTAP. Simplifies plugin selection and interface, as well
// as API.
// pDisplay normally is passed a handle to the GS plugins window.
EXPORT_C_(s32) SIOopen(void *pDisplay);
EXPORT_C_(void) SIOclose();
EXPORT_C_(void) SIOshutdown();
// Returns 0 if device doesn't exist. Means old pad plugins can just say nothing
// connected to other slots, and SIOpoll won't be called on those slots, ideally.
EXPORT_C_(s32) SIOstartPoll(u8 deviceType, u32 port, u32 slot, u8 *returnValue);
// Returns 0 on the last output byte.
EXPORT_C_(s32) SIOpoll(u8 value, u8 *returnValue);
// returns: SIO_TYPE_{PAD,MTAP,RM,MC}
EXPORT_C_(u32) SIOquery();
// extended funcs
EXPORT_C_(void) SIOconfigure();
EXPORT_C_(keyEvent*) CALLBACK SIOkeyEvent();
// Save one type at a time. If a plugin supports all 4 types,
// should expect 4 calls. Increases savestate compatibility.
EXPORT_C_(s32) SIOfreeze(u8 mode, freezeData *data, int type);
EXPORT_C_(void) SIOabout();
EXPORT_C_(s32) SIOtest();
enum {
SIO_TYPE_PAD = 0x00000001,
SIO_TYPE_MTAP = 0x00000004,
SIO_TYPE_RM = 0x00000040,
SIO_TYPE_MC = 0x00000100
} SioTypes;
#endif // __SIOAPI_H__

View File

@ -0,0 +1,77 @@
/* Pcsx2 - Pc Ps2 Emulator
* Copyright (C) 2002-2009 Pcsx2 Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef __SPU2API_H__
#define __SPU2API_H__
// Note; this header is experimental, and will be a shifting target. Only use this if you are willing to repeatedly fix breakage.
/*
* Based on PS2E Definitions by
linuzappz@hotmail.com,
* shadowpcsx2@yahoo.gr,
* and florinsasu@hotmail.com
*/
#include "Pcsx2Api.h"
EXPORT_C_(s32) SPU2init();
// pDisplay normally is passed a handle to the GS plugins window.
EXPORT_C_(s32) SPU2open(void *pDisplay);
EXPORT_C_(void) SPU2close();
EXPORT_C_(void) SPU2shutdown();
EXPORT_C_(void) SPU2write(u32 mem, u16 value);
EXPORT_C_(u16) SPU2read(u32 mem);
// The following calls are depreciated.
EXPORT_C_(void) SPU2readDMA4Mem(u16 *pMem, u32 size);
EXPORT_C_(void) SPU2readDMA7Mem(u16 *pMem, u32 size);
EXPORT_C_(void) SPU2writeDMA4Mem(u16 *pMem, u32 size);
EXPORT_C_(void) SPU2writeDMA7Mem(u16 *pMem, u32 size);
EXPORT_C_(void) SPU2interruptDMA4();
EXPORT_C_(void) SPU2interruptDMA7();
// These calls replace the calls above.
EXPORT_C_(void) SPU2readDMAMem(u16 *pMem, u32 size, u8 core);
EXPORT_C_(void) SPU2writeDMAMem(u16 *pMem, u32 size, u8 core);
EXPORT_C_(void) SPU2interruptDMA(u8 core);
// all addresses passed by dma will be pointers to the array starting at baseaddr
// This function is necessary to successfully save and reload the spu2 state
EXPORT_C_(void) SPU2setDMABaseAddr(uptr baseaddr);
EXPORT_C_(u32) SPU2ReadMemAddr(u8 core);
EXPORT_C_(void) SPU2WriteMemAddr(u8 core,u32 value);
EXPORT_C_(void) SPU2irqCallback(void (*SPU2callback)(),void (*DMA4callback)(),void (*DMA7callback)());
// extended funcs
// if start is true, starts recording spu2 data, else stops
// returns true if successful
EXPORT_C_(bool) SPU2setupRecording(bool start);
EXPORT_C_(void) SPU2keyEvent(keyEvent *ev);
EXPORT_C_(void) SPU2setClockPtr(u32* ptr);
EXPORT_C_(void) SPU2async(u32 cycles);
EXPORT_C_(s32) SPU2freeze(u8 mode, freezeData *data);
EXPORT_C_(void) SPU2configure();
EXPORT_C_(void) SPU2about();
EXPORT_C_(s32) SPU2test();
#endif

View File

@ -0,0 +1,65 @@
/* Pcsx2 - Pc Ps2 Emulator
* Copyright (C) 2002-2009 Pcsx2 Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef __USBAPI_H__
#define __USBAPI_H__
// Note; this header is experimental, and will be a shifting target. Only use this if you are willing to repeatedly fix breakage.
/*
* Based on PS2E Definitions by
linuzappz@hotmail.com,
* shadowpcsx2@yahoo.gr,
* and florinsasu@hotmail.com
*/
#include "Pcsx2Api.h"
typedef void (*USBcallback)(int cycles);
typedef int (*USBhandler)(void);
// Basic functions.
EXPORT_C_(s32) USBinit();
// pDisplay normally is passed a handle to the GS plugins window.
EXPORT_C_(s32) USBopen(void *pDisplay);
EXPORT_C_(void) USBclose();
EXPORT_C_(void) USBshutdown();
EXPORT_C_(u8) USBread8(u32 addr);
EXPORT_C_(u16) USBread16(u32 addr);
EXPORT_C_(u32) USBread32(u32 addr);
EXPORT_C_(void) USBwrite8(u32 addr, u8 value);
EXPORT_C_(void) USBwrite16(u32 addr, u16 value);
EXPORT_C_(void) USBwrite32(u32 addr, u32 value);
EXPORT_C_(void) USBasync(u32 cycles);
// cycles = IOP cycles before calling callback,
// if callback returns 1 the irq is triggered, else not
EXPORT_C_(void) USBirqCallback(USBcallback callback);
EXPORT_C_(USBhandler) USBirqHandler(void);
EXPORT_C_(void) USBsetRAM(void *mem);
// Extended functions
EXPORT_C_(void) USBkeyEvent(keyEvent *ev);
EXPORT_C_(s32) USBfreeze(u8 mode, freezeData *data);
EXPORT_C_(void) USBconfigure();
EXPORT_C_(void) USBabout();
EXPORT_C_(s32) USBtest();
#endif // __USBAPI_H__

View File

@ -79,35 +79,53 @@ enum cdvdActions
, cdvdAction_Read // note: not used yet.
};
//////////////////////////////////////////////////////////////////////////
// -- 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

View File

@ -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
*/

View File

@ -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;

View File

@ -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;
}

View File

@ -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() )
{

View File

@ -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;

View File

@ -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.
}

View File

@ -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)

View File

@ -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);

View File

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

View File

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

View File

@ -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;
};

View File

@ -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

View File

@ -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])

View File

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

View File

@ -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);

View File

@ -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

View File

@ -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"

View File

@ -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);

View File

@ -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");

View File

@ -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;

View File

@ -1868,10 +1868,10 @@ Known to work well with a couple games, namely Shadow of the Colossus (but break
<property name="spacing">0</property>
<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>

View File

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

View File

@ -104,11 +104,7 @@ void loadBiosRom( const char *ext, u8 *dest, long maxSize )
Bios1 = Path::Combine( Config.BiosDir, ext ) + ".bin";
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();
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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();
}

View File

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

View File

@ -71,6 +71,7 @@ _PADgsDriverInfo PAD1gsDriverInfo;
_PADconfigure PAD1configure;
_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;
}

View File

@ -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);

View File

@ -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 );

View File

@ -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

View File

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

View File

@ -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);
}

View File

@ -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);
}
//////////////////////////////////////////////////////////////////////////////////

View File

@ -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();

View File

@ -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);
}

View File

@ -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 )
{

View File

@ -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

View File

@ -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

View File

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

View File

@ -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 );

View File

@ -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);
}

View File

@ -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)

View File

@ -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 );
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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.

View File

@ -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

View File

@ -35,8 +35,6 @@ static void InitRoundClampModes( HWND hDlg, u32 new_eeopt, u32 new_vuopt )
else if (new_vuopt & 0x1) CheckRadioButton(hDlg, IDC_VU_CLAMPMODE0, IDC_VU_CLAMPMODE3, IDC_VU_CLAMPMODE0 + 1);
else 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;

View File

@ -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"
>

View File

@ -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);

View File

@ -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;
}
}

View File

@ -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

View File

@ -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));
}

View File

@ -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();
}
};

View File

@ -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.

View File

@ -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);

View File

@ -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);

View File

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

View File

@ -60,7 +60,8 @@ static u8 *recMem = NULL; // the recompiled blocks will be here
static BASEBLOCK *recRAM = NULL; // and the ptr to the blocks here
static BASEBLOCK *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 = {

View File

@ -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;

View File

@ -58,8 +58,6 @@ extern u32 pc; // recompiler pc (also used by the SuperVU! .. why? (a
extern int branch; // set for branch (also used by the SuperVU! .. why? (air))
extern 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 ) \

View File

@ -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];
}

View File

@ -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.

View File

@ -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
}
}

View File

@ -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 = {

View File

@ -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_);

View File

@ -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();
}

View File

@ -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_);
}

View File

@ -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);

View File

@ -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);
}

View File

@ -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]);

View File

@ -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

View File

@ -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();
}
}

View File

@ -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"

View File

@ -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?
};

View File

@ -146,18 +146,18 @@ microVUt(void) mVUallocFMAC3b(int& Fd) {
if (_W) { mVUloadReg<vuIndex>(reg, (uptr)&mVU->regs->VF[0].UL[0], _xyzw_ACC); } \
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