GregMiscellaneous: sync from trunk (3679:3727)

git-svn-id: http://pcsx2.googlecode.com/svn/branches/GregMiscellaneous@3729 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
gregory.hainaut@gmail.com 2010-09-05 15:33:08 +00:00
commit 5e8f776adb
146 changed files with 6586 additions and 8521 deletions

View File

@ -39013,12 +39013,12 @@ Compat = 5
Serial = SLPM-66676 Serial = SLPM-66676
Name = Kingdom Hearts Re: Chain of Memories Name = Kingdom Hearts Re: Chain of Memories
Region = NTSC-J Region = NTSC-J
Compat = 4 Compat = 5
--------------------------------------------- ---------------------------------------------
Serial = SLUS-21799 Serial = SLUS-21799
Name = Kingdom Hearts Re: Chain of Memories Name = Kingdom Hearts Re: Chain of Memories
Region = NTSC-U Region = NTSC-U
Compat = 4 Compat = 5
--------------------------------------------- ---------------------------------------------
Serial = SLUS-21820 Serial = SLUS-21820
Name = Legend Of Spyro - Dawn Of The Dragon Name = Legend Of Spyro - Dawn Of The Dragon

View File

@ -16,16 +16,23 @@
#ifndef __PCSX2TYPES_H__ #ifndef __PCSX2TYPES_H__
#define __PCSX2TYPES_H__ #define __PCSX2TYPES_H__
/* // --------------------------------------------------------------------------------------
* Based on PS2E Definitions by // Forward declarations
linuzappz@hotmail.com, // --------------------------------------------------------------------------------------
* shadowpcsx2@yahoo.gr, // Forward declarations for wxWidgets-supporting features.
* and florinsasu@hotmail.com // If you aren't linking against wxWidgets libraries, then functions that
*/ // depend on these types will not be usable (they will yield linker errors).
#ifdef __cplusplus
class wxString;
class FastFormatAscii;
class FastFormatUnicode;
#endif
////////////////////////////////////////////////////////////////////////////////////////// // --------------------------------------------------------------------------------------
// Basic Atomic Types // Basic Atomic Types
// --------------------------------------------------------------------------------------
#if defined(_MSC_VER) #if defined(_MSC_VER)
@ -111,28 +118,41 @@ typedef s32 sptr;
// performing explicit conversion from 64 and 32 bit values are provided instead. // performing explicit conversion from 64 and 32 bit values are provided instead.
// //
#ifdef __cplusplus #ifdef __cplusplus
struct u128 union u128
{ {
struct
{
u64 lo; u64 lo;
u64 hi; u64 hi;
};
// Explicit conversion from u64 u64 _u64[2];
u32 _u32[4];
u16 _u16[8];
u8 _u8[16];
// Explicit conversion from u64. Zero-extends the source through 128 bits.
static u128 From64( u64 src ) static u128 From64( u64 src )
{ {
u128 retval = { src, 0 }; u128 retval;
retval.lo = src;
retval.hi = 0;
return retval; return retval;
} }
// Explicit conversion from u32 // Explicit conversion from u32. Zero-extends the source through 128 bits.
static u128 From32( u32 src ) static u128 From32( u32 src )
{ {
u128 retval = { src, 0 }; u128 retval;
retval._u32[0] = src;
retval._u32[1] = 0;
retval.hi = 0;
return retval; return retval;
} }
operator u32() const { return (u32)lo; } operator u32() const { return _u32[0]; }
operator u16() const { return (u16)lo; } operator u16() const { return _u16[0]; }
operator u8() const { return (u8)lo; } operator u8() const { return _u8[0]; }
bool operator==( const u128& right ) const bool operator==( const u128& right ) const
{ {
@ -143,6 +163,17 @@ struct u128
{ {
return (lo != right.lo) && (hi != right.hi); return (lo != right.lo) && (hi != right.hi);
} }
// In order for the following ToString() and WriteTo methods to be available, you must
// be linking to both wxWidgets and the pxWidgets extension library. If you are not
// using them, then you will need to provide your own implementations of these methods.
wxString ToString() const;
wxString ToString64() const;
wxString ToString8() const;
void WriteTo( FastFormatAscii& dest ) const;
void WriteTo8( FastFormatAscii& dest ) const;
void WriteTo64( FastFormatAscii& dest ) const;
}; };
struct s128 struct s128
@ -183,13 +214,21 @@ struct s128
typedef union _u128_t typedef union _u128_t
{ {
struct
{
u64 lo; u64 lo;
u64 hi; u64 hi;
};
u64 _u64[2];
u32 _u32[4];
u16 _u16[8];
u8 _u8[16];
} u128; } u128;
typedef union _s128_t typedef union _s128_t
{ {
s64 lo; u64 lo;
s64 hi; s64 hi;
} s128; } s128;

View File

@ -127,11 +127,13 @@ public:
FastFormatAscii& Write( const char* fmt, ... ); FastFormatAscii& Write( const char* fmt, ... );
FastFormatAscii& WriteV( const char* fmt, va_list argptr ); FastFormatAscii& WriteV( const char* fmt, va_list argptr );
const char* GetResult() const; bool IsEmpty() const;
operator const char*() const;
const char* c_str() const { return m_dest->GetPtr(); }
operator const char*() const { return m_dest->GetPtr(); }
const wxString GetString() const; const wxString GetString() const;
operator wxString() const; //operator wxString() const;
}; };
class FastFormatUnicode class FastFormatUnicode
@ -149,18 +151,11 @@ public:
FastFormatUnicode& WriteV( const char* fmt, va_list argptr ); FastFormatUnicode& WriteV( const char* fmt, va_list argptr );
FastFormatUnicode& WriteV( const wxChar* fmt, va_list argptr ); FastFormatUnicode& WriteV( const wxChar* fmt, va_list argptr );
const wxChar* GetResult() const; bool IsEmpty() const;
const wxString GetString() const;
operator const wxChar*() const const wxChar* c_str() const { return (const wxChar*)m_dest->GetPtr(); }
{ operator const wxChar*() const { return (const wxChar*)m_dest->GetPtr(); }
return (const wxChar*)m_dest->GetPtr(); operator wxString() const { return (const wxChar*)m_dest->GetPtr(); }
}
operator wxString() const
{
return (const wxChar*)m_dest->GetPtr();
}
}; };
extern bool pxParseAssignmentString( const wxString& src, wxString& ldest, wxString& rdest ); extern bool pxParseAssignmentString( const wxString& src, wxString& ldest, wxString& rdest );

View File

@ -37,7 +37,7 @@ void* __fastcall pcsx2_aligned_malloc(size_t size, size_t align)
uptr aligned = (pasthead + align-1) & ~(align-1); uptr aligned = (pasthead + align-1) & ~(align-1);
AlignedMallocHeader* header = (AlignedMallocHeader*)(aligned-headsize); AlignedMallocHeader* header = (AlignedMallocHeader*)(aligned-headsize);
jASSUME( (uptr)header >= (uptr)p ); pxAssume( (uptr)header >= (uptr)p );
header->baseptr = p; header->baseptr = p;
header->size = size; header->size = size;

View File

@ -298,7 +298,7 @@ const IConsoleWriter ConsoleWriter_wxError =
}; };
// ===================================================================================================== // =====================================================================================================
// IConsoleWriter Implementations // IConsoleWriter (implementations)
// ===================================================================================================== // =====================================================================================================
// (all non-virtual members that do common work and then pass the result through DoWrite // (all non-virtual members that do common work and then pass the result through DoWrite
// or DoWriteLn) // or DoWriteLn)
@ -569,14 +569,14 @@ const NullConsoleWriter NullCon = {};
bool ConsoleLogSource::WriteV( ConsoleColors color, const char *fmt, va_list list ) const bool ConsoleLogSource::WriteV( ConsoleColors color, const char *fmt, va_list list ) const
{ {
ConsoleColorScope cs(color); ConsoleColorScope cs(color);
DoWrite( pxsFmtV(fmt,list).GetResult() ); DoWrite( pxsFmtV(fmt,list).c_str() );
return false; return false;
} }
bool ConsoleLogSource::WriteV( ConsoleColors color, const wxChar *fmt, va_list list ) const bool ConsoleLogSource::WriteV( ConsoleColors color, const wxChar *fmt, va_list list ) const
{ {
ConsoleColorScope cs(color); ConsoleColorScope cs(color);
DoWrite( pxsFmtV(fmt,list) ); DoWrite( pxsFmtV(fmt,list).c_str() );
return false; return false;
} }

View File

@ -49,21 +49,20 @@ pxDoAssertFnType* pxDoAssert = pxAssertImpl_LogIt;
// response times from the Output window... // response times from the Output window...
wxString DiagnosticOrigin::ToString( const wxChar* msg ) const wxString DiagnosticOrigin::ToString( const wxChar* msg ) const
{ {
wxString message; FastFormatUnicode message;
message.reserve( 2048 );
message.Printf( L"%s(%d) : assertion failed:\n", srcfile, line ); message.Write( L"%s(%d) : assertion failed:\n", srcfile, line );
if( function != NULL ) if( function != NULL )
message += L" Function: " + fromUTF8(function) + L"\n"; message.Write( " Function: %s\n", function );
message += L" Thread: " + Threading::pxGetCurrentThreadName() + L"\n"; message.Write(L" Thread: %s\n", Threading::pxGetCurrentThreadName().c_str() );
if( condition != NULL ) if( condition != NULL )
message += L" Condition: " + wxString(condition) + L"\n"; message.Write(L" Condition: %s\n", condition);
if( msg != NULL ) if( msg != NULL )
message += L" Message: " + wxString(msg) + L"\n"; message.Write(L" Message: %s\n", msg);
return message; return message;
} }

View File

@ -47,7 +47,7 @@ class FastFormatBuffers
protected: protected:
typedef SafeAlignedArray<CharType,16> BufferType; typedef SafeAlignedArray<CharType,16> BufferType;
static const uint BufferCount = 3; static const uint BufferCount = 4;
BufferType m_buffers[BufferCount]; BufferType m_buffers[BufferCount];
uint m_curslot; uint m_curslot;
@ -64,7 +64,7 @@ public:
m_buffers[i].Name = wxsFormat(L"%s Formatting Buffer (slot%d)", m_buffers[i].Name = wxsFormat(L"%s Formatting Buffer (slot%d)",
(sizeof(CharType)==1) ? L"Ascii" : L"Unicode", i); (sizeof(CharType)==1) ? L"Ascii" : L"Unicode", i);
m_buffers[i].MakeRoomFor(1024); m_buffers[i].MakeRoomFor(1024);
m_buffers[i].ChunkSize = 4096; m_buffers[i].ChunkSize = 2048;
} }
m_curslot = 0; m_curslot = 0;
@ -77,7 +77,7 @@ public:
bool HasFreeBuffer() const bool HasFreeBuffer() const
{ {
return m_curslot < BufferCount; return m_curslot < BufferCount-1;
} }
BufferType& GrabBuffer() BufferType& GrabBuffer()
@ -176,7 +176,7 @@ static __ri void format_that_unicode_mess( SafeArray<char>& buffer, uint writepo
while( true ) while( true )
{ {
int size = buffer.GetLength() / sizeof(wxChar); int size = buffer.GetLength() / sizeof(wxChar);
int len = wxVsnprintf((wxChar*)buffer.GetPtr(writepos), size-writepos, fmt, argptr); int len = wxVsnprintf((wxChar*)buffer.GetPtr(writepos*2), size-writepos, fmt, argptr);
// some implementations of vsnprintf() don't NUL terminate // some implementations of vsnprintf() don't NUL terminate
@ -267,12 +267,11 @@ FastFormatUnicode& FastFormatUnicode::Write( const wxChar* fmt, ... )
return *this; return *this;
} }
const wxChar* FastFormatUnicode::GetResult() const bool FastFormatUnicode::IsEmpty() const
{ {
return (wxChar*)m_dest->GetPtr(); return ((wxChar&)(*m_dest)[0]) == 0;
} }
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
// FastFormatAscii (implementations) // FastFormatAscii (implementations)
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
@ -295,10 +294,10 @@ const wxString FastFormatAscii::GetString() const
return fromAscii(m_dest->GetPtr()); return fromAscii(m_dest->GetPtr());
} }
FastFormatAscii::operator wxString() const /*FastFormatAscii::operator wxString() const
{ {
return fromAscii(m_dest->GetPtr()); return fromAscii(m_dest->GetPtr());
} }*/
FastFormatAscii& FastFormatAscii::WriteV( const char* fmt, va_list argptr ) FastFormatAscii& FastFormatAscii::WriteV( const char* fmt, va_list argptr )
{ {
@ -315,13 +314,8 @@ FastFormatAscii& FastFormatAscii::Write( const char* fmt, ... )
return *this; return *this;
} }
const char* FastFormatAscii::GetResult() const
{
return m_dest->GetPtr();
}
FastFormatAscii::operator const char*() const bool FastFormatAscii::IsEmpty() const
{ {
return m_dest->GetPtr(); return (*m_dest)[0] == 0;
} }

View File

@ -253,11 +253,13 @@ Threading::ScopedLock::~ScopedLock() throw()
Threading::ScopedLock::ScopedLock( const Mutex* locker ) Threading::ScopedLock::ScopedLock( const Mutex* locker )
{ {
m_IsLocked = false;
AssignAndLock( locker ); AssignAndLock( locker );
} }
Threading::ScopedLock::ScopedLock( const Mutex& locker ) Threading::ScopedLock::ScopedLock( const Mutex& locker )
{ {
m_IsLocked = false;
AssignAndLock( locker ); AssignAndLock( locker );
} }
@ -268,6 +270,8 @@ void Threading::ScopedLock::AssignAndLock( const Mutex& locker )
void Threading::ScopedLock::AssignAndLock( const Mutex* locker ) void Threading::ScopedLock::AssignAndLock( const Mutex* locker )
{ {
pxAssume(!m_IsLocked); // if we're already locked, changing the lock is bad mojo.
m_lock = const_cast<Mutex*>(locker); m_lock = const_cast<Mutex*>(locker);
if( !m_lock ) return; if( !m_lock ) return;

View File

@ -35,6 +35,42 @@ __fi wxString fromAscii( const char* src )
return wxString::FromAscii( src ); return wxString::FromAscii( src );
} }
wxString u128::ToString() const
{
return pxsFmt( L"0x%08X.%08X.%08X.%08X", _u32[0], _u32[1], _u32[2], _u32[3] );
}
wxString u128::ToString64() const
{
return pxsFmt( L"0x%08X%08X.%08X%08X", _u32[0], _u32[1], _u32[2], _u32[3] );
}
wxString u128::ToString8() const
{
FastFormatUnicode result;
result.Write( L"0x%02X.%02X", _u8[0], _u8[1] );
for (uint i=2; i<16; i+=2)
result.Write( L".%02X.%02X", _u8[i], _u8[i+1] );
return result;
}
void u128::WriteTo( FastFormatAscii& dest ) const
{
dest.Write( "0x%08X.%08X.%08X.%08X", _u32[0], _u32[1], _u32[2], _u32[3] );
}
void u128::WriteTo64( FastFormatAscii& dest ) const
{
dest.Write( "0x%08X%08X.%08X%08X", _u32[0], _u32[1], _u32[2], _u32[3] );
}
void u128::WriteTo8( FastFormatAscii& dest ) const
{
dest.Write( "0x%02X.%02X", _u8[0], _u8[1] );
for (uint i=2; i<16; i+=2)
dest.Write( ".%02X.%02X", _u8[i], _u8[i+1] );
}
// Splits a string into parts and adds the parts into the given SafeList. // Splits a string into parts and adds the parts into the given SafeList.
// This list is not cleared, so concatenating many splits into a single large list is // This list is not cleared, so concatenating many splits into a single large list is
// the 'default' behavior, unless you manually clear the SafeList prior to subsequent calls. // the 'default' behavior, unless you manually clear the SafeList prior to subsequent calls.

View File

@ -1,19 +1,19 @@
pcsx2 for debian pcsx2 for debian
========================= =========================
* This version have some majors modification against default upstream * This version has some major modifications against the default upstream version.
-> documents are stored in $XDG_CONFIG_HOME instead of $HOME/pcsx2 -> documents are stored in $XDG_CONFIG_HOME instead of $HOME/pcsx2
-> some features was removed to compile against libsound 1.3. Pcsx2 -> some features were removed so it could compile against libsound 1.3.
needs the version 1.5 Pcsx2 needs at least soundtouch 1.5.
* This package is highly experimental. * This package is highly experimental.
* Documentation needs some loves. Feel free to help. * Documentation needs some love. Feel free to help.
* -fPIC option was removed for multiple reason. * -fPIC option was removed for multiple reason.
- Code only support x86 architecture. - Code only support x86 architecture.
- Upstream code use ebx register so it is not compliant with PIC. - Upstream code uses the ebx register so it's not compliant with PIC.
- Impact too much performance. - Impacts the performance too much.
- only plugins so no others package link against us. - Only plugins. No package will link to them.
-- Gregory Hainaut <gregory.hainaut@gmail.com> Sat, 24 Apr 2010 23:11:10 +0200 -- Gregory Hainaut <gregory.hainaut@gmail.com> Sat, 24 Apr 2010 23:11:10 +0200

View File

@ -2,6 +2,7 @@ Source: pcsx2.snapshot
Section: games Section: games
Priority: optional Priority: optional
Maintainer: Gregory Hainaut <gregory.hainaut@gmail.com> Maintainer: Gregory Hainaut <gregory.hainaut@gmail.com>
# WARNING we need dpkg-dev 1.15.7 to support dpkg-buildflags but ubunutu 10.04 have only 1.15.5.6...
Build-Depends: debhelper (>= 7.0.50), dpkg-dev (>= 1.15.5.6), cmake (>=2.8), Build-Depends: debhelper (>= 7.0.50), dpkg-dev (>= 1.15.5.6), cmake (>=2.8),
gcc-multilib [amd64], g++-multilib [amd64], gcc-multilib [amd64], g++-multilib [amd64],
zlib1g-dev (>= 1:1.2.3.3) | lib32z1-dev (>= 1.2.3.3) [amd64], zlib1g-dev (>= 1:1.2.3.3) | lib32z1-dev (>= 1.2.3.3) [amd64],
@ -28,22 +29,23 @@ Build-Depends: debhelper (>= 7.0.50), dpkg-dev (>= 1.15.5.6), cmake (>=2.8),
# nvidia-cg-toolkit (>= 2.1.0017.deb1) | nvidia-cg-toolkit (>= 2.1.0017.deb1+nmu2) [amd64], # nvidia-cg-toolkit (>= 2.1.0017.deb1) | nvidia-cg-toolkit (>= 2.1.0017.deb1+nmu2) [amd64],
nvidia-cg-toolkit-pcsx2 | nvidia-cg-toolkit (>= 2.1), ia32-nvidia-cg-toolkit-pcsx2 [amd64], nvidia-cg-toolkit-pcsx2 | nvidia-cg-toolkit (>= 2.1), ia32-nvidia-cg-toolkit-pcsx2 [amd64],
ia32-libs (>= 20090808+nmu7) [amd64], ia32-libs-gtk (= 20100503+local1) [amd64] ia32-libs (>= 20090808+nmu7) [amd64], ia32-libs-gtk (= 20100503+local1) [amd64]
Standards-Version: 3.9.0 Standards-Version: 3.9.1
Homepage: http://pcsx2.net/ Homepage: http://pcsx2.net/
Package: pcsx2-unstable Package: pcsx2-unstable
# Warning amd64 need additional ia32libs # Warning amd64 need additional ia32libs
Architecture: i386 amd64 Architecture: i386 amd64
Depends: ${shlibs:Depends}, ${misc:Depends}, pcsx2-data-unstable (>= ${binary:Version}), pcsx2-plugins-unstable (>= ${binary:Version}) Depends: ${shlibs:Depends}, ${misc:Depends},
Conflicts: pcsx2 pcsx2-data-unstable (>= ${binary:Version}),
pcsx2-plugins-unstable (>= ${binary:Version})
Conflicts: pcsx2
Description: Playstation 2 emulator Description: Playstation 2 emulator
PCSX2 is a PlayStation 2 emulator for Windows and PCSX2 is a PlayStation 2 emulator for Windows and Linux, started by the same
Linux, started by the same team that brought you PCSX team that brought you PCSX (a Sony PlayStation 1 emulator).
(a Sony PlayStation 1 emulator).
. .
WARNING: it requieres a CPU with sse2 instructions. If your WARNING: It requires a CPU with SSE2 instructions. If your CPU does not support
CPU does not support this instruction set, it does not have this instruction set, it does not have enough horse power to run this emulator
enough horse power to run this emulator anyway. anyway.
. .
This package includes the main binary file. This package includes the main binary file.
@ -54,34 +56,33 @@ Depends: ${misc:Depends}
Recommends: pcsx2-unstable (>= ${binary:Version}), pcsx2-plugins-unstable (>= ${binary:Version}) Recommends: pcsx2-unstable (>= ${binary:Version}), pcsx2-plugins-unstable (>= ${binary:Version})
Conflicts: pcsx2-data Conflicts: pcsx2-data
Description: data for pcsx2 Description: data for pcsx2
PCSX2 is a PlayStation 2 emulator for Windows and PCSX2 is a PlayStation 2 emulator for Windows and Linux, started by the same
Linux, started by the same team that brought you PCSX team that brought you PCSX (a Sony PlayStation 1 emulator).
(a Sony PlayStation 1 emulator).
. .
WARNING: it requieres a CPU with sse2 instructions. If your WARNING: It requires a CPU with SSE2 instructions. If your CPU does not support
CPU does not support this instruction set, it does not have this instruction set, it does not have enough horse power to run this emulator
enough horse power to run this emulator anyway. anyway.
. .
This package includes data files. This package includes data files.
Package: pcsx2-plugins-unstable Package: pcsx2-plugins-unstable
# Warning amd64 need additional ia32libs # Warning amd64 need additional ia32libs
Architecture: i386 amd64 Architecture: i386 amd64
Depends: ${shlibs:Depends}, ${misc:Depends}
Recommends: pcsx2-unstable (>= ${binary:Version}), pcsx2-data-unstable (>= ${binary:Version}),
# manually add nvidia-cg-toolkit for zzogl. Do not why is not found by shlibs !!! # manually add nvidia-cg-toolkit for zzogl. Do not why is not found by shlibs !!!
Depends: ${shlibs:Depends}, ${misc:Depends},
nvidia-cg-toolkit-pcsx2 | nvidia-cg-toolkit (>= 2.1), ia32-nvidia-cg-toolkit-pcsx2 [amd64] nvidia-cg-toolkit-pcsx2 | nvidia-cg-toolkit (>= 2.1), ia32-nvidia-cg-toolkit-pcsx2 [amd64]
Recommends: pcsx2-unstable (>= ${binary:Version}),
pcsx2-data-unstable (>= ${binary:Version})
Conflicts: pcsx2-plugins Conflicts: pcsx2-plugins
Description: Various plugins for pcsx2 Description: Various plugins for pcsx2
PCSX2 is a PlayStation 2 emulator for Windows and PCSX2 is a PlayStation 2 emulator for Windows and Linux, started by the same
Linux, started by the same team that brought you PCSX team that brought you PCSX (a Sony PlayStation 1 emulator).
(a Sony PlayStation 1 emulator).
. .
WARNING: it requieres a CPU with sse2 instructions. If your WARNING: It requires a CPU with SSE2 instructions. If your CPU does not support
CPU does not support this instruction set, it does not have this instruction set, it does not have enough horse power to run this emulator
enough horse power to run this emulator anyway. anyway.
. .
This package includes the plugins of the emulator. This package includes the plugins for PCSX2.
Package: pcsx2-unstable-dbg Package: pcsx2-unstable-dbg
Section: debug Section: debug
@ -91,9 +92,12 @@ Architecture: i386 amd64
Depends: ${misc:Depends}, pcsx2-unstable (= ${binary:Version}) Depends: ${misc:Depends}, pcsx2-unstable (= ${binary:Version})
Conflicts: pcsx2-dbg Conflicts: pcsx2-dbg
Description: Debug symbols for pcsx2 Description: Debug symbols for pcsx2
PCSX2 is a PlayStation 2 emulator for Windows and PCSX2 is a PlayStation 2 emulator for Windows and Linux, started by the same
Linux, started by the same team that brought you PCSX team that brought you PCSX (a Sony PlayStation 1 emulator).
(a Sony PlayStation 1 emulator). .
WARNING: It requires a CPU with SSE2 instructions. If your CPU does not support
this instruction set, it does not have enough horse power to run this emulator
anyway.
. .
This package contains the debug symbol of pcsx2. This package contains the debug symbol of pcsx2.
@ -104,9 +108,12 @@ Priority: extra
Architecture: i386 amd64 Architecture: i386 amd64
Depends: ${misc:Depends}, pcsx2-plugins-unstable (= ${binary:Version}) Depends: ${misc:Depends}, pcsx2-plugins-unstable (= ${binary:Version})
Conflicts: pcsx2-plugins-dbg Conflicts: pcsx2-plugins-dbg
Description: Debug symbols for pcsx2-plugins Description: Debug symbols of the pcsx2-plugins
PCSX2 is a PlayStation 2 emulator for Windows and PCSX2 is a PlayStation 2 emulator for Windows and Linux, started by the same
Linux, started by the same team that brought you PCSX team that brought you PCSX (a Sony PlayStation 1 emulator).
(a Sony PlayStation 1 emulator).
. .
This package contains the debug symbol of pcsx2 plugins. WARNING: It requires a CPU with SSE2 instructions. If your CPU does not support
this instruction set, it does not have enough horse power to run this emulator
anyway.
.
This package contains the debug symbols of the pcsx2 plugins.

View File

@ -24,21 +24,22 @@ Build-Depends: debhelper (>= 7.0.50), dpkg-dev (>= 1.15.5.6), cmake (>=2.8),
libgl1-mesa-dev, libgl1-mesa-dev,
libglu1-mesa-dev, libglu1-mesa-dev,
nvidia-cg-toolkit-pcsx2 nvidia-cg-toolkit-pcsx2
Standards-Version: 3.9.0 Standards-Version: 3.9.1
Homepage: http://pcsx2.net/ Homepage: http://pcsx2.net/
Package: pcsx2-unstable Package: pcsx2-unstable
Architecture: i386 Architecture: i386
Depends: ${shlibs:Depends}, ${misc:Depends}, pcsx2-data-unstable (>= ${binary:Version}), pcsx2-plugins-unstable (>= ${binary:Version}) Depends: ${shlibs:Depends}, ${misc:Depends},
pcsx2-data-unstable (>= ${binary:Version}),
pcsx2-plugins-unstable (>= ${binary:Version})
Conflicts: pcsx2 Conflicts: pcsx2
Description: Playstation 2 emulator Description: Playstation 2 emulator
PCSX2 is a PlayStation 2 emulator for Windows and PCSX2 is a PlayStation 2 emulator for Windows and Linux, started by the same
Linux, started by the same team that brought you PCSX team that brought you PCSX (a Sony PlayStation 1 emulator).
(a Sony PlayStation 1 emulator).
. .
WARNING: it requieres a CPU with sse2 instructions. If your WARNING: It requires a CPU with SSE2 instructions. If your CPU does not support
CPU does not support this instruction set, it does not have this instruction set, it does not have enough horse power to run this emulator
enough horse power to run this emulator anyway. anyway.
. .
This package includes the main binary file. This package includes the main binary file.
@ -49,33 +50,32 @@ Depends: ${misc:Depends}
Recommends: pcsx2-unstable (>= ${binary:Version}), pcsx2-plugins-unstable (>= ${binary:Version}) Recommends: pcsx2-unstable (>= ${binary:Version}), pcsx2-plugins-unstable (>= ${binary:Version})
Conflicts: pcsx2-data Conflicts: pcsx2-data
Description: data for pcsx2 Description: data for pcsx2
PCSX2 is a PlayStation 2 emulator for Windows and PCSX2 is a PlayStation 2 emulator for Windows and Linux, started by the same
Linux, started by the same team that brought you PCSX team that brought you PCSX (a Sony PlayStation 1 emulator).
(a Sony PlayStation 1 emulator).
. .
WARNING: it requieres a CPU with sse2 instructions. If your WARNING: It requires a CPU with SSE2 instructions. If your CPU does not support
CPU does not support this instruction set, it does not have this instruction set, it does not have enough horse power to run this emulator
enough horse power to run this emulator anyway. anyway.
. .
This package includes data files. This package includes data files.
Package: pcsx2-plugins-unstable Package: pcsx2-plugins-unstable
Architecture: i386 Architecture: i386
Depends: ${shlibs:Depends}, ${misc:Depends}
Recommends: pcsx2-unstable (>= ${binary:Version}), pcsx2-data-unstable (>= ${binary:Version}),
# manually add nvidia-cg-toolkit for zzogl. Do not why is not found by shlibs !!! # manually add nvidia-cg-toolkit for zzogl. Do not why is not found by shlibs !!!
Depends: ${shlibs:Depends}, ${misc:Depends},
nvidia-cg-toolkit-pcsx2 | nvidia-cg-toolkit (>= 2.1) nvidia-cg-toolkit-pcsx2 | nvidia-cg-toolkit (>= 2.1)
Recommends: pcsx2-unstable (>= ${binary:Version}),
pcsx2-data-unstable (>= ${binary:Version})
Conflicts: pcsx2-plugins Conflicts: pcsx2-plugins
Description: Various plugins for pcsx2 Description: Various plugins for pcsx2
PCSX2 is a PlayStation 2 emulator for Windows and PCSX2 is a PlayStation 2 emulator for Windows and Linux, started by the same
Linux, started by the same team that brought you PCSX team that brought you PCSX (a Sony PlayStation 1 emulator).
(a Sony PlayStation 1 emulator).
. .
WARNING: it requieres a CPU with sse2 instructions. If your WARNING: It requires a CPU with SSE2 instructions. If your CPU does not support
CPU does not support this instruction set, it does not have this instruction set, it does not have enough horse power to run this emulator
enough horse power to run this emulator anyway. anyway.
. .
This package includes the plugins of the emulator. This package includes the plugins for PCSX2.
Package: pcsx2-unstable-dbg Package: pcsx2-unstable-dbg
Section: debug Section: debug
@ -84,9 +84,12 @@ Architecture: i386
Depends: ${misc:Depends}, pcsx2-unstable (= ${binary:Version}) Depends: ${misc:Depends}, pcsx2-unstable (= ${binary:Version})
Conflicts: pcsx2-dbg Conflicts: pcsx2-dbg
Description: Debug symbols for pcsx2 Description: Debug symbols for pcsx2
PCSX2 is a PlayStation 2 emulator for Windows and PCSX2 is a PlayStation 2 emulator for Windows and Linux, started by the same
Linux, started by the same team that brought you PCSX team that brought you PCSX (a Sony PlayStation 1 emulator).
(a Sony PlayStation 1 emulator). .
WARNING: It requires a CPU with SSE2 instructions. If your CPU does not support
this instruction set, it does not have enough horse power to run this emulator
anyway.
. .
This package contains the debug symbol of pcsx2. This package contains the debug symbol of pcsx2.
@ -96,9 +99,12 @@ Priority: extra
Architecture: i386 Architecture: i386
Depends: ${misc:Depends}, pcsx2-plugins-unstable (= ${binary:Version}) Depends: ${misc:Depends}, pcsx2-plugins-unstable (= ${binary:Version})
Conflicts: pcsx2-plugins-dbg Conflicts: pcsx2-plugins-dbg
Description: Debug symbols for pcsx2-plugins Description: Debug symbols of the pcsx2-plugins
PCSX2 is a PlayStation 2 emulator for Windows and PCSX2 is a PlayStation 2 emulator for Windows and Linux, started by the same
Linux, started by the same team that brought you PCSX team that brought you PCSX (a Sony PlayStation 1 emulator).
(a Sony PlayStation 1 emulator).
. .
This package contains the debug symbol of pcsx2 plugins. WARNING: It requires a CPU with SSE2 instructions. If your CPU does not support
this instruction set, it does not have enough horse power to run this emulator
anyway.
.
This package contains the debug symbols of the pcsx2 plugins.

View File

@ -155,6 +155,8 @@ License: BSD (3 clause)
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE. SUCH DAMAGE.
Files: plugins/zzogl-pg/opengl/ZeroGSShaders/* plugins/zzogl-pg/opengl/zpipe* plugins/zzogl-pg/opengl/zerogsmath.h plugins/zzogl-pg/opengl/memcpy_amd.cpp
Copyright: Unknown
The Debian packaging is: The Debian packaging is:

View File

@ -16,16 +16,22 @@
###################################################################### ######################################################################
# Global Parameter # Global Parameters
###################################################################### ######################################################################
# Svn parameter # Svn parameter
if [ -n "$1" ] ; then if [ -n "$1" ] ; then
SVN_CO_VERSION=$1; SVN_CO_VERSION=$1;
else else
echo "Please provide the subversion version as fisrt parameter" echo "Please provide the subversion revision number as the first parameter"
exit 1; exit 1;
fi fi
SVN_TRUNK="http://pcsx2.googlecode.com/svn/trunk" if [ -n "$2" ] ; then
# Use branch argument
SVN_TRUNK="http://pcsx2.googlecode.com/svn/branches/$2"
else
# by default take the trunk
SVN_TRUNK="http://pcsx2.googlecode.com/svn/trunk"
fi
# Debian name of package and tarball # Debian name of package and tarball
PKG_NAME="pcsx2.snapshot-${SVN_CO_VERSION}" PKG_NAME="pcsx2.snapshot-${SVN_CO_VERSION}"
@ -38,7 +44,7 @@ NEW_DIR=${TMP_DIR}/$PKG_NAME
###################################################################### ######################################################################
# Basic function # Basic functions
###################################################################### ######################################################################
get_svn_dir() get_svn_dir()
{ {
@ -58,8 +64,8 @@ get_svn_file()
{ {
for file in $* ; do for file in $* ; do
if [ ! -e `basename ${file}` ] ; then if [ ! -e `basename ${file}` ] ; then
# Versionning information are not support for a single file # Versioning information is not supported for a single file
# so you can not use svn co # therefore you can't use svn co
svn export --quiet ${SVN_TRUNK}/${file} -r $SVN_CO_VERSION; svn export --quiet ${SVN_TRUNK}/${file} -r $SVN_CO_VERSION;
fi fi
done done
@ -69,8 +75,8 @@ get_svn_file()
# Main script # Main script
###################################################################### ######################################################################
## Download the svn repository (only the usefull things) ## Download the svn repository (only the useful things)
echo "Download pcsx2 source rev ${SVN_CO_VERSION}" echo "Downloading pcsx2 source revision ${SVN_CO_VERSION}"
mkdir -p $ROOT_DIR; mkdir -p $ROOT_DIR;
(cd $ROOT_DIR; (cd $ROOT_DIR;
get_svn_file CMakeLists.txt; get_svn_file CMakeLists.txt;
@ -78,7 +84,8 @@ mkdir -p $ROOT_DIR;
get_svn_dir debian-unstable-upstream; get_svn_dir debian-unstable-upstream;
echo "Done") echo "Done")
echo "Donwload Linux compatible plugins ${SVN_CO_VERSION}" echo "Downloading Linux compatible plugins for revision ${SVN_CO_VERSION}"
# Note: Other plugins exist but they are not 100% copyright free.
mkdir -p $ROOT_DIR/plugins mkdir -p $ROOT_DIR/plugins
(cd $ROOT_DIR/plugins; (cd $ROOT_DIR/plugins;
get_svn_file plugins/CMakeLists.txt; get_svn_file plugins/CMakeLists.txt;
@ -98,14 +105,14 @@ echo "Note: some plugins are more or less deprecated CDVDisoEFP, CDVDlinuz, Zero
echo "Done") echo "Done")
## Installation ## Installation
echo "Copy the subversion repository in a tmp directory" echo "Copy the subversion repository to a temporary directory"
# Copy the dir # Copy the dir
rm -fr $NEW_DIR rm -fr $NEW_DIR
cp -r $ROOT_DIR $NEW_DIR cp -r $ROOT_DIR $NEW_DIR
echo "Remove .svn file" echo "Remove .svn directories"
find $NEW_DIR -name ".svn" -type d -exec rm -fr {} \; 2> /dev/null find $NEW_DIR -name ".svn" -type d -exec rm -fr {} \; 2> /dev/null
echo "Remove old build system (script and autotools)" echo "Remove old build system (scripts and autotools)"
find $NEW_DIR -name "build.sh" -exec rm -f {} \; find $NEW_DIR -name "build.sh" -exec rm -f {} \;
find $NEW_DIR -name "install-sh" -exec rm -f {} \; find $NEW_DIR -name "install-sh" -exec rm -f {} \;
find $NEW_DIR -name "depcomp" -exec rm -f {} \; find $NEW_DIR -name "depcomp" -exec rm -f {} \;
@ -113,22 +120,25 @@ find $NEW_DIR -name "missing" -exec rm -f {} \;
find $NEW_DIR -name "aclocal.m4" -exec rm -f {} \; find $NEW_DIR -name "aclocal.m4" -exec rm -f {} \;
find $NEW_DIR -name "configure.ac" -exec rm -f {} \; find $NEW_DIR -name "configure.ac" -exec rm -f {} \;
find $NEW_DIR -name "Makefile.am" -exec rm -f {} \; find $NEW_DIR -name "Makefile.am" -exec rm -f {} \;
echo "Remove 3rd party directory" echo "Remove 3rd party directories"
find $NEW_DIR -name "3rdparty" -exec rm -fr {} \; 2> /dev/null find $NEW_DIR -name "3rdparty" -exec rm -fr {} \; 2> /dev/null
# I really need to clean this mess one day
# echo "Remove plugins/zzogl-pg/opengl/ZeroGSShaders (some zlib source in the middle)"
# rm -fr $NEW_DIR/plugins/zzogl-pg/opengl/ZeroGSShaders
echo "Remove windows file (useless & copyright issue)" echo "Remove windows file (useless & copyright issue)"
find $NEW_DIR -iname "windows" -exec rm -fr {} \; 2> /dev/null find $NEW_DIR -iname "windows" -type d -exec rm -fr {} \; 2> /dev/null
find $NEW_DIR -name "Win32" -type d -exec rm -fr {} \; 2> /dev/null
rm -fr "${NEW_DIR}/plugins/zzogl-pg/opengl/Win32" rm -fr "${NEW_DIR}/plugins/zzogl-pg/opengl/Win32"
rm -fr "${NEW_DIR}/tools/GSDumpGUI" rm -fr "${NEW_DIR}/tools/GSDumpGUI"
rm -fr "${NEW_DIR}/common/vsprops" rm -fr "${NEW_DIR}/common/vsprops"
echo "Remove useless file (copyright issue)" echo "Remove useless files (copyright issues)"
rm -fr "${NEW_DIR}/plugins/zzogl-pg/opengl/ZeroGSShaders/zlib" rm -fr "${NEW_DIR}/plugins/zzogl-pg/opengl/ZeroGSShaders/zlib"
rm -fr "${NEW_DIR}/common/src/Utilities/x86/MemcpyFast.cpp" rm -fr "${NEW_DIR}/common/src/Utilities/x86/MemcpyFast.cpp"
rm -fr "${NEW_DIR}/plugins/CDVDnull/Linux"
## BUILD ## BUILD
echo "Build the tar gz file" echo "Build the tar.gz file"
tar -C ${TMP_DIR} -czf ${TAR_NAME}.gz $PKG_NAME tar -C $TMP_DIR -czf ${TAR_NAME}.gz $PKG_NAME
## Clean ## Clean
rm -fr $NEW_DIR rm -fr $NEW_DIR
rm -fr $ROOT_DIR

View File

@ -1,413 +0,0 @@
Index: pcsx2.snapshot-3369/pcsx2/CMakeLists.txt
===================================================================
--- pcsx2.snapshot-3369.orig/pcsx2/CMakeLists.txt
+++ pcsx2.snapshot-3369/pcsx2/CMakeLists.txt
@@ -17,12 +17,8 @@
set(CMAKE_CXX_FLAGS_RELEASE "")
# set common flags
-set(CommonFlags
+set(CommonFlags
-pthread
- -fno-guess-branch-probability
- -fno-dse
- -fno-tree-dse
- -fno-strict-aliasing
-m32
-march=i486
-msse
@@ -38,55 +34,51 @@
-W
-g)
+# Remove optimization that can break the code. Must be retested
+set(BadFlags_O0
+ -fno-guess-branch-probability
+ -fno-dse
+ -fno-tree-dse
+ )
+
+set(BadFlags_O1
+ -fno-argument-alias
+ -fno-branch-count-reg
+ -fno-ipa-pure-const
+ -fno-ipa-reference
+ -fno-omit-frame-pointer
+ -fno-split-wide-types
+ -fno-tree-copy-prop
+ -fno-tree-dse
+ -fno-tree-sink
+ )
+
+set(BadFlags_O2
+ -fno-expensive-optimizations
+ -fno-forward-propagate
+ -fno-inline-small-functions
+ -fno-ipa-cp
+ -fno-schedule-insns2
+ -fno-strict-aliasing
+ -fno-tree-builtin-call-dce
+ )
+
# set optimization flags
set(OptimizationFlags
- -falign-functions
- -falign-jumps
- -falign-labels
- -falign-loops
- -fcaller-saves
- -fcprop-registers
- -fcrossjumping
- -fcse-follow-jumps
-fcse-skip-blocks
- -fdefer-pop
- -fdelete-null-pointer-checks
- -fgcse
- -fgcse-lm
- -fif-conversion
- -fif-conversion2
- -fmerge-constants
- -foptimize-sibling-calls
- -fpeephole2
- -fregmove
- -freorder-blocks
- -freorder-functions
- -frerun-cse-after-loop
- -fsched-interblock
- -fsched-spec
-fstrict-overflow
- -fthread-jumps
- -ftree-ccp
- -ftree-ch
- -ftree-copyrename
- -ftree-dce
- -ftree-dominator-opts
- -ftree-fre
-ftree-lrs
- -ftree-pre
- -ftree-sra
- -ftree-ter
- -ftree-vrp
- -funit-at-a-time)
+ -O2
+ )
# Debug - Build
if(CMAKE_BUILD_TYPE STREQUAL Debug)
-
+
# executable name
set(pcsx2Name pcsx2)
-
+
# add defines
- add_definitions(${CommonFlags} ${DebugFlags} -DPCSX2_DEVBUILD -DPCSX2_DEBUG -DWX_PRECOMP)
+ add_definitions(${CommonFlags} ${DebugFlags} ${BadFlags_O0} -DPCSX2_DEVBUILD -DPCSX2_DEBUG -DWX_PRECOMP)
endif(CMAKE_BUILD_TYPE STREQUAL Debug)
# Devel - Build
@@ -94,9 +86,9 @@
# executable name
set(pcsx2Name pcsx2)
-
+
# add defines
- add_definitions(${CommonFlags} ${OptimizationFlags} -DPCSX2_DEVBUILD -DWX_PRECOMP -DNDEBUG)
+ add_definitions(${CommonFlags} ${OptimizationFlags} ${BadFlags_O0} ${BadFlags_O1} ${BadFlags_O2} -DPCSX2_DEVBUILD -DWX_PRECOMP -DNDEBUG)
endif(CMAKE_BUILD_TYPE STREQUAL Devel)
# Release - Build
@@ -104,9 +96,9 @@
# executable name
set(pcsx2Name pcsx2)
-
+
# add defines
- add_definitions(${CommonFlags} ${OptimizationFlags} -DWX_PRECOMP -DNDEBUG)
+ add_definitions(${CommonFlags} ${OptimizationFlags} ${BadFlags_O0} ${BadFlags_O1} ${BadFlags_O2} -DWX_PRECOMP -DNDEBUG)
endif(CMAKE_BUILD_TYPE STREQUAL Release)
# you must have both svn client executable and a source that contains svn metadata
@@ -606,7 +598,7 @@
set(Platform
${pcsx2LinuxSources}
${pcsx2LinuxHeaders})
-endif(Linux)
+endif(Linux)
# Windows
if(Windows)
@@ -619,7 +611,7 @@
if(MacOSX)
set(PlatformSources
)
-endif(MacOSX)
+endif(MacOSX)
# additonal include directories
include_directories(.
@@ -640,7 +632,7 @@
# link target with project internal libraries
target_link_libraries(${pcsx2Name} Utilities x86emitter)
-
+
# link target with wx
target_link_libraries(${pcsx2Name} ${wxWidgets_LIBRARIES})
Index: pcsx2.snapshot-3369/common/src/x86emitter/CMakeLists.txt
===================================================================
--- pcsx2.snapshot-3369.orig/common/src/x86emitter/CMakeLists.txt
+++ pcsx2.snapshot-3369/common/src/x86emitter/CMakeLists.txt
@@ -22,10 +22,6 @@
# set common flags
set(CommonFlags
-pthread
- -fno-guess-branch-probability
- -fno-dse
- -fno-tree-dse
- -fno-strict-aliasing
-m32
-march=i486
-msse
@@ -41,66 +37,63 @@
-W
-g)
+# Remove optimization that can break the code. Must be retested
+set(BadFlags_O0
+ -fno-guess-branch-probability
+ -fno-dse
+ -fno-tree-dse
+ )
+
+set(BadFlags_O1
+ -fno-argument-alias
+ -fno-branch-count-reg
+ -fno-ipa-pure-const
+ -fno-ipa-reference
+ -fno-omit-frame-pointer
+ -fno-split-wide-types
+ -fno-tree-copy-prop
+ -fno-tree-dse
+ -fno-tree-sink
+ )
+
+
+set(BadFlags_O2
+ -fno-expensive-optimizations
+ -fno-forward-propagate
+ -fno-inline-small-functions
+ -fno-ipa-cp
+ -fno-schedule-insns2
+ -fno-strict-aliasing
+ -fno-tree-builtin-call-dce
+ )
+
# set optimization flags
set(OptimizationFlags
- -falign-functions
- -falign-jumps
- -falign-labels
- -falign-loops
- -fcaller-saves
- -fcprop-registers
- -fcrossjumping
- -fcse-follow-jumps
-fcse-skip-blocks
- -fdefer-pop
- -fdelete-null-pointer-checks
- -fgcse
- -fgcse-lm
- -fif-conversion
- -fif-conversion2
- -fmerge-constants
- -foptimize-sibling-calls
- -fpeephole2
- -fregmove
- -freorder-blocks
- -freorder-functions
- -frerun-cse-after-loop
- -fsched-interblock
- -fsched-spec
-fstrict-overflow
- -fthread-jumps
- -ftree-ccp
- -ftree-ch
- -ftree-copyrename
- -ftree-dce
- -ftree-dominator-opts
- -ftree-fre
-ftree-lrs
- -ftree-pre
- -ftree-sra
- -ftree-ter
- -ftree-vrp
- -funit-at-a-time)
+ -O2
+ )
# Debug - Build
if(CMAKE_BUILD_TYPE STREQUAL Debug)
# add defines
- add_definitions(${CommonFlags} ${DebugFlags} -DPCSX2_DEVBUILD -DPCSX2_DEBUG)
+ add_definitions(${CommonFlags} ${DebugFlags} ${BadFlags_O0} -DPCSX2_DEVBUILD -DPCSX2_DEBUG)
endif(CMAKE_BUILD_TYPE STREQUAL Debug)
# Devel - Build
if(CMAKE_BUILD_TYPE STREQUAL Devel)
# add defines
- add_definitions(${CommonFlags} ${OptimizationFlags} -DPCSX2_DEVBUILD)
+ add_definitions(${CommonFlags} ${OptimizationFlags} ${BadFlags_O0} ${BadFlags_O1} ${BadFlags_O2} -DPCSX2_DEVBUILD)
endif(CMAKE_BUILD_TYPE STREQUAL Devel)
# Release - Build
if(CMAKE_BUILD_TYPE STREQUAL Release)
# add defines
- add_definitions(${CommonFlags} ${OptimizationFlags})
+ add_definitions(${CommonFlags} ${OptimizationFlags} ${BadFlags_O0} ${BadFlags_O1} ${BadFlags_O2})
endif(CMAKE_BUILD_TYPE STREQUAL Release)
# variable with all sources of this library
Index: pcsx2.snapshot-3369/common/src/Utilities/CMakeLists.txt
===================================================================
--- pcsx2.snapshot-3369.orig/common/src/Utilities/CMakeLists.txt
+++ pcsx2.snapshot-3369/common/src/Utilities/CMakeLists.txt
@@ -20,16 +20,12 @@
set(CMAKE_CXX_FLAGS_RELEASE "")
# set common flags
-set(CommonFlags
+set(CommonFlags
-pthread
-m32
-march=i486
-msse
-msse2
- -fno-dse
- -fno-guess-branch-probability
- -fno-strict-aliasing
- -fno-tree-dse
-pipe
-Wno-format
-Wno-unused-parameter
@@ -41,66 +37,64 @@
-g
-W)
+# Remove optimization that can break the code. Must be retested
+set(BadFlags_O0
+ -fno-guess-branch-probability
+ -fno-dse
+ -fno-tree-dse
+ )
+
+set(BadFlags_O1
+ -fno-argument-alias
+ -fno-branch-count-reg
+ -fno-ipa-pure-const
+ -fno-ipa-reference
+ -fno-omit-frame-pointer
+ -fno-split-wide-types
+ -fno-tree-copy-prop
+ -fno-tree-dse
+ -fno-tree-sink
+ )
+
+
+set(BadFlags_O2
+ -fno-expensive-optimizations
+ -fno-forward-propagate
+ -fno-inline-small-functions
+ -fno-ipa-cp
+ -fno-schedule-insns2
+ -fno-strict-aliasing
+ -fno-tree-builtin-call-dce
+ )
+
+
# set optimization flags
set(OptimizationFlags
- -falign-functions
- -falign-jumps
- -falign-labels
- -falign-loops
- -fcaller-saves
- -fcprop-registers
- -fcrossjumping
- -fcse-follow-jumps
-fcse-skip-blocks
- -fdefer-pop
- -fdelete-null-pointer-checks
- -fgcse
- -fgcse-lm
- -fif-conversion
- -fif-conversion2
- -fmerge-constants
- -foptimize-sibling-calls
- -fpeephole2
- -fregmove
- -freorder-blocks
- -freorder-functions
- -frerun-cse-after-loop
- -fsched-interblock
- -fsched-spec
-fstrict-overflow
- -fthread-jumps
- -ftree-ccp
- -ftree-ch
- -ftree-copyrename
- -ftree-dce
- -ftree-dominator-opts
- -ftree-fre
-ftree-lrs
- -ftree-pre
- -ftree-sra
- -ftree-ter
- -ftree-vrp
- -funit-at-a-time)
+ -O2
+ )
# Debug - Build
if(CMAKE_BUILD_TYPE STREQUAL Debug)
-
+
# add defines
- add_definitions(${CommonFlags} ${DebugFlags} -DPCSX2_DEBUG -DPCSX2_DEVBUILD)
+ add_definitions(${CommonFlags} ${DebugFlags} ${BadFlags_O0} -DPCSX2_DEBUG -DPCSX2_DEVBUILD)
endif(CMAKE_BUILD_TYPE STREQUAL Debug)
# Devel - Build
if(CMAKE_BUILD_TYPE STREQUAL Devel)
-
+
# add defines
- add_definitions(${CommonFlags} ${OptimizationFlags} -DPCSX2_DEVBUILD)
+ add_definitions(${CommonFlags} ${OptimizationFlags} ${BadFlags_O0} ${BadFlags_O1} ${BadFlags_O2} -DPCSX2_DEVBUILD)
endif(CMAKE_BUILD_TYPE STREQUAL Devel)
# Release - Build
if(CMAKE_BUILD_TYPE STREQUAL Release)
-
+
# add defines
- add_definitions(${CommonFlags} ${OptimizationFlags})
+ add_definitions(${CommonFlags} ${OptimizationFlags} ${BadFlags_O0} ${BadFlags_O1} ${BadFlags_O2})
endif(CMAKE_BUILD_TYPE STREQUAL Release)
# variable with all sources of this library
@@ -178,7 +172,7 @@
# link target with wx
target_link_libraries(${UtilitiesName} ${wxWidgets_LIBRARIES})
-
+
# Force the linker into 32 bits mode
target_link_libraries(${UtilitiesName} -m32)

View File

@ -1,78 +0,0 @@
Index: pcsx2.snapshot-3369/common/src/Utilities/CMakeLists.txt
===================================================================
--- pcsx2.snapshot-3369.orig/common/src/Utilities/CMakeLists.txt
+++ pcsx2.snapshot-3369/common/src/Utilities/CMakeLists.txt
@@ -39,21 +39,9 @@
# Remove optimization that can break the code. Must be retested
set(BadFlags_O0
- -fno-guess-branch-probability
- -fno-dse
- -fno-tree-dse
)
set(BadFlags_O1
- -fno-argument-alias
- -fno-branch-count-reg
- -fno-ipa-pure-const
- -fno-ipa-reference
- -fno-omit-frame-pointer
- -fno-split-wide-types
- -fno-tree-copy-prop
- -fno-tree-dse
- -fno-tree-sink
)
Index: pcsx2.snapshot-3369/common/src/x86emitter/CMakeLists.txt
===================================================================
--- pcsx2.snapshot-3369.orig/common/src/x86emitter/CMakeLists.txt
+++ pcsx2.snapshot-3369/common/src/x86emitter/CMakeLists.txt
@@ -39,21 +39,9 @@
# Remove optimization that can break the code. Must be retested
set(BadFlags_O0
- -fno-guess-branch-probability
- -fno-dse
- -fno-tree-dse
)
set(BadFlags_O1
- -fno-argument-alias
- -fno-branch-count-reg
- -fno-ipa-pure-const
- -fno-ipa-reference
- -fno-omit-frame-pointer
- -fno-split-wide-types
- -fno-tree-copy-prop
- -fno-tree-dse
- -fno-tree-sink
)
Index: pcsx2.snapshot-3369/pcsx2/CMakeLists.txt
===================================================================
--- pcsx2.snapshot-3369.orig/pcsx2/CMakeLists.txt
+++ pcsx2.snapshot-3369/pcsx2/CMakeLists.txt
@@ -36,21 +36,9 @@
# Remove optimization that can break the code. Must be retested
set(BadFlags_O0
- -fno-guess-branch-probability
- -fno-dse
- -fno-tree-dse
)
set(BadFlags_O1
- -fno-argument-alias
- -fno-branch-count-reg
- -fno-ipa-pure-const
- -fno-ipa-reference
- -fno-omit-frame-pointer
- -fno-split-wide-types
- -fno-tree-copy-prop
- -fno-tree-dse
- -fno-tree-sink
)
set(BadFlags_O2

View File

@ -1,54 +0,0 @@
Index: pcsx2.snapshot-3369/common/src/Utilities/CMakeLists.txt
===================================================================
--- pcsx2.snapshot-3369.orig/common/src/Utilities/CMakeLists.txt
+++ pcsx2.snapshot-3369/common/src/Utilities/CMakeLists.txt
@@ -46,13 +46,6 @@
set(BadFlags_O2
- -fno-expensive-optimizations
- -fno-forward-propagate
- -fno-inline-small-functions
- -fno-ipa-cp
- -fno-schedule-insns2
- -fno-strict-aliasing
- -fno-tree-builtin-call-dce
)
Index: pcsx2.snapshot-3369/common/src/x86emitter/CMakeLists.txt
===================================================================
--- pcsx2.snapshot-3369.orig/common/src/x86emitter/CMakeLists.txt
+++ pcsx2.snapshot-3369/common/src/x86emitter/CMakeLists.txt
@@ -46,13 +46,6 @@
set(BadFlags_O2
- -fno-expensive-optimizations
- -fno-forward-propagate
- -fno-inline-small-functions
- -fno-ipa-cp
- -fno-schedule-insns2
- -fno-strict-aliasing
- -fno-tree-builtin-call-dce
)
# set optimization flags
Index: pcsx2.snapshot-3369/pcsx2/CMakeLists.txt
===================================================================
--- pcsx2.snapshot-3369.orig/pcsx2/CMakeLists.txt
+++ pcsx2.snapshot-3369/pcsx2/CMakeLists.txt
@@ -42,13 +42,6 @@
)
set(BadFlags_O2
- -fno-expensive-optimizations
- -fno-forward-propagate
- -fno-inline-small-functions
- -fno-ipa-cp
- -fno-schedule-insns2
- -fno-strict-aliasing
- -fno-tree-builtin-call-dce
)
# set optimization flags

View File

@ -2,7 +2,3 @@
02_update_default_path.patch 02_update_default_path.patch
05_move_data_to_config.patch 05_move_data_to_config.patch
21_use_legacy_soundtouch_13.patch 21_use_legacy_soundtouch_13.patch
# Personnal patch that need advance testing
#55_cmake_opt_clean.patch
#56_cmake_enable_opt1.patch
#57_cmake_enable_opt2.patch

View File

@ -1,3 +1,6 @@
# PIC code cause regression in the library and issue with the ebx register. #* -fPIC option was removed for multiple reason.
# Morever library are plugins and the code is only compatible with x86. # - Code only support x86 architecture.
# - Upstream code uses the ebx register so it's not compliant with PIC.
# - Impacts the performance too much.
# - Only plugins. No package will link to them.
pcsx2-plugins-unstable: shlib-with-non-pic-code pcsx2-plugins-unstable: shlib-with-non-pic-code

View File

@ -1 +1,3 @@
bin/pcsx2 usr/games bin/pcsx2 usr/games
debian/pcsx2.desktop usr/share/applications
debian/pcsx2.xpm usr/share/pixmaps

View File

@ -41,9 +41,9 @@ clean:
dh_testroot dh_testroot
rm -f build-stamp rm -f build-stamp
# Backup some orig makefile if it not already done # Backup some orig makefile if it's not already done.
# I hope some will be delete by upstream when cmake port is over # I hope that some will be delete by upstream when the cmake port is over.
# Note in case we do not dl all plugins the test [ -f $${makefile} ] ensure the working # Note: In case that we do not dl all the plugins, the test [ -f $${makefile} ] ensures it works
for makefile in plugins/CDVDlinuz/Src/Linux/Makefile \ for makefile in plugins/CDVDlinuz/Src/Linux/Makefile \
plugins/CDVDiso/src/Linux/Makefile \ plugins/CDVDiso/src/Linux/Makefile \
plugins/CDVDiso/src/Windows/Makefile \ plugins/CDVDiso/src/Windows/Makefile \
@ -53,13 +53,13 @@ clean:
plugins/CDVDisoEFP/src/Linux/Makefile ; do \ plugins/CDVDisoEFP/src/Linux/Makefile ; do \
[ -f $${makefile}.orig ] || ( [ -f $${makefile} ] && mv $${makefile} $${makefile}.orig ) || true ; done [ -f $${makefile}.orig ] || ( [ -f $${makefile} ] && mv $${makefile} $${makefile}.orig ) || true ; done
# Add here commands to clean up after the build process. # Add here the commands to clean up after the build process.
[ -f Makefile ] && $(MAKE) clean || true [ -f Makefile ] && $(MAKE) clean || true
# Remove cmake stuff # Remove cmake stuff
rm -fr $$(find . -type d -name CMakeFiles) rm -fr $$(find . -type d -name CMakeFiles)
rm -f $$(find . -type f -name CMakeCache.txt) $$(find . -type f -name cmake_install.cmake) rm -f $$(find . -type f -name CMakeCache.txt) $$(find . -type f -name cmake_install.cmake)
rm -f $$(find . -type f -name Makefile) rm -f $$(find . -type f -name Makefile)
# File generated by bin2cpp # Files generated by bin2cpp
cd pcsx2/gui/Resources/ && rm -f App*.h Config*.h BackgroundLogo.h ButtonIcon_Camera.h Dualshock.h cd pcsx2/gui/Resources/ && rm -f App*.h Config*.h BackgroundLogo.h ButtonIcon_Camera.h Dualshock.h
# leftover of cmake # leftover of cmake
rm -f bin/plugins/ps2hw.dat rm -f bin/plugins/ps2hw.dat
@ -69,62 +69,15 @@ clean:
dh_clean dh_clean
install: ## Uncomment this, if fglrx driver is installed
install: build #override_dh_shlibdeps:
dh_testdir # dh_shlibdeps -- --ignore-missing-info
dh_testroot
dh_prep
dh_installdirs
### the project build usefull thing in ./bin so directly install override_dh_strip:
### from this directory to the debian pkg directory (skip debian/tmp)
# Ubuntu use debian/tmp as default sourcedir...
# copy bin into debian tmp
mkdir -p debian/tmp
cp -fr bin debian/tmp
dh_install --sourcedir=debian/tmp
# install menu and icon
cp debian/pcsx2.desktop debian/pcsx2-unstable/usr/share/applications
cp debian/pcsx2.xpm debian/pcsx2-unstable/usr/share/pixmaps
# lintian override
dh_lintian
# Build architecture-independent files here.
binary-indep: build install
dh_testdir -i
dh_testroot -i
dh_installchangelogs -i
dh_installdocs -i
dh_installman -i
dh_link -i
dh_compress -i
dh_fixperms -i
dh_installdeb -i
dh_gencontrol -i
dh_md5sums -i
dh_builddeb -i
# Build architecture-dependent files here.
binary-arch: build install
dh_testdir -a
dh_testroot -a
dh_installchangelogs -a
dh_installdocs -a
dh_installmenu -a
dh_installman -a
dh_strip --package=pcsx2-unstable --dbg-package=pcsx2-unstable-dbg dh_strip --package=pcsx2-unstable --dbg-package=pcsx2-unstable-dbg
dh_strip --package=pcsx2-plugins-unstable --dbg-package=pcsx2-plugins-unstable-dbg dh_strip --package=pcsx2-plugins-unstable --dbg-package=pcsx2-plugins-unstable-dbg
dh_link -a
dh_compress -a
dh_fixperms -a
dh_makeshlibs -a
dh_installdeb -a
dh_shlibdeps -a
dh_gencontrol -a
dh_md5sums -a
dh_builddeb -a
binary: binary-indep binary-arch %:
.PHONY: build clean binary-indep binary-arch binary install dh $@ --parallel
.PHONY: build clean install

View File

@ -41,9 +41,9 @@ clean:
dh_testroot dh_testroot
rm -f build-stamp rm -f build-stamp
# Backup some orig makefile if it not already done # Backup some orig makefile if it's not already done.
# I hope some will be delete by upstream when cmake port is over # I hope that some will be delete by upstream when the cmake port is over.
# Note in case we do not dl all plugins the test [ -f $${makefile} ] ensure the working # Note: In case that we do not dl all the plugins, the test [ -f $${makefile} ] ensures it works
for makefile in plugins/CDVDlinuz/Src/Linux/Makefile \ for makefile in plugins/CDVDlinuz/Src/Linux/Makefile \
plugins/CDVDiso/src/Linux/Makefile \ plugins/CDVDiso/src/Linux/Makefile \
plugins/CDVDiso/src/Windows/Makefile \ plugins/CDVDiso/src/Windows/Makefile \
@ -53,13 +53,13 @@ clean:
plugins/CDVDisoEFP/src/Linux/Makefile ; do \ plugins/CDVDisoEFP/src/Linux/Makefile ; do \
[ -f $${makefile}.orig ] || ( [ -f $${makefile} ] && mv $${makefile} $${makefile}.orig ) || true ; done [ -f $${makefile}.orig ] || ( [ -f $${makefile} ] && mv $${makefile} $${makefile}.orig ) || true ; done
# Add here commands to clean up after the build process. # Add here the commands to clean up after the build process.
[ -f Makefile ] && $(MAKE) clean || true [ -f Makefile ] && $(MAKE) clean || true
# Remove cmake stuff # Remove cmake stuff
rm -fr $$(find . -type d -name CMakeFiles) rm -fr $$(find . -type d -name CMakeFiles)
rm -f $$(find . -type f -name CMakeCache.txt) $$(find . -type f -name cmake_install.cmake) rm -f $$(find . -type f -name CMakeCache.txt) $$(find . -type f -name cmake_install.cmake)
rm -f $$(find . -type f -name Makefile) rm -f $$(find . -type f -name Makefile)
# File generated by bin2cpp # Files generated by bin2cpp
cd pcsx2/gui/Resources/ && rm -f App*.h Config*.h BackgroundLogo.h ButtonIcon_Camera.h Dualshock.h cd pcsx2/gui/Resources/ && rm -f App*.h Config*.h BackgroundLogo.h ButtonIcon_Camera.h Dualshock.h
# leftover of cmake # leftover of cmake
rm -f bin/plugins/ps2hw.dat rm -f bin/plugins/ps2hw.dat
@ -69,65 +69,15 @@ clean:
dh_clean dh_clean
install: # Allow compilation when fglrx is installed
install: build override_dh_shlibdeps:
dh_testdir dh_shlibdeps -- --ignore-missing-info
dh_testroot
dh_prep
dh_installdirs
### the project build usefull thing in ./bin so directly install override_dh_strip:
### from this directory to the debian pkg directory (skip debian/tmp)
# Ubuntu use debian/tmp as default sourcedir...
# copy bin into debian tmp
mkdir -p debian/tmp
cp -fr bin debian/tmp
dh_install --sourcedir=debian/tmp
# install menu and icon
cp debian/pcsx2.desktop debian/pcsx2-unstable/usr/share/applications
cp debian/pcsx2.xpm debian/pcsx2-unstable/usr/share/pixmaps
# lintian override
dh_lintian
# Build architecture-independent files here.
binary-indep: build install
dh_testdir -i
dh_testroot -i
dh_installchangelogs -i
dh_installdocs -i
dh_installman -i
dh_link -i
dh_compress -i
dh_fixperms -i
dh_installdeb -i
dh_gencontrol -i
dh_md5sums -i
dh_builddeb -i
# Build architecture-dependent files here.
binary-arch: build install
dh_testdir -a
dh_testroot -a
dh_installchangelogs -a
dh_installdocs -a
dh_installmenu -a
dh_installman -a
dh_strip --package=pcsx2-unstable --dbg-package=pcsx2-unstable-dbg dh_strip --package=pcsx2-unstable --dbg-package=pcsx2-unstable-dbg
dh_strip --package=pcsx2-plugins-unstable --dbg-package=pcsx2-plugins-unstable-dbg dh_strip --package=pcsx2-plugins-unstable --dbg-package=pcsx2-plugins-unstable-dbg
dh_link -a
dh_compress -a
dh_fixperms -a
dh_makeshlibs -a
dh_installdeb -a
# XXX: WARNING to test the package on my system I must add the option (--exclude)
# due to fglrx drivers modify libGL. It must be re-enable for final packaging
# dh_shlibdeps -a
dh_shlibdeps -a --exclude=libzzogl
dh_gencontrol -a
dh_md5sums -a
dh_builddeb -a
binary: binary-indep binary-arch %:
.PHONY: build clean binary-indep binary-arch binary install dh $@ --parallel
.PHONY: build clean install

View File

@ -6,5 +6,6 @@
# Compulsory line, this is a version 3 file # Compulsory line, this is a version 3 file
version=3 version=3
# Note upstream do not release source files. It advices to pick them from subversion # Note: Upstream does not release prepackaged source files.
# It's adviced to get them from their subversion repository.
# http://pcsx2.googlecode.com/files/Pcsx2-linux-beta-(.*).tar.gz # http://pcsx2.googlecode.com/files/Pcsx2-linux-beta-(.*).tar.gz

View File

@ -16,10 +16,6 @@
#ifndef __CDVD_ISO_READER_H__ #ifndef __CDVD_ISO_READER_H__
#define __CDVD_ISO_READER_H__ #define __CDVD_ISO_READER_H__
#ifdef _MSC_VER
#pragma warning(disable:4018)
#endif
#include <stdio.h> #include <stdio.h>
#include "IopCommon.h" #include "IopCommon.h"

View File

@ -137,7 +137,8 @@ isoFile *isoOpen(const char *filename)
iso->handle = _openfile( iso->filename, O_RDONLY); iso->handle = _openfile( iso->filename, O_RDONLY);
if (iso->handle == NULL) if (iso->handle == NULL)
{ {
Console.Error("error loading %s", iso->filename); Console.Error("ISO loader: Cannot access %s", iso->filename);
Console.Error(">> Make sure the iso file is not mounted in any disk emulation software! <<");
return NULL; return NULL;
} }

View File

@ -29,10 +29,6 @@
#define _FILE_OFFSET_BITS 64 #define _FILE_OFFSET_BITS 64
#ifdef _MSC_VER
# pragma warning(disable:4018) // disable signed/unsigned mismatch error
#endif
#include "IopCommon.h" #include "IopCommon.h"
#include <stdio.h> #include <stdio.h>

View File

@ -165,7 +165,6 @@ set(pcsx2Sources
Vif_Codes.cpp Vif_Codes.cpp
Vif_Transfer.cpp Vif_Transfer.cpp
Vif_Unpack.cpp Vif_Unpack.cpp
Vif_Unpack.inl
vtlb.cpp vtlb.cpp
VU0.cpp VU0.cpp
VUmicro.cpp VUmicro.cpp
@ -226,6 +225,7 @@ set(pcsx2Headers
Vif_Dma.h Vif_Dma.h
Vif.h Vif.h
Vif_Unpack.h Vif_Unpack.h
Vif_Unpack.inl
vtlb.h vtlb.h
VUflags.h VUflags.h
VUmicro.h VUmicro.h
@ -295,7 +295,6 @@ set(pcsx2GuiSources
gui/Panels/BaseApplicableConfigPanel.cpp gui/Panels/BaseApplicableConfigPanel.cpp
gui/Panels/MemoryCardListView.cpp gui/Panels/MemoryCardListView.cpp
gui/Dialogs/BaseConfigurationDialog.cpp gui/Dialogs/BaseConfigurationDialog.cpp
gui/Dialogs/BaseConfigurationDialog.inl
gui/Dialogs/BiosSelectorDialog.cpp gui/Dialogs/BiosSelectorDialog.cpp
gui/Dialogs/ConfirmationDialogs.cpp gui/Dialogs/ConfirmationDialogs.cpp
gui/Dialogs/CreateMemoryCardDialog.cpp gui/Dialogs/CreateMemoryCardDialog.cpp
@ -353,6 +352,7 @@ set(pcsx2GuiHeaders
gui/AppGameDatabase.h gui/AppGameDatabase.h
gui/ConsoleLogger.h gui/ConsoleLogger.h
gui/CpuUsageProvider.h gui/CpuUsageProvider.h
gui/Dialogs/BaseConfigurationDialog.inl
gui/Dialogs/ConfigurationDialog.h gui/Dialogs/ConfigurationDialog.h
gui/Dialogs/LogOptionsDialog.h gui/Dialogs/LogOptionsDialog.h
gui/Dialogs/ModalPopups.h gui/Dialogs/ModalPopups.h
@ -371,6 +371,7 @@ set(pcsx2GuiHeaders
set(pcsx2IPUSources set(pcsx2IPUSources
IPU/IPU.cpp IPU/IPU.cpp
IPU/IPU_Fifo.cpp IPU/IPU_Fifo.cpp
IPU/IPUdma.cpp
IPU/mpeg2lib/Idct.cpp IPU/mpeg2lib/Idct.cpp
IPU/mpeg2lib/Mpeg.cpp IPU/mpeg2lib/Mpeg.cpp
IPU/yuv2rgb.cpp) IPU/yuv2rgb.cpp)
@ -379,6 +380,7 @@ set(pcsx2IPUSources
set(pcsx2IPUHeaders set(pcsx2IPUHeaders
IPU/IPU.h IPU/IPU.h
IPU/IPU_Fifo.h IPU/IPU_Fifo.h
IPU/IPUdma.h
IPU/yuv2rgb.h) IPU/yuv2rgb.h)
# Linux sources # Linux sources
@ -394,12 +396,15 @@ set(pcsx2LinuxHeaders
set(pcsx2ps2Sources set(pcsx2ps2Sources
ps2/BiosTools.cpp ps2/BiosTools.cpp
ps2/GIFpath.cpp ps2/GIFpath.cpp
ps2/LegacyDmac.cpp
ps2/Iop/IopHwRead.cpp ps2/Iop/IopHwRead.cpp
ps2/Iop/IopHwWrite.cpp) ps2/Iop/IopHwWrite.cpp)
# ps2 headers # ps2 headers
set(pcsx2ps2Headers set(pcsx2ps2Headers
ps2/BiosTools.h ps2/BiosTools.h
ps2/eeHwTraceLog.inl
ps2/HwInternal.h
ps2/Iop/IopHw_Internal.h) ps2/Iop/IopHw_Internal.h)
# RDebug sources # RDebug sources
@ -495,20 +500,6 @@ set(pcsx2x86Sources
x86/ix86-32/iR5900Shift.cpp x86/ix86-32/iR5900Shift.cpp
x86/ix86-32/iR5900Templates.cpp x86/ix86-32/iR5900Templates.cpp
x86/ix86-32/recVTLB.cpp x86/ix86-32/recVTLB.cpp
x86/microVU_Alloc.inl
x86/microVU_Analyze.inl
x86/microVU_Branch.inl
x86/microVU_Clamp.inl
x86/microVU_Compile.inl
x86/microVU.cpp
x86/microVU_Execute.inl
x86/microVU_Flags.inl
x86/microVU_Log.inl
x86/microVU_Lower.inl
x86/microVU_Macro.inl
x86/microVU_Misc.inl
x86/microVU_Tables.inl
x86/microVU_Upper.inl
x86/newVif_Dynarec.cpp x86/newVif_Dynarec.cpp
x86/newVif_Unpack.cpp x86/newVif_Unpack.cpp
x86/newVif_UnpackSSE.cpp x86/newVif_UnpackSSE.cpp
@ -538,6 +529,20 @@ set(pcsx2x86Headers
x86/microVU.h x86/microVU.h
x86/microVU_IR.h x86/microVU_IR.h
x86/microVU_Misc.h x86/microVU_Misc.h
x86/microVU_Alloc.inl
x86/microVU_Analyze.inl
x86/microVU_Branch.inl
x86/microVU_Clamp.inl
x86/microVU_Compile.inl
x86/microVU.cpp
x86/microVU_Execute.inl
x86/microVU_Flags.inl
x86/microVU_Log.inl
x86/microVU_Lower.inl
x86/microVU_Macro.inl
x86/microVU_Misc.inl
x86/microVU_Tables.inl
x86/microVU_Upper.inl
x86/newVif.h x86/newVif.h
x86/newVif_BlockBuffer.h x86/newVif_BlockBuffer.h
x86/newVif_HashBucket.h x86/newVif_HashBucket.h

View File

@ -428,7 +428,7 @@ void MTC0()
} }
int CPCOND0() { int CPCOND0() {
return ((dmacRegs->stat.CIS | ~dmacRegs->pcr.CPC) == 0x3ff); return ((dmacRegs.stat.CIS | ~dmacRegs.pcr.CPC) == 0x3ff);
} }
//#define CPCOND0 1 //#define CPCOND0 1

View File

@ -17,12 +17,6 @@
#include "Pcsx2Defs.h" #include "Pcsx2Defs.h"
static const s64 _1mb = 0x100000;
static const s64 _8mb = _1mb * 8;
static const s64 _16mb = _1mb * 16;
static const s64 _256mb = _1mb * 256;
static const s64 _1gb = _256mb * 4;
static const u32 BIAS = 2; // Bus is half of the actual ps2 speed static const u32 BIAS = 2; // Bus is half of the actual ps2 speed
static const u32 PS2CLK = 294912000; //hz /* 294.912 mhz */ static const u32 PS2CLK = 294912000; //hz /* 294.912 mhz */

View File

@ -343,11 +343,11 @@ struct Pcsx2Config
void LoadSave( IniInterface& conf ); void LoadSave( IniInterface& conf );
void Set( const wxString& list, bool enabled=true ); void Set( const wxString& list, bool enabled=true );
bool Clear( const wxString& list ) { Set( list, false ); } void Clear( const wxString& list ) { Set( list, false ); }
bool Get( GamefixId id ) const; bool Get( GamefixId id ) const;
void Set( GamefixId id, bool enabled=true ); void Set( GamefixId id, bool enabled=true );
bool Clear( GamefixId id ) { Set( id, false ); } void Clear( GamefixId id ) { Set( id, false ); }
bool operator ==( const GamefixOptions& right ) const bool operator ==( const GamefixOptions& right ) const
{ {

View File

@ -15,11 +15,11 @@
#include "PrecompiledHeader.h" #include "PrecompiledHeader.h"
#include "Common.h"
#include <time.h> #include <time.h>
#include <cmath> #include <cmath>
#include "Common.h"
#include "R3000A.h" #include "R3000A.h"
#include "Counters.h" #include "Counters.h"
#include "IopCounters.h" #include "IopCounters.h"
@ -27,6 +27,8 @@
#include "GS.h" #include "GS.h"
#include "VUmicro.h" #include "VUmicro.h"
#include "ps2/HwInternal.h"
using namespace Threading; using namespace Threading;
extern u8 psxhblankgate; extern u8 psxhblankgate;
@ -45,6 +47,15 @@ SyncCounter vsyncCounter;
u32 nextsCounter; // records the cpuRegs.cycle value of the last call to rcntUpdate() u32 nextsCounter; // records the cpuRegs.cycle value of the last call to rcntUpdate()
s32 nextCounter; // delta from nextsCounter, in cycles, until the next rcntUpdate() s32 nextCounter; // delta from nextsCounter, in cycles, until the next rcntUpdate()
// Forward declarations needed because C/C++ both are wimpy single-pass compilers.
static void rcntStartGate(bool mode, u32 sCycle);
static void rcntEndGate(bool mode, u32 sCycle);
static void rcntWcount(int index, u32 value);
static void rcntWmode(int index, u32 value);
static void rcntWtarget(int index, u32 value);
static void rcntWhold(int index, u32 value);
void rcntReset(int index) { void rcntReset(int index) {
counters[index].count = 0; counters[index].count = 0;
@ -575,7 +586,7 @@ static __fi void _rcntSetGate( int index )
} }
// mode - 0 means hblank source, 8 means vblank source. // mode - 0 means hblank source, 8 means vblank source.
__fi void rcntStartGate(bool isVblank, u32 sCycle) static __fi void rcntStartGate(bool isVblank, u32 sCycle)
{ {
int i; int i;
@ -636,7 +647,7 @@ __fi void rcntStartGate(bool isVblank, u32 sCycle)
} }
// mode - 0 means hblank signal, 8 means vblank signal. // mode - 0 means hblank signal, 8 means vblank signal.
__fi void rcntEndGate(bool isVblank , u32 sCycle) static __fi void rcntEndGate(bool isVblank , u32 sCycle)
{ {
int i; int i;
@ -677,7 +688,15 @@ __fi void rcntEndGate(bool isVblank , u32 sCycle)
// rcntUpdate, since we're being called from there anyway. // rcntUpdate, since we're being called from there anyway.
} }
__fi void rcntWmode(int index, u32 value) static __fi u32 rcntCycle(int index)
{
if (counters[index].mode.IsCounting && (counters[index].mode.ClockSource != 0x3))
return counters[index].count + ((cpuRegs.cycle - counters[index].sCycleT) / counters[index].rate);
else
return counters[index].count;
}
static __fi void rcntWmode(int index, u32 value)
{ {
if(counters[index].mode.IsCounting) { if(counters[index].mode.IsCounting) {
if(counters[index].mode.ClockSource != 0x3) { if(counters[index].mode.ClockSource != 0x3) {
@ -711,7 +730,7 @@ __fi void rcntWmode(int index, u32 value)
_rcntSet( index ); _rcntSet( index );
} }
__fi void rcntWcount(int index, u32 value) static __fi void rcntWcount(int index, u32 value)
{ {
EECNT_LOG("EE Counter[%d] writeCount = %x, oldcount=%x, target=%x", index, value, counters[index].count, counters[index].target ); EECNT_LOG("EE Counter[%d] writeCount = %x, oldcount=%x, target=%x", index, value, counters[index].count, counters[index].target );
@ -737,7 +756,7 @@ __fi void rcntWcount(int index, u32 value)
_rcntSet( index ); _rcntSet( index );
} }
__fi void rcntWtarget(int index, u32 value) static __fi void rcntWtarget(int index, u32 value)
{ {
EECNT_LOG("EE Counter[%d] writeTarget = %x", index, value); EECNT_LOG("EE Counter[%d] writeTarget = %x", index, value);
@ -766,7 +785,7 @@ __fi void rcntWtarget(int index, u32 value)
_rcntSet( index ); _rcntSet( index );
} }
__fi void rcntWhold(int index, u32 value) static __fi void rcntWhold(int index, u32 value)
{ {
EECNT_LOG("EE Counter[%d] Hold Write = %x", index, value); EECNT_LOG("EE Counter[%d] Hold Write = %x", index, value);
counters[index].hold = value; counters[index].hold = value;
@ -787,14 +806,76 @@ __fi u32 rcntRcount(int index)
return ret; return ret;
} }
__fi u32 rcntCycle(int index) template< uint page >
__fi u16 rcntRead32( u32 mem )
{ {
if (counters[index].mode.IsCounting && (counters[index].mode.ClockSource != 0x3)) // Important DevNote:
return counters[index].count + ((cpuRegs.cycle - counters[index].sCycleT) / counters[index].rate); // Yes this uses a u16 return value on purpose! The upper bits 16 of the counter registers
else // are all fixed to 0, so we always truncate everything in these two pages using a u16
return counters[index].count; // return value! --air
iswitch( mem ) {
icase(RCNT0_COUNT) return (u16)rcntRcount(0);
icase(RCNT0_MODE) return (u16)counters[0].modeval;
icase(RCNT0_TARGET) return (u16)counters[0].target;
icase(RCNT0_HOLD) return (u16)counters[0].hold;
icase(RCNT1_COUNT) return (u16)rcntRcount(1);
icase(RCNT1_MODE) return (u16)counters[1].modeval;
icase(RCNT1_TARGET) return (u16)counters[1].target;
icase(RCNT1_HOLD) return (u16)counters[1].hold;
icase(RCNT2_COUNT) return (u16)rcntRcount(2);
icase(RCNT2_MODE) return (u16)counters[2].modeval;
icase(RCNT2_TARGET) return (u16)counters[2].target;
icase(RCNT3_COUNT) return (u16)rcntRcount(3);
icase(RCNT3_MODE) return (u16)counters[3].modeval;
icase(RCNT3_TARGET) return (u16)counters[3].target;
}
return psHu16(mem);
} }
template< uint page >
__fi bool rcntWrite32( u32 mem, mem32_t& value )
{
pxAssume( mem >= RCNT0_COUNT && mem < 0x10002000 );
// [TODO] : counters should actually just use the EE's hw register space for storing
// count, mode, target, and hold. This will allow for a simplified handler for register
// reads.
iswitch( mem ) {
icase(RCNT0_COUNT) return rcntWcount(0, value), false;
icase(RCNT0_MODE) return rcntWmode(0, value), false;
icase(RCNT0_TARGET) return rcntWtarget(0, value), false;
icase(RCNT0_HOLD) return rcntWhold(0, value), false;
icase(RCNT1_COUNT) return rcntWcount(1, value), false;
icase(RCNT1_MODE) return rcntWmode(1, value), false;
icase(RCNT1_TARGET) return rcntWtarget(1, value), false;
icase(RCNT1_HOLD) return rcntWhold(1, value), false;
icase(RCNT2_COUNT) return rcntWcount(2, value), false;
icase(RCNT2_MODE) return rcntWmode(2, value), false;
icase(RCNT2_TARGET) return rcntWtarget(2, value), false;
icase(RCNT3_COUNT) return rcntWcount(3, value), false;
icase(RCNT3_MODE) return rcntWmode(3, value), false;
icase(RCNT3_TARGET) return rcntWtarget(3, value), false;
}
// unhandled .. do memory writeback.
return true;
}
template u16 rcntRead32<0x00>( u32 mem );
template u16 rcntRead32<0x01>( u32 mem );
template bool rcntWrite32<0x00>( u32 mem, mem32_t& value );
template bool rcntWrite32<0x01>( u32 mem, mem32_t& value );
void SaveStateBase::rcntFreeze() void SaveStateBase::rcntFreeze()
{ {
Freeze( counters ); Freeze( counters );

View File

@ -13,8 +13,7 @@
* If not, see <http://www.gnu.org/licenses/>. * If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef __COUNTERS_H__ #pragma once
#define __COUNTERS_H__
struct EECNT_MODE struct EECNT_MODE
{ {
@ -137,16 +136,10 @@ extern void rcntUpdate_vSync();
extern void rcntUpdate(); extern void rcntUpdate();
extern void rcntInit(); extern void rcntInit();
extern void rcntStartGate(bool mode, u32 sCycle);
extern void rcntEndGate(bool mode, u32 sCycle);
extern void rcntWcount(int index, u32 value);
extern void rcntWmode(int index, u32 value);
extern void rcntWtarget(int index, u32 value);
extern void rcntWhold(int index, u32 value);
extern u32 rcntRcount(int index); extern u32 rcntRcount(int index);
extern u32 rcntCycle(int index); template< uint page > extern bool rcntWrite32( u32 mem, mem32_t& value );
template< uint page > extern u16 rcntRead32( u32 mem ); // returns u16 by design! (see implementation for details)
extern u32 UpdateVSyncRate(); extern u32 UpdateVSyncRate();
extern void frameLimitReset(); extern void frameLimitReset();
#endif /* __COUNTERS_H__ */

View File

@ -342,17 +342,19 @@ struct SysConsoleLogPack
extern SysTraceLogPack SysTrace; extern SysTraceLogPack SysTrace;
extern SysConsoleLogPack SysConsole; extern SysConsoleLogPack SysConsole;
extern void __Log( const char* fmt, ... );
// Helper macro for cut&paste. Note that we intentionally use a top-level *inline* bitcheck // Helper macro for cut&paste. Note that we intentionally use a top-level *inline* bitcheck
// against Trace.Enabled, to avoid extra overhead in Debug builds when logging is disabled. // against Trace.Enabled, to avoid extra overhead in Debug builds when logging is disabled.
// (specifically this allows debug builds to skip havingto resolve all the parameters being // (specifically this allows debug builds to skip havingto resolve all the parameters being
// passed into the function) // passed into the function)
#define macTrace(trace) SysTrace.trace.IsActive() && SysTrace.trace.Write
#ifdef PCSX2_DEVBUILD #ifdef PCSX2_DEVBUILD
# define SysTraceActive(trace) SysTrace.trace.IsActive()
extern void __Log( const char* fmt, ... ); # define macTrace(trace) SysTraceActive(trace) && SysTrace.trace.Write
#else
# define SysTraceActive(trace) (false)
# define macTrace(trace)
#endif
#define SIF_LOG macTrace(SIF) #define SIF_LOG macTrace(SIF)
@ -385,45 +387,9 @@ extern void __Log( const char* fmt, ... );
#define GPU_LOG macTrace(IOP.GPU) #define GPU_LOG macTrace(IOP.GPU)
#define CDVD_LOG macTrace(IOP.CDVD) #define CDVD_LOG macTrace(IOP.CDVD)
#else // PCSX2_DEVBUILD
#define CPU_LOG 0&&
#define MEM_LOG 0&&
#define HW_LOG 0&&
#define DMA_LOG 0&&
#define BIOS_LOG 0&&
#define VU0_LOG 0&&
#define COP0_LOG 0&&
#define UnknownHW_LOG 0&&
#define VIF_LOG 0&&
#define SPR_LOG 0&&
#define GIF_LOG 0&&
#define SIF_LOG 0&&
#define IPU_LOG 0&&
#define VUM_LOG 0&&
#define VifCodeLog 0&&
#define PSXCPU_LOG 0&&
#define PSXMEM_LOG 0&&
#define PSXHW_LOG 0&&
#define PSXUnkHW_LOG 0&&
#define PSXBIOS_LOG 0&&
#define PSXDMA_LOG 0&&
#define PAD_LOG 0&&
#define CDR_LOG 0&&
#define CDVD_LOG 0&&
#define GPU_LOG 0&&
#define PSXCNT_LOG 0&&
#define EECNT_LOG 0&&
#define EMU_LOG 0&&
#define CACHE_LOG 0&&
#define MEMCARDS_LOG 0&&
#endif
#define ELF_LOG SysConsole.ELF.IsActive() && SysConsole.ELF.Write #define ELF_LOG SysConsole.ELF.IsActive() && SysConsole.ELF.Write
#define eeRecPerfLog SysConsole.eeRecPerf.IsActive() && SysConsole.eeRecPerf #define eeRecPerfLog SysConsole.eeRecPerf.IsActive() && SysConsole.eeRecPerf
#define eeConLog SysConsole.eeConsole.IsActive() && SysConsole.eeConsole.Write #define eeConLog SysConsole.eeConsole.IsActive() && SysConsole.eeConsole.Write
#define eeDeci2Log SysConsole.deci2.IsActive() && SysConsole.deci2.Write #define eeDeci2Log SysConsole.deci2.IsActive() && SysConsole.deci2.Write
#define iopConLog SysConsole.iopConsole.IsActive() && SysConsole.iopConsole.Write #define iopConLog SysConsole.iopConsole.IsActive()&& SysConsole.iopConsole.Write

View File

@ -171,10 +171,6 @@ union tDMA_QWC {
tDMA_TAG tag() const { return (tDMA_TAG)_u32; } tDMA_TAG tag() const { return (tDMA_TAG)_u32; }
}; };
static void setDmacStat(u32 num);
static tDMA_TAG *dmaGetAddr(u32 addr, bool write);
static void throwBusError(const char *s);
struct DMACh { struct DMACh {
tDMA_CHCR chcr; tDMA_CHCR chcr;
u32 _null0[3]; u32 _null0[3];
@ -200,63 +196,14 @@ struct DMACh {
qwc = ptag[0].QWC; qwc = ptag[0].QWC;
} }
bool transfer(const char *s, tDMA_TAG* ptag) bool transfer(const char *s, tDMA_TAG* ptag);
{ void unsafeTransfer(tDMA_TAG* ptag);
if (ptag == NULL) // Is ptag empty? tDMA_TAG *getAddr(u32 addr, u32 num, bool write);
{ tDMA_TAG *DMAtransfer(u32 addr, u32 num);
throwBusError(s); tDMA_TAG dma_tag();
return false;
}
chcrTransfer(ptag);
qwcTransfer(ptag); wxString cmq_to_str() const;
return true; wxString cmqt_to_str() const;
}
void unsafeTransfer(tDMA_TAG* ptag)
{
chcrTransfer(ptag);
qwcTransfer(ptag);
}
tDMA_TAG *getAddr(u32 addr, u32 num, bool write)
{
tDMA_TAG *ptr = dmaGetAddr(addr, write);
if (ptr == NULL)
{
throwBusError("dmaGetAddr");
setDmacStat(num);
chcr.STR = false;
}
return ptr;
}
tDMA_TAG *DMAtransfer(u32 addr, u32 num)
{
tDMA_TAG *tag = getAddr(addr, num, false);
if (tag == NULL) return NULL;
chcrTransfer(tag);
qwcTransfer(tag);
return tag;
}
tDMA_TAG dma_tag()
{
return chcr.tag();
}
wxString cmq_to_str() const
{
return wxsFormat(L"chcr = %lx, madr = %lx, qwc = %lx", chcr._u32, madr, qwc);
}
wxString cmqt_to_str() const
{
return wxsFormat(L"chcr = %lx, madr = %lx, qwc = %lx, tadr = %1x", chcr._u32, madr, qwc, tadr);
}
}; };
enum INTCIrqs enum INTCIrqs
@ -524,7 +471,7 @@ union tDMAC_ADDR
wxCharBuffer ToUTF8(bool sprIsValid=true) const wxCharBuffer ToUTF8(bool sprIsValid=true) const
{ {
return FastFormatAscii().Write((sprIsValid && SPR) ? "0x%04X(SPR)" : "0x%08X", ADDR).GetResult(); return FastFormatAscii().Write((sprIsValid && SPR) ? "0x%04X(SPR)" : "0x%08X", ADDR).c_str();
} }
}; };
@ -588,88 +535,28 @@ struct INTCregisters
u32 _padding2[3]; u32 _padding2[3];
}; };
#define dmacRegs ((DMACregisters*)(eeMem->HW+0xE000)) #define intcRegs ((INTCregisters*)(eeHw+0xF000))
#define intcRegs ((INTCregisters*)(eeMem->HW+0xF000))
static __fi void throwBusError(const char *s) static DMACregisters& dmacRegs = (DMACregisters&)eeHw[0xE000];
{
Console.Error("%s BUSERR", s);
dmacRegs->stat.BEIS = true;
}
static __fi void setDmacStat(u32 num) // Various useful locations
{ static DMACh& vif0ch = (DMACh&)eeHw[0x8000];
dmacRegs->stat.set_flags(1 << num); static DMACh& vif1ch = (DMACh&)eeHw[0x9000];
} static DMACh& gifch = (DMACh&)eeHw[0xA000];
static DMACh& spr0ch = (DMACh&)eeHw[0xD000];
static DMACh& spr1ch = (DMACh&)eeHw[0xD400];
// Note: Dma addresses are guaranteed to be aligned to 16 bytes (128 bits) extern void throwBusError(const char *s);
static __fi tDMA_TAG *SPRdmaGetAddr(u32 addr, bool write) extern void setDmacStat(u32 num);
{ extern tDMA_TAG *SPRdmaGetAddr(u32 addr, bool write);
// if (addr & 0xf) { DMA_LOG("*PCSX2*: DMA address not 128bit aligned: %8.8x", addr); } extern tDMA_TAG *dmaGetAddr(u32 addr, bool write);
//For some reason Getaway references SPR Memory from itself using SPR0, oh well, let it i guess...
if((addr & 0x70000000) == 0x70000000)
{
return (tDMA_TAG*)&eeMem->Scratch[addr & 0x3ff0];
}
// FIXME: Why??? DMA uses physical addresses
addr &= 0x1ffffff0;
if (addr < Ps2MemSize::Base)
{
return (tDMA_TAG*)&eeMem->Main[addr];
}
else if (addr < 0x10000000)
{
return (tDMA_TAG*)(write ? eeMem->ZeroWrite : eeMem->ZeroRead);
}
else if ((addr >= 0x11004000) && (addr < 0x11010000))
{
//Access for VU Memory
return (tDMA_TAG*)vtlb_GetPhyPtr(addr & 0x1FFFFFF0);
}
else
{
Console.Error( "*PCSX2*: DMA error: %8.8x", addr);
return NULL;
}
}
// Note: Dma addresses are guaranteed to be aligned to 16 bytes (128 bits)
static __ri tDMA_TAG *dmaGetAddr(u32 addr, bool write)
{
// if (addr & 0xf) { DMA_LOG("*PCSX2*: DMA address not 128bit aligned: %8.8x", addr); }
if (DMA_TAG(addr).SPR) return (tDMA_TAG*)&eeMem->Scratch[addr & 0x3ff0];
// FIXME: Why??? DMA uses physical addresses
addr &= 0x1ffffff0;
if (addr < Ps2MemSize::Base)
{
return (tDMA_TAG*)&eeMem->Main[addr];
}
else if (addr < 0x10000000)
{
return (tDMA_TAG*)(write ? eeMem->ZeroWrite : eeMem->ZeroRead);
}
else if (addr < 0x10004000)
{
// Secret scratchpad address for DMA = end of maximum main memory?
//Console.Warning("Writing to the scratchpad without the SPR flag set!");
return (tDMA_TAG*)&eeMem->Scratch[addr & 0x3ff0];
}
else
{
Console.Error( "*PCSX2*: DMA error: %8.8x", addr);
return NULL;
}
}
extern void hwIntcIrq(int n); extern void hwIntcIrq(int n);
extern void hwDmacIrq(int n); extern void hwDmacIrq(int n);
extern bool hwMFIFOWrite(u32 addr, const u128* data, uint size_qwc); extern bool hwMFIFOWrite(u32 addr, const u128* data, uint size_qwc);
extern bool hwDmacSrcChainWithStack(DMACh *dma, int id); extern bool hwDmacSrcChainWithStack(DMACh& dma, int id);
extern bool hwDmacSrcChain(DMACh *dma, int id); extern bool hwDmacSrcChain(DMACh& dma, int id);
template< uint page > u32 dmacRead32( u32 mem );
template< uint page > extern bool dmacWrite32( u32 mem, mem32_t& value );

View File

@ -129,10 +129,10 @@ void iDumpRegisters(u32 startpc, u32 temp)
__Log("gif: %x %x %x", psHu32(0x3000), psHu32(0x3010), psHu32(0x3020)); __Log("gif: %x %x %x", psHu32(0x3000), psHu32(0x3010), psHu32(0x3020));
for(i = 0; i < ArraySize(dmacs); ++i) { for(i = 0; i < ArraySize(dmacs); ++i) {
DMACh* p = (DMACh*)(&eeMem->HW[dmacs[i]]); DMACh* p = (DMACh*)(&eeHw[dmacs[i]]);
__Log("dma%d c%x m%x q%x t%x s%x", i, p->chcr._u32, p->madr, p->qwc, p->tadr, p->sadr); __Log("dma%d c%x m%x q%x t%x s%x", i, p->chcr._u32, p->madr, p->qwc, p->tadr, p->sadr);
} }
__Log(L"dmac " + dmacRegs->ctrl.desc() + L" " + dmacRegs->stat.desc() + L" " + dmacRegs->rbsr.desc() + L" " + dmacRegs->rbor.desc()); __Log(L"dmac " + dmacRegs.ctrl.desc() + L" " + dmacRegs.stat.desc() + L" " + dmacRegs.rbsr.desc() + L" " + dmacRegs.rbor.desc());
__Log(L"intc " + intcRegs->stat.desc() + L" " + intcRegs->mask.desc()); __Log(L"intc " + intcRegs->stat.desc() + L" " + intcRegs->mask.desc());
__Log("sif: %x %x %x %x %x", psHu32(SBUS_F200), psHu32(SBUS_F220), psHu32(SBUS_F230), psHu32(SBUS_F240), psHu32(SBUS_F260)); __Log("sif: %x %x %x %x %x", psHu32(SBUS_F200), psHu32(SBUS_F220), psHu32(SBUS_F230), psHu32(SBUS_F240), psHu32(SBUS_F260));
#endif #endif

View File

@ -28,8 +28,6 @@
/////////////////////////// Quick & dirty FIFO :D //////////////////////// /////////////////////////// Quick & dirty FIFO :D ////////////////////////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// ** NOTE: cannot use XMM/MMX regs **
// Notes on FIFO implementation // Notes on FIFO implementation
// //
// The FIFO consists of four separate pages of HW register memory, each mapped to a // The FIFO consists of four separate pages of HW register memory, each mapped to a
@ -40,167 +38,108 @@
// 0x6000 - 0x7000 : GS (all registers map to 0x6000) // 0x6000 - 0x7000 : GS (all registers map to 0x6000)
// 0x7000 - 0x8000 : IPU (registers map to 0x7000 and 0x7010, respectively) // 0x7000 - 0x8000 : IPU (registers map to 0x7000 and 0x7010, respectively)
////////////////////////////////////////////////////////////////////////// void __fastcall ReadFIFO_VIF1(mem128_t* out)
// ReadFIFO Pages
void __fastcall ReadFIFO_page_4(u32 mem, mem128_t* out)
{ {
pxAssert( (mem >= VIF0_FIFO) && (mem < VIF1_FIFO) ); if (vif1Regs.stat.test(VIF1_STAT_INT | VIF1_STAT_VSS | VIF1_STAT_VIS | VIF1_STAT_VFS) )
VIF_LOG("ReadFIFO/VIF0 0x%08X", mem);
CopyQWC( out, &psHu128(VIF0_FIFO) );
}
void __fastcall ReadFIFO_page_5(u32 mem, mem128_t* out)
{
pxAssert( (mem >= VIF1_FIFO) && (mem < GIF_FIFO) );
VIF_LOG("ReadFIFO/VIF1, addr=0x%08X", mem);
if (vif1Regs->stat.test(VIF1_STAT_INT | VIF1_STAT_VSS | VIF1_STAT_VIS | VIF1_STAT_VFS) )
DevCon.Warning( "Reading from vif1 fifo when stalled" ); DevCon.Warning( "Reading from vif1 fifo when stalled" );
if(vif1Regs->stat.FQC == 0) Console.Warning("FQC = 0 on VIF FIFO READ!"); pxAssertRel(vif1Regs.stat.FQC != 0, "FQC = 0 on VIF FIFO READ!");
if (vif1Regs->stat.FDR) if (vif1Regs.stat.FDR)
{ {
if(vif1Regs->stat.FQC > vif1.GSLastDownloadSize) if(vif1Regs.stat.FQC > vif1.GSLastDownloadSize)
{ {
DevCon.Warning("Warning! GS Download size < FIFO count!"); DevCon.Warning("Warning! GS Download size < FIFO count!");
} }
if (vif1Regs->stat.FQC > 0) if (vif1Regs.stat.FQC > 0)
{ {
GetMTGS().WaitGS(); GetMTGS().WaitGS();
GSreadFIFO(&psHu64(VIF1_FIFO)); GSreadFIFO(&psHu64(VIF1_FIFO));
vif1.GSLastDownloadSize--; vif1.GSLastDownloadSize--;
if (vif1.GSLastDownloadSize <= 16) if (vif1.GSLastDownloadSize <= 16)
gifRegs->stat.OPH = false; gifRegs.stat.OPH = false;
vif1Regs->stat.FQC = min((u32)16, vif1.GSLastDownloadSize); vif1Regs.stat.FQC = min((u32)16, vif1.GSLastDownloadSize);
} }
} }
CopyQWC( out, &psHu128(VIF1_FIFO) ); CopyQWC( out, &psHu128(VIF1_FIFO) );
VIF_LOG("ReadFIFO/VIF1 -> %ls", out->ToString().c_str());
} }
void __fastcall ReadFIFO_page_6(u32 mem, mem128_t* out)
{
pxAssert( (mem >= GIF_FIFO) && (mem < IPUout_FIFO) );
DevCon.Warning( "ReadFIFO/GIF, addr=0x%x", mem );
CopyQWC( out, &psHu128(GIF_FIFO) );
}
// ReadFIFO_page_7 is contained in IPU_Fifo.cpp
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// WriteFIFO Pages // WriteFIFO Pages
//
void __fastcall WriteFIFO_page_4(u32 mem, const mem128_t *value) void __fastcall WriteFIFO_VIF0(const mem128_t *value)
{ {
pxAssert( (mem >= VIF0_FIFO) && (mem < VIF1_FIFO) ); VIF_LOG("WriteFIFO/VIF0 <- %ls", value->ToString().c_str());
VIF_LOG("WriteFIFO/VIF0, addr=0x%08X", mem);
CopyQWC(&psHu128(VIF0_FIFO), value); CopyQWC(&psHu128(VIF0_FIFO), value);
vif0ch->qwc += 1; vif0ch.qwc += 1;
if(vif0.irqoffset != 0 && vif0.vifstalled == true) DevCon.Warning("Offset on VIF0 FIFO start!"); if(vif0.irqoffset != 0 && vif0.vifstalled == true) DevCon.Warning("Offset on VIF0 FIFO start!");
bool ret = VIF0transfer((u32*)value, 4); bool ret = VIF0transfer((u32*)value, 4);
if (vif0.cmd) if (vif0.cmd)
{ {
if(vif0.done == true && vif0ch->qwc == 0) vif0Regs->stat.VPS = VPS_WAITING; if(vif0.done && vif0ch.qwc == 0) vif0Regs.stat.VPS = VPS_WAITING;
} }
else else
{ {
vif0Regs->stat.VPS = VPS_IDLE; vif0Regs.stat.VPS = VPS_IDLE;
} }
pxAssertDev( ret, "vif stall code not implemented" ); pxAssertDev( ret, "vif stall code not implemented" );
} }
void __fastcall WriteFIFO_page_5(u32 mem, const mem128_t *value) void __fastcall WriteFIFO_VIF1(const mem128_t *value)
{ {
pxAssert( (mem >= VIF1_FIFO) && (mem < GIF_FIFO) ); VIF_LOG("WriteFIFO/VIF1 <- %ls", value->ToString().c_str());
VIF_LOG("WriteFIFO/VIF1, addr=0x%08X", mem);
CopyQWC(&psHu128(VIF1_FIFO), value); CopyQWC(&psHu128(VIF1_FIFO), value);
if (vif1Regs->stat.FDR) if (vif1Regs.stat.FDR)
DevCon.Warning("writing to fifo when fdr is set!"); DevCon.Warning("writing to fifo when fdr is set!");
if (vif1Regs->stat.test(VIF1_STAT_INT | VIF1_STAT_VSS | VIF1_STAT_VIS | VIF1_STAT_VFS) ) if (vif1Regs.stat.test(VIF1_STAT_INT | VIF1_STAT_VSS | VIF1_STAT_VIS | VIF1_STAT_VFS) )
DevCon.Warning("writing to vif1 fifo when stalled"); DevCon.Warning("writing to vif1 fifo when stalled");
vif1ch->qwc += 1; vif1ch.qwc += 1;
if(vif1.irqoffset != 0 && vif1.vifstalled == true) DevCon.Warning("Offset on VIF1 FIFO start!"); if(vif1.irqoffset != 0 && vif1.vifstalled == true) DevCon.Warning("Offset on VIF1 FIFO start!");
bool ret = VIF1transfer((u32*)value, 4); bool ret = VIF1transfer((u32*)value, 4);
if(GSTransferStatus.PTH2 == STOPPED_MODE && gifRegs->stat.APATH == GIF_APATH2) if(GSTransferStatus.PTH2 == STOPPED_MODE && gifRegs.stat.APATH == GIF_APATH2)
{ {
if(gifRegs->stat.DIR == 0)gifRegs->stat.OPH = false; if(gifRegs.stat.DIR == 0)gifRegs.stat.OPH = false;
gifRegs->stat.APATH = GIF_APATH_IDLE; gifRegs.stat.APATH = GIF_APATH_IDLE;
if(gifRegs->stat.P1Q) gsPath1Interrupt(); if(gifRegs.stat.P1Q) gsPath1Interrupt();
} }
if (vif1.cmd) if (vif1.cmd)
{ {
if(vif1.done == true && vif1ch->qwc == 0) vif1Regs->stat.VPS = VPS_WAITING; if(vif1.done == true && vif1ch.qwc == 0) vif1Regs.stat.VPS = VPS_WAITING;
} }
else else
{ {
vif1Regs->stat.VPS = VPS_IDLE; vif1Regs.stat.VPS = VPS_IDLE;
} }
pxAssertDev( ret, "vif stall code not implemented" ); pxAssertDev( ret, "vif stall code not implemented" );
} }
// Dummy GIF-TAG Packet to Guarantee Count = 1 // Dummy GIF-TAG Packet to Guarantee Count = 1
__aligned16 u32 nloop0_packet[4] = {0, 0, 0, 0}; __aligned16 u128 nloop0_packet;
void __fastcall WriteFIFO_page_6(u32 mem, const mem128_t *value) void __fastcall WriteFIFO_GIF(const mem128_t *value)
{ {
pxAssert( (mem >= GIF_FIFO) && (mem < IPUout_FIFO) ); GIF_LOG("WriteFIFO/GIF <- %ls", value->ToString().c_str());
GIF_LOG("WriteFIFO/GIF, addr=0x%08X", mem);
CopyQWC(&psHu128(GIF_FIFO), value); CopyQWC(&psHu128(GIF_FIFO), value);
CopyQWC(nloop0_packet, value); CopyQWC(&nloop0_packet, value);
GetMTGS().PrepDataPacket(GIF_PATH_3, 1); GetMTGS().PrepDataPacket(GIF_PATH_3, 1);
GIFPath_CopyTag( GIF_PATH_3, (u128*)nloop0_packet, 1 ); GIFPath_CopyTag( GIF_PATH_3, &nloop0_packet, 1 );
GetMTGS().SendDataPacket(); GetMTGS().SendDataPacket();
if(GSTransferStatus.PTH3 == STOPPED_MODE && gifRegs->stat.APATH == GIF_APATH3 ) if(GSTransferStatus.PTH3 == STOPPED_MODE && gifRegs.stat.APATH == GIF_APATH3 )
{ {
if(gifRegs->stat.DIR == 0)gifRegs->stat.OPH = false; if(gifRegs.stat.DIR == 0)gifRegs.stat.OPH = false;
gifRegs->stat.APATH = GIF_APATH_IDLE; gifRegs.stat.APATH = GIF_APATH_IDLE;
if(gifRegs->stat.P1Q) gsPath1Interrupt(); if(gifRegs.stat.P1Q) gsPath1Interrupt();
}
}
void __fastcall WriteFIFO_page_7(u32 mem, const mem128_t *value)
{
pxAssert( (mem >= IPUout_FIFO) && (mem < D0_CHCR) );
// All addresses in this page map to 0x7000 and 0x7010:
mem &= 0x10;
IPU_LOG( "WriteFIFO, addr=0x%x", mem );
if( mem == 0 )
{
// Should this raise a PS2 exception or just ignore silently?
Console.Warning( "WriteFIFO/IPUout (ignored)" );
}
else
{
IPU_LOG("WriteFIFO in[%d] <- %8.8X_%8.8X_%8.8X_%8.8X",
mem/16, ((u32*)value)[3], ((u32*)value)[2], ((u32*)value)[1], ((u32*)value)[0]);
//committing every 16 bytes
while( ipu_fifo.in.write((u32*)value, 1) == 0 )
{
Console.WriteLn("IPU sleeping");
Threading::Timeslice();
}
} }
} }

View File

@ -56,9 +56,9 @@ extern u32 SIGNAL_Data_Pending[2];
void gsGIFReset() void gsGIFReset()
{ {
gifRegs->stat.reset(); gifRegs.stat.reset();
gifRegs->ctrl.reset(); gifRegs.ctrl.reset();
gifRegs->mode.reset(); gifRegs.mode.reset();
} }
void gsReset() void gsReset()
@ -128,7 +128,7 @@ static __fi void gsCSRwrite( const tGS_CSR& csr )
SIGNAL_IMR_Pending = false; SIGNAL_IMR_Pending = false;
if(gifRegs->stat.P1Q && gifRegs->stat.APATH <= GIF_APATH1) gsPath1Interrupt(); if(gifRegs.stat.P1Q && gifRegs.stat.APATH <= GIF_APATH1) gsPath1Interrupt();
} }
if(csr.FINISH) CSRreg.FINISH = false; if(csr.FINISH) CSRreg.FINISH = false;
@ -286,9 +286,9 @@ void __fastcall gsWrite64_page_01( u32 mem, const mem64_t* value )
//Only problem is it kills killzone :(. //Only problem is it kills killzone :(.
// (yes it *is* a complete hack; both lines here in fact --air) // (yes it *is* a complete hack; both lines here in fact --air)
//========================================================================= //=========================================================================
//gifRegs->stat.OPH = true; // Bleach wants it, Killzone hates it. //gifRegs.stat.OPH = true; // Bleach wants it, Killzone hates it.
gifRegs->stat.DIR = (u32)value[0]; gifRegs.stat.DIR = (u32)value[0];
//========================================================================= //=========================================================================
// BUSDIR INSANITY !! MTGS FLUSH NEEDED // BUSDIR INSANITY !! MTGS FLUSH NEEDED
// //
@ -459,8 +459,6 @@ void SaveStateBase::gsFreeze()
{ {
FreezeMem(PS2MEM_GS, 0x2000); FreezeMem(PS2MEM_GS, 0x2000);
Freeze(SIGNAL_IMR_Pending); Freeze(SIGNAL_IMR_Pending);
if( GetVersion() > 0 )
Freeze(gsRegionMode); Freeze(gsRegionMode);
gifPathFreeze(); gifPathFreeze();

View File

@ -54,9 +54,9 @@ void gsPath1Interrupt()
if((gifRegs->stat.APATH <= GIF_APATH1 || (gifRegs->stat.IP3 == true && gifRegs->stat.APATH == GIF_APATH3)) && Path1WritePos > 0 && !gifRegs->stat.PSE) if((gifRegs.stat.APATH <= GIF_APATH1 || (gifRegs.stat.IP3 == true && gifRegs.stat.APATH == GIF_APATH3)) && Path1WritePos > 0 && !gifRegs.stat.PSE)
{ {
gifRegs->stat.P1Q = false; gifRegs.stat.P1Q = false;
if (uint size = (Path1WritePos - Path1ReadPos)) if (uint size = (Path1WritePos - Path1ReadPos))
{ {
@ -70,8 +70,8 @@ void gsPath1Interrupt()
if(GSTransferStatus.PTH1 == STOPPED_MODE) if(GSTransferStatus.PTH1 == STOPPED_MODE)
{ {
gifRegs->stat.OPH = false; gifRegs.stat.OPH = false;
gifRegs->stat.APATH = GIF_APATH_IDLE; gifRegs.stat.APATH = GIF_APATH_IDLE;
} }
} }
GetMTGS().SendDataPacket(); GetMTGS().SendDataPacket();
@ -84,8 +84,8 @@ void gsPath1Interrupt()
} }
else else
{ {
if(gifRegs->stat.PSE) DevCon.Warning("Path1 paused by GIF_CTRL"); if(gifRegs.stat.PSE) DevCon.Warning("Path1 paused by GIF_CTRL");
DevCon.Warning("Looping??? IP3 %x APATH %x OPH %x", gifRegs->stat.IP3, gifRegs->stat.APATH, gifRegs->stat.OPH); DevCon.Warning("Looping??? IP3 %x APATH %x OPH %x", gifRegs.stat.IP3, gifRegs.stat.APATH, gifRegs.stat.OPH);
//if(!(cpuRegs.interrupt & (1<<28)) && Path1WritePos > 0)CPU_INT(28, 128); //if(!(cpuRegs.interrupt & (1<<28)) && Path1WritePos > 0)CPU_INT(28, 128);
} }
@ -104,25 +104,25 @@ __fi void gsInterrupt()
return; return;
} }
if(GSTransferStatus.PTH3 >= PENDINGSTOP_MODE && gifRegs->stat.APATH == GIF_APATH3 ) if(GSTransferStatus.PTH3 >= PENDINGSTOP_MODE && gifRegs.stat.APATH == GIF_APATH3 )
{ {
gifRegs->stat.OPH = false; gifRegs.stat.OPH = false;
GSTransferStatus.PTH3 = STOPPED_MODE; GSTransferStatus.PTH3 = STOPPED_MODE;
gifRegs->stat.APATH = GIF_APATH_IDLE; gifRegs.stat.APATH = GIF_APATH_IDLE;
if(gifRegs->stat.P1Q) gsPath1Interrupt(); if(gifRegs.stat.P1Q) gsPath1Interrupt();
} }
if (!(gif->chcr.STR)) if (!(gifch.chcr.STR))
{ {
//Console.WriteLn("Eh? why are you still interrupting! chcr %x, qwc %x, done = %x", gif->chcr._u32, gif->qwc, done); //Console.WriteLn("Eh? why are you still interrupting! chcr %x, qwc %x, done = %x", gifch.chcr._u32, gifch.qwc, done);
return; return;
} }
if ((gif->qwc > 0) || (!gspath3done)) if ((gifch.qwc > 0) || (!gspath3done))
{ {
if (!dmacRegs->ctrl.DMAE) if (!dmacRegs.ctrl.DMAE)
{ {
Console.Warning("gs dma masked, re-scheduling..."); Console.Warning("gs dma masked, re-scheduling...");
// re-raise the int shortly in the future // re-raise the int shortly in the future
@ -136,14 +136,14 @@ __fi void gsInterrupt()
gspath3done = false; gspath3done = false;
gscycles = 0; gscycles = 0;
gif->chcr.STR = false; gifch.chcr.STR = false;
//// ////
/*gifRegs->stat.OPH = false; /*gifRegs.stat.OPH = false;
GSTransferStatus.PTH3 = STOPPED_MODE; GSTransferStatus.PTH3 = STOPPED_MODE;
gifRegs->stat.APATH = GIF_APATH_IDLE;*/ gifRegs.stat.APATH = GIF_APATH_IDLE;*/
//// ////
gifRegs->stat.clear_flags(GIF_STAT_FQC); gifRegs.stat.clear_flags(GIF_STAT_FQC);
clearFIFOstuff(false); clearFIFOstuff(false);
hwDmacIrq(DMAC_GIF); hwDmacIrq(DMAC_GIF);
//DevCon.Warning("GIF DMA end"); //DevCon.Warning("GIF DMA end");
@ -166,20 +166,20 @@ int _GIFchain()
{ {
tDMA_TAG *pMem; tDMA_TAG *pMem;
pMem = dmaGetAddr(gif->madr, false); pMem = dmaGetAddr(gifch.madr, false);
if (pMem == NULL) if (pMem == NULL)
{ {
// reset path3, fixes dark cloud 2 // reset path3, fixes dark cloud 2
GIFPath_Clear( GIF_PATH_3 ); GIFPath_Clear( GIF_PATH_3 );
//must increment madr and clear qwc, else it loops //must increment madr and clear qwc, else it loops
gif->madr += gif->qwc * 16; gifch.madr += gifch.qwc * 16;
gif->qwc = 0; gifch.qwc = 0;
Console.Warning( "Hackfix - NULL GIFchain" ); Console.Warning( "Hackfix - NULL GIFchain" );
return -1; return -1;
} }
return WRITERING_DMA(pMem, gif->qwc); return WRITERING_DMA(pMem, gifch.qwc);
} }
static __fi void GIFchain() static __fi void GIFchain()
@ -187,12 +187,12 @@ static __fi void GIFchain()
// qwc check now done outside this function // qwc check now done outside this function
// Voodoocycles // Voodoocycles
// >> 2 so Drakan and Tekken 5 don't mess up in some PATH3 transfer. Cycles to interrupt were getting huge.. // >> 2 so Drakan and Tekken 5 don't mess up in some PATH3 transfer. Cycles to interrupt were getting huge..
/*if (gif->qwc)*/ gscycles+= ( _GIFchain() * BIAS); /* guessing */ /*if (gifch.qwc)*/ gscycles+= ( _GIFchain() * BIAS); /* guessing */
} }
static __fi bool checkTieBit(tDMA_TAG* &ptag) static __fi bool checkTieBit(tDMA_TAG* &ptag)
{ {
if (gif->chcr.TIE && ptag->IRQ) if (gifch.chcr.TIE && ptag->IRQ)
{ {
GIF_LOG("dmaIrq Set"); GIF_LOG("dmaIrq Set");
gspath3done = true; gspath3done = true;
@ -204,38 +204,38 @@ static __fi bool checkTieBit(tDMA_TAG* &ptag)
static __fi tDMA_TAG* ReadTag() static __fi tDMA_TAG* ReadTag()
{ {
tDMA_TAG* ptag = dmaGetAddr(gif->tadr, false); //Set memory pointer to TADR tDMA_TAG* ptag = dmaGetAddr(gifch.tadr, false); //Set memory pointer to TADR
if (!(gif->transfer("Gif", ptag))) return NULL; if (!(gifch.transfer("Gif", ptag))) return NULL;
gif->madr = ptag[1]._u32; //MADR = ADDR field + SPR gifch.madr = ptag[1]._u32; //MADR = ADDR field + SPR
gscycles += 2; // Add 1 cycles from the QW read for the tag gscycles += 2; // Add 1 cycles from the QW read for the tag
gspath3done = hwDmacSrcChainWithStack(gif, ptag->ID); gspath3done = hwDmacSrcChainWithStack(gifch, ptag->ID);
return ptag; return ptag;
} }
static __fi tDMA_TAG* ReadTag2() static __fi tDMA_TAG* ReadTag2()
{ {
tDMA_TAG* ptag = dmaGetAddr(gif->tadr, false); //Set memory pointer to TADR tDMA_TAG* ptag = dmaGetAddr(gifch.tadr, false); //Set memory pointer to TADR
gif->unsafeTransfer(ptag); gifch.unsafeTransfer(ptag);
gif->madr = ptag[1]._u32; gifch.madr = ptag[1]._u32;
gspath3done = hwDmacSrcChainWithStack(gif, ptag->ID); gspath3done = hwDmacSrcChainWithStack(gifch, ptag->ID);
return ptag; return ptag;
} }
bool CheckPaths(int Channel) bool CheckPaths(int Channel)
{ {
if(GSTransferStatus.PTH3 <= IMAGE_MODE && gifRegs->mode.IMT) if(GSTransferStatus.PTH3 <= IMAGE_MODE && gifRegs.mode.IMT)
{ {
if((gifRegs->stat.P1Q == true || gifRegs->stat.P2Q == true) || (gifRegs->stat.APATH > GIF_APATH_IDLE && gifRegs->stat.APATH < GIF_APATH3)) if((gifRegs.stat.P1Q == true || gifRegs.stat.P2Q == true) || (gifRegs.stat.APATH > GIF_APATH_IDLE && gifRegs.stat.APATH < GIF_APATH3))
{ {
if((vif1.cmd & 0x7f) != 0x51 || gifRegs->stat.P1Q == true) if((vif1.cmd & 0x7f) != 0x51 || gifRegs.stat.P1Q == true)
{ {
gifRegs->stat.IP3 = true; gifRegs.stat.IP3 = true;
if(gifRegs->stat.P1Q) gsPath1Interrupt(); if(gifRegs.stat.P1Q) gsPath1Interrupt();
CPU_INT(DMAC_GIF, 16); CPU_INT(DMAC_GIF, 16);
return false; return false;
} }
@ -244,15 +244,15 @@ bool CheckPaths(int Channel)
else if((GSTransferStatus.PTH3 == IDLE_MODE)|| (GSTransferStatus.PTH3 == STOPPED_MODE)) else if((GSTransferStatus.PTH3 == IDLE_MODE)|| (GSTransferStatus.PTH3 == STOPPED_MODE))
{ {
//This should cover both scenarios, as DIRECTHL doesn't gain priority when image mode is running (PENDINGIMAGE_MODE == fininshed). //This should cover both scenarios, as DIRECTHL doesn't gain priority when image mode is running (PENDINGIMAGE_MODE == fininshed).
if((gifRegs->stat.P1Q == true || gifRegs->stat.P2Q == true) || (gifRegs->stat.APATH > GIF_APATH_IDLE && gifRegs->stat.APATH < GIF_APATH3)) if((gifRegs.stat.P1Q == true || gifRegs.stat.P2Q == true) || (gifRegs.stat.APATH > GIF_APATH_IDLE && gifRegs.stat.APATH < GIF_APATH3))
{ {
gifRegs->stat.IP3 = true; gifRegs.stat.IP3 = true;
CPU_INT(DMAC_GIF, 16); CPU_INT(DMAC_GIF, 16);
return false; return false;
} }
} }
gifRegs->stat.IP3 = false; gifRegs.stat.IP3 = false;
return true; return true;
} }
@ -262,18 +262,18 @@ void GIFdma()
gscycles = prevcycles; gscycles = prevcycles;
if (gifRegs->ctrl.PSE) // temporarily stop if (gifRegs.ctrl.PSE) // temporarily stop
{ {
Console.WriteLn("Gif dma temp paused? (non MFIFO GIF)"); Console.WriteLn("Gif dma temp paused? (non MFIFO GIF)");
CPU_INT(DMAC_GIF, 16); CPU_INT(DMAC_GIF, 16);
return; return;
} }
if ((dmacRegs->ctrl.STD == STD_GIF) && (prevcycles != 0)) if ((dmacRegs.ctrl.STD == STD_GIF) && (prevcycles != 0))
{ {
//Console.WriteLn("GS Stall Control Source = %x, Drain = %x\n MADR = %x, STADR = %x", (psHu32(0xe000) >> 4) & 0x3, (psHu32(0xe000) >> 6) & 0x3, gif->madr, psHu32(DMAC_STADR)); //Console.WriteLn("GS Stall Control Source = %x, Drain = %x\n MADR = %x, STADR = %x", (psHu32(0xe000) >> 4) & 0x3, (psHu32(0xe000) >> 6) & 0x3, gifch.madr, psHu32(DMAC_STADR));
if ((gif->madr + (gif->qwc * 16)) > dmacRegs->stadr.ADDR) if ((gifch.madr + (gifch.qwc * 16)) > dmacRegs.stadr.ADDR)
{ {
CPU_INT(DMAC_GIF, 4); CPU_INT(DMAC_GIF, 4);
gscycles = 0; gscycles = 0;
@ -281,24 +281,24 @@ void GIFdma()
} }
prevcycles = 0; prevcycles = 0;
gif->qwc = 0; gifch.qwc = 0;
} }
clearFIFOstuff(true); clearFIFOstuff(true);
gifRegs->stat.FQC = min((u16)0x10, gif->qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3] gifRegs.stat.FQC = min((u16)0x10, gifch.qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3]
if (vif1Regs->mskpath3 || gifRegs->mode.M3R) if (vif1Regs.mskpath3 || gifRegs.mode.M3R)
{ {
if (gif->qwc == 0) if (gifch.qwc == 0)
{ {
if ((gif->chcr.MOD == CHAIN_MODE) && gif->chcr.STR) if ((gifch.chcr.MOD == CHAIN_MODE) && gifch.chcr.STR)
{ {
//DevCon.Warning("GIF Reading Tag Masked MSK = %x", vif1Regs->mskpath3); //DevCon.Warning("GIF Reading Tag Masked MSK = %x", vif1Regs.mskpath3);
ptag = ReadTag(); ptag = ReadTag();
gifRegs->stat.FQC = min((u16)0x10, gif->qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3] gifRegs.stat.FQC = min((u16)0x10, gifch.qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3]
if (ptag == NULL) return; if (ptag == NULL) return;
GIF_LOG("PTH3 MASK gifdmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx tadr=%lx", ptag[1]._u32, ptag[0]._u32, gif->qwc, ptag->ID, gif->madr, gif->tadr); GIF_LOG("PTH3 MASK gifdmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx tadr=%lx", ptag[1]._u32, ptag[0]._u32, gifch.qwc, ptag->ID, gifch.madr, gifch.tadr);
//Check TIE bit of CHCR and IRQ bit of tag //Check TIE bit of CHCR and IRQ bit of tag
if (checkTieBit(ptag)) GIF_LOG("PATH3 MSK dmaIrq Set"); if (checkTieBit(ptag)) GIF_LOG("PATH3 MSK dmaIrq Set");
@ -308,26 +308,26 @@ void GIFdma()
if (GSTransferStatus.PTH3 == IDLE_MODE) if (GSTransferStatus.PTH3 == IDLE_MODE)
{ {
GIF_LOG("PTH3 MASK Paused by VIF QWC %x", gif->qwc); GIF_LOG("PTH3 MASK Paused by VIF QWC %x", gifch.qwc);
//DevCon.Warning("GIF Paused by Mask MSK = %x", vif1Regs->mskpath3); //DevCon.Warning("GIF Paused by Mask MSK = %x", vif1Regs.mskpath3);
if(gif->qwc == 0) gsInterrupt(); if(gifch.qwc == 0) gsInterrupt();
else gifRegs->stat.set_flags(GIF_STAT_P3Q); else gifRegs.stat.set_flags(GIF_STAT_P3Q);
return; return;
} }
gifRegs->stat.FQC = min((u16)0x10, gif->qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3] gifRegs.stat.FQC = min((u16)0x10, gifch.qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3]
//Check with Path3 masking games //Check with Path3 masking games
if (gif->qwc > 0) { if (gifch.qwc > 0) {
gifRegs->stat.set_flags(GIF_STAT_P3Q); gifRegs.stat.set_flags(GIF_STAT_P3Q);
if(CheckPaths(DMAC_GIF) == false) return; if(CheckPaths(DMAC_GIF) == false) return;
gifRegs->stat.clear_flags(GIF_STAT_P3Q); gifRegs.stat.clear_flags(GIF_STAT_P3Q);
GIF_LOG("PTH3 MASK Transferring"); GIF_LOG("PTH3 MASK Transferring");
GIFchain(); GIFchain();
/*if(GSTransferStatus.PTH3 == PENDINGSTOP_MODE && gifRegs->stat.APATH == GIF_APATH_IDLE) /*if(GSTransferStatus.PTH3 == PENDINGSTOP_MODE && gifRegs.stat.APATH == GIF_APATH_IDLE)
{ {
GSTransferStatus.PTH3 = STOPPED_MODE; GSTransferStatus.PTH3 = STOPPED_MODE;
}*/ }*/
@ -338,54 +338,54 @@ void GIFdma()
} }
// Transfer Dn_QWC from Dn_MADR to GIF // Transfer Dn_QWC from Dn_MADR to GIF
if ((gif->chcr.MOD == NORMAL_MODE) || (gif->qwc > 0)) // Normal Mode if ((gifch.chcr.MOD == NORMAL_MODE) || (gifch.qwc > 0)) // Normal Mode
{ {
if ((dmacRegs->ctrl.STD == STD_GIF) && (gif->chcr.MOD == NORMAL_MODE)) if ((dmacRegs.ctrl.STD == STD_GIF) && (gifch.chcr.MOD == NORMAL_MODE))
{ {
//Console.WriteLn("DMA Stall Control on GIF normal"); //Console.WriteLn("DMA Stall Control on GIF normal");
} }
gifRegs->stat.FQC = min((u16)0x10, gif->qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3] gifRegs.stat.FQC = min((u16)0x10, gifch.qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3]
//Check with Path3 masking games //Check with Path3 masking games
//DevCon.Warning("GIF Transferring Normal/ChainQWC MSK = %x", vif1Regs->mskpath3); //DevCon.Warning("GIF Transferring Normal/ChainQWC MSK = %x", vif1Regs.mskpath3);
if (gif->qwc > 0) { if (gifch.qwc > 0) {
gifRegs->stat.set_flags(GIF_STAT_P3Q); gifRegs.stat.set_flags(GIF_STAT_P3Q);
if(CheckPaths(DMAC_GIF) == false) return; if(CheckPaths(DMAC_GIF) == false) return;
gifRegs->stat.clear_flags(GIF_STAT_P3Q); gifRegs.stat.clear_flags(GIF_STAT_P3Q);
GIFchain(); //Transfers the data set by the switch GIFchain(); //Transfers the data set by the switch
CPU_INT(DMAC_GIF, gscycles); CPU_INT(DMAC_GIF, gscycles);
return; return;
} else DevCon.Warning("GIF Normalmode or QWC going to invalid case? CHCR %x", gif->chcr._u32); } else DevCon.Warning("GIF Normalmode or QWC going to invalid case? CHCR %x", gifch.chcr._u32);
//else DevCon.WriteLn("GIFdma() case 2, but qwc = 0!"); //Don't do 0 GIFchain and then return, fixes Dual Hearts //else DevCon.WriteLn("GIFdma() case 2, but qwc = 0!"); //Don't do 0 GIFchain and then return, fixes Dual Hearts
} }
if ((gif->chcr.MOD == CHAIN_MODE) && (!gspath3done)) // Chain Mode if ((gifch.chcr.MOD == CHAIN_MODE) && (!gspath3done)) // Chain Mode
{ {
ptag = ReadTag(); ptag = ReadTag();
if (ptag == NULL) return; if (ptag == NULL) return;
//DevCon.Warning("GIF Reading Tag MSK = %x", vif1Regs->mskpath3); //DevCon.Warning("GIF Reading Tag MSK = %x", vif1Regs.mskpath3);
GIF_LOG("gifdmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx tadr=%lx", ptag[1]._u32, ptag[0]._u32, gif->qwc, ptag->ID, gif->madr, gif->tadr); GIF_LOG("gifdmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx tadr=%lx", ptag[1]._u32, ptag[0]._u32, gifch.qwc, ptag->ID, gifch.madr, gifch.tadr);
gifRegs->stat.FQC = min((u16)0x10, gif->qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3] gifRegs.stat.FQC = min((u16)0x10, gifch.qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3]
if (dmacRegs->ctrl.STD == STD_GIF) if (dmacRegs.ctrl.STD == STD_GIF)
{ {
// there are still bugs, need to also check if gif->madr +16*qwc >= stadr, if not, stall // there are still bugs, need to also check if gifch.madr +16*qwc >= stadr, if not, stall
if (!gspath3done && ((gif->madr + (gif->qwc * 16)) > dmacRegs->stadr.ADDR) && (ptag->ID == TAG_REFS)) if (!gspath3done && ((gifch.madr + (gifch.qwc * 16)) > dmacRegs.stadr.ADDR) && (ptag->ID == TAG_REFS))
{ {
// stalled. // stalled.
// We really need to test this. Pay attention to prevcycles, as it used to trigger GIFchains in the code above. (rama) // We really need to test this. Pay attention to prevcycles, as it used to trigger GIFchains in the code above. (rama)
//Console.WriteLn("GS Stall Control start Source = %x, Drain = %x\n MADR = %x, STADR = %x", (psHu32(0xe000) >> 4) & 0x3, (psHu32(0xe000) >> 6) & 0x3,gif->madr, psHu32(DMAC_STADR)); //Console.WriteLn("GS Stall Control start Source = %x, Drain = %x\n MADR = %x, STADR = %x", (psHu32(0xe000) >> 4) & 0x3, (psHu32(0xe000) >> 6) & 0x3,gifch.madr, psHu32(DMAC_STADR));
prevcycles = gscycles; prevcycles = gscycles;
//gif->tadr -= 16; //gifch.tadr -= 16;
// Quake III revolution wants to see tadr move. // Quake III revolution wants to see tadr move.
// Simple Media System (homebrew) as well. // Simple Media System (homebrew) as well.
// -16 also seems right (it shifts the bg image right if anything else). // -16 also seems right (it shifts the bg image right if anything else).
gif->tadr -= 16; gifch.tadr -= 16;
// Next line also needs to be here, according to ref // Next line also needs to be here, according to ref
gif->qwc = 0; gifch.qwc = 0;
hwDmacIrq(DMAC_STALL_SIS); hwDmacIrq(DMAC_STALL_SIS);
CPU_INT(DMAC_GIF, gscycles); CPU_INT(DMAC_GIF, gscycles);
gscycles = 0; gscycles = 0;
@ -394,7 +394,7 @@ void GIFdma()
} }
checkTieBit(ptag); checkTieBit(ptag);
/*if(gif->qwc == 0) /*if(gifch.qwc == 0)
{ {
gsInterrupt(); gsInterrupt();
return; return;
@ -403,34 +403,34 @@ void GIFdma()
prevcycles = 0; prevcycles = 0;
CPU_INT(DMAC_GIF, gscycles); CPU_INT(DMAC_GIF, gscycles);
gifRegs->stat.FQC = min((u16)0x10, gif->qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // OPH=1 | APATH=3] gifRegs.stat.FQC = min((u16)0x10, gifch.qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // OPH=1 | APATH=3]
} }
void dmaGIF() void dmaGIF()
{ {
//We used to add wait time for the buffer to fill here, fixing some timing problems in path 3 masking //We used to add wait time for the buffer to fill here, fixing some timing problems in path 3 masking
//It takes the time of 24 QW for the BUS to become ready - The Punisher And Streetball //It takes the time of 24 QW for the BUS to become ready - The Punisher And Streetball
//DevCon.Warning("dmaGIFstart chcr = %lx, madr = %lx, qwc = %lx\n tadr = %lx, asr0 = %lx, asr1 = %lx", gif->chcr._u32, gif->madr, gif->qwc, gif->tadr, gif->asr0, gif->asr1); //DevCon.Warning("dmaGIFstart chcr = %lx, madr = %lx, qwc = %lx\n tadr = %lx, asr0 = %lx, asr1 = %lx", gifch.chcr._u32, gifch.madr, gifch.qwc, gifch.tadr, gifch.asr0, gifch.asr1);
gspath3done = false; // For some reason this doesn't clear? So when the system starts the thread, we will clear it :) gspath3done = false; // For some reason this doesn't clear? So when the system starts the thread, we will clear it :)
gifRegs->stat.FQC |= 0x10; // hack ;) gifRegs.stat.FQC |= 0x10; // hack ;)
if (gif->chcr.MOD == NORMAL_MODE) { //Else it really is a normal transfer and we want to quit, else it gets confused with chains if (gifch.chcr.MOD == NORMAL_MODE) { //Else it really is a normal transfer and we want to quit, else it gets confused with chains
gspath3done = true; gspath3done = true;
} }
clearFIFOstuff(true); clearFIFOstuff(true);
if(gif->chcr.MOD == CHAIN_MODE && gif->qwc > 0) if(gifch.chcr.MOD == CHAIN_MODE && gifch.qwc > 0)
{ {
//DevCon.Warning(L"GIF QWC on Chain " + gif->chcr.desc()); //DevCon.Warning(L"GIF QWC on Chain " + gifch.chcr.desc());
if ((gif->chcr.tag().ID == TAG_REFE) || (gif->chcr.tag().ID == TAG_END)) if ((gifch.chcr.tag().ID == TAG_REFE) || (gifch.chcr.tag().ID == TAG_END))
{ {
gspath3done = true; gspath3done = true;
} }
} }
if (dmacRegs->ctrl.MFD == MFD_GIF) // GIF MFIFO if (dmacRegs.ctrl.MFD == MFD_GIF) // GIF MFIFO
{ {
//Console.WriteLn("GIF MFIFO"); //Console.WriteLn("GIF MFIFO");
gifMFIFOInterrupt(); gifMFIFOInterrupt();
@ -443,7 +443,7 @@ void dmaGIF()
// called from only one location, so forceinline it: // called from only one location, so forceinline it:
static __fi bool mfifoGIFrbTransfer() static __fi bool mfifoGIFrbTransfer()
{ {
u32 mfifoqwc = min(gifqwc, (u32)gif->qwc); u32 mfifoqwc = min(gifqwc, (u32)gifch.qwc);
u32 *src; u32 *src;
GetMTGS().PrepDataPacket(GIF_PATH_3, mfifoqwc); GetMTGS().PrepDataPacket(GIF_PATH_3, mfifoqwc);
@ -453,21 +453,21 @@ static __fi bool mfifoGIFrbTransfer()
// memory similarly to how it wraps VU1 memory on PATH1. // memory similarly to how it wraps VU1 memory on PATH1.
/* Check if the transfer should wrap around the ring buffer */ /* Check if the transfer should wrap around the ring buffer */
if ((gif->madr + mfifoqwc * 16) > (dmacRegs->rbor.ADDR + dmacRegs->rbsr.RMSK + 16)) if ((gifch.madr + mfifoqwc * 16) > (dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16))
{ {
uint s1 = ((dmacRegs->rbor.ADDR + dmacRegs->rbsr.RMSK + 16) - gif->madr) >> 4; uint s1 = ((dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16) - gifch.madr) >> 4;
uint s2 = (mfifoqwc - s1); uint s2 = (mfifoqwc - s1);
/* it does (wrap around), so first copy 's1' bytes from 'addr' to 'data' */ /* it does (wrap around), so first copy 's1' bytes from 'addr' to 'data' */
/* and second copy 's2' bytes from 'maddr' to '&data[s1]' */ /* and second copy 's2' bytes from 'maddr' to '&data[s1]' */
src = (u32*)PSM(gif->madr); src = (u32*)PSM(gifch.madr);
if (src == NULL) return false; if (src == NULL) return false;
uint copied = GIFPath_CopyTag(GIF_PATH_3, (u128*)src, s1); uint copied = GIFPath_CopyTag(GIF_PATH_3, (u128*)src, s1);
if (copied == s1) // but only copy second if first didn't abort prematurely for some reason. if (copied == s1) // but only copy second if first didn't abort prematurely for some reason.
{ {
src = (u32*)PSM(dmacRegs->rbor.ADDR); src = (u32*)PSM(dmacRegs.rbor.ADDR);
if (src == NULL) return false; if (src == NULL) return false;
copied += GIFPath_CopyTag(GIF_PATH_3, (u128*)src, s2); copied += GIFPath_CopyTag(GIF_PATH_3, (u128*)src, s2);
} }
@ -476,11 +476,11 @@ static __fi bool mfifoGIFrbTransfer()
} }
else else
{ {
/* it doesn't, so just transfer 'qwc*16' words from 'gif->madr' to GS */ /* it doesn't, so just transfer 'qwc*16' words from 'gifch.madr' to GS */
src = (u32*)PSM(gif->madr); src = (u32*)PSM(gifch.madr);
if (src == NULL) return false; if (src == NULL) return false;
mfifoqwc = GIFPath_CopyTag(GIF_PATH_3, (u128*)src, mfifoqwc); mfifoqwc = GIFPath_CopyTag(GIF_PATH_3, (u128*)src, mfifoqwc);
gif->madr = dmacRegs->rbor.ADDR + (gif->madr & dmacRegs->rbsr.RMSK); gifch.madr = dmacRegs.rbor.ADDR + (gifch.madr & dmacRegs.rbsr.RMSK);
} }
GetMTGS().SendDataPacket(); GetMTGS().SendDataPacket();
@ -493,10 +493,10 @@ static __fi bool mfifoGIFrbTransfer()
static __fi bool mfifoGIFchain() static __fi bool mfifoGIFchain()
{ {
/* Is QWC = 0? if so there is nothing to transfer */ /* Is QWC = 0? if so there is nothing to transfer */
if (gif->qwc == 0) return true; if (gifch.qwc == 0) return true;
if (gif->madr >= dmacRegs->rbor.ADDR && if (gifch.madr >= dmacRegs.rbor.ADDR &&
gif->madr <= (dmacRegs->rbor.ADDR + dmacRegs->rbsr.RMSK)) gifch.madr <= (dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK))
{ {
if (!mfifoGIFrbTransfer()) return false; if (!mfifoGIFrbTransfer()) return false;
} }
@ -504,10 +504,10 @@ static __fi bool mfifoGIFchain()
{ {
int mfifoqwc; int mfifoqwc;
tDMA_TAG *pMem = dmaGetAddr(gif->madr, false); tDMA_TAG *pMem = dmaGetAddr(gifch.madr, false);
if (pMem == NULL) return false; if (pMem == NULL) return false;
mfifoqwc = WRITERING_DMA(pMem, gif->qwc); mfifoqwc = WRITERING_DMA(pMem, gifch.qwc);
mfifocycles += (mfifoqwc) * 2; /* guessing */ mfifocycles += (mfifoqwc) * 2; /* guessing */
} }
@ -516,7 +516,7 @@ static __fi bool mfifoGIFchain()
static u32 qwctag(u32 mask) static u32 qwctag(u32 mask)
{ {
return (dmacRegs->rbor.ADDR + (mask & dmacRegs->rbsr.RMSK)); return (dmacRegs.rbor.ADDR + (mask & dmacRegs.rbsr.RMSK));
} }
void mfifoGIFtransfer(int qwc) void mfifoGIFtransfer(int qwc)
@ -536,16 +536,16 @@ void mfifoGIFtransfer(int qwc)
gifempty = false; gifempty = false;
} }
if (gifRegs->ctrl.PSE) // temporarily stop if (gifRegs.ctrl.PSE) // temporarily stop
{ {
Console.WriteLn("Gif dma temp paused?"); Console.WriteLn("Gif dma temp paused?");
CPU_INT(DMAC_MFIFO_GIF, 16); CPU_INT(DMAC_MFIFO_GIF, 16);
return; return;
} }
if (gif->qwc == 0) if (gifch.qwc == 0)
{ {
if (gif->tadr == spr0->madr) if (gifch.tadr == spr0ch.madr)
{ {
//if( gifqwc > 1 ) DevCon.WriteLn("gif mfifo tadr==madr but qwc = %d", gifqwc); //if( gifqwc > 1 ) DevCon.WriteLn("gif mfifo tadr==madr but qwc = %d", gifqwc);
hwDmacIrq(DMAC_MFIFO_EMPTY); hwDmacIrq(DMAC_MFIFO_EMPTY);
@ -554,55 +554,55 @@ void mfifoGIFtransfer(int qwc)
return; return;
} }
gif->tadr = qwctag(gif->tadr); gifch.tadr = qwctag(gifch.tadr);
ptag = dmaGetAddr(gif->tadr, false); ptag = dmaGetAddr(gifch.tadr, false);
gif->unsafeTransfer(ptag); gifch.unsafeTransfer(ptag);
gif->madr = ptag[1]._u32; gifch.madr = ptag[1]._u32;
mfifocycles += 2; mfifocycles += 2;
GIF_LOG("dmaChain %8.8x_%8.8x size=%d, id=%d, madr=%lx, tadr=%lx mfifo qwc = %x spr0 madr = %x", GIF_LOG("dmaChain %8.8x_%8.8x size=%d, id=%d, madr=%lx, tadr=%lx mfifo qwc = %x spr0 madr = %x",
ptag[1]._u32, ptag[0]._u32, gif->qwc, ptag->ID, gif->madr, gif->tadr, gifqwc, spr0->madr); ptag[1]._u32, ptag[0]._u32, gifch.qwc, ptag->ID, gifch.madr, gifch.tadr, gifqwc, spr0ch.madr);
gifqwc--; gifqwc--;
switch (ptag->ID) switch (ptag->ID)
{ {
case TAG_REFE: // Refe - Transfer Packet According to ADDR field case TAG_REFE: // Refe - Transfer Packet According to ADDR field
gif->tadr = qwctag(gif->tadr + 16); gifch.tadr = qwctag(gifch.tadr + 16);
gifstate = GIF_STATE_DONE; //End Transfer gifstate = GIF_STATE_DONE; //End Transfer
break; break;
case TAG_CNT: // CNT - Transfer QWC following the tag. case TAG_CNT: // CNT - Transfer QWC following the tag.
gif->madr = qwctag(gif->tadr + 16); //Set MADR to QW after Tag gifch.madr = qwctag(gifch.tadr + 16); //Set MADR to QW after Tag
gif->tadr = qwctag(gif->madr + (gif->qwc << 4)); //Set TADR to QW following the data gifch.tadr = qwctag(gifch.madr + (gifch.qwc << 4)); //Set TADR to QW following the data
gifstate = GIF_STATE_READY; gifstate = GIF_STATE_READY;
break; break;
case TAG_NEXT: // Next - Transfer QWC following tag. TADR = ADDR case TAG_NEXT: // Next - Transfer QWC following tag. TADR = ADDR
{ {
u32 temp = gif->madr; //Temporarily Store ADDR u32 temp = gifch.madr; //Temporarily Store ADDR
gif->madr = qwctag(gif->tadr + 16); //Set MADR to QW following the tag gifch.madr = qwctag(gifch.tadr + 16); //Set MADR to QW following the tag
gif->tadr = temp; //Copy temporarily stored ADDR to Tag gifch.tadr = temp; //Copy temporarily stored ADDR to Tag
gifstate = GIF_STATE_READY; gifstate = GIF_STATE_READY;
break; break;
} }
case TAG_REF: // Ref - Transfer QWC from ADDR field case TAG_REF: // Ref - Transfer QWC from ADDR field
case TAG_REFS: // Refs - Transfer QWC from ADDR field (Stall Control) case TAG_REFS: // Refs - Transfer QWC from ADDR field (Stall Control)
gif->tadr = qwctag(gif->tadr + 16); //Set TADR to next tag gifch.tadr = qwctag(gifch.tadr + 16); //Set TADR to next tag
gifstate = GIF_STATE_READY; gifstate = GIF_STATE_READY;
break; break;
case TAG_END: // End - Transfer QWC following the tag case TAG_END: // End - Transfer QWC following the tag
gif->madr = qwctag(gif->tadr + 16); //Set MADR to data following the tag gifch.madr = qwctag(gifch.tadr + 16); //Set MADR to data following the tag
gif->tadr = qwctag(gif->madr + (gif->qwc << 4)); //Set TADR to QW following the data gifch.tadr = qwctag(gifch.madr + (gifch.qwc << 4)); //Set TADR to QW following the data
gifstate = GIF_STATE_DONE; //End Transfer gifstate = GIF_STATE_DONE; //End Transfer
break; break;
} }
if ((gif->chcr.TIE) && (ptag->IRQ)) if ((gifch.chcr.TIE) && (ptag->IRQ))
{ {
SPR_LOG("dmaIrq Set"); SPR_LOG("dmaIrq Set");
gifstate = GIF_STATE_DONE; gifstate = GIF_STATE_DONE;
@ -612,14 +612,14 @@ void mfifoGIFtransfer(int qwc)
if (!mfifoGIFchain()) if (!mfifoGIFchain())
{ {
Console.WriteLn("GIF dmaChain error size=%d, madr=%lx, tadr=%lx", gif->qwc, gif->madr, gif->tadr); Console.WriteLn("GIF dmaChain error size=%d, madr=%lx, tadr=%lx", gifch.qwc, gifch.madr, gifch.tadr);
gifstate = GIF_STATE_STALL; gifstate = GIF_STATE_STALL;
} }
if ((gif->qwc == 0) && (gifstate & GIF_STATE_DONE)) gifstate = GIF_STATE_STALL; if ((gifch.qwc == 0) && (gifstate & GIF_STATE_DONE)) gifstate = GIF_STATE_STALL;
CPU_INT(DMAC_MFIFO_GIF,mfifocycles); CPU_INT(DMAC_MFIFO_GIF,mfifocycles);
SPR_LOG("mfifoGIFtransfer end %x madr %x, tadr %x", gif->chcr._u32, gif->madr, gif->tadr); SPR_LOG("mfifoGIFtransfer end %x madr %x, tadr %x", gifch.chcr._u32, gifch.madr, gifch.tadr);
} }
void gifMFIFOInterrupt() void gifMFIFOInterrupt()
@ -634,16 +634,16 @@ void gifMFIFOInterrupt()
return; return;
} }
if(GSTransferStatus.PTH3 == STOPPED_MODE && gifRegs->stat.APATH == GIF_APATH3 ) if(GSTransferStatus.PTH3 == STOPPED_MODE && gifRegs.stat.APATH == GIF_APATH3 )
{ {
gifRegs->stat.OPH = false; gifRegs.stat.OPH = false;
gifRegs->stat.APATH = GIF_APATH_IDLE; gifRegs.stat.APATH = GIF_APATH_IDLE;
if(gifRegs->stat.P1Q) gsPath1Interrupt(); if(gifRegs.stat.P1Q) gsPath1Interrupt();
} }
if(CheckPaths(11) == false) return; if(CheckPaths(11) == false) return;
if (!(gif->chcr.STR)) if (!(gifch.chcr.STR))
{ {
Console.WriteLn("WTF GIFMFIFO"); Console.WriteLn("WTF GIFMFIFO");
cpuRegs.interrupt &= ~(1 << 11); cpuRegs.interrupt &= ~(1 << 11);
@ -659,7 +659,7 @@ void gifMFIFOInterrupt()
gifstate |= GIF_STATE_EMPTY; gifstate |= GIF_STATE_EMPTY;
gifempty = true; gifempty = true;
gifRegs->stat.IMT = false; gifRegs.stat.IMT = false;
return; return;
} }
mfifoGIFtransfer(0); mfifoGIFtransfer(0);
@ -667,7 +667,7 @@ void gifMFIFOInterrupt()
} }
#ifdef PCSX2_DEVBUILD #ifdef PCSX2_DEVBUILD
if ((gifstate & GIF_STATE_READY) || (gif->qwc > 0)) if ((gifstate & GIF_STATE_READY) || (gifch.qwc > 0))
{ {
Console.Error("gifMFIFO Panic > Shouldn't go here!"); Console.Error("gifMFIFO Panic > Shouldn't go here!");
return; return;
@ -679,10 +679,10 @@ void gifMFIFOInterrupt()
gspath3done = false; gspath3done = false;
gscycles = 0; gscycles = 0;
gifRegs->stat.clear_flags(GIF_STAT_APATH3 | GIF_STAT_P3Q | GIF_STAT_FQC); // APATH, P3Q, FQC = 0 gifRegs.stat.clear_flags(GIF_STAT_APATH3 | GIF_STAT_P3Q | GIF_STAT_FQC); // APATH, P3Q, FQC = 0
vif1Regs->stat.VGW = false; vif1Regs.stat.VGW = false;
gif->chcr.STR = false; gifch.chcr.STR = false;
gifstate = GIF_STATE_READY; gifstate = GIF_STATE_READY;
hwDmacIrq(DMAC_GIF); hwDmacIrq(DMAC_GIF);
clearFIFOstuff(false); clearFIFOstuff(false);

View File

@ -277,7 +277,7 @@ struct GIFregisters
u32 padding9[3]; u32 padding9[3];
}; };
#define gifRegs ((GIFregisters*)(eeMem->HW+0x3000)) static GIFregisters& gifRegs = (GIFregisters&)eeHw[0x3000];
extern tGSTransferStatus GSTransferStatus; extern tGSTransferStatus GSTransferStatus;

View File

@ -18,6 +18,7 @@
#include "Hardware.h" #include "Hardware.h"
#include "newVif.h" #include "newVif.h"
#include "IPU/IPUdma.h"
using namespace R5900; using namespace R5900;
@ -45,17 +46,12 @@ void hwInit()
hwInitialized = true; hwInitialized = true;
} }
/*void hwShutdown()
{
ipuShutdown();
}*/
void hwReset() void hwReset()
{ {
hwInit(); hwInit();
memzero_ptr<Ps2MemSize::Hardware>( eeMem->HW ); memzero_ptr<Ps2MemSize::Hardware>( eeHw );
//memset(eeMem->HW+0x2000, 0, 0x0000e000); //memset(eeHw+0x2000, 0, 0x0000e000);
psHu32(SBUS_F260) = 0x1D000060; psHu32(SBUS_F260) = 0x1D000060;
@ -72,6 +68,9 @@ void hwReset()
ipuReset(); ipuReset();
vif0Reset(); vif0Reset();
vif1Reset(); vif1Reset();
// needed for legacy DMAC
ipuDmaReset();
} }
__fi void intcInterrupt() __fi void intcInterrupt()
@ -104,7 +103,7 @@ __fi void dmacInterrupt()
return; return;
} }
if (!(dmacRegs->ctrl.DMAE) || psHu8(DMAC_ENABLER+2) == 1) if (!(dmacRegs.ctrl.DMAE) || psHu8(DMAC_ENABLER+2) == 1)
{ {
//DevCon.Warning("DMAC Suspended or Disabled on interrupt"); //DevCon.Warning("DMAC Suspended or Disabled on interrupt");
return; return;
@ -131,7 +130,7 @@ void hwDmacIrq(int n)
__ri bool hwMFIFOWrite(u32 addr, const u128* data, uint qwc) __ri bool hwMFIFOWrite(u32 addr, const u128* data, uint qwc)
{ {
// all FIFO addresses should always be QWC-aligned. // all FIFO addresses should always be QWC-aligned.
pxAssume((dmacRegs->rbor.ADDR & 15) == 0); pxAssume((dmacRegs.rbor.ADDR & 15) == 0);
pxAssume((addr & 15) == 0); pxAssume((addr & 15) == 0);
// DMAC Address resolution: FIFO can be placed anywhere in the *physical* memory map // DMAC Address resolution: FIFO can be placed anywhere in the *physical* memory map
@ -139,24 +138,24 @@ __ri bool hwMFIFOWrite(u32 addr, const u128* data, uint qwc)
// valid/invalid page areas of ram, so realistically we only need to test the base address // valid/invalid page areas of ram, so realistically we only need to test the base address
// of the FIFO for address validity. // of the FIFO for address validity.
if (u128* dst = (u128*)PSM(dmacRegs->rbor.ADDR)) if (u128* dst = (u128*)PSM(dmacRegs.rbor.ADDR))
{ {
const u32 ringsize = (dmacRegs->rbsr.RMSK / 16) + 1; const u32 ringsize = (dmacRegs.rbsr.RMSK / 16) + 1;
pxAssertMsg( PSM(dmacRegs->rbor.ADDR+ringsize-1) != NULL, "Scratchpad/MFIFO ringbuffer spans into invalid (unmapped) physical memory!" ); pxAssertMsg( PSM(dmacRegs.rbor.ADDR+ringsize-1) != NULL, "Scratchpad/MFIFO ringbuffer spans into invalid (unmapped) physical memory!" );
uint startpos = (addr & dmacRegs->rbsr.RMSK)/16; uint startpos = (addr & dmacRegs.rbsr.RMSK)/16;
MemCopy_WrappedDest( data, dst, startpos, ringsize, qwc ); MemCopy_WrappedDest( data, dst, startpos, ringsize, qwc );
} }
else else
{ {
SPR_LOG( "Scratchpad/MFIFO: invalid base physical address: 0x%08x", dmacRegs->rbor.ADDR ); SPR_LOG( "Scratchpad/MFIFO: invalid base physical address: 0x%08x", dmacRegs.rbor.ADDR );
pxFailDev( wxsFormat( L"Scratchpad/MFIFO: Invalid base physical address: 0x%08x", dmacRegs->rbor.ADDR) ); pxFailDev( wxsFormat( L"Scratchpad/MFIFO: Invalid base physical address: 0x%08x", dmacRegs.rbor.ADDR) );
return false; return false;
} }
return true; return true;
} }
__ri bool hwDmacSrcChainWithStack(DMACh *dma, int id) { __ri bool hwDmacSrcChainWithStack(DMACh& dma, int id) {
switch (id) { switch (id) {
case TAG_REFE: // Refe - Transfer Packet According to ADDR field case TAG_REFE: // Refe - Transfer Packet According to ADDR field
//End Transfer //End Transfer
@ -164,49 +163,49 @@ __ri bool hwDmacSrcChainWithStack(DMACh *dma, int id) {
case TAG_CNT: // CNT - Transfer QWC following the tag. case TAG_CNT: // CNT - Transfer QWC following the tag.
// Set MADR to QW afer tag, and set TADR to QW following the data. // Set MADR to QW afer tag, and set TADR to QW following the data.
dma->madr = dma->tadr + 16; dma.madr = dma.tadr + 16;
dma->tadr = dma->madr + (dma->qwc << 4); dma.tadr = dma.madr + (dma.qwc << 4);
return false; return false;
case TAG_NEXT: // Next - Transfer QWC following tag. TADR = ADDR case TAG_NEXT: // Next - Transfer QWC following tag. TADR = ADDR
{ {
// Set MADR to QW following the tag, and set TADR to the address formerly in MADR. // Set MADR to QW following the tag, and set TADR to the address formerly in MADR.
u32 temp = dma->madr; u32 temp = dma.madr;
dma->madr = dma->tadr + 16; dma.madr = dma.tadr + 16;
dma->tadr = temp; dma.tadr = temp;
return false; return false;
} }
case TAG_REF: // Ref - Transfer QWC from ADDR field case TAG_REF: // Ref - Transfer QWC from ADDR field
case TAG_REFS: // Refs - Transfer QWC from ADDR field (Stall Control) case TAG_REFS: // Refs - Transfer QWC from ADDR field (Stall Control)
//Set TADR to next tag //Set TADR to next tag
dma->tadr += 16; dma.tadr += 16;
return false; return false;
case TAG_CALL: // Call - Transfer QWC following the tag, save succeeding tag case TAG_CALL: // Call - Transfer QWC following the tag, save succeeding tag
{ {
// Store the address in MADR in temp, and set MADR to the data following the tag. // Store the address in MADR in temp, and set MADR to the data following the tag.
u32 temp = dma->madr; u32 temp = dma.madr;
dma->madr = dma->tadr + 16; dma.madr = dma.tadr + 16;
if(temp == 0) if(temp == 0)
{ {
DevCon.Warning("DMA Chain CALL next tag error. Tag Addr = 0"); DevCon.Warning("DMA Chain CALL next tag error. Tag Addr = 0");
dma->tadr = dma->madr + (dma->qwc << 4); dma.tadr = dma.madr + (dma.qwc << 4);
return false; return false;
} }
// Stash an address on the address stack pointer. // Stash an address on the address stack pointer.
switch(dma->chcr.ASP) switch(dma.chcr.ASP)
{ {
case 0: //Check if ASR0 is empty case 0: //Check if ASR0 is empty
// Store the succeeding tag in asr0, and mark chcr as having 1 address. // Store the succeeding tag in asr0, and mark chcr as having 1 address.
dma->asr0 = dma->madr + (dma->qwc << 4); dma.asr0 = dma.madr + (dma.qwc << 4);
dma->chcr.ASP++; dma.chcr.ASP++;
break; break;
case 1: case 1:
// Store the succeeding tag in asr1, and mark chcr as having 2 addresses. // Store the succeeding tag in asr1, and mark chcr as having 2 addresses.
dma->asr1 = dma->madr + (dma->qwc << 4); dma.asr1 = dma.madr + (dma.qwc << 4);
dma->chcr.ASP++; dma.chcr.ASP++;
break; break;
default: default:
@ -215,48 +214,48 @@ __ri bool hwDmacSrcChainWithStack(DMACh *dma, int id) {
} }
// Set TADR to the address from MADR we stored in temp. // Set TADR to the address from MADR we stored in temp.
dma->tadr = temp; dma.tadr = temp;
return false; return false;
} }
case TAG_RET: // Ret - Transfer QWC following the tag, load next tag case TAG_RET: // Ret - Transfer QWC following the tag, load next tag
//Set MADR to data following the tag. //Set MADR to data following the tag.
dma->madr = dma->tadr + 16; dma.madr = dma.tadr + 16;
// Snag an address from the address stack pointer. // Snag an address from the address stack pointer.
switch(dma->chcr.ASP) switch(dma.chcr.ASP)
{ {
case 2: case 2:
// Pull asr1 from the stack, give it to TADR, and decrease the # of addresses. // Pull asr1 from the stack, give it to TADR, and decrease the # of addresses.
dma->tadr = dma->asr1; dma.tadr = dma.asr1;
dma->asr1 = 0; dma.asr1 = 0;
dma->chcr.ASP--; dma.chcr.ASP--;
break; break;
case 1: case 1:
// Pull asr0 from the stack, give it to TADR, and decrease the # of addresses. // Pull asr0 from the stack, give it to TADR, and decrease the # of addresses.
dma->tadr = dma->asr0; dma.tadr = dma.asr0;
dma->asr0 = 0; dma.asr0 = 0;
dma->chcr.ASP--; dma.chcr.ASP--;
break; break;
case 0: case 0:
// There aren't any addresses to pull, so end the transfer. // There aren't any addresses to pull, so end the transfer.
//dma->tadr += 16; //Clear tag address - Kills Klonoa 2 //dma.tadr += 16; //Clear tag address - Kills Klonoa 2
return true; return true;
default: default:
// If ASR1 and ASR0 are messed up, end the transfer. // If ASR1 and ASR0 are messed up, end the transfer.
//Console.Error("TAG_RET: ASR 1 & 0 == 1. This shouldn't happen!"); //Console.Error("TAG_RET: ASR 1 & 0 == 1. This shouldn't happen!");
//dma->tadr += 16; //Clear tag address - Kills Klonoa 2 //dma.tadr += 16; //Clear tag address - Kills Klonoa 2
return true; return true;
} }
return false; return false;
case TAG_END: // End - Transfer QWC following the tag case TAG_END: // End - Transfer QWC following the tag
//Set MADR to data following the tag, and end the transfer. //Set MADR to data following the tag, and end the transfer.
dma->madr = dma->tadr + 16; dma.madr = dma.tadr + 16;
//Don't Increment tadr; breaks Soul Calibur II and III //Don't Increment tadr; breaks Soul Calibur II and III
return true; return true;
} }
@ -264,7 +263,7 @@ __ri bool hwDmacSrcChainWithStack(DMACh *dma, int id) {
return false; return false;
} }
bool hwDmacSrcChain(DMACh *dma, int id) bool hwDmacSrcChain(DMACh& dma, int id)
{ {
u32 temp; u32 temp;
@ -276,26 +275,26 @@ bool hwDmacSrcChain(DMACh *dma, int id)
case TAG_CNT: // CNT - Transfer QWC following the tag. case TAG_CNT: // CNT - Transfer QWC following the tag.
// Set MADR to QW after the tag, and TADR to QW following the data. // Set MADR to QW after the tag, and TADR to QW following the data.
dma->madr = dma->tadr + 16; dma.madr = dma.tadr + 16;
dma->tadr = dma->madr + (dma->qwc << 4); dma.tadr = dma.madr + (dma.qwc << 4);
return false; return false;
case TAG_NEXT: // Next - Transfer QWC following tag. TADR = ADDR case TAG_NEXT: // Next - Transfer QWC following tag. TADR = ADDR
// Set MADR to QW following the tag, and set TADR to the address formerly in MADR. // Set MADR to QW following the tag, and set TADR to the address formerly in MADR.
temp = dma->madr; temp = dma.madr;
dma->madr = dma->tadr + 16; dma.madr = dma.tadr + 16;
dma->tadr = temp; dma.tadr = temp;
return false; return false;
case TAG_REF: // Ref - Transfer QWC from ADDR field case TAG_REF: // Ref - Transfer QWC from ADDR field
case TAG_REFS: // Refs - Transfer QWC from ADDR field (Stall Control) case TAG_REFS: // Refs - Transfer QWC from ADDR field (Stall Control)
//Set TADR to next tag //Set TADR to next tag
dma->tadr += 16; dma.tadr += 16;
return false; return false;
case TAG_END: // End - Transfer QWC following the tag case TAG_END: // End - Transfer QWC following the tag
//Set MADR to data following the tag, and end the transfer. //Set MADR to data following the tag, and end the transfer.
dma->madr = dma->tadr + 16; dma.madr = dma.tadr + 16;
//Don't Increment tadr; breaks Soul Calibur II and III //Don't Increment tadr; breaks Soul Calibur II and III
return true; return true;
} }

View File

@ -13,28 +13,84 @@
* If not, see <http://www.gnu.org/licenses/>. * If not, see <http://www.gnu.org/licenses/>.
*/ */
#pragma once
#ifndef __HW_H__ namespace EEMemoryMap
#define __HW_H__ {
static const uint RCNT0_Start = 0x10000000;
static const uint RCNT0_End = 0x10000800;
static const uint RCNT1_Start = 0x10000800;
static const uint RCNT1_End = 0x10001000;
static const uint RCNT2_Start = 0x10001000;
static const uint RCNT2_End = 0x10001800;
static const uint RCNT3_Start = 0x10001800;
static const uint RCNT3_End = 0x10002000;
////////////////////////////////////////////////////////////////////////// static const uint IPU_Start = 0x10002000;
// Hardware FIFOs (128 bit access only!) static const uint IPU_End = 0x10003000;
//
// VIF0 -- 0x10004000 -- eeMem->HW[0x4000]
// VIF1 -- 0x10005000 -- eeMem->HW[0x5000]
// GIF -- 0x10006000 -- eeMem->HW[0x6000]
// IPUout -- 0x10007000 -- eeMem->HW[0x7000]
// IPUin -- 0x10007010 -- eeMem->HW[0x7010]
void __fastcall ReadFIFO_page_4(u32 mem, mem128_t *out); static const uint GIF_Start = 0x10003000;
void __fastcall ReadFIFO_page_5(u32 mem, mem128_t *out); static const uint GIF_End = 0x10003800;
void __fastcall ReadFIFO_page_6(u32 mem, mem128_t *out);
void __fastcall ReadFIFO_page_7(u32 mem, mem128_t *out);
void __fastcall WriteFIFO_page_4(u32 mem, const mem128_t *value); static const uint VIF0_Start = 0x10003800;
void __fastcall WriteFIFO_page_5(u32 mem, const mem128_t *value); static const uint VIF0_End = 0x10003C00;
void __fastcall WriteFIFO_page_6(u32 mem, const mem128_t *value); static const uint VIF1_Start = 0x10003C00;
void __fastcall WriteFIFO_page_7(u32 mem, const mem128_t *value); static const uint VIF1_End = 0x10004000;
static const uint VIF0_FIFO_Start = 0x10004000;
static const uint VIF0_FIFO_End = 0x10005000;
static const uint VIF1_FIFO_Start = 0x10005000;
static const uint VIF1_FIFO_End = 0x10006000;
static const uint GIF_FIFO_Start = 0x10006000;
static const uint GIF_FIFO_End = 0x10007000;
static const uint IPU_FIFO_Start = 0x10007000;
static const uint IPU_FIFO_End = 0x10008000;
static const uint VIF0dma_Start = 0x10008000;
static const uint VIF0dma_End = 0x10009000;
static const uint VIF1dma_Start = 0x10009000;
static const uint VIF1dma_End = 0x1000A000;
static const uint GIFdma_Start = 0x1000A000;
static const uint GIFdma_End = 0x1000B000;
static const uint fromIPU_Start = 0x1000B000;
static const uint fromIPU_End = 0x1000B400;
static const uint toIPU_Start = 0x1000B400;
static const uint toIPU_End = 0x1000C000;
static const uint SIF0dma_Start = 0x1000C000;
static const uint SIF0dma_End = 0x1000C400;
static const uint SIF1dma_Start = 0x1000C400;
static const uint SIF1dma_End = 0x1000C800;
static const uint SIF2dma_Start = 0x1000C800;
static const uint SIF2dma_End = 0x1000D000;
static const uint fromSPR_Start = 0x1000D000;
static const uint fromSPR_End = 0x1000D400;
static const uint toSPR_Start = 0x1000D400;
static const uint toSPR_End = 0x1000E000;
static const uint DMAC_Start = 0x1000E000;
static const uint DMAC_End = 0x1000F000;
static const uint INTC_Start = 0x1000F000;
static const uint INTC_End = 0x1000F100;
static const uint SIO_Start = 0x1000F100;
static const uint SIO_End = 0x1000F200;
static const uint SBUS_Start = 0x1000F200;
static const uint SBUS_End = 0x1000F400;
// MCH area -- Really not sure what this area is. Information is lacking.
static const uint MCH_Start = 0x1000F400;
static const uint MCH_End = 0x1000F500;
// Extended master control register area for DMAC.
static const uint DMACext_Start = 0x1000F500;
static const uint DMACext_End = 0x1000F600;
};
// HW defines // HW defines
enum EERegisterAddresses enum EERegisterAddresses
@ -86,14 +142,14 @@ enum EERegisterAddresses
VIF0_ITOPS = 0x10003890, VIF0_ITOPS = 0x10003890,
VIF0_ITOP = 0x100038d0, VIF0_ITOP = 0x100038d0,
VIF0_TOP = 0x100038e0, VIF0_TOP = 0x100038e0,
VIF0_R0 = 0x10003900, VIF0_ROW0 = 0x10003900,
VIF0_R1 = 0x10003910, VIF0_ROW1 = 0x10003910,
VIF0_R2 = 0x10003920, VIF0_ROW2 = 0x10003920,
VIF0_R3 = 0x10003930, VIF0_ROW3 = 0x10003930,
VIF0_C0 = 0x10003940, VIF0_COL0 = 0x10003940,
VIF0_C1 = 0x10003950, VIF0_COL1 = 0x10003950,
VIF0_C2 = 0x10003960, VIF0_COL2 = 0x10003960,
VIF0_C3 = 0x10003970, VIF0_COL3 = 0x10003970,
VIF1_STAT = 0x10003c00, VIF1_STAT = 0x10003c00,
VIF1_FBRST = 0x10003c10, VIF1_FBRST = 0x10003c10,
@ -110,14 +166,14 @@ enum EERegisterAddresses
VIF1_TOPS = 0x10003cc0, VIF1_TOPS = 0x10003cc0,
VIF1_ITOP = 0x10003cd0, VIF1_ITOP = 0x10003cd0,
VIF1_TOP = 0x10003ce0, VIF1_TOP = 0x10003ce0,
VIF1_R0 = 0x10003d00, VIF1_ROW0 = 0x10003d00,
VIF1_R1 = 0x10003d10, VIF1_ROW1 = 0x10003d10,
VIF1_R2 = 0x10003d20, VIF1_ROW2 = 0x10003d20,
VIF1_R3 = 0x10003d30, VIF1_ROW3 = 0x10003d30,
VIF1_C0 = 0x10003d40, VIF1_COL0 = 0x10003d40,
VIF1_C1 = 0x10003d50, VIF1_COL1 = 0x10003d50,
VIF1_C2 = 0x10003d60, VIF1_COL2 = 0x10003d60,
VIF1_C3 = 0x10003d70, VIF1_COL3 = 0x10003d70,
VIF0_FIFO = 0x10004000, VIF0_FIFO = 0x10004000,
VIF1_FIFO = 0x10005000, VIF1_FIFO = 0x10005000,
@ -134,6 +190,13 @@ enum EERegisterAddresses
D0_ASR0 = 0x10008040, D0_ASR0 = 0x10008040,
D0_ASR1 = 0x10008050, D0_ASR1 = 0x10008050,
VIF0_CHCR = 0x10008000,
VIF0_MADR = 0x10008010,
VIF0_QWC = 0x10008020,
VIF0_TADR = 0x10008030,
VIF0_ASR0 = 0x10008040,
VIF0_ASR1 = 0x10008050,
//VIF1 //VIF1
D1_CHCR = 0x10009000, D1_CHCR = 0x10009000,
D1_MADR = 0x10009010, D1_MADR = 0x10009010,
@ -141,7 +204,13 @@ enum EERegisterAddresses
D1_TADR = 0x10009030, D1_TADR = 0x10009030,
D1_ASR0 = 0x10009040, D1_ASR0 = 0x10009040,
D1_ASR1 = 0x10009050, D1_ASR1 = 0x10009050,
D1_SADR = 0x10009080,
VIF1_CHCR = 0x10009000,
VIF1_MADR = 0x10009010,
VIF1_QWC = 0x10009020,
VIF1_TADR = 0x10009030,
VIF1_ASR0 = 0x10009040,
VIF1_ASR1 = 0x10009050,
//GS //GS
D2_CHCR = 0x1000A000, D2_CHCR = 0x1000A000,
@ -150,44 +219,82 @@ enum EERegisterAddresses
D2_TADR = 0x1000A030, D2_TADR = 0x1000A030,
D2_ASR0 = 0x1000A040, D2_ASR0 = 0x1000A040,
D2_ASR1 = 0x1000A050, D2_ASR1 = 0x1000A050,
D2_SADR = 0x1000A080,
GIF_CHCR = 0x1000A000,
GIF_MADR = 0x1000A010,
GIF_QWC = 0x1000A020,
GIF_TADR = 0x1000A030,
GIF_ASR0 = 0x1000A040,
GIF_ASR1 = 0x1000A050,
//fromIPU //fromIPU
D3_CHCR = 0x1000B000, D3_CHCR = 0x1000B000,
D3_MADR = 0x1000B010, D3_MADR = 0x1000B010,
D3_QWC = 0x1000B020, D3_QWC = 0x1000B020,
D3_TADR = 0x1000B030, D3_TADR = 0x1000B030,
D3_SADR = 0x1000B080,
fromIPU_CHCR = 0x1000B000,
fromIPU_MADR = 0x1000B010,
fromIPU_QWC = 0x1000B020,
fromIPU_TADR = 0x1000B030,
//toIPU //toIPU
D4_CHCR = 0x1000B400, D4_CHCR = 0x1000B400,
D4_MADR = 0x1000B410, D4_MADR = 0x1000B410,
D4_QWC = 0x1000B420, D4_QWC = 0x1000B420,
D4_TADR = 0x1000B430, D4_TADR = 0x1000B430,
D4_SADR = 0x1000B480,
toIPU_CHCR = 0x1000B400,
toIPU_MADR = 0x1000B410,
toIPU_QWC = 0x1000B420,
toIPU_TADR = 0x1000B430,
//SIF0 //SIF0
D5_CHCR = 0x1000C000, D5_CHCR = 0x1000C000,
D5_MADR = 0x1000C010, D5_MADR = 0x1000C010,
D5_QWC = 0x1000C020, D5_QWC = 0x1000C020,
SIF0_CHCR = 0x1000C000,
SIF0_MADR = 0x1000C010,
SIF0_QWC = 0x1000C020,
//SIF1 //SIF1
D6_CHCR = 0x1000C400, D6_CHCR = 0x1000C400,
D6_MADR = 0x1000C410, D6_MADR = 0x1000C410,
D6_QWC = 0x1000C420, D6_QWC = 0x1000C420,
D6_TADR = 0x1000C430, D6_TADR = 0x1000C430,
SIF1_CHCR = 0x1000C400,
SIF1_MADR = 0x1000C410,
SIF1_QWC = 0x1000C420,
SIF1_TADR = 0x1000C430,
//SIF2 //SIF2
D7_CHCR = 0x1000C800, D7_CHCR = 0x1000C800,
D7_MADR = 0x1000C810, D7_MADR = 0x1000C810,
D7_QWC = 0x1000C820, D7_QWC = 0x1000C820,
SIF2_CHCR = 0x1000C800,
SIF2_MADR = 0x1000C810,
SIF2_QWC = 0x1000C820,
//fromSPR //fromSPR
D8_CHCR = 0x1000D000, D8_CHCR = 0x1000D000,
D8_MADR = 0x1000D010, D8_MADR = 0x1000D010,
D8_QWC = 0x1000D020, D8_QWC = 0x1000D020,
D8_SADR = 0x1000D080,
fromSPR_CHCR = 0x1000D000,
fromSPR_MADR = 0x1000D010,
fromSPR_QWC = 0x1000D020,
//toSPR
D9_CHCR = 0x1000D400, D9_CHCR = 0x1000D400,
D9_MADR = 0x1000D010,
D9_QWC = 0x1000D020,
toSPR_CHCR = 0x1000D400,
toSPR_MADR = 0x1000D410,
toSPR_QWC = 0x1000D420,
DMAC_CTRL = 0x1000E000, DMAC_CTRL = 0x1000E000,
DMAC_STAT = 0x1000E010, DMAC_STAT = 0x1000E010,
@ -264,53 +371,7 @@ union tGS_SMODE2
bool IsInterlaced() const { return INT; } bool IsInterlaced() const { return INT; }
}; };
void hwReset(); extern void hwReset();
// hw read functions
extern mem8_t hwRead8 (u32 mem);
extern mem16_t hwRead16(u32 mem);
extern mem32_t __fastcall hwRead32_page_00(u32 mem);
extern mem32_t __fastcall hwRead32_page_01(u32 mem);
extern mem32_t __fastcall hwRead32_page_02(u32 mem);
extern mem32_t __fastcall hwRead32_page_0F(u32 mem);
extern mem32_t __fastcall hwRead32_page_0F_INTC_HACK(u32 mem);
extern mem32_t __fastcall hwRead32_generic(u32 mem);
extern void __fastcall hwRead64_page_00(u32 mem, mem64_t* result );
extern void __fastcall hwRead64_page_01(u32 mem, mem64_t* result );
extern void __fastcall hwRead64_page_02(u32 mem, mem64_t* result );
extern void __fastcall hwRead64_generic_INTC_HACK(u32 mem, mem64_t *out);
extern void __fastcall hwRead64_generic(u32 mem, mem64_t* result );
extern void __fastcall hwRead128_page_00(u32 mem, mem128_t* result );
extern void __fastcall hwRead128_page_01(u32 mem, mem128_t* result );
extern void __fastcall hwRead128_page_02(u32 mem, mem128_t* result );
extern void __fastcall hwRead128_generic(u32 mem, mem128_t *out);
// hw write functions
extern void hwWrite8 (u32 mem, u8 value);
extern void hwWrite16(u32 mem, u16 value);
extern void __fastcall hwWrite32_page_00( u32 mem, mem32_t value );
extern void __fastcall hwWrite32_page_01( u32 mem, mem32_t value );
extern void __fastcall hwWrite32_page_02( u32 mem, mem32_t value );
extern void __fastcall hwWrite32_page_03( u32 mem, mem32_t value );
extern void __fastcall hwWrite32_page_0B( u32 mem, mem32_t value );
extern void __fastcall hwWrite32_page_0E( u32 mem, mem32_t value );
extern void __fastcall hwWrite32_page_0F( u32 mem, mem32_t value );
extern void __fastcall hwWrite32_generic( u32 mem, mem32_t value );
extern void __fastcall hwWrite64_page_00( u32 mem, const mem64_t* srcval );
extern void __fastcall hwWrite64_page_01( u32 mem, const mem64_t* srcval );
extern void __fastcall hwWrite64_page_02( u32 mem, const mem64_t* srcval );
extern void __fastcall hwWrite64_page_03( u32 mem, const mem64_t* srcval );
extern void __fastcall hwWrite64_page_0E( u32 mem, const mem64_t* srcval );
extern void __fastcall hwWrite64_generic( u32 mem, const mem64_t* srcval );
extern void __fastcall hwWrite128_generic(u32 mem, const mem128_t *srcval);
extern const int rdram_devices; extern const int rdram_devices;
extern int rdram_sdevid; extern int rdram_sdevid;
#endif /* __HW_H__ */

View File

@ -16,9 +16,11 @@
#include "PrecompiledHeader.h" #include "PrecompiledHeader.h"
#include "Common.h" #include "Common.h"
#include "Hardware.h" #include "Hardware.h"
#include "ps2/HwInternal.h"
#include "ps2/eeHwTraceLog.inl"
using namespace R5900; using namespace R5900;
static __fi void IntCHackCheck() static __fi void IntCHackCheck()
@ -29,308 +31,76 @@ static __fi void IntCHackCheck()
if( diff > 0 ) cpuRegs.cycle = g_nextBranchCycle; if( diff > 0 ) cpuRegs.cycle = g_nextBranchCycle;
} }
///////////////////////////////////////////////////////////////////////// static const uint HwF_VerboseConLog = 1<<0;
// Hardware READ 8 bit static const uint HwF_IntcStatHack = 1<<1; // used for Reads only.
__fi mem8_t hwRead8(u32 mem) template< uint page > void __fastcall _hwRead128(u32 mem, mem128_t* result );
template< uint page, bool intcstathack >
mem32_t __fastcall _hwRead32(u32 mem)
{ {
u8 ret; pxAssume( (mem & 0x03) == 0 );
const u16 masked_mem = mem & 0xffff; switch( page )
// TODO re-implement this warning along with a *complete* logging of all hw activity.
// (implementation should be modelled after thee iopHWRead/iopHwWrite files)
if( mem >= IPU_CMD && mem < D0_CHCR )
{ {
#ifdef PCSX2_DEVBUILD case 0x00: return rcntRead32<0x00>( mem );
HW_LOG("8bit Hardware IPU Read at 0x%x, value=0x%x", mem, psHu8(mem) ); case 0x01: return rcntRead32<0x01>( mem );
#endif
return psHu8(mem); case 0x02: return ipuRead32( mem );
}
// DevCon.Warning("Unexpected hwRead8 from 0x%x", mem); case 0x03: return dmacRead32<0x03>( mem );
#ifdef PCSX2_DEVBUILD
switch((mem >> 12) & 0xf)
{
case 0x03:
if(masked_mem >= 0x3800) HW_LOG("VIF%x Register Read8 at 0x%x, value=0x%x", (masked_mem < 0x3c00) ? 0 : 1, mem, psHu32(mem) );
else HW_LOG("GIF Register Read8 at 0x%x, value=0x%x", mem, psHu32(mem) );
case 0x04: case 0x04:
case 0x05: case 0x05:
case 0x06: case 0x06:
case 0x07: case 0x07:
case 0x08:
case 0x09:
case 0x0a:
case 0x0b:
case 0x0c:
case 0x0d:
{ {
const char* regName = "Unknown"; // [Ps2Confirm] Reading from FIFOs using non-128 bit reads is a complete mystery.
// No game is known to attempt such a thing (yay!), so probably nothing for us to
// worry about. Chances are, though, doing so is "legal" and yields some sort
// of reproducible behavior. Candidate for real hardware testing.
switch( mem & 0xf0) // Current assumption: Reads 128 bits and discards the unused portion.
{
case 0x00: regName = "CHCR"; break; DevCon.WriteLn( Color_Cyan, "Reading 32-bit FIFO data" );
case 0x10: regName = "MADR"; break;
case 0x20: regName = "QWC"; break; u128 out128;
case 0x30: regName = "TADR"; break; _hwRead128<page>(mem, &out128);
case 0x40: regName = "ASR0"; break; return out128._u32[(mem >> 2) & 0x3];
case 0x50: regName = "ASR1"; break;
case 0x80: regName = "SADDR"; break;
} }
HW_LOG("Hardware Read 8 at 0x%x (%ls %s), value=0x%x", mem, ChcrName(mem & ~0xff), regName, psHu8(mem) );
ret = psHu8(mem);
return ret;
}
}
#endif
switch (mem)
{
case RCNT0_COUNT: ret = (u8)rcntRcount(0); break;
case RCNT0_MODE: ret = (u8)counters[0].modeval; break;
case RCNT0_TARGET: ret = (u8)counters[0].target; break;
case RCNT0_HOLD: ret = (u8)counters[0].hold; break;
case RCNT0_COUNT + 1: ret = (u8)(rcntRcount(0)>>8); break;
case RCNT0_MODE + 1: ret = (u8)(counters[0].modeval>>8); break;
case RCNT0_TARGET + 1: ret = (u8)(counters[0].target>>8); break;
case RCNT0_HOLD + 1: ret = (u8)(counters[0].hold>>8); break;
case RCNT1_COUNT: ret = (u8)rcntRcount(1); break;
case RCNT1_MODE: ret = (u8)counters[1].modeval; break;
case RCNT1_TARGET: ret = (u8)counters[1].target; break;
case RCNT1_HOLD: ret = (u8)counters[1].hold; break;
case RCNT1_COUNT + 1: ret = (u8)(rcntRcount(1)>>8); break;
case RCNT1_MODE + 1: ret = (u8)(counters[1].modeval>>8); break;
case RCNT1_TARGET + 1: ret = (u8)(counters[1].target>>8); break;
case RCNT1_HOLD + 1: ret = (u8)(counters[1].hold>>8); break;
case RCNT2_COUNT: ret = (u8)rcntRcount(2); break;
case RCNT2_MODE: ret = (u8)counters[2].modeval; break;
case RCNT2_TARGET: ret = (u8)counters[2].target; break;
case RCNT2_COUNT + 1: ret = (u8)(rcntRcount(2)>>8); break;
case RCNT2_MODE + 1: ret = (u8)(counters[2].modeval>>8); break;
case RCNT2_TARGET + 1: ret = (u8)(counters[2].target>>8); break;
case RCNT3_COUNT: ret = (u8)rcntRcount(3); break;
case RCNT3_MODE: ret = (u8)counters[3].modeval; break;
case RCNT3_TARGET: ret = (u8)counters[3].target; break;
case RCNT3_COUNT + 1: ret = (u8)(rcntRcount(3)>>8); break;
case RCNT3_MODE + 1: ret = (u8)(counters[3].modeval>>8); break;
case RCNT3_TARGET + 1: ret = (u8)(counters[3].target>>8); break;
default:
if ((mem & 0xffffff0f) == SBUS_F200)
{
switch (mem)
{
case SBUS_F240:
ret = psHu32(mem);
//psHu32(mem) &= ~0x4000;
break; break;
case SBUS_F260: case 0x0f:
ret = 0;
break;
default:
ret = psHu32(mem);
break;
}
return (u8)ret;
}
ret = psHu8(mem);
UnknownHW_LOG("Hardware Read 8 from 0x%x = 0x%x", mem, ret);
break;
}
return ret;
}
/////////////////////////////////////////////////////////////////////////
// Hardware READ 16 bit
__fi mem16_t hwRead16(u32 mem)
{
u16 ret;
const u16 masked_mem = mem & 0xffff;
// TODO re-implement this warning along with a *complete* logging of all hw activity.
// (implementation should be modelled after the iopHWRead/iopHwWrite files)
if( mem >= IPU_CMD && mem < D0_CHCR )
{ {
#ifdef PCSX2_DEVBUILD
HW_LOG("16 bit Hardware IPU Read at 0x%x, value=0x%x", mem, psHu16(mem) );
#endif
return psHu16(mem);
}
// Console.Warning("Unexpected hwRead16 from 0x%x", mem);
#ifdef PCSX2_DEVBUILD
switch((mem >> 12) & 0xf)
{
case 0x03:
if(masked_mem >= 0x3800) HW_LOG("VIF%x Register Read8 at 0x%x, value=0x%x", (masked_mem < 0x3c00) ? 0 : 1, mem, psHu32(mem) );
else HW_LOG("GIF Register Read8 at 0x%x, value=0x%x", mem, psHu32(mem) );
case 0x04:
case 0x05:
case 0x06:
case 0x07:
case 0x08:
case 0x09:
case 0x0a:
case 0x0b:
case 0x0c:
case 0x0d:
{
const char* regName = "Unknown";
switch( mem & 0xf0)
{
case 0x00: regName = "CHCR"; break;
case 0x10: regName = "MADR"; break;
case 0x20: regName = "QWC"; break;
case 0x30: regName = "TADR"; break;
case 0x40: regName = "ASR0"; break;
case 0x50: regName = "ASR1"; break;
case 0x80: regName = "SADDR"; break;
}
HW_LOG("Hardware Read16 at 0x%x (%ls %s), value=0x%x", mem, ChcrName(mem & ~0xff), regName, psHu16(mem) );
ret = psHu16(mem);
return ret;
}
}
#endif
switch (mem)
{
case RCNT0_COUNT: ret = (u16)rcntRcount(0); break;
case RCNT0_MODE: ret = (u16)counters[0].modeval; break;
case RCNT0_TARGET: ret = (u16)counters[0].target; break;
case RCNT0_HOLD: ret = (u16)counters[0].hold; break;
case RCNT1_COUNT: ret = (u16)rcntRcount(1); break;
case RCNT1_MODE: ret = (u16)counters[1].modeval; break;
case RCNT1_TARGET: ret = (u16)counters[1].target; break;
case RCNT1_HOLD: ret = (u16)counters[1].hold; break;
case RCNT2_COUNT: ret = (u16)rcntRcount(2); break;
case RCNT2_MODE: ret = (u16)counters[2].modeval; break;
case RCNT2_TARGET: ret = (u16)counters[2].target; break;
case RCNT3_COUNT: ret = (u16)rcntRcount(3); break;
case RCNT3_MODE: ret = (u16)counters[3].modeval; break;
case RCNT3_TARGET: ret = (u16)counters[3].target; break;
default:
if ((mem & 0xffffff0f) == SBUS_F200)
{
switch (mem)
{
case SBUS_F240:
ret = psHu16(mem) | 0x0102;
psHu32(mem) &= ~0x4000; // not commented out like in bit mode?
break;
case SBUS_F260:
ret = 0;
break;
default:
ret = psHu32(mem);
break;
}
return (u16)ret;
}
ret = psHu16(mem);
UnknownHW_LOG("Hardware Read16 at 0x%x, value= 0x%x", ret, mem);
break;
}
return ret;
}
/////////////////////////////////////////////////////////////////////////
// Hardware READ 32 bit
// Reads hardware registers for page 0 (counters 0 and 1)
mem32_t __fastcall hwRead32_page_00(u32 mem)
{
mem &= 0xffff;
switch( mem )
{
case 0x00: return (u16)rcntRcount(0);
case 0x10: return (u16)counters[0].modeval;
case 0x20: return (u16)counters[0].target;
case 0x30: return (u16)counters[0].hold;
case 0x800: return (u16)rcntRcount(1);
case 0x810: return (u16)counters[1].modeval;
case 0x820: return (u16)counters[1].target;
case 0x830: return (u16)counters[1].hold;
}
return *((u32*)&eeMem->HW[mem]);
}
// Reads hardware registers for page 1 (counters 2 and 3)
mem32_t __fastcall hwRead32_page_01(u32 mem)
{
mem &= 0xffff;
switch( mem )
{
case 0x1000: return (u16)rcntRcount(2);
case 0x1010: return (u16)counters[2].modeval;
case 0x1020: return (u16)counters[2].target;
case 0x1800: return (u16)rcntRcount(3);
case 0x1810: return (u16)counters[3].modeval;
case 0x1820: return (u16)counters[3].target;
}
return *((u32*)&eeMem->HW[mem]);
}
// Reads hardware registers for page 15 (0x0F).
// This is used internally to produce two inline versions, one with INTC_HACK, and one without.
static __fi mem32_t __hwRead32_page_0F( u32 mem, bool intchack )
{
// *Performance Warning* This function is called -A-LOT. Be wary when making changes. It
// could impact FPS significantly.
mem &= 0xffff;
// INTC_STAT shortcut for heavy spinning. // INTC_STAT shortcut for heavy spinning.
// Performance Note: Visual Studio handles this best if we just manually check for it here, // Performance Note: Visual Studio handles this best if we just manually check for it here,
// outside the context of the switch statement below. This is likely fixed by PGO also, // outside the context of the switch statement below. This is likely fixed by PGO also,
// but it's an easy enough conditional to account for anyways. // but it's an easy enough conditional to account for anyways.
static const uint ics = INTC_STAT & 0xffff; if (mem == INTC_STAT)
if( mem == ics ) // INTC_STAT
{ {
if( intchack ) IntCHackCheck(); if (intcstathack) IntCHackCheck();
return *((u32*)&eeMem->HW[ics]); return psHu32(INTC_STAT);
} }
//if ((mem & 0x1000f200) == 0x1000f200)
// Console.Error("SBUS");
switch( mem ) switch( mem )
{ {
case 0xf010: case SIO_ISR:
HW_LOG("INTC_MASK Read32, value=0x%x", psHu32(INTC_MASK)); case SBUS_F260:
break; case 0x1000f410:
case MCH_RICM:
case 0xf130: // SIO_ISR
case 0xf260: // SBUS_F260
case 0xf410: // 0x1000f410
case 0xf430: // MCH_RICM
return 0; return 0;
case 0xf240: // SBUS_F240 case SBUS_F240:
return psHu32(0xf240) | 0xF0000102; return psHu32(SBUS_F240) | 0xF0000102;
case 0xf440: // MCH_DRD case MCH_DRD:
if( !((psHu32(0xf430) >> 6) & 0xF) ) if( !((psHu32(MCH_RICM) >> 6) & 0xF) )
{ {
switch ((psHu32(0xf430)>>16) & 0xFFF) switch ((psHu32(MCH_RICM)>>16) & 0xFFF)
{ {
//MCH_RICM: x:4|SA:12|x:5|SDEV:1|SOP:4|SBC:1|SDEV:5 //MCH_RICM: x:4|SA:12|x:5|SDEV:1|SOP:4|SBC:1|SDEV:5
@ -350,149 +120,181 @@ static __fi mem32_t __hwRead32_page_0F( u32 mem, bool intchack )
return 0x0090; //SVER=0 | CORG=4(5x9x6) | SPT=1 | DEVTYP=0 | BYTE=0 return 0x0090; //SVER=0 | CORG=4(5x9x6) | SPT=1 | DEVTYP=0 | BYTE=0
case 0x40://DEVID case 0x40://DEVID
return psHu32(0xf430) & 0x1F; // =SDEV return psHu32(MCH_RICM) & 0x1F; // =SDEV
} }
} }
return 0; return 0;
} }
return *((u32*)&eeMem->HW[mem]); }
break;
}
return psHu32(mem);
} }
mem32_t __fastcall hwRead32_page_0F(u32 mem) template< uint page >
mem32_t __fastcall hwRead32(u32 mem)
{ {
return __hwRead32_page_0F( mem, false ); mem32_t retval = _hwRead32<page,false>(mem);
eeHwTraceLog( mem, retval, true );
return retval;
} }
mem32_t __fastcall hwRead32_page_0F_INTC_HACK(u32 mem) mem32_t __fastcall hwRead32_page_0F_INTC_HACK(u32 mem)
{ {
return __hwRead32_page_0F( mem, true ); mem32_t retval = _hwRead32<0x0f,true>(mem);
eeHwTraceLog( mem, retval, true );
return retval;
} }
mem32_t __fastcall hwRead32_page_02(u32 mem) // --------------------------------------------------------------------------------------
// hwRead8 / hwRead16 / hwRead64 / hwRead128
// --------------------------------------------------------------------------------------
template< uint page >
mem8_t __fastcall _hwRead8(u32 mem)
{ {
return ipuRead32( mem ); u32 ret32 = _hwRead32<page, false>(mem & ~0x03);
return ((u8*)&ret32)[mem & 0x03];
} }
// Used for all pages not explicitly specified above. template< uint page >
mem32_t __fastcall hwRead32_generic(u32 mem) mem8_t __fastcall hwRead8(u32 mem)
{ {
const u16 masked_mem = mem & 0xffff; mem8_t ret8 = _hwRead8<0x0f>(mem);
eeHwTraceLog( mem, ret8, true );
return ret8;
}
switch( masked_mem>>12 ) // switch out as according to the 4k page of the access. template< uint page >
{ mem16_t __fastcall _hwRead16(u32 mem)
case 0x03: {
if(masked_mem >= 0x3800) HW_LOG("VIF%x Register Read32 at 0x%x, value=0x%x", (masked_mem < 0x3c00) ? 0 : 1, mem, psHu32(mem) ); pxAssume( (mem & 0x01) == 0 );
else HW_LOG("GIF Register Read32 at 0x%x, value=0x%x", mem, psHu32(mem) );
// Fixme: OPH hack. Toggle the flag on each GIF_STAT access. (rama) u32 ret32 = _hwRead32<page, false>(mem & ~0x03);
if (CHECK_OPHFLAGHACK) return ((u16*)&ret32)[(mem>>1) & 0x01];
}
template< uint page >
mem16_t __fastcall hwRead16(u32 mem)
{
u16 ret16 = _hwRead16<page>(mem);
eeHwTraceLog( mem, ret16, true );
return ret16;
}
mem16_t __fastcall hwRead16_page_0F_INTC_HACK(u32 mem)
{
pxAssume( (mem & 0x01) == 0 );
u32 ret32 = _hwRead32<0x0f, true>(mem & ~0x03);
u16 ret16 = ((u16*)&ret32)[(mem>>1) & 0x01];
eeHwTraceLog( mem, ret16, "Read" );
return ret16;
}
template< uint page >
static void _hwRead64(u32 mem, mem64_t* result )
{
pxAssume( (mem & 0x07) == 0 );
switch (page)
{ {
if (masked_mem == 0x3020) case 0x02:
gifRegs->stat.OPH = !gifRegs->stat.OPH; *result = ipuRead64(mem);
} return;
break;
///////////////////////////////////////////////////////
// Most of the following case handlers are for developer builds only (logging).
// It'll all optimize to ziltch in public release builds.
#ifdef PCSX2_DEVBUILD
case 0x04: case 0x04:
case 0x05: case 0x05:
case 0x06: case 0x06:
case 0x07: case 0x07:
case 0x08:
case 0x09:
case 0x0a:
case 0x0b:
case 0x0c:
case 0x0d:
{ {
const char* regName = "Unknown"; // [Ps2Confirm] Reading from FIFOs using non-128 bit reads is a complete mystery.
// No game is known to attempt such a thing (yay!), so probably nothing for us to
// worry about. Chances are, though, doing so is "legal" and yields some sort
// of reproducible behavior. Candidate for real hardware testing.
switch( mem & 0xf0) // Current assumption: Reads 128 bits and discards the unused portion.
{
case 0x00: regName = "CHCR"; break; uint wordpart = (mem >> 3) & 0x1;
case 0x10: regName = "MADR"; break; DevCon.WriteLn( Color_Cyan, "Reading 64-bit FIFO data (%s 64 bits discarded)", wordpart ? "upper" : "lower" );
case 0x20: regName = "QWC"; break;
case 0x30: regName = "TADR"; break; u128 out128;
case 0x40: regName = "ASR0"; break; _hwRead128<page>(mem, &out128);
case 0x50: regName = "ASR1"; break; *result = out128._u64[wordpart];
case 0x80: regName = "SADDR"; break; }
return;
} }
HW_LOG("Hardware Read32 at 0x%x (%ls %s), value=0x%x", mem, ChcrName(mem & ~0xff), regName, psHu32(mem) ); *result = _hwRead32<page,false>( mem );
} }
break;
#endif template< uint page >
case 0x0e: void __fastcall hwRead64(u32 mem, mem64_t* result )
#ifdef PCSX2_DEVBUILD {
HW_LOG("DMAC Control Regs addr=0x%x Read32, value=0x%x", mem, psHu32(mem)); _hwRead64<page>( mem, result );
#else eeHwTraceLog( mem, *result, true );
if( mem == DMAC_STAT) }
HW_LOG("DMAC_STAT Read32, value=0x%x", psHu32(DMAC_STAT));
#endif template< uint page >
void __fastcall _hwRead128(u32 mem, mem128_t* result )
{
pxAssume( (mem & 0x0f) == 0 );
// FIFOs are the only "legal" 128 bit registers, so we Handle them first.
// All other registers fall back on the 64-bit handler (and from there
// all non-IPU reads fall back to the 32-bit handler).
switch (page)
{
case 0x05:
ReadFIFO_VIF1( result );
break; break;
jNO_DEFAULT; case 0x07:
if (mem & 0x10)
ZeroQWC( result ); // IPUin is write-only
else
ReadFIFO_IPUout( result );
break;
case 0x04:
case 0x06:
// VIF0 and GIF are write-only.
// [Ps2Confirm] Reads from these FIFOs (and IPUin) do one of the following:
// return zero, leave contents of the dest register unchanged, or in some
// indeterminate state. The actual behavior probably isn't important.
ZeroQWC( result );
break;
default:
_hwRead64<page>( mem, &result->lo );
result->hi = 0;
break;
} }
return *((u32*)&eeMem->HW[masked_mem]);
} }
///////////////////////////////////////////////////////////////////////// template< uint page >
// Hardware READ 64 bit void __fastcall hwRead128(u32 mem, mem128_t* result )
void __fastcall hwRead64_page_00(u32 mem, mem64_t* result )
{ {
*result = hwRead32_page_00( mem ); _hwRead128<page>( mem, result );
eeHwTraceLog( mem, *result, true );
} }
void __fastcall hwRead64_page_01(u32 mem, mem64_t* result ) #define InstantizeHwRead(pageidx) \
{ template mem8_t __fastcall hwRead8<pageidx>(u32 mem); \
*result = hwRead32_page_01( mem ); template mem16_t __fastcall hwRead16<pageidx>(u32 mem); \
} template mem32_t __fastcall hwRead32<pageidx>(u32 mem); \
template void __fastcall hwRead64<pageidx>(u32 mem, mem64_t* result ); \
template void __fastcall hwRead128<pageidx>(u32 mem, mem128_t* result ); \
template mem32_t __fastcall _hwRead32<pageidx, false>(u32 mem);
void __fastcall hwRead64_page_02(u32 mem, mem64_t* result ) InstantizeHwRead(0x00); InstantizeHwRead(0x08);
{ InstantizeHwRead(0x01); InstantizeHwRead(0x09);
*result = ipuRead64(mem); InstantizeHwRead(0x02); InstantizeHwRead(0x0a);
} InstantizeHwRead(0x03); InstantizeHwRead(0x0b);
InstantizeHwRead(0x04); InstantizeHwRead(0x0c);
void __fastcall hwRead64_generic_INTC_HACK(u32 mem, mem64_t* result ) InstantizeHwRead(0x05); InstantizeHwRead(0x0d);
{ InstantizeHwRead(0x06); InstantizeHwRead(0x0e);
if (mem == INTC_STAT) IntCHackCheck(); InstantizeHwRead(0x07); InstantizeHwRead(0x0f);
*result = psHu64(mem);
UnknownHW_LOG("Hardware Read 64 at %x",mem);
}
void __fastcall hwRead64_generic(u32 mem, mem64_t* result )
{
*result = psHu64(mem);
UnknownHW_LOG("Hardware Read 64 at %x",mem);
}
/////////////////////////////////////////////////////////////////////////
// Hardware READ 128 bit
void __fastcall hwRead128_page_00(u32 mem, mem128_t* result )
{
result->lo = hwRead32_page_00( mem );
result->hi = 0;
}
void __fastcall hwRead128_page_01(u32 mem, mem128_t* result )
{
result->lo = hwRead32_page_01( mem );
result->hi = 0;
}
void __fastcall hwRead128_page_02(u32 mem, mem128_t* result )
{
// IPU is currently unhandled in 128 bit mode.
HW_LOG("Hardware Read 128 at %x (IPU)",mem);
}
void __fastcall hwRead128_generic(u32 mem, mem128_t* out)
{
CopyQWC(out, &psHu128(mem));
UnknownHW_LOG("Hardware Read 128 at %x",mem);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -17,10 +17,6 @@
#include "IPU_Fifo.h" #include "IPU_Fifo.h"
#ifdef _MSC_VER
//#pragma pack(1)
#endif
#define ipumsk( src ) ( (src) & 0xff ) #define ipumsk( src ) ( (src) & 0xff )
#define ipucase( src ) case ipumsk(src) #define ipucase( src ) case ipumsk(src)
@ -29,26 +25,6 @@
#define IPU_FORCEINLINE __fi #define IPU_FORCEINLINE __fi
struct IPUStatus {
bool InProgress;
u8 DMAMode;
bool DMAFinished;
bool IRQTriggered;
u8 TagFollow;
u32 TagAddr;
bool stalled;
u8 ChainMode;
u32 NextMem;
};
#define DMA_MODE_NORMAL 0
#define DMA_MODE_CHAIN 1
#define IPU1_TAG_FOLLOW 0
#define IPU1_TAG_QWC 1
#define IPU1_TAG_ADDR 2
#define IPU1_TAG_NONE 3
// //
// Bitfield Structures // Bitfield Structures
// //
@ -102,10 +78,6 @@ struct tIPU_BP {
} }
}; };
#ifdef _WIN32
//#pragma pack()
#endif
union tIPU_CMD_IDEC union tIPU_CMD_IDEC
{ {
struct struct
@ -178,47 +150,6 @@ union tIPU_CMD_CSC
void log_from_RGB32() const; void log_from_RGB32() const;
}; };
union tIPU_DMA
{
struct
{
bool GIFSTALL : 1;
bool TIE0 :1;
bool TIE1 : 1;
bool ACTV1 : 1;
bool DOTIE1 : 1;
bool FIREINT0 : 1;
bool FIREINT1 : 1;
bool VIFSTALL : 1;
bool SIFSTALL : 1;
};
u32 _u32;
tIPU_DMA( u32 val ){ _u32 = val; }
bool test(u32 flags) const { return !!(_u32 & flags); }
void set_flags(u32 flags) { _u32 |= flags; }
void clear_flags(u32 flags) { _u32 &= ~flags; }
void reset() { _u32 = 0; }
wxString desc() const
{
wxString temp(L"g_nDMATransfer[");
if (GIFSTALL) temp += L" GIFSTALL ";
if (TIE0) temp += L" TIE0 ";
if (TIE1) temp += L" TIE1 ";
if (ACTV1) temp += L" ACTV1 ";
if (DOTIE1) temp += L" DOTIE1 ";
if (FIREINT0) temp += L" FIREINT0 ";
if (FIREINT1) temp += L" FIREINT1 ";
if (VIFSTALL) temp += L" VIFSTALL ";
if (SIFSTALL) temp += L" SIFSTALL ";
temp += L"]";
return temp;
}
};
enum SCE_IPU enum SCE_IPU
{ {
SCE_IPU_BCLR = 0x0 SCE_IPU_BCLR = 0x0
@ -245,8 +176,6 @@ struct IPUregisters {
u32 dummy3[2]; u32 dummy3[2];
}; };
#define ipuRegs ((IPUregisters*)(&eeMem->HW[0x2000]))
struct tIPU_cmd struct tIPU_cmd
{ {
int index; int index;
@ -271,32 +200,22 @@ struct tIPU_cmd
} }
}; };
static IPUregisters& ipuRegs = (IPUregisters&)eeHw[0x2000];
extern tIPU_cmd ipu_cmd; extern tIPU_cmd ipu_cmd;
extern int coded_block_pattern; extern int coded_block_pattern;
extern IPUStatus IPU1Status;
extern tIPU_DMA g_nDMATransfer;
extern int ipuInit(); extern int ipuInit();
extern void ipuReset(); extern void ipuReset();
extern void ipuShutdown();
extern int ipuFreeze(gzFile f, int Mode);
extern bool ipuCanFreeze();
extern u32 ipuRead32(u32 mem); extern u32 ipuRead32(u32 mem);
extern u64 ipuRead64(u32 mem); extern u64 ipuRead64(u32 mem);
extern void ipuWrite32(u32 mem,u32 value); extern bool ipuWrite32(u32 mem,u32 value);
extern void ipuWrite64(u32 mem,u64 value); extern bool ipuWrite64(u32 mem,u64 value);
extern void IPUCMD_WRITE(u32 val); extern void IPUCMD_WRITE(u32 val);
extern void ipuSoftReset(); extern void ipuSoftReset();
extern void IPUProcessInterrupt(); extern void IPUProcessInterrupt();
extern void ipu0Interrupt();
extern void ipu1Interrupt();
extern void dmaIPU0();
extern void dmaIPU1();
extern int IPU0dma();
extern int IPU1dma();
extern u16 __fastcall FillInternalBuffer(u32 * pointer, u32 advance, u32 size); extern u16 __fastcall FillInternalBuffer(u32 * pointer, u32 advance, u32 size);
extern u8 __fastcall getBits128(u8 *address, u32 advance); extern u8 __fastcall getBits128(u8 *address, u32 advance);

View File

@ -16,6 +16,7 @@
#include "PrecompiledHeader.h" #include "PrecompiledHeader.h"
#include "Common.h" #include "Common.h"
#include "IPU.h" #include "IPU.h"
#include "IPU/IPUdma.h"
#include "mpeg2lib/Mpeg.h" #include "mpeg2lib/Mpeg.h"
@ -35,7 +36,7 @@ void IPU_Fifo_Input::clear()
{ {
memzero(data); memzero(data);
g_BP.IFC = 0; g_BP.IFC = 0;
ipuRegs->ctrl.IFC = 0; ipuRegs.ctrl.IFC = 0;
readpos = 0; readpos = 0;
writepos = 0; writepos = 0;
} }
@ -43,7 +44,7 @@ void IPU_Fifo_Input::clear()
void IPU_Fifo_Output::clear() void IPU_Fifo_Output::clear()
{ {
memzero(data); memzero(data);
ipuRegs->ctrl.OFC = 0; ipuRegs.ctrl.OFC = 0;
readpos = 0; readpos = 0;
writepos = 0; writepos = 0;
} }
@ -89,9 +90,9 @@ int IPU_Fifo_Output::write(const u32 *value, int size)
{ {
int transsize, firsttrans; int transsize, firsttrans;
if ((int)ipuRegs->ctrl.OFC >= 8) IPU0dma(); if ((int)ipuRegs.ctrl.OFC >= 8) IPU0dma();
transsize = min(size, 8 - (int)ipuRegs->ctrl.OFC); transsize = min(size, 8 - (int)ipuRegs.ctrl.OFC);
firsttrans = transsize; firsttrans = transsize;
while (transsize-- > 0) while (transsize-- > 0)
@ -104,7 +105,7 @@ int IPU_Fifo_Output::write(const u32 *value, int size)
value += 4; value += 4;
} }
ipuRegs->ctrl.OFC += firsttrans; ipuRegs.ctrl.OFC += firsttrans;
IPU0dma(); IPU0dma();
return firsttrans; return firsttrans;
@ -150,7 +151,7 @@ void IPU_Fifo_Output::_readsingle(void *value)
void IPU_Fifo_Output::read(void *value, int size) void IPU_Fifo_Output::read(void *value, int size)
{ {
ipuRegs->ctrl.OFC -= size; ipuRegs.ctrl.OFC -= size;
while (size > 0) while (size > 0)
{ {
_readsingle(value); _readsingle(value);
@ -161,38 +162,51 @@ void IPU_Fifo_Output::read(void *value, int size)
void IPU_Fifo_Output::readsingle(void *value) void IPU_Fifo_Output::readsingle(void *value)
{ {
if (ipuRegs->ctrl.OFC > 0) if (ipuRegs.ctrl.OFC > 0)
{ {
ipuRegs->ctrl.OFC--; ipuRegs.ctrl.OFC--;
_readsingle(value); _readsingle(value);
} }
} }
__fi bool decoder_t::ReadIpuData(u128* out) __fi bool decoder_t::ReadIpuData(u128* out)
{ {
if(decoder.ipu0_data == 0) return false; if(ipu0_data == 0)
_mm_store_ps((float*)out, _mm_load_ps((float*)GetIpuDataPtr())); {
IPU_LOG( "ReadFIFO/IPUout -> (fifo empty/no data available)" );
return false;
}
CopyQWC(out, GetIpuDataPtr());
--ipu0_data; --ipu0_data;
++ipu0_idx; ++ipu0_idx;
IPU_LOG( "ReadFIFO/IPUout -> %ls", out->ToString().c_str() );
return true; return true;
} }
void __fastcall ReadFIFO_page_7(u32 mem, mem128_t* out) void __fastcall ReadFIFO_IPUout(mem128_t* out)
{ {
pxAssert( (mem >= IPUout_FIFO) && (mem < D0_CHCR) ); // FIXME! When ReadIpuData() doesn't succeed (returns false), the EE should probably stall
// until a value becomes available. This isn't exactly easy to do since the virtualized EE
// in PCSX2 *has* to be running in order for the IPU DMA to upload new input data to allow
// IPUout's FIFO to fill. Thus if we implement an EE stall, PCSX2 deadlocks. Grr. --air
// All addresses in this page map to 0x7000 and 0x7010:
mem &= 0x10;
if (mem == 0) // IPUout_FIFO
{
if (decoder.ReadIpuData(out)) if (decoder.ReadIpuData(out))
{ {
ipu_fifo.out.readpos = (ipu_fifo.out.readpos + 4) & 31; ipu_fifo.out.readpos = (ipu_fifo.out.readpos + 4) & 31;
} }
} }
else // IPUin_FIFO
ipu_fifo.out.readsingle((void*)out); void __fastcall WriteFIFO_IPUin(const mem128_t* value)
{
IPU_LOG( "WriteFIFO/IPUin <- %ls", value->ToString().c_str() );
//committing every 16 bytes
if( ipu_fifo.in.write((u32*)value, 1) == 0 )
{
IPUProcessInterrupt();
}
} }

509
pcsx2/IPU/IPUdma.cpp Normal file
View File

@ -0,0 +1,509 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2010 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 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 PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include "PrecompiledHeader.h"
#include "Common.h"
#include "IPU.h"
#include "IPU/IPUdma.h"
#include "mpeg2lib/Mpeg.h"
#include "Vif.h"
#include "Gif.h"
#include "Vif_Dma.h"
static IPUStatus IPU1Status;
static tIPU_DMA g_nDMATransfer;
void ipuDmaReset()
{
IPU1Status.InProgress = false;
IPU1Status.DMAMode = DMA_MODE_NORMAL;
IPU1Status.DMAFinished = true;
g_nDMATransfer.reset();
}
void SaveStateBase::ipuDmaFreeze()
{
FreezeTag( "IPUdma" );
Freeze(g_nDMATransfer);
Freeze(IPU1Status);
}
static __fi bool ipuDmacPartialChain(tDMA_TAG tag)
{
switch (tag.ID)
{
case TAG_REFE: // refe
ipu1dma.tadr += 16;
return true;
case TAG_END: // end
ipu1dma.tadr = ipu1dma.madr;
return true;
}
return false;
}
static __fi void ipuDmacSrcChain()
{
switch (IPU1Status.ChainMode)
{
case TAG_REFE: // refe
//if(IPU1Status.InProgress == false) ipu1dma.tadr += 16;
IPU1Status.DMAFinished = true;
break;
case TAG_CNT: // cnt
// Set the taddr to the next tag
ipu1dma.tadr = ipu1dma.madr;
//if(IPU1Status.DMAFinished == false) IPU1Status.DMAFinished = false;
break;
case TAG_NEXT: // next
ipu1dma.tadr = IPU1Status.NextMem;
//if(IPU1Status.DMAFinished == false) IPU1Status.DMAFinished = false;
break;
case TAG_REF: // ref
//if(IPU1Status.InProgress == false)ipu1dma.tadr += 16;
//if(IPU1Status.DMAFinished == false) IPU1Status.DMAFinished = false;
break;
case TAG_END: // end
ipu1dma.tadr = ipu1dma.madr;
IPU1Status.DMAFinished = true;
break;
}
}
static __fi bool WaitGSPaths()
{
if(CHECK_IPUWAITHACK)
{
if(GSTransferStatus.PTH3 < STOPPED_MODE && GSTransferStatus.PTH3 != IDLE_MODE)
{
//GIF_LOG("Flushing gif chcr %x tadr %x madr %x qwc %x", gif->chcr._u32, gif->tadr, gif->madr, gif->qwc);
//DevCon.WriteLn("Waiting for GIF");
return false;
}
if(GSTransferStatus.PTH2 != STOPPED_MODE)
{
//DevCon.WriteLn("Waiting for VIF");
return false;
}
if(GSTransferStatus.PTH1 != STOPPED_MODE)
{
//DevCon.WriteLn("Waiting for VU");
return false;
}
}
return true;
}
static __fi int IPU1chain() {
int totalqwc = 0;
if (ipu1dma.qwc > 0 && IPU1Status.InProgress == true)
{
int qwc = ipu1dma.qwc;
u32 *pMem;
pMem = (u32*)dmaGetAddr(ipu1dma.madr, false);
if (pMem == NULL)
{
Console.Error("ipu1dma NULL!");
return totalqwc;
}
//Write our data to the fifo
qwc = ipu_fifo.in.write(pMem, qwc);
ipu1dma.madr += qwc << 4;
ipu1dma.qwc -= qwc;
totalqwc += qwc;
}
if( ipu1dma.qwc == 0)
{
//Update TADR etc
if(IPU1Status.DMAMode == DMA_MODE_CHAIN) ipuDmacSrcChain();
//If the transfer has finished or we have room in the FIFO, schedule to the interrupt code.
//No data left
IPU1Status.InProgress = false;
} //If we still have data the commands should pull this across when need be.
return totalqwc;
}
//static __fi bool WaitGSPaths()
//{
// //Wait for all GS paths to be clear
// if (GSTransferStatus._u32 != 0x2a)
// {
// if(GSTransferStatus.PTH3 != STOPPED_MODE && vif1Regs.mskpath3) return true;
// IPU_LOG("Waiting for GS transfers to finish %x", GSTransferStatus._u32);
// IPU_INT_TO(4);
// return false;
// }
// return true;
//}
int IPU1dma()
{
int ipu1cycles = 0;
int totalqwc = 0;
//We need to make sure GIF has flushed before sending IPU data, it seems to REALLY screw FFX videos
//if(!WaitGSPaths()) return totalqwc;
if(ipu1dma.chcr.STR == false || IPU1Status.DMAMode == 2)
{
//We MUST stop the IPU from trying to fill the FIFO with more data if the DMA has been suspended
//if we don't, we risk causing the data to go out of sync with the fifo and we end up losing some!
//This is true for Dragons Quest 8 and probably others which suspend the DMA.
DevCon.Warning("IPU1 running when IPU1 DMA disabled! CHCR %x QWC %x", ipu1dma.chcr._u32, ipu1dma.qwc);
return 0;
}
IPU_LOG("IPU1 DMA Called QWC %x Finished %d In Progress %d tadr %x", ipu1dma.qwc, IPU1Status.DMAFinished, IPU1Status.InProgress, ipu1dma.tadr);
switch(IPU1Status.DMAMode)
{
case DMA_MODE_NORMAL:
{
if(!WaitGSPaths())
{ // legacy WaitGSPaths() for now
IPU_INT_TO(4); //Give it a short wait.
return totalqwc;
}
IPU_LOG("Processing Normal QWC left %x Finished %d In Progress %d", ipu1dma.qwc, IPU1Status.DMAFinished, IPU1Status.InProgress);
if(IPU1Status.InProgress == true) totalqwc += IPU1chain();
}
break;
case DMA_MODE_CHAIN:
{
if(IPU1Status.InProgress == true) //No transfer is ready to go so we need to set one up
{
if(!WaitGSPaths())
{ // legacy WaitGSPaths() for now
IPU_INT_TO(4); //Give it a short wait.
return totalqwc;
}
IPU_LOG("Processing Chain QWC left %x Finished %d In Progress %d", ipu1dma.qwc, IPU1Status.DMAFinished, IPU1Status.InProgress);
totalqwc += IPU1chain();
//Set the TADR forward
}
if(IPU1Status.InProgress == false && IPU1Status.DMAFinished == false) //No transfer is ready to go so we need to set one up
{
tDMA_TAG* ptag = dmaGetAddr(ipu1dma.tadr, false); //Set memory pointer to TADR
if (!ipu1dma.transfer("IPU1", ptag))
{
return totalqwc;
}
ipu1cycles += 1; // Add 1 cycles from the QW read for the tag
IPU1Status.ChainMode = ptag->ID;
if(ipu1dma.chcr.TTE) DevCon.Warning("TTE?");
switch (IPU1Status.ChainMode)
{
case TAG_REFE: // refe
// do not change tadr
//ipu1dma.tadr += 16;
ipu1dma.tadr += 16;
ipu1dma.madr = ptag[1]._u32;
IPU_LOG("Tag should end on %x", ipu1dma.tadr);
break;
case TAG_CNT: // cnt
ipu1dma.madr = ipu1dma.tadr + 16;
IPU_LOG("Tag should end on %x", ipu1dma.madr + ipu1dma.qwc * 16);
//ipu1dma.tadr = ipu1dma.madr + (ipu1dma.qwc * 16);
// Set the taddr to the next tag
//IPU1Status.DMAFinished = false;
break;
case TAG_NEXT: // next
ipu1dma.madr = ipu1dma.tadr + 16;
IPU1Status.NextMem = ptag[1]._u32;
IPU_LOG("Tag should end on %x", IPU1Status.NextMem);
//IPU1Status.DMAFinished = false;
break;
case TAG_REF: // ref
ipu1dma.madr = ptag[1]._u32;
ipu1dma.tadr += 16;
IPU_LOG("Tag should end on %x", ipu1dma.tadr);
//IPU1Status.DMAFinished = false;
break;
case TAG_END: // end
// do not change tadr
ipu1dma.madr = ipu1dma.tadr + 16;
ipu1dma.tadr += 16;
IPU_LOG("Tag should end on %x", ipu1dma.madr + ipu1dma.qwc * 16);
break;
default:
Console.Error("IPU ERROR: different transfer mode!, Please report to PCSX2 Team");
break;
}
//if(ipu1dma.qwc == 0) Console.Warning("Blank QWC!");
if(ipu1dma.qwc > 0) IPU1Status.InProgress = true;
IPU_LOG("dmaIPU1 dmaChain %8.8x_%8.8x size=%d, addr=%lx, fifosize=%x",
ptag[1]._u32, ptag[0]._u32, ipu1dma.qwc, ipu1dma.madr, 8 - g_BP.IFC);
if (ipu1dma.chcr.TIE && ptag->IRQ) //Tag Interrupt is set, so schedule the end/interrupt
IPU1Status.DMAFinished = true;
if(!WaitGSPaths() && ipu1dma.qwc > 0)
{ // legacy WaitGSPaths() for now
IPU_INT_TO(4); //Give it a short wait.
return totalqwc;
}
IPU_LOG("Processing Start Chain QWC left %x Finished %d In Progress %d", ipu1dma.qwc, IPU1Status.DMAFinished, IPU1Status.InProgress);
totalqwc += IPU1chain();
//Set the TADR forward
}
}
break;
}
//Do this here to prevent double settings on Chain DMA's
if(totalqwc > 0 || ipu1dma.qwc == 0)
{
IPU_INT_TO(totalqwc * BIAS);
IPUProcessInterrupt();
}
else
{
cpuRegs.eCycle[4] = 0x9999;//IPU_INT_TO(2048);
}
IPU_LOG("Completed Call IPU1 DMA QWC Remaining %x Finished %d In Progress %d tadr %x", ipu1dma.qwc, IPU1Status.DMAFinished, IPU1Status.InProgress, ipu1dma.tadr);
return totalqwc;
}
int IPU0dma()
{
int readsize;
static int totalsize = 0;
tDMA_TAG* pMem;
if ((!(ipu0dma.chcr.STR) || (cpuRegs.interrupt & (1 << DMAC_FROM_IPU))) || (ipu0dma.qwc == 0))
return 0;
pxAssert(!(ipu0dma.chcr.TTE));
IPU_LOG("dmaIPU0 chcr = %lx, madr = %lx, qwc = %lx",
ipu0dma.chcr._u32, ipu0dma.madr, ipu0dma.qwc);
pxAssert(ipu0dma.chcr.MOD == NORMAL_MODE);
pMem = dmaGetAddr(ipu0dma.madr, true);
readsize = min(ipu0dma.qwc, (u16)ipuRegs.ctrl.OFC);
totalsize+=readsize;
ipu_fifo.out.read(pMem, readsize);
ipu0dma.madr += readsize << 4;
ipu0dma.qwc -= readsize; // note: qwc is u16
if (ipu0dma.qwc == 0)
{
if (dmacRegs.ctrl.STS == STS_fromIPU) // STS == fromIPU
{
dmacRegs.stadr.ADDR = ipu0dma.madr;
switch (dmacRegs.ctrl.STD)
{
case NO_STD:
break;
case STD_GIF: // GIF
Console.Warning("GIFSTALL");
g_nDMATransfer.GIFSTALL = true;
break;
case STD_VIF1: // VIF
Console.Warning("VIFSTALL");
g_nDMATransfer.VIFSTALL = true;
break;
case STD_SIF1:
Console.Warning("SIFSTALL");
g_nDMATransfer.SIFSTALL = true;
break;
}
}
//Fixme ( voodoocycles ):
//This was IPU_INT_FROM(readsize*BIAS );
//This broke vids in Digital Devil Saga
//Note that interrupting based on totalsize is just guessing..
IPU_INT_FROM( readsize * BIAS );
totalsize = 0;
}
return readsize;
}
__fi void dmaIPU0() // fromIPU
{
if (ipu0dma.pad != 0)
{
// Note: pad is the padding right above qwc, so we're testing whether qwc
// has overflowed into pad.
DevCon.Warning(L"IPU0dma's upper 16 bits set to %x", ipu0dma.pad);
ipu0dma.qwc = ipu0dma.pad = 0;
//If we are going to clear down IPU0, we should end it too. Going to test this scenario on the PS2 mind - Refraction
ipu0dma.chcr.STR = false;
hwDmacIrq(DMAC_FROM_IPU);
}
IPUProcessInterrupt();
}
__fi void dmaIPU1() // toIPU
{
IPU_LOG("IPU1DMAStart QWC %x, MADR %x, CHCR %x, TADR %x", ipu1dma.qwc, ipu1dma.madr, ipu1dma.chcr._u32, ipu1dma.tadr);
if (ipu1dma.pad != 0)
{
// Note: pad is the padding right above qwc, so we're testing whether qwc
// has overflowed into pad.
DevCon.Warning(L"IPU1dma's upper 16 bits set to %x\n", ipu1dma.pad);
ipu1dma.qwc = ipu1dma.pad = 0;
// If we are going to clear down IPU1, we should end it too.
// Going to test this scenario on the PS2 mind - Refraction
ipu1dma.chcr.STR = false;
hwDmacIrq(DMAC_TO_IPU);
}
if (ipu1dma.chcr.MOD == CHAIN_MODE) //Chain Mode
{
IPU_LOG("Setting up IPU1 Chain mode");
if(ipu1dma.qwc == 0)
{
IPU1Status.InProgress = false;
IPU1Status.DMAFinished = false;
}
else
{ //Attempting to continue a previous chain
IPU_LOG("Resuming DMA TAG %x", (ipu1dma.chcr.TAG >> 12));
//We MUST check the CHCR for the tag it last knew, it can be manipulated!
IPU1Status.ChainMode = (ipu1dma.chcr.TAG >> 12) & 0x7;
IPU1Status.InProgress = true;
IPU1Status.DMAFinished = ((ipu1dma.chcr.TAG >> 15) && ipu1dma.chcr.TIE) ? true : false;
}
IPU1Status.DMAMode = DMA_MODE_CHAIN;
IPU1dma();
}
else //Normal Mode
{
if(ipu1dma.qwc == 0)
{
ipu1dma.chcr.STR = false;
// Hack to force stop IPU
ipuRegs.cmd.BUSY = 0;
ipuRegs.ctrl.BUSY = 0;
ipuRegs.topbusy = 0;
//
hwDmacIrq(DMAC_TO_IPU);
Console.Warning("IPU1 Normal error!");
}
else
{
IPU_LOG("Setting up IPU1 Normal mode");
IPU1Status.InProgress = true;
IPU1Status.DMAFinished = true;
IPU1Status.DMAMode = DMA_MODE_NORMAL;
IPU1dma();
}
}
}
extern void GIFdma();
void ipu0Interrupt()
{
IPU_LOG("ipu0Interrupt: %x", cpuRegs.cycle);
if (g_nDMATransfer.FIREINT0)
{
g_nDMATransfer.FIREINT0 = false;
hwIntcIrq(INTC_IPU);
}
if (g_nDMATransfer.GIFSTALL)
{
// gif
Console.Warning("IPU GIF Stall");
g_nDMATransfer.GIFSTALL = false;
//if (gif->chcr.STR) GIFdma();
}
if (g_nDMATransfer.VIFSTALL)
{
// vif
Console.Warning("IPU VIF Stall");
g_nDMATransfer.VIFSTALL = false;
//if (vif1ch.chcr.STR) dmaVIF1();
}
if (g_nDMATransfer.SIFSTALL)
{
// sif
Console.Warning("IPU SIF Stall");
g_nDMATransfer.SIFSTALL = false;
// Not totally sure whether this needs to be done or not, so I'm
// leaving it commented out for the moment.
//if (sif1dma.chcr.STR) SIF1Dma();
}
if (g_nDMATransfer.TIE0)
{
g_nDMATransfer.TIE0 = false;
}
ipu0dma.chcr.STR = false;
hwDmacIrq(DMAC_FROM_IPU);
}
IPU_FORCEINLINE void ipu1Interrupt()
{
IPU_LOG("ipu1Interrupt %x:", cpuRegs.cycle);
if(IPU1Status.DMAFinished == false || IPU1Status.InProgress == true) //Sanity Check
{
IPU1dma();
return;
}
IPU_LOG("ipu1 finish %x:", cpuRegs.cycle);
ipu1dma.chcr.STR = false;
IPU1Status.DMAMode = 2;
hwDmacIrq(DMAC_TO_IPU);
}

93
pcsx2/IPU/IPUdma.h Normal file
View File

@ -0,0 +1,93 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2010 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 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 PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "IPU.h"
static DMACh& ipu0dma = (DMACh&)eeHw[0xb000];
static DMACh& ipu1dma = (DMACh&)eeHw[0xb400];
struct IPUStatus {
bool InProgress;
u8 DMAMode;
bool DMAFinished;
bool IRQTriggered;
u8 TagFollow;
u32 TagAddr;
bool stalled;
u8 ChainMode;
u32 NextMem;
};
#define DMA_MODE_NORMAL 0
#define DMA_MODE_CHAIN 1
#define IPU1_TAG_FOLLOW 0
#define IPU1_TAG_QWC 1
#define IPU1_TAG_ADDR 2
#define IPU1_TAG_NONE 3
union tIPU_DMA
{
struct
{
bool GIFSTALL : 1;
bool TIE0 :1;
bool TIE1 : 1;
bool ACTV1 : 1;
bool DOTIE1 : 1;
bool FIREINT0 : 1;
bool FIREINT1 : 1;
bool VIFSTALL : 1;
bool SIFSTALL : 1;
};
u32 _u32;
tIPU_DMA( u32 val ){ _u32 = val; }
tIPU_DMA() { }
bool test(u32 flags) const { return !!(_u32 & flags); }
void set_flags(u32 flags) { _u32 |= flags; }
void clear_flags(u32 flags) { _u32 &= ~flags; }
void reset() { _u32 = 0; }
wxString desc() const
{
wxString temp(L"g_nDMATransfer[");
if (GIFSTALL) temp += L" GIFSTALL ";
if (TIE0) temp += L" TIE0 ";
if (TIE1) temp += L" TIE1 ";
if (ACTV1) temp += L" ACTV1 ";
if (DOTIE1) temp += L" DOTIE1 ";
if (FIREINT0) temp += L" FIREINT0 ";
if (FIREINT1) temp += L" FIREINT1 ";
if (VIFSTALL) temp += L" VIFSTALL ";
if (SIFSTALL) temp += L" SIFSTALL ";
temp += L"]";
return temp;
}
};
extern void ipu0Interrupt();
extern void ipu1Interrupt();
extern void dmaIPU0();
extern void dmaIPU1();
extern int IPU0dma();
extern int IPU1dma();
extern void ipuDmaReset();

View File

@ -680,7 +680,7 @@ static __fi bool slice_non_intra_DCT(s16 * const dest, const int stride, const b
void __fi finishmpeg2sliceIDEC() void __fi finishmpeg2sliceIDEC()
{ {
ipuRegs->ctrl.SCD = 0; ipuRegs.ctrl.SCD = 0;
coded_block_pattern = decoder.coded_block_pattern; coded_block_pattern = decoder.coded_block_pattern;
g_BP.BP += decoder.bitstream_bits - 16; g_BP.BP += decoder.bitstream_bits - 16;
@ -710,8 +710,8 @@ bool mpeg2sliceIDEC()
decoder.dc_dct_pred[2] = 128 << decoder.intra_dc_precision; decoder.dc_dct_pred[2] = 128 << decoder.intra_dc_precision;
decoder.mbc = 0; decoder.mbc = 0;
ipuRegs->top = 0; ipuRegs.top = 0;
ipuRegs->ctrl.ECD = 0; ipuRegs.ctrl.ECD = 0;
case 1: case 1:
ipu_cmd.pos[0] = 1; ipu_cmd.pos[0] = 1;
@ -907,17 +907,17 @@ finish_idec:
{ {
if (g_BP.BP & 7) g_BP.BP += 8 - (g_BP.BP & 7); if (g_BP.BP & 7) g_BP.BP += 8 - (g_BP.BP & 7);
ipuRegs->ctrl.SCD = 1; ipuRegs.ctrl.SCD = 1;
} }
case 4: case 4:
if (!getBits32((u8*)&ipuRegs->top, 0)) if (!getBits32((u8*)&ipuRegs.top, 0))
{ {
ipu_cmd.pos[0] = 4; ipu_cmd.pos[0] = 4;
return false; return false;
} }
BigEndian(ipuRegs->top, ipuRegs->top); BigEndian(ipuRegs.top, ipuRegs.top);
break; break;
} }
@ -942,8 +942,8 @@ bool mpeg2_slice()
decoder.dc_dct_pred[2] = 128 << decoder.intra_dc_precision; decoder.dc_dct_pred[2] = 128 << decoder.intra_dc_precision;
} }
ipuRegs->ctrl.ECD = 0; ipuRegs.ctrl.ECD = 0;
ipuRegs->top = 0; ipuRegs.top = 0;
memzero_sse_a(mb8); memzero_sse_a(mb8);
memzero_sse_a(mb16); memzero_sse_a(mb16);
case 1: case 1:
@ -1082,7 +1082,7 @@ bool mpeg2_slice()
} }
// Send The MacroBlock via DmaIpuFrom // Send The MacroBlock via DmaIpuFrom
ipuRegs->ctrl.SCD = 0; ipuRegs.ctrl.SCD = 0;
coded_block_pattern = decoder.coded_block_pattern; coded_block_pattern = decoder.coded_block_pattern;
g_BP.BP += (int)decoder.bitstream_bits - 16; g_BP.BP += (int)decoder.bitstream_bits - 16;
@ -1128,17 +1128,17 @@ bool mpeg2_slice()
{ {
if (g_BP.BP & 7) g_BP.BP += 8 - (g_BP.BP & 7); if (g_BP.BP & 7) g_BP.BP += 8 - (g_BP.BP & 7);
ipuRegs->ctrl.SCD = 1; ipuRegs.ctrl.SCD = 1;
} }
case 5: case 5:
if (!getBits32((u8*)&ipuRegs->top, 0)) if (!getBits32((u8*)&ipuRegs.top, 0))
{ {
ipu_cmd.pos[0] = 5; ipu_cmd.pos[0] = 5;
return false; return false;
} }
BigEndian(ipuRegs->top, ipuRegs->top); BigEndian(ipuRegs.top, ipuRegs.top);
decoder.bitstream_bits = 0; decoder.bitstream_bits = 0;
break; break;
} }

View File

@ -468,7 +468,7 @@ void __fastcall iopMemWrite32(u32 mem, u32 value)
// wtf? why were we writing to the EE's sif space? Commenting this out doesn't // 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 // break any of my games, and should be more correct, but I guess we'll see. --air
//*(u32*)(eeMem->HW+0xf200+(mem&0xf0)) = value; //*(u32*)(eeHw+0xf200+(mem&0xf0)) = value;
return; return;
} }
else if (t == 0x1000) else if (t == 0x1000)

View File

@ -137,6 +137,60 @@
<Add library="$(SvnRootDir)/deps/release/libUtilities.a" /> <Add library="$(SvnRootDir)/deps/release/libUtilities.a" />
</Linker> </Linker>
</Target> </Target>
<Target title="Devel-Debug">
<Option platforms="Windows;Unix;" />
<Option output="$(SvnRootDir)/bin/pcsx2-deb" prefix_auto="1" extension_auto="1" />
<Option working_dir="$(SvnRootDir)/bin/" />
<Option object_output="./.objs/devel" />
<Option external_deps="../../tools/bin/bin2cpp;" />
<Option type="0" />
<Option compiler="gcc" />
<Compiler>
<Add option="-fdefer-pop" />
<Add option="-fcprop-registers" />
<Add option="-fif-conversion" />
<Add option="-fif-conversion2" />
<Add option="-ftree-ccp" />
<Add option="-ftree-dce" />
<Add option="-ftree-dominator-opts" />
<Add option="-ftree-ter" />
<Add option="-ftree-lrs" />
<Add option="-ftree-sra" />
<Add option="-ftree-copyrename" />
<Add option="-ftree-fre" />
<Add option="-ftree-ch" />
<Add option="-funit-at-a-time" />
<Add option="-fmerge-constants" />
<Add option="-fthread-jumps" />
<Add option="-fcrossjumping" />
<Add option="-foptimize-sibling-calls" />
<Add option="-fcse-follow-jumps" />
<Add option="-fcse-skip-blocks" />
<Add option="-fgcse -fgcse-lm" />
<Add option="-frerun-cse-after-loop" />
<Add option="-fcaller-saves" />
<Add option="-fpeephole2" />
<Add option="-fsched-interblock -fsched-spec" />
<Add option="-fregmove" />
<Add option="-fstrict-overflow" />
<Add option="-fdelete-null-pointer-checks" />
<Add option="-freorder-blocks -freorder-functions" />
<Add option="-falign-functions -falign-jumps" />
<Add option="-falign-loops -falign-labels" />
<Add option="-ftree-vrp" />
<Add option="-ftree-pre" />
<Add option="-DPCSX2_DEVBUILD" />
<Add option="-DPCSX2_DEVEL" />
<Add option="-DNDEBUG" />
</Compiler>
<ResourceCompiler>
<Add directory="$(ProjectRootDir)/gui" />
</ResourceCompiler>
<Linker>
<Add library="$(SvnRootDir)/deps/devel/libx86emitter.a" />
<Add library="$(SvnRootDir)/deps/devel/libUtilities.a" />
</Linker>
</Target>
<Environment> <Environment>
<Variable name="SvnRootDir" value="../../" /> <Variable name="SvnRootDir" value="../../" />
<Variable name="ProjectRootDir" value='&quot;$(SvnRootDir)/pcsx2/&quot;' /> <Variable name="ProjectRootDir" value='&quot;$(SvnRootDir)/pcsx2/&quot;' />
@ -240,6 +294,8 @@
<Unit filename="../IPU/IPU.h" /> <Unit filename="../IPU/IPU.h" />
<Unit filename="../IPU/IPU_Fifo.cpp" /> <Unit filename="../IPU/IPU_Fifo.cpp" />
<Unit filename="../IPU/IPU_Fifo.h" /> <Unit filename="../IPU/IPU_Fifo.h" />
<Unit filename="../IPU/IPUdma.cpp" />
<Unit filename="../IPU/IPUdma.h" />
<Unit filename="../IPU/mpeg2lib/Idct.cpp" /> <Unit filename="../IPU/mpeg2lib/Idct.cpp" />
<Unit filename="../IPU/mpeg2lib/Mpeg.cpp" /> <Unit filename="../IPU/mpeg2lib/Mpeg.cpp" />
<Unit filename="../IPU/mpeg2lib/Mpeg.h" /> <Unit filename="../IPU/mpeg2lib/Mpeg.h" />
@ -522,9 +578,11 @@
<Unit filename="../ps2/BiosTools.cpp" /> <Unit filename="../ps2/BiosTools.cpp" />
<Unit filename="../ps2/BiosTools.h" /> <Unit filename="../ps2/BiosTools.h" />
<Unit filename="../ps2/GIFpath.cpp" /> <Unit filename="../ps2/GIFpath.cpp" />
<Unit filename="../ps2/HwInternal.h" />
<Unit filename="../ps2/Iop/IopHwRead.cpp" /> <Unit filename="../ps2/Iop/IopHwRead.cpp" />
<Unit filename="../ps2/Iop/IopHwWrite.cpp" /> <Unit filename="../ps2/Iop/IopHwWrite.cpp" />
<Unit filename="../ps2/Iop/IopHw_Internal.h" /> <Unit filename="../ps2/Iop/IopHw_Internal.h" />
<Unit filename="../ps2/LegacyDmac.cpp" />
<Unit filename="../vtlb.cpp" /> <Unit filename="../vtlb.cpp" />
<Unit filename="../vtlb.h" /> <Unit filename="../vtlb.h" />
<Unit filename="../x86/BaseblockEx.cpp" /> <Unit filename="../x86/BaseblockEx.cpp" />

View File

@ -171,14 +171,11 @@ void PLZCW() {
_PLZCW (1); _PLZCW (1);
} }
__fi void PMFHL_CLAMP(u16 dst, u16 src) __fi void PMFHL_CLAMP(u16& dst, s32 src)
{ {
if ((int)src > (int)0x00007fff) if (src > 0x7fff) dst = 0x7fff;
dst = 0x7fff; else if (src < -0x8000) dst = 0x8000;
else if ((int)src < (int)0xffff8000) // Ints only go up to 0x7FFFFFFF. Something's not right here. --arcum42 else dst = (u16)src;
dst = 0x8000;
else
dst = (u16)src;
} }
void PMFHL() { void PMFHL() {

View File

@ -35,15 +35,14 @@ BIOS
*/ */
#include "PrecompiledHeader.h" #include "PrecompiledHeader.h"
#include "IopCommon.h"
#pragma warning(disable:4799) // No EMMS at end of function
#include <wx/file.h> #include <wx/file.h>
#include "IopCommon.h"
#include "VUmicro.h" #include "VUmicro.h"
#include "GS.h" #include "GS.h"
#include "System/PageFaultSource.h" #include "System/PageFaultSource.h"
#include "ps2/HwInternal.h"
#include "ps2/BiosTools.h" #include "ps2/BiosTools.h"
#ifdef ENABLECACHE #ifdef ENABLECACHE
@ -154,7 +153,6 @@ void memMapPhy()
vtlb_MapBlock(psxM,0x1c000000,0x00800000); vtlb_MapBlock(psxM,0x1c000000,0x00800000);
// Generic Handlers; These fallback to mem* stuff... // Generic Handlers; These fallback to mem* stuff...
vtlb_MapHandler(tlb_fallback_1,0x10000000,0x10000);
vtlb_MapHandler(tlb_fallback_7,0x14000000,0x10000); vtlb_MapHandler(tlb_fallback_7,0x14000000,0x10000);
vtlb_MapHandler(tlb_fallback_4,0x18000000,0x10000); vtlb_MapHandler(tlb_fallback_4,0x18000000,0x10000);
vtlb_MapHandler(tlb_fallback_5,0x1a000000,0x10000); vtlb_MapHandler(tlb_fallback_5,0x1a000000,0x10000);
@ -166,17 +164,9 @@ void memMapPhy()
// Hardware Register Handlers : specialized/optimized per-page handling of HW register accesses // Hardware Register Handlers : specialized/optimized per-page handling of HW register accesses
// (note that hw_by_page handles are assigned in memReset prior to calling this function) // (note that hw_by_page handles are assigned in memReset prior to calling this function)
vtlb_MapHandler(hw_by_page[0x0], 0x10000000, 0x01000);
vtlb_MapHandler(hw_by_page[0x1], 0x10001000, 0x01000); for( uint i=0; i<16; ++i)
vtlb_MapHandler(hw_by_page[0x2], 0x10002000, 0x01000); vtlb_MapHandler(hw_by_page[i], 0x10000000 + (0x01000 * i), 0x01000);
vtlb_MapHandler(hw_by_page[0x3], 0x10003000, 0x01000);
vtlb_MapHandler(hw_by_page[0x4], 0x10004000, 0x01000);
vtlb_MapHandler(hw_by_page[0x5], 0x10005000, 0x01000);
vtlb_MapHandler(hw_by_page[0x6], 0x10006000, 0x01000);
vtlb_MapHandler(hw_by_page[0x7], 0x10007000, 0x01000);
vtlb_MapHandler(hw_by_page[0xb], 0x1000b000, 0x01000);
vtlb_MapHandler(hw_by_page[0xe], 0x1000e000, 0x01000);
vtlb_MapHandler(hw_by_page[0xf], 0x1000f000, 0x01000);
vtlb_MapHandler(gs_page_0, 0x12000000, 0x01000); vtlb_MapHandler(gs_page_0, 0x12000000, 0x01000);
vtlb_MapHandler(gs_page_1, 0x12001000, 0x01000); vtlb_MapHandler(gs_page_1, 0x12001000, 0x01000);
@ -256,8 +246,6 @@ static mem8_t __fastcall _ext_memRead8 (u32 mem)
{ {
switch (p) switch (p)
{ {
case 1: // hwm
return hwRead8(mem);
case 3: // psh4 case 3: // psh4
return psxHw4Read8(mem); return psxHw4Read8(mem);
case 6: // gsm case 6: // gsm
@ -280,8 +268,6 @@ static mem16_t __fastcall _ext_memRead16(u32 mem)
{ {
switch (p) switch (p)
{ {
case 1: // hwm
return hwRead16(mem);
case 4: // b80 case 4: // b80
MEM_LOG("b800000 Memory read16 address %x", mem); MEM_LOG("b800000 Memory read16 address %x", mem);
return 0; return 0;
@ -358,9 +344,6 @@ template<int p>
static void __fastcall _ext_memWrite8 (u32 mem, mem8_t value) static void __fastcall _ext_memWrite8 (u32 mem, mem8_t value)
{ {
switch (p) { switch (p) {
case 1: // hwm
hwWrite8(mem, value);
return;
case 3: // psh4 case 3: // psh4
psxHw4Write8(mem, value); return; psxHw4Write8(mem, value); return;
case 6: // gsm case 6: // gsm
@ -379,9 +362,6 @@ template<int p>
static void __fastcall _ext_memWrite16(u32 mem, mem16_t value) static void __fastcall _ext_memWrite16(u32 mem, mem16_t value)
{ {
switch (p) { switch (p) {
case 1: // hwm
hwWrite16(mem, value);
return;
case 5: // ba0 case 5: // ba0
MEM_LOG("ba00000 Memory write16 to address %x with data %x", mem, value); MEM_LOG("ba00000 Memory write16 to address %x with data %x", mem, value);
return; return;
@ -602,10 +582,12 @@ protected:
void OnPageFaultEvent( const PageFaultInfo& info, bool& handled ); void OnPageFaultEvent( const PageFaultInfo& info, bool& handled );
}; };
mmap_PageFaultHandler mmap_faultHandler; static mmap_PageFaultHandler mmap_faultHandler;
EEVM_MemoryAllocMess* eeMem = NULL; EEVM_MemoryAllocMess* eeMem = NULL;
__pagealigned u8 eeHw[Ps2MemSize::Hardware];
void memAlloc() void memAlloc()
{ {
if( eeMem == NULL ) if( eeMem == NULL )
@ -630,13 +612,28 @@ void memBindConditionalHandlers()
{ {
if( hw_by_page[0xf] == -1 ) return; if( hw_by_page[0xf] == -1 ) return;
vtlbMemR32FP* page0F32( EmuConfig.Speedhacks.IntcStat ? hwRead32_page_0F_INTC_HACK : hwRead32_page_0F ); if (EmuConfig.Speedhacks.IntcStat)
vtlbMemR64FP* page0F64( EmuConfig.Speedhacks.IntcStat ? hwRead64_generic_INTC_HACK : hwRead64_generic ); {
vtlbMemR16FP* page0F16(hwRead16_page_0F_INTC_HACK);
vtlbMemR32FP* page0F32(hwRead32_page_0F_INTC_HACK);
//vtlbMemR64FP* page0F64(hwRead64_generic_INTC_HACK);
vtlb_ReassignHandler( hw_by_page[0xf], vtlb_ReassignHandler( hw_by_page[0xf],
_ext_memRead8<1>, _ext_memRead16<1>, page0F32, page0F64, hwRead128_generic, hwRead8<0x0f>, page0F16, page0F32, hwRead64<0x0f>, hwRead128<0x0f>,
_ext_memWrite8<1>, _ext_memWrite16<1>, hwWrite32_page_0F, hwWrite64_generic, hwWrite128_generic hwWrite8<0x0f>, hwWrite16<0x0f>, hwWrite32<0x0f>, hwWrite64<0x0f>, hwWrite128<0x0f>
); );
}
else
{
vtlbMemR16FP* page0F16(hwRead16<0x0f>);
vtlbMemR32FP* page0F32(hwRead32<0x0f>);
//vtlbMemR64FP* page0F64(hwRead64<0x0f>);
vtlb_ReassignHandler( hw_by_page[0xf],
hwRead8<0x0f>, page0F16, page0F32, hwRead64<0x0f>, hwRead128<0x0f>,
hwWrite8<0x0f>, hwWrite16<0x0f>, hwWrite32<0x0f>, hwWrite64<0x0f>, hwWrite128<0x0f>
);
}
} }
// Resets memory mappings, unmaps TLBs, reloads bios roms, etc. // Resets memory mappings, unmaps TLBs, reloads bios roms, etc.
@ -664,7 +661,6 @@ void memReset()
tlb_fallback_3 = vtlb_RegisterHandlerTempl1(_ext_mem,3); tlb_fallback_3 = vtlb_RegisterHandlerTempl1(_ext_mem,3);
tlb_fallback_4 = vtlb_RegisterHandlerTempl1(_ext_mem,4); tlb_fallback_4 = vtlb_RegisterHandlerTempl1(_ext_mem,4);
tlb_fallback_5 = vtlb_RegisterHandlerTempl1(_ext_mem,5); tlb_fallback_5 = vtlb_RegisterHandlerTempl1(_ext_mem,5);
//tlb_fallback_6 = vtlb_RegisterHandlerTempl1(_ext_mem,6);
tlb_fallback_7 = vtlb_RegisterHandlerTempl1(_ext_mem,7); tlb_fallback_7 = vtlb_RegisterHandlerTempl1(_ext_mem,7);
tlb_fallback_8 = vtlb_RegisterHandlerTempl1(_ext_mem,8); tlb_fallback_8 = vtlb_RegisterHandlerTempl1(_ext_mem,8);
@ -701,68 +697,29 @@ void memReset()
); );
//////////////////////////////////////////////////////////////////////////////////////////
// psHw Optimized Mappings // psHw Optimized Mappings
// The HW Registers have been split into pages to improve optimization. // The HW Registers have been split into pages to improve optimization.
// Anything not explicitly mapped into one of the hw_by_page handlers will be handled
// by the default/generic tlb_fallback_1 handler.
tlb_fallback_1 = vtlb_RegisterHandler( #define hwHandlerTmpl(page) \
_ext_memRead8<1>, _ext_memRead16<1>, hwRead32_generic, hwRead64_generic, hwRead128_generic, hwRead8<page>, hwRead16<page>, hwRead32<page>, hwRead64<page>, hwRead128<page>, \
_ext_memWrite8<1>, _ext_memWrite16<1>, hwWrite32_generic, hwWrite64_generic, hwWrite128_generic hwWrite8<page>, hwWrite16<page>,hwWrite32<page>,hwWrite64<page>,hwWrite128<page>
);
hw_by_page[0x0] = vtlb_RegisterHandler( hw_by_page[0x0] = vtlb_RegisterHandler( hwHandlerTmpl(0x00) );
_ext_memRead8<1>, _ext_memRead16<1>, hwRead32_page_00, hwRead64_page_00, hwRead128_page_00, hw_by_page[0x1] = vtlb_RegisterHandler( hwHandlerTmpl(0x01) );
_ext_memWrite8<1>, _ext_memWrite16<1>, hwWrite32_page_00, hwWrite64_page_00, hwWrite128_generic hw_by_page[0x2] = vtlb_RegisterHandler( hwHandlerTmpl(0x02) );
); hw_by_page[0x3] = vtlb_RegisterHandler( hwHandlerTmpl(0x03) );
hw_by_page[0x4] = vtlb_RegisterHandler( hwHandlerTmpl(0x04) );
hw_by_page[0x1] = vtlb_RegisterHandler( hw_by_page[0x5] = vtlb_RegisterHandler( hwHandlerTmpl(0x05) );
_ext_memRead8<1>, _ext_memRead16<1>, hwRead32_page_01, hwRead64_page_01, hwRead128_page_01, hw_by_page[0x6] = vtlb_RegisterHandler( hwHandlerTmpl(0x06) );
_ext_memWrite8<1>, _ext_memWrite16<1>, hwWrite32_page_01, hwWrite64_page_01, hwWrite128_generic hw_by_page[0x7] = vtlb_RegisterHandler( hwHandlerTmpl(0x07) );
); hw_by_page[0x8] = vtlb_RegisterHandler( hwHandlerTmpl(0x08) );
hw_by_page[0x9] = vtlb_RegisterHandler( hwHandlerTmpl(0x09) );
hw_by_page[0x2] = vtlb_RegisterHandler( hw_by_page[0xa] = vtlb_RegisterHandler( hwHandlerTmpl(0x0a) );
_ext_memRead8<1>, _ext_memRead16<1>, hwRead32_page_02, hwRead64_page_02, hwRead128_page_02, hw_by_page[0xb] = vtlb_RegisterHandler( hwHandlerTmpl(0x0b) );
_ext_memWrite8<1>, _ext_memWrite16<1>, hwWrite32_page_02, hwWrite64_page_02, hwWrite128_generic hw_by_page[0xc] = vtlb_RegisterHandler( hwHandlerTmpl(0x0c) );
); hw_by_page[0xd] = vtlb_RegisterHandler( hwHandlerTmpl(0x0d) );
hw_by_page[0xe] = vtlb_RegisterHandler( hwHandlerTmpl(0x0e) );
hw_by_page[0x3] = vtlb_RegisterHandler( hw_by_page[0xf] = vtlb_NewHandler(); // redefined later based on speedhacking prefs
_ext_memRead8<1>, _ext_memRead16<1>, hwRead32_generic, hwRead64_generic, hwRead128_generic,
_ext_memWrite8<1>, _ext_memWrite16<1>, hwWrite32_page_03, hwWrite64_page_03, hwWrite128_generic
);
hw_by_page[0x4] = vtlb_RegisterHandler(
_ext_memRead8<1>, _ext_memRead16<1>, hwRead32_generic, hwRead64_generic, ReadFIFO_page_4,
_ext_memWrite8<1>, _ext_memWrite16<1>, hwWrite32_generic, hwWrite64_generic, WriteFIFO_page_4
);
hw_by_page[0x5] = vtlb_RegisterHandler(
_ext_memRead8<1>, _ext_memRead16<1>, hwRead32_generic, hwRead64_generic, ReadFIFO_page_5,
_ext_memWrite8<1>, _ext_memWrite16<1>, hwWrite32_generic, hwWrite64_generic, WriteFIFO_page_5
);
hw_by_page[0x6] = vtlb_RegisterHandler(
_ext_memRead8<1>, _ext_memRead16<1>, hwRead32_generic, hwRead64_generic, ReadFIFO_page_6,
_ext_memWrite8<1>, _ext_memWrite16<1>, hwWrite32_generic, hwWrite64_generic, WriteFIFO_page_6
);
hw_by_page[0x7] = vtlb_RegisterHandler(
_ext_memRead8<1>, _ext_memRead16<1>, hwRead32_generic, hwRead64_generic, ReadFIFO_page_7,
_ext_memWrite8<1>, _ext_memWrite16<1>, hwWrite32_generic, hwWrite64_generic, WriteFIFO_page_7
);
hw_by_page[0xb] = vtlb_RegisterHandler(
_ext_memRead8<1>, _ext_memRead16<1>, hwRead32_generic, hwRead64_generic, hwRead128_generic,
_ext_memWrite8<1>, _ext_memWrite16<1>, hwWrite32_page_0B, hwWrite64_generic, hwWrite128_generic
);
hw_by_page[0xe] = vtlb_RegisterHandler(
_ext_memRead8<1>, _ext_memRead16<1>, hwRead32_generic, hwRead64_generic, hwRead128_generic,
_ext_memWrite8<1>, _ext_memWrite16<1>, hwWrite32_page_0E, hwWrite64_page_0E, hwWrite128_generic
);
hw_by_page[0xf] = vtlb_NewHandler();
memBindConditionalHandlers(); memBindConditionalHandlers();
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////

View File

@ -34,33 +34,22 @@ static __fi void ZeroQWC( void* dest )
_mm_store_ps( (float*)dest, _mm_setzero_ps() ); _mm_store_ps( (float*)dest, _mm_setzero_ps() );
} }
// Various useful locations static __fi void ZeroQWC( u128& dest )
#define spr0 ((DMACh*)&eeMem->HW[0xD000]) {
#define spr1 ((DMACh*)&eeMem->HW[0xD400]) _mm_store_ps( (float*)&dest, _mm_setzero_ps() );
}
#define gif ((DMACh*)&eeMem->HW[0xA000])
#define vif0ch ((DMACh*)&eeMem->HW[0x8000])
#define vif1ch ((DMACh*)&eeMem->HW[0x9000])
#define sif0dma ((DMACh*)&eeMem->HW[0xc000])
#define sif1dma ((DMACh*)&eeMem->HW[0xc400])
#define sif2dma ((DMACh*)&eeMem->HW[0xc800])
#define ipu0dma ((DMACh *)&eeMem->HW[0xb000])
#define ipu1dma ((DMACh *)&eeMem->HW[0xb400])
#define PSM(mem) (vtlb_GetPhyPtr((mem)&0x1fffffff)) //pcsx2 is a competition.The one with most hacks wins :D #define PSM(mem) (vtlb_GetPhyPtr((mem)&0x1fffffff)) //pcsx2 is a competition.The one with most hacks wins :D
#define psHs8(mem) (*(s8 *)&eeMem->HW[(mem) & 0xffff]) #define psHs8(mem) (*(s8 *)&eeHw[(mem) & 0xffff])
#define psHs16(mem) (*(s16*)&eeMem->HW[(mem) & 0xffff]) #define psHs16(mem) (*(s16*)&eeHw[(mem) & 0xffff])
#define psHs32(mem) (*(s32*)&eeMem->HW[(mem) & 0xffff]) #define psHs32(mem) (*(s32*)&eeHw[(mem) & 0xffff])
#define psHs64(mem) (*(s64*)&eeMem->HW[(mem) & 0xffff]) #define psHs64(mem) (*(s64*)&eeHw[(mem) & 0xffff])
#define psHu8(mem) (*(u8 *)&eeMem->HW[(mem) & 0xffff]) #define psHu8(mem) (*(u8 *)&eeHw[(mem) & 0xffff])
#define psHu16(mem) (*(u16*)&eeMem->HW[(mem) & 0xffff]) #define psHu16(mem) (*(u16*)&eeHw[(mem) & 0xffff])
#define psHu32(mem) (*(u32*)&eeMem->HW[(mem) & 0xffff]) #define psHu32(mem) (*(u32*)&eeHw[(mem) & 0xffff])
#define psHu64(mem) (*(u64*)&eeMem->HW[(mem) & 0xffff]) #define psHu64(mem) (*(u64*)&eeHw[(mem) & 0xffff])
#define psHu128(mem)(*(u128*)&eeMem->HW[(mem) & 0xffff]) #define psHu128(mem)(*(u128*)&eeHw[(mem) & 0xffff])
#define psMs8(mem) (*(s8 *)&eeMem->Main[(mem) & 0x1ffffff]) #define psMs8(mem) (*(s8 *)&eeMem->Main[(mem) & 0x1ffffff])
#define psMs16(mem) (*(s16*)&eeMem->Main[(mem) & 0x1ffffff]) #define psMs16(mem) (*(s16*)&eeMem->Main[(mem) & 0x1ffffff])
@ -114,8 +103,6 @@ static __fi void ZeroQWC( void* dest )
#define psSu64(mem) (*(u64 *)&eeMem->Scratch[(mem) & 0x3fff]) #define psSu64(mem) (*(u64 *)&eeMem->Scratch[(mem) & 0x3fff])
#define psSu128(mem) (*(u128*)&eeMem->Scratch[(mem) & 0x3fff]) #define psSu128(mem) (*(u128*)&eeMem->Scratch[(mem) & 0x3fff])
#define psH_DMACh(mem) (*(DMACh*)&eeMem->HW[(mem) & 0xffff])
extern void memAlloc(); extern void memAlloc();
extern void memReset(); // clears PS2 ram and loads the bios. Throws Exception::FileNotFound on error. extern void memReset(); // clears PS2 ram and loads the bios. Throws Exception::FileNotFound on error.
extern void memShutdown(); extern void memShutdown();
@ -135,13 +122,21 @@ extern void mmap_ResetBlockTracking();
#define memRead8 vtlb_memRead<mem8_t> #define memRead8 vtlb_memRead<mem8_t>
#define memRead16 vtlb_memRead<mem16_t> #define memRead16 vtlb_memRead<mem16_t>
#define memRead32 vtlb_memRead<mem32_t> #define memRead32 vtlb_memRead<mem32_t>
#define memRead64 vtlb_memRead64
#define memRead128 vtlb_memRead128
#define memWrite8 vtlb_memWrite<mem8_t> #define memWrite8 vtlb_memWrite<mem8_t>
#define memWrite16 vtlb_memWrite<mem16_t> #define memWrite16 vtlb_memWrite<mem16_t>
#define memWrite32 vtlb_memWrite<mem32_t> #define memWrite32 vtlb_memWrite<mem32_t>
#define memWrite64 vtlb_memWrite64
#define memWrite128 vtlb_memWrite128 static __fi void memRead64(u32 mem, mem64_t* out) { vtlb_memRead64(mem, out); }
static __fi void memRead64(u32 mem, mem64_t& out) { vtlb_memRead64(mem, &out); }
static __fi void memRead128(u32 mem, mem128_t* out) { vtlb_memRead128(mem, out); }
static __fi void memRead128(u32 mem, mem128_t& out) { vtlb_memRead128(mem, &out); }
static __fi void memWrite64(u32 mem, const mem64_t* val) { vtlb_memWrite64(mem, val); }
static __fi void memWrite64(u32 mem, const mem64_t& val) { vtlb_memWrite64(mem, &val); }
static __fi void memWrite128(u32 mem, const mem128_t* val) { vtlb_memWrite128(mem, val); }
static __fi void memWrite128(u32 mem, const mem128_t& val) { vtlb_memWrite128(mem, &val); }
extern u16 ba0R16(u32 mem); extern u16 ba0R16(u32 mem);

View File

@ -37,15 +37,55 @@ typedef u32 mem32_t;
typedef u64 mem64_t; typedef u64 mem64_t;
typedef u128 mem128_t; typedef u128 mem128_t;
// --------------------------------------------------------------------------------------
// Future-Planned VTLB pagefault scheme!
// --------------------------------------------------------------------------------------
// When enabled, the VTLB will use a large-area reserved memory range of 512megs for EE
// physical ram/rom access. The base ram will be committed at 0x00000000, and ROMs will be
// at 0x1fc00000, etc. All memory ranges in between will be uncommitted memory -- which
// means that the memory will *not* count against the operating system's physical memory
// pool.
//
// When the VTLB generates memory operations (loads/stores), it will assume that the op
// is addressing either RAM or ROM, and by assuming that it can generate a completely efficient
// direct memory access (one AND and one MOV instruction). If the access is to another area of
// memory, such as hardware registers or scratchpad, the access will generate a page fault, the
// compiled block will be cleared and re-compiled using "full" VTLB translation logic.
//
#define VTLB_UsePageFaulting 0
#if VTLB_UsePageFaulting
// The order of the components in this struct *matter* -- it has been laid out so that the
// full breadth of PS2 RAM and ROM mappings are directly supported.
struct EEVM_MemoryAllocMess
{
u8 (&Main)[Ps2MemSize::Base]; // Main memory (hard-wired to 32MB)
u8 _padding1[0x1e000000-Ps2MemSize::Base]
u8 (&ROM1)[Ps2MemSize::Rom1]; // DVD player
u8 _padding2[0x1e040000-(0x1e000000+Ps2MemSize::Rom1)]
u8 (&EROM)[Ps2MemSize::ERom]; // DVD player extensions
u8 _padding3[0x1e400000-(0x1e040000+Ps2MemSize::EROM)]
u8 (&ROM2)[Ps2MemSize::Rom2]; // Chinese extensions
u8 _padding4[0x1fc00000-(0x1e040000+Ps2MemSize::Rom2)];
u8 (&ROM)[Ps2MemSize::Rom]; // Boot rom (4MB)
};
#else
struct EEVM_MemoryAllocMess struct EEVM_MemoryAllocMess
{ {
u8 Scratch[Ps2MemSize::Scratch]; // Scratchpad! u8 Scratch[Ps2MemSize::Scratch]; // Scratchpad!
u8 Main[Ps2MemSize::Base]; // Main memory (hard-wired to 32MB) u8 Main[Ps2MemSize::Base]; // Main memory (hard-wired to 32MB)
u8 HW[Ps2MemSize::Hardware]; // Hardware registers
u8 ROM[Ps2MemSize::Rom]; // Boot rom (4MB) u8 ROM[Ps2MemSize::Rom]; // Boot rom (4MB)
u8 ROM1[Ps2MemSize::Rom1]; // DVD player u8 ROM1[Ps2MemSize::Rom1]; // DVD player
u8 ROM2[Ps2MemSize::Rom2]; // Chinese extensions (?) u8 ROM2[Ps2MemSize::Rom2]; // Chinese extensions
u8 EROM[Ps2MemSize::ERom]; // DVD player extensions (?) u8 EROM[Ps2MemSize::ERom]; // DVD player extensions
// Two 1 megabyte (max DMA) buffers for reading and writing to high memory (>32MB). // Two 1 megabyte (max DMA) buffers for reading and writing to high memory (>32MB).
// Such accesses are not documented as causing bus errors but as the memory does // Such accesses are not documented as causing bus errors but as the memory does
@ -56,4 +96,13 @@ struct EEVM_MemoryAllocMess
u8 ZeroWrite[_1mb]; u8 ZeroWrite[_1mb];
}; };
#endif
// EE Hardware registers.
// DevNote: These are done as a static array instead of a pointer in order to allow for simpler
// macros and reference handles to be defined (we can safely use compile-time references to
// registers instead of having to use instance variables).
extern __pagealigned u8 eeHw[Ps2MemSize::Hardware];
extern EEVM_MemoryAllocMess* eeMem; extern EEVM_MemoryAllocMess* eeMem;

View File

@ -78,6 +78,7 @@ typedef int BOOL;
#define TRUE 1 #define TRUE 1
#define FALSE 0 #define FALSE 0
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
// Begin Pcsx2 Includes: Add items here that are local to Pcsx2 but stay relatively // Begin Pcsx2 Includes: Add items here that are local to Pcsx2 but stay relatively
// unchanged for long periods of time, or happen to be used by almost everything, so they // unchanged for long periods of time, or happen to be used by almost everything, so they
@ -100,15 +101,24 @@ typedef int BOOL;
#include "Config.h" #include "Config.h"
typedef void FnType_Void();
typedef FnType_Void* Fnptr_Void;
static const s64 _1mb = 0x100000;
static const s64 _8mb = _1mb * 8;
static const s64 _16mb = _1mb * 16;
static const s64 _256mb = _1mb * 256;
static const s64 _1gb = _256mb * 4;
//////////////////////////////////////////////////////////////////////////////////////////
// Compiler/OS specific macros and defines -- Begin Section
// Linux isn't set up for svn version numbers yet. // Linux isn't set up for svn version numbers yet.
#ifdef __LINUX__ #ifdef __LINUX__
# define SVN_REV 0 # define SVN_REV 0
# define SVN_MODS 0 # define SVN_MODS 0
#endif #endif
//////////////////////////////////////////////////////////////////////////////////////////
// Compiler/OS specific macros and defines -- Begin Section
#if defined(_MSC_VER) #if defined(_MSC_VER)
# define strnicmp _strnicmp # define strnicmp _strnicmp

View File

@ -26,6 +26,7 @@
#include "R5900Exceptions.h" #include "R5900Exceptions.h"
#include "Hardware.h" #include "Hardware.h"
#include "IPU/IPUdma.h"
#include "Elfheader.h" #include "Elfheader.h"
#include "CDVD/CDVD.h" #include "CDVD/CDVD.h"
@ -287,9 +288,11 @@ static __fi void TESTINT( u8 n, void (*callback)() )
cpuSetNextBranch( cpuRegs.sCycle[n], cpuRegs.eCycle[n] ); cpuSetNextBranch( cpuRegs.sCycle[n], cpuRegs.eCycle[n] );
} }
// [TODO] move this function to LegacyDmac.cpp, and remove most of the DMAC-related headers from
// being included into R5900.cpp.
static __fi void _cpuTestInterrupts() static __fi void _cpuTestInterrupts()
{ {
if (!dmacRegs->ctrl.DMAE || psHu8(DMAC_ENABLER+2) == 1) if (!dmacRegs.ctrl.DMAE || (psHu8(DMAC_ENABLER+2) & 1))
{ {
//Console.Write("DMAC Disabled or suspended"); //Console.Write("DMAC Disabled or suspended");
return; return;
@ -415,7 +418,7 @@ __fi void _cpuBranchTest_Shared()
//if( EEsCycle < -450 ) //if( EEsCycle < -450 )
// Console.WriteLn( " IOP ahead by: %d cycles", -EEsCycle ); // Console.WriteLn( " IOP ahead by: %d cycles", -EEsCycle );
// Experimental and Probably Unnecessry Logic --> // Experimental and Probably Unnecessary Logic -->
// Check if the EE already has an exception pending, and if so we shouldn't // Check if the EE already has an exception pending, and if so we shouldn't
// waste too much time updating the IOP. Theory being that the EE and IOP should // waste too much time updating the IOP. Theory being that the EE and IOP should
// run closely in sync during raised exception events. But in practice it didn't // run closely in sync during raised exception events. But in practice it didn't
@ -502,11 +505,8 @@ __ri void cpuTestINTCInts()
cpuRegs.sCycle[30] = cpuRegs.cycle; cpuRegs.sCycle[30] = cpuRegs.cycle;
cpuRegs.eCycle[30] = 4; //Needs to be 4 to account for bus delays/pipelines etc cpuRegs.eCycle[30] = 4; //Needs to be 4 to account for bus delays/pipelines etc
// only set the next branch delta if the exception won't be handled for
// the current branch...
if( !eeEventTestIsActive )
cpuSetNextBranchDelta( 4 ); cpuSetNextBranchDelta( 4 );
else if(psxCycleEE > 0) if(eeEventTestIsActive && (psxCycleEE > 0))
{ {
psxBreak += psxCycleEE; // record the number of cycles the IOP didn't run. psxBreak += psxCycleEE; // record the number of cycles the IOP didn't run.
psxCycleEE = 0; psxCycleEE = 0;
@ -529,11 +529,8 @@ __fi void cpuTestDMACInts()
cpuRegs.sCycle[31] = cpuRegs.cycle; cpuRegs.sCycle[31] = cpuRegs.cycle;
cpuRegs.eCycle[31] = 4; //Needs to be 4 to account for bus delays/pipelines etc cpuRegs.eCycle[31] = 4; //Needs to be 4 to account for bus delays/pipelines etc
// only set the next branch delta if the exception won't be handled for
// the current branch...
if( !eeEventTestIsActive )
cpuSetNextBranchDelta( 4 ); cpuSetNextBranchDelta( 4 );
else if(psxCycleEE > 0) if(eeEventTestIsActive && (psxCycleEE > 0))
{ {
psxBreak += psxCycleEE; // record the number of cycles the IOP didn't run. psxBreak += psxCycleEE; // record the number of cycles the IOP didn't run.
psxCycleEE = 0; psxCycleEE = 0;

View File

@ -816,7 +816,7 @@ void SQ()
// an address error due to unaligned access isn't possible like it is on other loads/stores. // an address error due to unaligned access isn't possible like it is on other loads/stores.
u32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; u32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_;
memWrite128(addr & ~0xf, cpuRegs.GPR.r[_Rt_].UD); memWrite128(addr & ~0xf, cpuRegs.GPR.r[_Rt_].UQ);
} }
/********************************************************* /*********************************************************
@ -868,8 +868,7 @@ void SYSCALL()
} }
// The only thing this code is used for is the one log message, so don't execute it if we aren't logging bios messages. // The only thing this code is used for is the one log message, so don't execute it if we aren't logging bios messages.
#ifdef PCSX2_DEVBUILD if (SysTraceActive(EE.Bios) && (call == 0x77))
if (SysTrace.EE.Bios.IsActive() && (call == 0x77))
{ {
t_sif_dma_transfer *dmat; t_sif_dma_transfer *dmat;
//struct t_sif_cmd_header *hdr; //struct t_sif_cmd_header *hdr;
@ -891,7 +890,6 @@ void SYSCALL()
dmat->dest, dmat->src); dmat->dest, dmat->src);
} }
} }
#endif
cpuRegs.pc -= 4; cpuRegs.pc -= 4;
cpuException(0x20, cpuRegs.branch); cpuException(0x20, cpuRegs.branch);

View File

@ -51,96 +51,96 @@ int _SPR0chain()
{ {
tDMA_TAG *pMem; tDMA_TAG *pMem;
if (spr0->qwc == 0) return 0; if (spr0ch.qwc == 0) return 0;
pMem = SPRdmaGetAddr(spr0->madr, true); pMem = SPRdmaGetAddr(spr0ch.madr, true);
if (pMem == NULL) return -1; if (pMem == NULL) return -1;
switch (dmacRegs->ctrl.MFD) switch (dmacRegs.ctrl.MFD)
{ {
case MFD_VIF1: case MFD_VIF1:
case MFD_GIF: case MFD_GIF:
if ((spr0->madr & ~dmacRegs->rbsr.RMSK) != dmacRegs->rbor.ADDR) if ((spr0ch.madr & ~dmacRegs.rbsr.RMSK) != dmacRegs.rbor.ADDR)
Console.WriteLn("SPR MFIFO Write outside MFIFO area"); Console.WriteLn("SPR MFIFO Write outside MFIFO area");
else else
mfifotransferred += spr0->qwc; mfifotransferred += spr0ch.qwc;
hwMFIFOWrite(spr0->madr, &psSu128(spr0->sadr), spr0->qwc); hwMFIFOWrite(spr0ch.madr, &psSu128(spr0ch.sadr), spr0ch.qwc);
spr0->madr += spr0->qwc << 4; spr0ch.madr += spr0ch.qwc << 4;
spr0->madr = dmacRegs->rbor.ADDR + (spr0->madr & dmacRegs->rbsr.RMSK); spr0ch.madr = dmacRegs.rbor.ADDR + (spr0ch.madr & dmacRegs.rbsr.RMSK);
break; break;
case NO_MFD: case NO_MFD:
case MFD_RESERVED: case MFD_RESERVED:
memcpy_qwc(pMem, &psSu128(spr0->sadr), spr0->qwc); memcpy_qwc(pMem, &psSu128(spr0ch.sadr), spr0ch.qwc);
// clear VU mem also! // clear VU mem also!
TestClearVUs(spr0->madr, spr0->qwc << 2); // Wtf is going on here? AFAIK, only VIF should affect VU micromem (cottonvibes) TestClearVUs(spr0ch.madr, spr0ch.qwc << 2); // Wtf is going on here? AFAIK, only VIF should affect VU micromem (cottonvibes)
spr0->madr += spr0->qwc << 4; spr0ch.madr += spr0ch.qwc << 4;
break; break;
} }
spr0->sadr += spr0->qwc << 4; spr0ch.sadr += spr0ch.qwc << 4;
return (spr0->qwc); // bus is 1/2 the ee speed return (spr0ch.qwc); // bus is 1/2 the ee speed
} }
__fi void SPR0chain() __fi void SPR0chain()
{ {
CPU_INT(DMAC_FROM_SPR, _SPR0chain() / BIAS); CPU_INT(DMAC_FROM_SPR, _SPR0chain() / BIAS);
spr0->qwc = 0; spr0ch.qwc = 0;
} }
void _SPR0interleave() void _SPR0interleave()
{ {
int qwc = spr0->qwc; int qwc = spr0ch.qwc;
int sqwc = dmacRegs->sqwc.SQWC; int sqwc = dmacRegs.sqwc.SQWC;
int tqwc = dmacRegs->sqwc.TQWC; int tqwc = dmacRegs.sqwc.TQWC;
tDMA_TAG *pMem; tDMA_TAG *pMem;
if (tqwc == 0) tqwc = qwc; if (tqwc == 0) tqwc = qwc;
//Console.WriteLn("dmaSPR0 interleave"); //Console.WriteLn("dmaSPR0 interleave");
SPR_LOG("SPR0 interleave size=%d, tqwc=%d, sqwc=%d, addr=%lx sadr=%lx", SPR_LOG("SPR0 interleave size=%d, tqwc=%d, sqwc=%d, addr=%lx sadr=%lx",
spr0->qwc, tqwc, sqwc, spr0->madr, spr0->sadr); spr0ch.qwc, tqwc, sqwc, spr0ch.madr, spr0ch.sadr);
CPU_INT(DMAC_FROM_SPR, qwc / BIAS); CPU_INT(DMAC_FROM_SPR, qwc / BIAS);
while (qwc > 0) while (qwc > 0)
{ {
spr0->qwc = std::min(tqwc, qwc); spr0ch.qwc = std::min(tqwc, qwc);
qwc -= spr0->qwc; qwc -= spr0ch.qwc;
pMem = SPRdmaGetAddr(spr0->madr, true); pMem = SPRdmaGetAddr(spr0ch.madr, true);
switch (dmacRegs->ctrl.MFD) switch (dmacRegs.ctrl.MFD)
{ {
case MFD_VIF1: case MFD_VIF1:
case MFD_GIF: case MFD_GIF:
hwMFIFOWrite(spr0->madr, &psSu128(spr0->sadr), spr0->qwc); hwMFIFOWrite(spr0ch.madr, &psSu128(spr0ch.sadr), spr0ch.qwc);
mfifotransferred += spr0->qwc; mfifotransferred += spr0ch.qwc;
break; break;
case NO_MFD: case NO_MFD:
case MFD_RESERVED: case MFD_RESERVED:
// clear VU mem also! // clear VU mem also!
TestClearVUs(spr0->madr, spr0->qwc << 2); TestClearVUs(spr0ch.madr, spr0ch.qwc << 2);
memcpy_qwc(pMem, &psSu128(spr0->sadr), spr0->qwc); memcpy_qwc(pMem, &psSu128(spr0ch.sadr), spr0ch.qwc);
break; break;
} }
spr0->sadr += spr0->qwc * 16; spr0ch.sadr += spr0ch.qwc * 16;
spr0->madr += (sqwc + spr0->qwc) * 16; spr0ch.madr += (sqwc + spr0ch.qwc) * 16;
} }
spr0->qwc = 0; spr0ch.qwc = 0;
} }
static __fi void _dmaSPR0() static __fi void _dmaSPR0()
{ {
if (dmacRegs->ctrl.STS == STS_fromSPR) if (dmacRegs.ctrl.STS == STS_fromSPR)
{ {
Console.WriteLn("SPR0 stall %d", dmacRegs->ctrl.STS); Console.WriteLn("SPR0 stall %d", dmacRegs.ctrl.STS);
} }
// Transfer Dn_QWC from SPR to Dn_MADR // Transfer Dn_QWC from SPR to Dn_MADR
switch(spr0->chcr.MOD) switch(spr0ch.chcr.MOD)
{ {
case NORMAL_MODE: case NORMAL_MODE:
{ {
@ -153,23 +153,23 @@ static __fi void _dmaSPR0()
tDMA_TAG *ptag; tDMA_TAG *ptag;
bool done = false; bool done = false;
if (spr0->qwc > 0) if (spr0ch.qwc > 0)
{ {
SPR0chain(); SPR0chain();
return; return;
} }
// Destination Chain Mode // Destination Chain Mode
ptag = (tDMA_TAG*)&psSu32(spr0->sadr); ptag = (tDMA_TAG*)&psSu32(spr0ch.sadr);
spr0->sadr += 16; spr0ch.sadr += 16;
spr0->unsafeTransfer(ptag); spr0ch.unsafeTransfer(ptag);
spr0->madr = ptag[1]._u32; //MADR = ADDR field + SPR spr0ch.madr = ptag[1]._u32; //MADR = ADDR field + SPR
SPR_LOG("spr0 dmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx spr=%lx", SPR_LOG("spr0 dmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx spr=%lx",
ptag[1]._u32, ptag[0]._u32, spr0->qwc, ptag->ID, spr0->madr, spr0->sadr); ptag[1]._u32, ptag[0]._u32, spr0ch.qwc, ptag->ID, spr0ch.madr, spr0ch.sadr);
if (dmacRegs->ctrl.STS == STS_fromSPR) // STS == fromSPR if (dmacRegs.ctrl.STS == STS_fromSPR) // STS == fromSPR
{ {
Console.WriteLn("SPR stall control"); Console.WriteLn("SPR stall control");
} }
@ -177,7 +177,7 @@ static __fi void _dmaSPR0()
switch (ptag->ID) switch (ptag->ID)
{ {
case TAG_CNTS: // CNTS - Transfer QWC following the tag (Stall Control) case TAG_CNTS: // CNTS - Transfer QWC following the tag (Stall Control)
if (dmacRegs->ctrl.STS == STS_fromSPR) dmacRegs->stadr.ADDR = spr0->madr + (spr0->qwc * 16); //Copy MADR to DMAC_STADR stall addr register if (dmacRegs.ctrl.STS == STS_fromSPR) dmacRegs.stadr.ADDR = spr0ch.madr + (spr0ch.qwc * 16); //Copy MADR to DMAC_STADR stall addr register
break; break;
case TAG_CNT: // CNT - Transfer QWC following the tag. case TAG_CNT: // CNT - Transfer QWC following the tag.
@ -191,7 +191,7 @@ static __fi void _dmaSPR0()
SPR0chain(); SPR0chain();
if (spr0->chcr.TIE && ptag->IRQ) //Check TIE bit of CHCR and IRQ bit of tag if (spr0ch.chcr.TIE && ptag->IRQ) //Check TIE bit of CHCR and IRQ bit of tag
{ {
//Console.WriteLn("SPR0 TIE"); //Console.WriteLn("SPR0 TIE");
done = true; done = true;
@ -199,7 +199,7 @@ static __fi void _dmaSPR0()
spr0finished = done; spr0finished = done;
SPR_LOG("spr0 dmaChain complete %8.8x_%8.8x size=%d, id=%d, addr=%lx spr=%lx", SPR_LOG("spr0 dmaChain complete %8.8x_%8.8x size=%d, id=%d, addr=%lx spr=%lx",
ptag[1]._u32, ptag[0]._u32, spr0->qwc, ptag->ID, spr0->madr); ptag[1]._u32, ptag[0]._u32, spr0ch.qwc, ptag->ID, spr0ch.madr);
break; break;
} }
//case INTERLEAVE_MODE: //case INTERLEAVE_MODE:
@ -215,27 +215,27 @@ static __fi void _dmaSPR0()
void SPRFROMinterrupt() void SPRFROMinterrupt()
{ {
if (!spr0finished || spr0->qwc > 0) if (!spr0finished || spr0ch.qwc > 0)
{ {
_dmaSPR0(); _dmaSPR0();
if(mfifotransferred != 0) if(mfifotransferred != 0)
{ {
switch (dmacRegs->ctrl.MFD) switch (dmacRegs.ctrl.MFD)
{ {
case MFD_VIF1: // Most common case. case MFD_VIF1: // Most common case.
{ {
if ((spr0->madr & ~dmacRegs->rbsr.RMSK) != dmacRegs->rbor.ADDR) Console.WriteLn("VIF MFIFO Write outside MFIFO area"); if ((spr0ch.madr & ~dmacRegs.rbsr.RMSK) != dmacRegs.rbor.ADDR) Console.WriteLn("VIF MFIFO Write outside MFIFO area");
spr0->madr = dmacRegs->rbor.ADDR + (spr0->madr & dmacRegs->rbsr.RMSK); spr0ch.madr = dmacRegs.rbor.ADDR + (spr0ch.madr & dmacRegs.rbsr.RMSK);
//Console.WriteLn("mfifoVIF1transfer %x madr %x, tadr %x", vif1ch->chcr._u32, vif1ch->madr, vif1ch->tadr); //Console.WriteLn("mfifoVIF1transfer %x madr %x, tadr %x", vif1ch.chcr._u32, vif1ch.madr, vif1ch.tadr);
mfifoVIF1transfer(mfifotransferred); mfifoVIF1transfer(mfifotransferred);
mfifotransferred = 0; mfifotransferred = 0;
break; break;
} }
case MFD_GIF: case MFD_GIF:
{ {
if ((spr0->madr & ~dmacRegs->rbsr.RMSK) != dmacRegs->rbor.ADDR) Console.WriteLn("GIF MFIFO Write outside MFIFO area"); if ((spr0ch.madr & ~dmacRegs.rbsr.RMSK) != dmacRegs.rbor.ADDR) Console.WriteLn("GIF MFIFO Write outside MFIFO area");
spr0->madr = dmacRegs->rbor.ADDR + (spr0->madr & dmacRegs->rbsr.RMSK); spr0ch.madr = dmacRegs.rbor.ADDR + (spr0ch.madr & dmacRegs.rbsr.RMSK);
//Console.WriteLn("mfifoGIFtransfer %x madr %x, tadr %x", gif->chcr._u32, gif->madr, gif->tadr); //Console.WriteLn("mfifoGIFtransfer %x madr %x, tadr %x", gif->chcr._u32, gif->madr, gif->tadr);
mfifoGIFtransfer(mfifotransferred); mfifoGIFtransfer(mfifotransferred);
mfifotransferred = 0; mfifotransferred = 0;
@ -249,22 +249,22 @@ void SPRFROMinterrupt()
} }
spr0->chcr.STR = false; spr0ch.chcr.STR = false;
hwDmacIrq(DMAC_FROM_SPR); hwDmacIrq(DMAC_FROM_SPR);
} }
void dmaSPR0() // fromSPR void dmaSPR0() // fromSPR
{ {
SPR_LOG("dmaSPR0 chcr = %lx, madr = %lx, qwc = %lx, sadr = %lx", SPR_LOG("dmaSPR0 chcr = %lx, madr = %lx, qwc = %lx, sadr = %lx",
spr0->chcr._u32, spr0->madr, spr0->qwc, spr0->sadr); spr0ch.chcr._u32, spr0ch.madr, spr0ch.qwc, spr0ch.sadr);
spr0finished = false; //Init spr0finished = false; //Init
if(spr0->chcr.MOD == CHAIN_MODE && spr0->qwc > 0) if(spr0ch.chcr.MOD == CHAIN_MODE && spr0ch.qwc > 0)
{ {
//DevCon.Warning(L"SPR0 QWC on Chain " + spr0->chcr.desc()); //DevCon.Warning(L"SPR0 QWC on Chain " + spr0ch.chcr.desc());
if (spr0->chcr.tag().ID == TAG_END) // but not TAG_REFE? if (spr0ch.chcr.tag().ID == TAG_END) // but not TAG_REFE?
{ {
spr0finished = true; spr0finished = true;
} }
@ -275,58 +275,58 @@ void dmaSPR0() // fromSPR
__fi static void SPR1transfer(const void* data, int qwc) __fi static void SPR1transfer(const void* data, int qwc)
{ {
memcpy_qwc(&psSu128(spr1->sadr), data, qwc); memcpy_qwc(&psSu128(spr1ch.sadr), data, qwc);
spr1->sadr += qwc * 16; spr1ch.sadr += qwc * 16;
} }
int _SPR1chain() int _SPR1chain()
{ {
tDMA_TAG *pMem; tDMA_TAG *pMem;
if (spr1->qwc == 0) return 0; if (spr1ch.qwc == 0) return 0;
pMem = SPRdmaGetAddr(spr1->madr, false); pMem = SPRdmaGetAddr(spr1ch.madr, false);
if (pMem == NULL) return -1; if (pMem == NULL) return -1;
SPR1transfer(pMem, spr1->qwc); SPR1transfer(pMem, spr1ch.qwc);
spr1->madr += spr1->qwc * 16; spr1ch.madr += spr1ch.qwc * 16;
return (spr1->qwc); return (spr1ch.qwc);
} }
__fi void SPR1chain() __fi void SPR1chain()
{ {
CPU_INT(DMAC_TO_SPR, _SPR1chain() / BIAS); CPU_INT(DMAC_TO_SPR, _SPR1chain() / BIAS);
spr1->qwc = 0; spr1ch.qwc = 0;
} }
void _SPR1interleave() void _SPR1interleave()
{ {
int qwc = spr1->qwc; int qwc = spr1ch.qwc;
int sqwc = dmacRegs->sqwc.SQWC; int sqwc = dmacRegs.sqwc.SQWC;
int tqwc = dmacRegs->sqwc.TQWC; int tqwc = dmacRegs.sqwc.TQWC;
tDMA_TAG *pMem; tDMA_TAG *pMem;
if (tqwc == 0) tqwc = qwc; if (tqwc == 0) tqwc = qwc;
SPR_LOG("SPR1 interleave size=%d, tqwc=%d, sqwc=%d, addr=%lx sadr=%lx", SPR_LOG("SPR1 interleave size=%d, tqwc=%d, sqwc=%d, addr=%lx sadr=%lx",
spr1->qwc, tqwc, sqwc, spr1->madr, spr1->sadr); spr1ch.qwc, tqwc, sqwc, spr1ch.madr, spr1ch.sadr);
CPU_INT(DMAC_TO_SPR, qwc / BIAS); CPU_INT(DMAC_TO_SPR, qwc / BIAS);
while (qwc > 0) while (qwc > 0)
{ {
spr1->qwc = std::min(tqwc, qwc); spr1ch.qwc = std::min(tqwc, qwc);
qwc -= spr1->qwc; qwc -= spr1ch.qwc;
pMem = SPRdmaGetAddr(spr1->madr, false); pMem = SPRdmaGetAddr(spr1ch.madr, false);
memcpy_qwc(&psSu128(spr1->sadr), pMem, spr1->qwc); memcpy_qwc(&psSu128(spr1ch.sadr), pMem, spr1ch.qwc);
spr1->sadr += spr1->qwc * 16; spr1ch.sadr += spr1ch.qwc * 16;
spr1->madr += (sqwc + spr1->qwc) * 16; spr1ch.madr += (sqwc + spr1ch.qwc) * 16;
} }
spr1->qwc = 0; spr1ch.qwc = 0;
} }
void _dmaSPR1() // toSPR work function void _dmaSPR1() // toSPR work function
{ {
switch(spr1->chcr.MOD) switch(spr1ch.chcr.MOD)
{ {
case NORMAL_MODE: case NORMAL_MODE:
{ {
@ -341,39 +341,39 @@ void _dmaSPR1() // toSPR work function
tDMA_TAG *ptag; tDMA_TAG *ptag;
bool done = false; bool done = false;
if (spr1->qwc > 0) if (spr1ch.qwc > 0)
{ {
SPR_LOG("spr1 Normal or in Progress size=%d, addr=%lx taddr=%lx saddr=%lx", spr1->qwc, spr1->madr, spr1->tadr, spr1->sadr); SPR_LOG("spr1 Normal or in Progress size=%d, addr=%lx taddr=%lx saddr=%lx", spr1ch.qwc, spr1ch.madr, spr1ch.tadr, spr1ch.sadr);
// Transfer Dn_QWC from Dn_MADR to SPR1 // Transfer Dn_QWC from Dn_MADR to SPR1
SPR1chain(); SPR1chain();
return; return;
} }
// Chain Mode // Chain Mode
ptag = SPRdmaGetAddr(spr1->tadr, false); //Set memory pointer to TADR ptag = SPRdmaGetAddr(spr1ch.tadr, false); //Set memory pointer to TADR
if (!spr1->transfer("SPR1 Tag", ptag)) if (!spr1ch.transfer("SPR1 Tag", ptag))
{ {
done = true; done = true;
spr1finished = done; spr1finished = done;
} }
spr1->madr = ptag[1]._u32; //MADR = ADDR field + SPR spr1ch.madr = ptag[1]._u32; //MADR = ADDR field + SPR
// Transfer dma tag if tte is set // Transfer dma tag if tte is set
if (spr1->chcr.TTE) if (spr1ch.chcr.TTE)
{ {
SPR_LOG("SPR TTE: %x_%x\n", ptag[3]._u32, ptag[2]._u32); SPR_LOG("SPR TTE: %x_%x\n", ptag[3]._u32, ptag[2]._u32);
SPR1transfer(ptag, 1); //Transfer Tag SPR1transfer(ptag, 1); //Transfer Tag
} }
SPR_LOG("spr1 dmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx taddr=%lx saddr=%lx", SPR_LOG("spr1 dmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx taddr=%lx saddr=%lx",
ptag[1]._u32, ptag[0]._u32, spr1->qwc, ptag->ID, spr1->madr, spr1->tadr, spr1->sadr); ptag[1]._u32, ptag[0]._u32, spr1ch.qwc, ptag->ID, spr1ch.madr, spr1ch.tadr, spr1ch.sadr);
done = (hwDmacSrcChain(spr1, ptag->ID)); done = (hwDmacSrcChain(spr1ch, ptag->ID));
SPR1chain(); //Transfers the data set by the switch SPR1chain(); //Transfers the data set by the switch
if (spr1->chcr.TIE && ptag->IRQ) //Check TIE bit of CHCR and IRQ bit of tag if (spr1ch.chcr.TIE && ptag->IRQ) //Check TIE bit of CHCR and IRQ bit of tag
{ {
SPR_LOG("dmaIrq Set"); SPR_LOG("dmaIrq Set");
@ -398,15 +398,15 @@ void dmaSPR1() // toSPR
{ {
SPR_LOG("dmaSPR1 chcr = 0x%x, madr = 0x%x, qwc = 0x%x\n" SPR_LOG("dmaSPR1 chcr = 0x%x, madr = 0x%x, qwc = 0x%x\n"
" tadr = 0x%x, sadr = 0x%x", " tadr = 0x%x, sadr = 0x%x",
spr1->chcr._u32, spr1->madr, spr1->qwc, spr1ch.chcr._u32, spr1ch.madr, spr1ch.qwc,
spr1->tadr, spr1->sadr); spr1ch.tadr, spr1ch.sadr);
spr1finished = false; //Init spr1finished = false; //Init
if(spr1->chcr.MOD == CHAIN_MODE && spr1->qwc > 0) if(spr1ch.chcr.MOD == CHAIN_MODE && spr1ch.qwc > 0)
{ {
//DevCon.Warning(L"SPR1 QWC on Chain " + spr1->chcr.desc()); //DevCon.Warning(L"SPR1 QWC on Chain " + spr1ch.chcr.desc());
if ((spr1->chcr.tag().ID == TAG_END) || (spr1->chcr.tag().ID == TAG_REFE)) if ((spr1ch.chcr.tag().ID == TAG_END) || (spr1ch.chcr.tag().ID == TAG_REFE))
{ {
spr1finished = true; spr1finished = true;
} }
@ -418,14 +418,14 @@ void dmaSPR1() // toSPR
void SPRTOinterrupt() void SPRTOinterrupt()
{ {
SPR_LOG("SPR1 Interrupt"); SPR_LOG("SPR1 Interrupt");
if (!spr1finished || spr1->qwc > 0) if (!spr1finished || spr1ch.qwc > 0)
{ {
_dmaSPR1(); _dmaSPR1();
return; return;
} }
SPR_LOG("SPR1 End"); SPR_LOG("SPR1 End");
spr1->chcr.STR = false; spr1ch.chcr.STR = false;
hwDmacIrq(DMAC_TO_SPR); hwDmacIrq(DMAC_TO_SPR);
} }

View File

@ -154,7 +154,7 @@ void SaveStateBase::FreezeMainMemory()
// --------------------------- // ---------------------------
FreezeMem(eeMem->Main, Ps2MemSize::Base); // 32 MB main memory FreezeMem(eeMem->Main, Ps2MemSize::Base); // 32 MB main memory
FreezeMem(eeMem->Scratch, Ps2MemSize::Scratch); // scratch pad FreezeMem(eeMem->Scratch, Ps2MemSize::Scratch); // scratch pad
FreezeMem(eeMem->HW, Ps2MemSize::Hardware); // hardware memory FreezeMem(eeHw, Ps2MemSize::Hardware); // hardware memory
FreezeMem(psxM, Ps2MemSize::IopRam); // 2 MB main memory FreezeMem(psxM, Ps2MemSize::IopRam); // 2 MB main memory
FreezeMem(psxH, Ps2MemSize::IopHardware); // hardware memory FreezeMem(psxH, Ps2MemSize::IopHardware); // hardware memory
@ -194,6 +194,7 @@ void SaveStateBase::FreezeRegisters()
vif1Freeze(); vif1Freeze();
sifFreeze(); sifFreeze();
ipuFreeze(); ipuFreeze();
ipuDmaFreeze();
gifFreeze(); gifFreeze();
sprFreeze(); sprFreeze();

View File

@ -24,7 +24,7 @@
// the lower 16 bit value. IF the change is breaking of all compatibility with old // 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. // states, increment the upper 16 bit value, and clear the lower 16 bits to 0.
static const u32 g_SaveVersion = 0x8b480000; static const u32 g_SaveVersion = 0x8b490000;
// this function is meant to be used in the place of GSfreeze, and provides a safe layer // this function is meant to be used in the place of GSfreeze, and provides a safe layer
// between the GS saving function and the MTGS's needs. :) // between the GS saving function and the MTGS's needs. :)
@ -214,6 +214,7 @@ protected:
#endif #endif
void sifFreeze(); void sifFreeze();
void ipuFreeze(); void ipuFreeze();
void ipuDmaFreeze();
void gifFreeze(); void gifFreeze();
void sprFreeze(); void sprFreeze();

View File

@ -28,9 +28,9 @@ void sifInit()
__fi void dmaSIF2() __fi void dmaSIF2()
{ {
SIF_LOG(wxString(L"dmaSIF2" + sif2dma->cmq_to_str()).To8BitData()); SIF_LOG(wxString(L"dmaSIF2" + sif2dma.cmq_to_str()).To8BitData());
sif2dma->chcr.STR = false; sif2dma.chcr.STR = false;
hwDmacIrq(DMAC_SIF2); hwDmacIrq(DMAC_SIF2);
Console.WriteLn("*PCSX2*: dmaSIF2"); Console.WriteLn("*PCSX2*: dmaSIF2");
} }

View File

@ -16,7 +16,12 @@
#ifndef __SIF_H__ #ifndef __SIF_H__
#define __SIF_H__ #define __SIF_H__
#define FIFO_SIF_W 128 static const int FIFO_SIF_W = 128;
static DMACh& sif0dma = (DMACh&)eeHw[0xc000];
static DMACh& sif1dma = (DMACh&)eeHw[0xc400];
static DMACh& sif2dma = (DMACh&)eeHw[0xc800];
struct sifData struct sifData
{ {

View File

@ -35,14 +35,14 @@ static __fi void Sif0Init()
// Write from Fifo to EE. // Write from Fifo to EE.
static __fi bool WriteFifoToEE() static __fi bool WriteFifoToEE()
{ {
const int readSize = min((s32)sif0dma->qwc, sif0.fifo.size >> 2); const int readSize = min((s32)sif0dma.qwc, sif0.fifo.size >> 2);
tDMA_TAG *ptag; tDMA_TAG *ptag;
//SIF_LOG(" EE SIF doing transfer %04Xqw to %08X", readSize, sif0dma->madr); //SIF_LOG(" EE SIF doing transfer %04Xqw to %08X", readSize, sif0dma.madr);
SIF_LOG("Write Fifo to EE: ----------- %lX of %lX", readSize << 2, sif0dma->qwc << 2); SIF_LOG("Write Fifo to EE: ----------- %lX of %lX", readSize << 2, sif0dma.qwc << 2);
ptag = sif0dma->getAddr(sif0dma->madr, DMAC_SIF0, true); ptag = sif0dma.getAddr(sif0dma.madr, DMAC_SIF0, true);
if (ptag == NULL) if (ptag == NULL)
{ {
DevCon.Warning("Write Fifo to EE: ptag == NULL"); DevCon.Warning("Write Fifo to EE: ptag == NULL");
@ -52,11 +52,11 @@ static __fi bool WriteFifoToEE()
sif0.fifo.read((u32*)ptag, readSize << 2); sif0.fifo.read((u32*)ptag, readSize << 2);
// Clearing handled by vtlb memory protection and manual blocks. // Clearing handled by vtlb memory protection and manual blocks.
//Cpu->Clear(sif0dma->madr, readSize*4); //Cpu->Clear(sif0dma.madr, readSize*4);
sif0dma->madr += readSize << 4; sif0dma.madr += readSize << 4;
sif0.ee.cycles += readSize; // fixme : BIAS is factored in above sif0.ee.cycles += readSize; // fixme : BIAS is factored in above
sif0dma->qwc -= readSize; sif0dma.qwc -= readSize;
return true; return true;
} }
@ -87,14 +87,14 @@ static __fi bool ProcessEETag()
sif0.fifo.read((u32*)&tag[0], 4); // Tag sif0.fifo.read((u32*)&tag[0], 4); // Tag
SIF_LOG("SIF0 EE read tag: %x %x %x %x", tag[0], tag[1], tag[2], tag[3]); SIF_LOG("SIF0 EE read tag: %x %x %x %x", tag[0], tag[1], tag[2], tag[3]);
sif0dma->unsafeTransfer(((tDMA_TAG*)(tag))); sif0dma.unsafeTransfer(((tDMA_TAG*)(tag)));
sif0dma->madr = tag[1]; sif0dma.madr = tag[1];
tDMA_TAG ptag(tag[0]); tDMA_TAG ptag(tag[0]);
SIF_LOG("SIF0 EE dest chain tag madr:%08X qwc:%04X id:%X irq:%d(%08X_%08X)", SIF_LOG("SIF0 EE dest chain tag madr:%08X qwc:%04X id:%X irq:%d(%08X_%08X)",
sif0dma->madr, sif0dma->qwc, ptag.ID, ptag.IRQ, tag[1], tag[0]); sif0dma.madr, sif0dma.qwc, ptag.ID, ptag.IRQ, tag[1], tag[0]);
if (sif0dma->chcr.TIE && ptag.IRQ) if (sif0dma.chcr.TIE && ptag.IRQ)
{ {
//Console.WriteLn("SIF0 TIE"); //Console.WriteLn("SIF0 TIE");
sif0.ee.end = true; sif0.ee.end = true;
@ -104,13 +104,13 @@ static __fi bool ProcessEETag()
{ {
case TAG_REFE: case TAG_REFE:
sif0.ee.end = true; sif0.ee.end = true;
if (dmacRegs->ctrl.STS != NO_STS) if (dmacRegs.ctrl.STS != NO_STS)
dmacRegs->stadr.ADDR = sif0dma->madr + (sif0dma->qwc * 16); dmacRegs.stadr.ADDR = sif0dma.madr + (sif0dma.qwc * 16);
break; break;
case TAG_REFS: case TAG_REFS:
if (dmacRegs->ctrl.STS != NO_STS) if (dmacRegs.ctrl.STS != NO_STS)
dmacRegs->stadr.ADDR = sif0dma->madr + (sif0dma->qwc * 16); dmacRegs.stadr.ADDR = sif0dma.madr + (sif0dma.qwc * 16);
break; break;
case TAG_END: case TAG_END:
@ -177,7 +177,7 @@ static __fi void EndIOP()
// Handle the EE transfer. // Handle the EE transfer.
static __fi void HandleEETransfer() static __fi void HandleEETransfer()
{ {
if(sif0dma->chcr.STR == false) if(sif0dma.chcr.STR == false)
{ {
DevCon.Warning("Replacement for irq prevention hack EE SIF0"); DevCon.Warning("Replacement for irq prevention hack EE SIF0");
sif0.ee.end = false; sif0.ee.end = false;
@ -185,22 +185,22 @@ static __fi void HandleEETransfer()
return; return;
} }
if (dmacRegs->ctrl.STS == STS_SIF0) if (dmacRegs.ctrl.STS == STS_SIF0)
{ {
DevCon.Warning("SIF0 stall control"); DevCon.Warning("SIF0 stall control");
} }
/*if (sif0dma->qwc == 0) /*if (sif0dma.qwc == 0)
if (sif0dma->chcr.MOD == NORMAL_MODE) if (sif0dma.chcr.MOD == NORMAL_MODE)
if (!sif0.ee.end){ if (!sif0.ee.end){
DevCon.Warning("sif0 irq prevented"); DevCon.Warning("sif0 irq prevented");
done = true; done = true;
return; return;
}*/ }*/
if (sif0dma->qwc <= 0) if (sif0dma.qwc <= 0)
{ {
if ((sif0dma->chcr.MOD == NORMAL_MODE) || sif0.ee.end) if ((sif0dma.chcr.MOD == NORMAL_MODE) || sif0.ee.end)
{ {
// Stop transferring ee, and signal an interrupt. // Stop transferring ee, and signal an interrupt.
done = true; done = true;
@ -214,7 +214,7 @@ static __fi void HandleEETransfer()
} }
} }
if (sif0dma->qwc > 0) // If we're writing something, continue to do so. if (sif0dma.qwc > 0) // If we're writing something, continue to do so.
{ {
// Write from Fifo to EE. // Write from Fifo to EE.
if (sif0.fifo.size > 0) if (sif0.fifo.size > 0)
@ -306,7 +306,7 @@ __fi void SIF0Dma()
} }
if (sif0.ee.busy) if (sif0.ee.busy)
{ {
if(sif0.fifo.size >= 4 || (sif0.ee.end == true && sif0dma->qwc == 0)) if(sif0.fifo.size >= 4 || (sif0.ee.end == true && sif0dma.qwc == 0))
{ {
BusyCheck++; BusyCheck++;
HandleEETransfer(); HandleEETransfer();
@ -326,19 +326,19 @@ __fi void sif0Interrupt()
__fi void EEsif0Interrupt() __fi void EEsif0Interrupt()
{ {
hwDmacIrq(DMAC_SIF0); hwDmacIrq(DMAC_SIF0);
sif0dma->chcr.STR = false; sif0dma.chcr.STR = false;
} }
__fi void dmaSIF0() __fi void dmaSIF0()
{ {
SIF_LOG(wxString(L"dmaSIF0" + sif0dma->cmqt_to_str()).To8BitData()); SIF_LOG(wxString(L"dmaSIF0" + sif0dma.cmqt_to_str()).To8BitData());
if (sif0.fifo.readPos != sif0.fifo.writePos) if (sif0.fifo.readPos != sif0.fifo.writePos)
{ {
SIF_LOG("warning, sif0.fifoReadPos != sif0.fifoWritePos"); SIF_LOG("warning, sif0.fifoReadPos != sif0.fifoWritePos");
} }
//if(sif0dma->chcr.MOD == CHAIN_MODE && sif0dma->qwc > 0) DevCon.Warning(L"SIF0 QWC on Chain CHCR " + sif0dma->chcr.desc()); //if(sif0dma.chcr.MOD == CHAIN_MODE && sif0dma.qwc > 0) DevCon.Warning(L"SIF0 QWC on Chain CHCR " + sif0dma.chcr.desc());
psHu32(SBUS_F240) |= 0x2000; psHu32(SBUS_F240) |= 0x2000;
sif0.ee.busy = true; sif0.ee.busy = true;

View File

@ -38,11 +38,11 @@ static __fi bool WriteEEtoFifo()
// There's some data ready to transfer into the fifo.. // There's some data ready to transfer into the fifo..
SIF_LOG("Sif 1: Write EE to Fifo"); SIF_LOG("Sif 1: Write EE to Fifo");
const int writeSize = min((s32)sif1dma->qwc, sif1.fifo.free() >> 2); const int writeSize = min((s32)sif1dma.qwc, sif1.fifo.free() >> 2);
tDMA_TAG *ptag; tDMA_TAG *ptag;
ptag = sif1dma->getAddr(sif1dma->madr, DMAC_SIF1, false); ptag = sif1dma.getAddr(sif1dma.madr, DMAC_SIF1, false);
if (ptag == NULL) if (ptag == NULL)
{ {
DevCon.Warning("Write EE to Fifo: ptag == NULL"); DevCon.Warning("Write EE to Fifo: ptag == NULL");
@ -51,9 +51,9 @@ static __fi bool WriteEEtoFifo()
sif1.fifo.write((u32*)ptag, writeSize << 2); sif1.fifo.write((u32*)ptag, writeSize << 2);
sif1dma->madr += writeSize << 4; sif1dma.madr += writeSize << 4;
sif1.ee.cycles += writeSize; // fixme : BIAS is factored in above sif1.ee.cycles += writeSize; // fixme : BIAS is factored in above
sif1dma->qwc -= writeSize; sif1dma.qwc -= writeSize;
return true; return true;
} }
@ -84,21 +84,21 @@ static __fi bool ProcessEETag()
tDMA_TAG *ptag; tDMA_TAG *ptag;
SIF_LOG("Sif1: ProcessEETag"); SIF_LOG("Sif1: ProcessEETag");
// Process DMA tag at sif1dma->tadr // Process DMA tag at sif1dma.tadr
ptag = sif1dma->DMAtransfer(sif1dma->tadr, DMAC_SIF1); ptag = sif1dma.DMAtransfer(sif1dma.tadr, DMAC_SIF1);
if (ptag == NULL) if (ptag == NULL)
{ {
Console.WriteLn("Sif1 ProcessEETag: ptag = NULL"); Console.WriteLn("Sif1 ProcessEETag: ptag = NULL");
return false; return false;
} }
if (sif1dma->chcr.TTE) if (sif1dma.chcr.TTE)
{ {
Console.WriteLn("SIF1 TTE"); Console.WriteLn("SIF1 TTE");
sif1.fifo.write((u32*)ptag + 2, 2); sif1.fifo.write((u32*)ptag + 2, 2);
} }
if (sif1dma->chcr.TIE && ptag->IRQ) if (sif1dma.chcr.TIE && ptag->IRQ)
{ {
Console.WriteLn("SIF1 TIE"); Console.WriteLn("SIF1 TIE");
sif1.ee.end = true; sif1.ee.end = true;
@ -109,30 +109,30 @@ static __fi bool ProcessEETag()
{ {
case TAG_REFE: case TAG_REFE:
sif1.ee.end = true; sif1.ee.end = true;
sif1dma->madr = ptag[1]._u32; sif1dma.madr = ptag[1]._u32;
sif1dma->tadr += 16; sif1dma.tadr += 16;
break; break;
case TAG_CNT: case TAG_CNT:
sif1dma->madr = sif1dma->tadr + 16; sif1dma.madr = sif1dma.tadr + 16;
sif1dma->tadr = sif1dma->madr + (sif1dma->qwc << 4); sif1dma.tadr = sif1dma.madr + (sif1dma.qwc << 4);
break; break;
case TAG_NEXT: case TAG_NEXT:
sif1dma->madr = sif1dma->tadr + 16; sif1dma.madr = sif1dma.tadr + 16;
sif1dma->tadr = ptag[1]._u32; sif1dma.tadr = ptag[1]._u32;
break; break;
case TAG_REF: case TAG_REF:
case TAG_REFS: case TAG_REFS:
sif1dma->madr = ptag[1]._u32; sif1dma.madr = ptag[1]._u32;
sif1dma->tadr += 16; sif1dma.tadr += 16;
break; break;
case TAG_END: case TAG_END:
sif1.ee.end = true; sif1.ee.end = true;
sif1dma->madr = sif1dma->tadr + 16; sif1dma.madr = sif1dma.tadr + 16;
sif1dma->tadr = sif1dma->madr + (sif1dma->qwc << 4); sif1dma.tadr = sif1dma.madr + (sif1dma.qwc << 4);
break; break;
default: default:
@ -203,31 +203,31 @@ static __fi void EndIOP()
// Handle the EE transfer. // Handle the EE transfer.
static __fi void HandleEETransfer() static __fi void HandleEETransfer()
{ {
if(sif1dma->chcr.STR == false) if(sif1dma.chcr.STR == false)
{ {
DevCon.Warning("Replacement for irq prevention hack EE SIF1"); DevCon.Warning("Replacement for irq prevention hack EE SIF1");
sif1.ee.end = false; sif1.ee.end = false;
sif1.ee.busy = false; sif1.ee.busy = false;
return; return;
} }
if (dmacRegs->ctrl.STD == STD_SIF1) if (dmacRegs.ctrl.STD == STD_SIF1)
{ {
DevCon.Warning("SIF1 stall control"); // STD == fromSIF1 DevCon.Warning("SIF1 stall control"); // STD == fromSIF1
} }
/*if (sif1dma->qwc == 0) /*if (sif1dma.qwc == 0)
if (sif1dma->chcr.MOD == NORMAL_MODE) if (sif1dma.chcr.MOD == NORMAL_MODE)
if (!sif1.ee.end){ if (!sif1.ee.end){
DevCon.Warning("sif1 irq prevented CHCR %x QWC %x", sif1dma->chcr, sif1dma->qwc); DevCon.Warning("sif1 irq prevented CHCR %x QWC %x", sif1dma.chcr, sif1dma.qwc);
done = true; done = true;
return; return;
}*/ }*/
// If there's no more to transfer. // If there's no more to transfer.
if (sif1dma->qwc <= 0) if (sif1dma.qwc <= 0)
{ {
// If NORMAL mode or end of CHAIN then stop DMA. // If NORMAL mode or end of CHAIN then stop DMA.
if ((sif1dma->chcr.MOD == NORMAL_MODE) || sif1.ee.end) if ((sif1dma.chcr.MOD == NORMAL_MODE) || sif1.ee.end)
{ {
done = true; done = true;
EndEE(); EndEE();
@ -292,7 +292,7 @@ __fi void SIF1Dma()
if (sif1.ee.busy) if (sif1.ee.busy)
{ {
if(sif1.fifo.free() > 0 || (sif1.ee.end == true && sif1dma->qwc == 0)) if(sif1.fifo.free() > 0 || (sif1.ee.end == true && sif1dma.qwc == 0))
{ {
BusyCheck++; BusyCheck++;
HandleEETransfer(); HandleEETransfer();
@ -322,21 +322,21 @@ __fi void sif1Interrupt()
__fi void EEsif1Interrupt() __fi void EEsif1Interrupt()
{ {
hwDmacIrq(DMAC_SIF1); hwDmacIrq(DMAC_SIF1);
sif1dma->chcr.STR = false; sif1dma.chcr.STR = false;
} }
// Do almost exactly the same thing as psxDma10 in IopDma.cpp. // Do almost exactly the same thing as psxDma10 in IopDma.cpp.
// Main difference is this checks for iop, where psxDma10 checks for ee. // Main difference is this checks for iop, where psxDma10 checks for ee.
__fi void dmaSIF1() __fi void dmaSIF1()
{ {
SIF_LOG(wxString(L"dmaSIF1" + sif1dma->cmqt_to_str()).To8BitData()); SIF_LOG(wxString(L"dmaSIF1" + sif1dma.cmqt_to_str()).To8BitData());
if (sif1.fifo.readPos != sif1.fifo.writePos) if (sif1.fifo.readPos != sif1.fifo.writePos)
{ {
SIF_LOG("warning, sif1.fifoReadPos != sif1.fifoWritePos"); SIF_LOG("warning, sif1.fifoReadPos != sif1.fifoWritePos");
} }
//if(sif1dma->chcr.MOD == CHAIN_MODE && sif1dma->qwc > 0) DevCon.Warning(L"SIF1 QWC on Chain CHCR " + sif1dma->chcr.desc()); //if(sif1dma.chcr.MOD == CHAIN_MODE && sif1dma.qwc > 0) DevCon.Warning(L"SIF1 QWC on Chain CHCR " + sif1dma.chcr.desc());
psHu32(SBUS_F240) |= 0x4000; psHu32(SBUS_F240) |= 0x4000;
sif1.ee.busy = true; sif1.ee.busy = true;

View File

@ -16,10 +16,6 @@
#pragma once #pragma once
#include "Vif.h" #include "Vif.h"
#ifdef _MSC_VER // Most of the structs here should be packed
# pragma pack(1)
#endif
enum VURegFlags enum VURegFlags
{ {
REG_STATUS_FLAG = 16, REG_STATUS_FLAG = 16,
@ -68,7 +64,7 @@ union VECTOR {
s16 SS[8]; s16 SS[8];
u8 UC[16]; u8 UC[16];
s8 SC[16]; s8 SC[16];
} __packed; };
struct REG_VI { struct REG_VI {
union { union {
@ -82,7 +78,7 @@ struct REG_VI {
}; };
u32 padding[3]; // needs padding to make them 128bit; VU0 maps VU1's VI regs as 128bits to addr 0x4xx0 in u32 padding[3]; // needs padding to make them 128bit; VU0 maps VU1's VI regs as 128bits to addr 0x4xx0 in
// VU0 mem, with only lower 16 bits valid, and the upper 112bits are hardwired to 0 (cottonvibes) // VU0 mem, with only lower 16 bits valid, and the upper 112bits are hardwired to 0 (cottonvibes)
} __packed; };
//#define VUFLAG_BREAKONMFLAG 0x00000001 //#define VUFLAG_BREAKONMFLAG 0x00000001
#define VUFLAG_MFLAGSET 0x00000002 #define VUFLAG_MFLAGSET 0x00000002
@ -120,45 +116,61 @@ struct ialuPipe {
u32 Cycle; u32 Cycle;
}; };
struct VURegs { struct __aligned16 VURegs {
VECTOR VF[32]; // VF and VI need to be first in this struct for proper mapping VECTOR VF[32]; // VF and VI need to be first in this struct for proper mapping
REG_VI VI[32]; // needs to be 128bit x 32 (cottonvibes) REG_VI VI[32]; // needs to be 128bit x 32 (cottonvibes)
VECTOR ACC; VECTOR ACC;
REG_VI q; REG_VI q;
REG_VI p; REG_VI p;
uint idx; // VU index (0 or 1)
// flags/cycle are needed by VIF dma code, so they have to be here (for now)
// We may replace these by accessors in the future, if merited.
u32 cycle;
u32 flags;
// Current opcode being interpreted or recompiled (this var is used by Interps and superVU
// but not microVU. Would like to have it local to their respective classes... someday)
u32 code;
// branch/branchpc are used by interpreter only, but making them local to the interpreter
// classes requires considerable code refactoring. Maybe later. >_<
u32 branch;
u32 branchpc;
// MAC/Status flags -- these are used by interpreters and superVU, but are kind of hacky
// and shouldn't be relied on for any useful/valid info. Would like to move them out of
// this struct eventually.
u32 macflag; u32 macflag;
u32 statusflag; u32 statusflag;
u32 clipflag; u32 clipflag;
u32 cycle;
u32 flags;
void (*vuExec)(VURegs*);
VIFregisters *vifRegs;
u8 *Mem; u8 *Mem;
u8 *Micro; u8 *Micro;
u32 code; u32 ebit;
u32 maxmem;
u32 maxmicro;
u16 branch;
u16 ebit;
u32 branchpc;
fmacPipe fmac[8]; fmacPipe fmac[8];
fdivPipe fdiv; fdivPipe fdiv;
efuPipe efu; efuPipe efu;
ialuPipe ialu[8]; ialuPipe ialu[8];
VURegs() : VURegs()
Mem( NULL )
, Micro( NULL )
{ {
Mem = NULL;
Micro = NULL;
} }
} __packed;
bool IsVU1() const;
bool IsVU0() const;
VIFregisters& GetVifRegs() const
{
return IsVU1() ? vif1Regs : vif0Regs;
}
};
enum VUPipeState enum VUPipeState
{ {
@ -171,27 +183,16 @@ enum VUPipeState
VUPIPE_XGKICK VUPIPE_XGKICK
}; };
struct _VURegsNum { extern __aligned16 VURegs vuRegs[2];
u8 pipe; // if 0xff, COP2
u8 VFwrite;
u8 VFwxyzw;
u8 VFr0xyzw;
u8 VFr1xyzw;
u8 VFread0;
u8 VFread1;
u32 VIwrite;
u32 VIread;
int cycles;
};
#ifdef _MSC_VER // Restore to default pack alignment // Obsolete(?) -- I think I'd rather use vu0Regs/vu1Regs or actually have these explicit to any
# pragma pack() // CPP file that needs them only. --air
#endif static VURegs& VU0 = vuRegs[0];
static VURegs& VU1 = vuRegs[1];
extern VURegs* g_pVU1; // Do not use __fi here because it fires 'multiple definition' error in GCC
extern __aligned16 VURegs VU0; inline bool VURegs::IsVU1() const { return this == &vuRegs[1]; }
inline bool VURegs::IsVU0() const { return this == &vuRegs[0]; }
#define VU1 (*g_pVU1)
extern u32* GET_VU_MEM(VURegs* VU, u32 addr); extern u32* GET_VU_MEM(VURegs* VU, u32 addr);

View File

@ -44,8 +44,6 @@
using namespace R5900; using namespace R5900;
__aligned16 VURegs VU0;
void COP2_BC2() { Int_COP2BC2PrintTable[_Rt_]();} void COP2_BC2() { Int_COP2BC2PrintTable[_Rt_]();}
void COP2_SPECIAL() { Int_COP2SPECIAL1PrintTable[_Funct_]();} void COP2_SPECIAL() { Int_COP2SPECIAL1PrintTable[_Funct_]();}
@ -88,14 +86,9 @@ namespace OpcodeImpl
void LQC2() { void LQC2() {
u32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + (s16)cpuRegs.code; u32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + (s16)cpuRegs.code;
if (_Ft_) { if (_Ft_) {
#ifdef __LINUX__ memRead128(addr, VU0.VF[_Ft_].UQ);
// Ifdeffing mainly because I haven't gotten around to checking it in Windows yet.
memRead128(addr, &VU0.VF[_Ft_].UQ);
#else
memRead128(addr, VU0.VF[_Ft_].UD);
#endif
} else { } else {
u64 val[2]; u128 val;
memRead128(addr, val); memRead128(addr, val);
} }
} }
@ -105,9 +98,7 @@ namespace OpcodeImpl
// HUH why ? doesn't make any sense ... // HUH why ? doesn't make any sense ...
void SQC2() { void SQC2() {
u32 addr = _Imm_ + cpuRegs.GPR.r[_Rs_].UL[0]; u32 addr = _Imm_ + cpuRegs.GPR.r[_Rs_].UL[0];
//memWrite64(addr, VU0.VF[_Ft_].UD[0]); memWrite128(addr, VU0.VF[_Ft_].UQ);
//memWrite64(addr+8,VU0.VF[_Ft_].UD[1]);
memWrite128(addr, VU0.VF[_Ft_].UD);
} }
}}} }}}
@ -180,158 +171,3 @@ void CTC2() {
break; break;
} }
} }
//---------------------------------------------------------------------------------------
__fi void SYNCMSFLAGS()
{
VU0.VI[REG_STATUS_FLAG].UL = VU0.statusflag;
VU0.VI[REG_MAC_FLAG].UL = VU0.macflag;
}
__fi void SYNCFDIV()
{
VU0.VI[REG_Q].UL = VU0.q.UL;
VU0.VI[REG_STATUS_FLAG].UL = VU0.statusflag;
}
void VABS() { VU0.code = cpuRegs.code; _vuABS(&VU0); }
void VADD() { VU0.code = cpuRegs.code; _vuADD(&VU0); SYNCMSFLAGS(); }
void VADDi() { VU0.code = cpuRegs.code; _vuADDi(&VU0); SYNCMSFLAGS(); }
void VADDq() { VU0.code = cpuRegs.code; _vuADDq(&VU0); SYNCMSFLAGS(); }
void VADDx() { VU0.code = cpuRegs.code; _vuADDx(&VU0); SYNCMSFLAGS(); }
void VADDy() { VU0.code = cpuRegs.code; _vuADDy(&VU0); SYNCMSFLAGS(); }
void VADDz() { VU0.code = cpuRegs.code; _vuADDz(&VU0); SYNCMSFLAGS(); }
void VADDw() { VU0.code = cpuRegs.code; _vuADDw(&VU0); SYNCMSFLAGS(); }
void VADDA() { VU0.code = cpuRegs.code; _vuADDA(&VU0); SYNCMSFLAGS(); }
void VADDAi() { VU0.code = cpuRegs.code; _vuADDAi(&VU0); SYNCMSFLAGS(); }
void VADDAq() { VU0.code = cpuRegs.code; _vuADDAq(&VU0); SYNCMSFLAGS(); }
void VADDAx() { VU0.code = cpuRegs.code; _vuADDAx(&VU0); SYNCMSFLAGS(); }
void VADDAy() { VU0.code = cpuRegs.code; _vuADDAy(&VU0); SYNCMSFLAGS(); }
void VADDAz() { VU0.code = cpuRegs.code; _vuADDAz(&VU0); SYNCMSFLAGS(); }
void VADDAw() { VU0.code = cpuRegs.code; _vuADDAw(&VU0); SYNCMSFLAGS(); }
void VSUB() { VU0.code = cpuRegs.code; _vuSUB(&VU0); SYNCMSFLAGS(); }
void VSUBi() { VU0.code = cpuRegs.code; _vuSUBi(&VU0); SYNCMSFLAGS(); }
void VSUBq() { VU0.code = cpuRegs.code; _vuSUBq(&VU0); SYNCMSFLAGS(); }
void VSUBx() { VU0.code = cpuRegs.code; _vuSUBx(&VU0); SYNCMSFLAGS(); }
void VSUBy() { VU0.code = cpuRegs.code; _vuSUBy(&VU0); SYNCMSFLAGS(); }
void VSUBz() { VU0.code = cpuRegs.code; _vuSUBz(&VU0); SYNCMSFLAGS(); }
void VSUBw() { VU0.code = cpuRegs.code; _vuSUBw(&VU0); SYNCMSFLAGS(); }
void VSUBA() { VU0.code = cpuRegs.code; _vuSUBA(&VU0); SYNCMSFLAGS(); }
void VSUBAi() { VU0.code = cpuRegs.code; _vuSUBAi(&VU0); SYNCMSFLAGS(); }
void VSUBAq() { VU0.code = cpuRegs.code; _vuSUBAq(&VU0); SYNCMSFLAGS(); }
void VSUBAx() { VU0.code = cpuRegs.code; _vuSUBAx(&VU0); SYNCMSFLAGS(); }
void VSUBAy() { VU0.code = cpuRegs.code; _vuSUBAy(&VU0); SYNCMSFLAGS(); }
void VSUBAz() { VU0.code = cpuRegs.code; _vuSUBAz(&VU0); SYNCMSFLAGS(); }
void VSUBAw() { VU0.code = cpuRegs.code; _vuSUBAw(&VU0); SYNCMSFLAGS(); }
void VMUL() { VU0.code = cpuRegs.code; _vuMUL(&VU0); SYNCMSFLAGS(); }
void VMULi() { VU0.code = cpuRegs.code; _vuMULi(&VU0); SYNCMSFLAGS(); }
void VMULq() { VU0.code = cpuRegs.code; _vuMULq(&VU0); SYNCMSFLAGS(); }
void VMULx() { VU0.code = cpuRegs.code; _vuMULx(&VU0); SYNCMSFLAGS(); }
void VMULy() { VU0.code = cpuRegs.code; _vuMULy(&VU0); SYNCMSFLAGS(); }
void VMULz() { VU0.code = cpuRegs.code; _vuMULz(&VU0); SYNCMSFLAGS(); }
void VMULw() { VU0.code = cpuRegs.code; _vuMULw(&VU0); SYNCMSFLAGS(); }
void VMULA() { VU0.code = cpuRegs.code; _vuMULA(&VU0); SYNCMSFLAGS(); }
void VMULAi() { VU0.code = cpuRegs.code; _vuMULAi(&VU0); SYNCMSFLAGS(); }
void VMULAq() { VU0.code = cpuRegs.code; _vuMULAq(&VU0); SYNCMSFLAGS(); }
void VMULAx() { VU0.code = cpuRegs.code; _vuMULAx(&VU0); SYNCMSFLAGS(); }
void VMULAy() { VU0.code = cpuRegs.code; _vuMULAy(&VU0); SYNCMSFLAGS(); }
void VMULAz() { VU0.code = cpuRegs.code; _vuMULAz(&VU0); SYNCMSFLAGS(); }
void VMULAw() { VU0.code = cpuRegs.code; _vuMULAw(&VU0); SYNCMSFLAGS(); }
void VMADD() { VU0.code = cpuRegs.code; _vuMADD(&VU0); SYNCMSFLAGS(); }
void VMADDi() { VU0.code = cpuRegs.code; _vuMADDi(&VU0); SYNCMSFLAGS(); }
void VMADDq() { VU0.code = cpuRegs.code; _vuMADDq(&VU0); SYNCMSFLAGS(); }
void VMADDx() { VU0.code = cpuRegs.code; _vuMADDx(&VU0); SYNCMSFLAGS(); }
void VMADDy() { VU0.code = cpuRegs.code; _vuMADDy(&VU0); SYNCMSFLAGS(); }
void VMADDz() { VU0.code = cpuRegs.code; _vuMADDz(&VU0); SYNCMSFLAGS(); }
void VMADDw() { VU0.code = cpuRegs.code; _vuMADDw(&VU0); SYNCMSFLAGS(); }
void VMADDA() { VU0.code = cpuRegs.code; _vuMADDA(&VU0); SYNCMSFLAGS(); }
void VMADDAi() { VU0.code = cpuRegs.code; _vuMADDAi(&VU0); SYNCMSFLAGS(); }
void VMADDAq() { VU0.code = cpuRegs.code; _vuMADDAq(&VU0); SYNCMSFLAGS(); }
void VMADDAx() { VU0.code = cpuRegs.code; _vuMADDAx(&VU0); SYNCMSFLAGS(); }
void VMADDAy() { VU0.code = cpuRegs.code; _vuMADDAy(&VU0); SYNCMSFLAGS(); }
void VMADDAz() { VU0.code = cpuRegs.code; _vuMADDAz(&VU0); SYNCMSFLAGS(); }
void VMADDAw() { VU0.code = cpuRegs.code; _vuMADDAw(&VU0); SYNCMSFLAGS(); }
void VMSUB() { VU0.code = cpuRegs.code; _vuMSUB(&VU0); SYNCMSFLAGS(); }
void VMSUBi() { VU0.code = cpuRegs.code; _vuMSUBi(&VU0); SYNCMSFLAGS(); }
void VMSUBq() { VU0.code = cpuRegs.code; _vuMSUBq(&VU0); SYNCMSFLAGS(); }
void VMSUBx() { VU0.code = cpuRegs.code; _vuMSUBx(&VU0); SYNCMSFLAGS(); }
void VMSUBy() { VU0.code = cpuRegs.code; _vuMSUBy(&VU0); SYNCMSFLAGS(); }
void VMSUBz() { VU0.code = cpuRegs.code; _vuMSUBz(&VU0); SYNCMSFLAGS(); }
void VMSUBw() { VU0.code = cpuRegs.code; _vuMSUBw(&VU0); SYNCMSFLAGS(); }
void VMSUBA() { VU0.code = cpuRegs.code; _vuMSUBA(&VU0); SYNCMSFLAGS(); }
void VMSUBAi() { VU0.code = cpuRegs.code; _vuMSUBAi(&VU0); SYNCMSFLAGS(); }
void VMSUBAq() { VU0.code = cpuRegs.code; _vuMSUBAq(&VU0); SYNCMSFLAGS(); }
void VMSUBAx() { VU0.code = cpuRegs.code; _vuMSUBAx(&VU0); SYNCMSFLAGS(); }
void VMSUBAy() { VU0.code = cpuRegs.code; _vuMSUBAy(&VU0); SYNCMSFLAGS(); }
void VMSUBAz() { VU0.code = cpuRegs.code; _vuMSUBAz(&VU0); SYNCMSFLAGS(); }
void VMSUBAw() { VU0.code = cpuRegs.code; _vuMSUBAw(&VU0); SYNCMSFLAGS(); }
void VMAX() { VU0.code = cpuRegs.code; _vuMAX(&VU0); }
void VMAXi() { VU0.code = cpuRegs.code; _vuMAXi(&VU0); }
void VMAXx() { VU0.code = cpuRegs.code; _vuMAXx(&VU0); }
void VMAXy() { VU0.code = cpuRegs.code; _vuMAXy(&VU0); }
void VMAXz() { VU0.code = cpuRegs.code; _vuMAXz(&VU0); }
void VMAXw() { VU0.code = cpuRegs.code; _vuMAXw(&VU0); }
void VMINI() { VU0.code = cpuRegs.code; _vuMINI(&VU0); }
void VMINIi() { VU0.code = cpuRegs.code; _vuMINIi(&VU0); }
void VMINIx() { VU0.code = cpuRegs.code; _vuMINIx(&VU0); }
void VMINIy() { VU0.code = cpuRegs.code; _vuMINIy(&VU0); }
void VMINIz() { VU0.code = cpuRegs.code; _vuMINIz(&VU0); }
void VMINIw() { VU0.code = cpuRegs.code; _vuMINIw(&VU0); }
void VOPMULA() { VU0.code = cpuRegs.code; _vuOPMULA(&VU0); SYNCMSFLAGS(); }
void VOPMSUB() { VU0.code = cpuRegs.code; _vuOPMSUB(&VU0); SYNCMSFLAGS(); }
void VNOP() { VU0.code = cpuRegs.code; _vuNOP(&VU0); }
void VFTOI0() { VU0.code = cpuRegs.code; _vuFTOI0(&VU0); }
void VFTOI4() { VU0.code = cpuRegs.code; _vuFTOI4(&VU0); }
void VFTOI12() { VU0.code = cpuRegs.code; _vuFTOI12(&VU0); }
void VFTOI15() { VU0.code = cpuRegs.code; _vuFTOI15(&VU0); }
void VITOF0() { VU0.code = cpuRegs.code; _vuITOF0(&VU0); }
void VITOF4() { VU0.code = cpuRegs.code; _vuITOF4(&VU0); }
void VITOF12() { VU0.code = cpuRegs.code; _vuITOF12(&VU0); }
void VITOF15() { VU0.code = cpuRegs.code; _vuITOF15(&VU0); }
void VCLIPw() { VU0.code = cpuRegs.code; _vuCLIP(&VU0); VU0.VI[REG_CLIP_FLAG].UL = VU0.clipflag; }
void VDIV() { VU0.code = cpuRegs.code; _vuDIV(&VU0); SYNCFDIV(); }
void VSQRT() { VU0.code = cpuRegs.code; _vuSQRT(&VU0); SYNCFDIV(); }
void VRSQRT() { VU0.code = cpuRegs.code; _vuRSQRT(&VU0); SYNCFDIV(); }
void VIADD() { VU0.code = cpuRegs.code; _vuIADD(&VU0); }
void VIADDI() { VU0.code = cpuRegs.code; _vuIADDI(&VU0); }
void VIADDIU() { VU0.code = cpuRegs.code; _vuIADDIU(&VU0); }
void VIAND() { VU0.code = cpuRegs.code; _vuIAND(&VU0); }
void VIOR() { VU0.code = cpuRegs.code; _vuIOR(&VU0); }
void VISUB() { VU0.code = cpuRegs.code; _vuISUB(&VU0); }
void VISUBIU() { VU0.code = cpuRegs.code; _vuISUBIU(&VU0); }
void VMOVE() { VU0.code = cpuRegs.code; _vuMOVE(&VU0); }
void VMFIR() { VU0.code = cpuRegs.code; _vuMFIR(&VU0); }
void VMTIR() { VU0.code = cpuRegs.code; _vuMTIR(&VU0); }
void VMR32() { VU0.code = cpuRegs.code; _vuMR32(&VU0); }
void VLQ() { VU0.code = cpuRegs.code; _vuLQ(&VU0); }
void VLQD() { VU0.code = cpuRegs.code; _vuLQD(&VU0); }
void VLQI() { VU0.code = cpuRegs.code; _vuLQI(&VU0); }
void VSQ() { VU0.code = cpuRegs.code; _vuSQ(&VU0); }
void VSQD() { VU0.code = cpuRegs.code; _vuSQD(&VU0); }
void VSQI() { VU0.code = cpuRegs.code; _vuSQI(&VU0); }
void VILW() { VU0.code = cpuRegs.code; _vuILW(&VU0); }
void VISW() { VU0.code = cpuRegs.code; _vuISW(&VU0); }
void VILWR() { VU0.code = cpuRegs.code; _vuILWR(&VU0); }
void VISWR() { VU0.code = cpuRegs.code; _vuISWR(&VU0); }
void VRINIT() { VU0.code = cpuRegs.code; _vuRINIT(&VU0); }
void VRGET() { VU0.code = cpuRegs.code; _vuRGET(&VU0); }
void VRNEXT() { VU0.code = cpuRegs.code; _vuRNEXT(&VU0); }
void VRXOR() { VU0.code = cpuRegs.code; _vuRXOR(&VU0); }
void VWAITQ() { VU0.code = cpuRegs.code; _vuWAITQ(&VU0); }
void VFSAND() { VU0.code = cpuRegs.code; _vuFSAND(&VU0); }
void VFSEQ() { VU0.code = cpuRegs.code; _vuFSEQ(&VU0); }
void VFSOR() { VU0.code = cpuRegs.code; _vuFSOR(&VU0); }
void VFSSET() { VU0.code = cpuRegs.code; _vuFSSET(&VU0); }
void VFMAND() { VU0.code = cpuRegs.code; _vuFMAND(&VU0); }
void VFMEQ() { VU0.code = cpuRegs.code; _vuFMEQ(&VU0); }
void VFMOR() { VU0.code = cpuRegs.code; _vuFMOR(&VU0); }
void VFCAND() { VU0.code = cpuRegs.code; _vuFCAND(&VU0); }
void VFCEQ() { VU0.code = cpuRegs.code; _vuFCEQ(&VU0); }
void VFCOR() { VU0.code = cpuRegs.code; _vuFCOR(&VU0); }
void VFCSET() { VU0.code = cpuRegs.code; _vuFCSET(&VU0); }
void VFCGET() { VU0.code = cpuRegs.code; _vuFCGET(&VU0); }
void VXITOP() { VU0.code = cpuRegs.code; _vuXITOP(&VU0); }

View File

@ -20,11 +20,10 @@
#include "PrecompiledHeader.h" #include "PrecompiledHeader.h"
#include "Common.h" #include "Common.h"
#include "VUmicro.h"
#include <cmath> #include <cmath>
#include "VUmicro.h"
using namespace R5900; using namespace R5900;
#define VF_VAL(x) ((x==0x80000000)?0:(x)) #define VF_VAL(x) ((x==0x80000000)?0:(x))
@ -34,13 +33,7 @@ void vu0ResetRegs()
{ {
VU0.VI[REG_VPU_STAT].UL &= ~0xff; // stop vu0 VU0.VI[REG_VPU_STAT].UL &= ~0xff; // stop vu0
VU0.VI[REG_FBRST].UL &= ~0xff; // stop vu0 VU0.VI[REG_FBRST].UL &= ~0xff; // stop vu0
vif0Regs->stat.VEW = false; vif0Regs.stat.VEW = false;
}
void VU0MI_XGKICK() {
}
void VU0MI_XTOP() {
} }
void __fastcall vu0ExecMicro(u32 addr) { void __fastcall vu0ExecMicro(u32 addr) {
@ -58,362 +51,3 @@ void __fastcall vu0ExecMicro(u32 addr) {
_vuExecMicroDebug(VU0); _vuExecMicroDebug(VU0);
CpuVU0->ExecuteBlock(1); CpuVU0->ExecuteBlock(1);
} }
void VU0unknown() {
pxFailDev("Unknown VU micromode opcode called");
CPU_LOG("Unknown VU micromode opcode called");
}
void VU0regsunknown(_VURegsNum *VUregsn) {
pxFailDev("Unknown VU micromode opcode called");
CPU_LOG("Unknown VU micromode opcode called");
}
_vuRegsTables(VU0, VU0regs);
/****************************************/
/* VU Micromode Upper instructions */
/****************************************/
void VU0MI_ABS() { _vuABS(&VU0); }
void VU0MI_ADD() { _vuADD(&VU0); }
void VU0MI_ADDi() { _vuADDi(&VU0); }
void VU0MI_ADDq() { _vuADDq(&VU0); }
void VU0MI_ADDx() { _vuADDx(&VU0); }
void VU0MI_ADDy() { _vuADDy(&VU0); }
void VU0MI_ADDz() { _vuADDz(&VU0); }
void VU0MI_ADDw() { _vuADDw(&VU0); }
void VU0MI_ADDA() { _vuADDA(&VU0); }
void VU0MI_ADDAi() { _vuADDAi(&VU0); }
void VU0MI_ADDAq() { _vuADDAq(&VU0); }
void VU0MI_ADDAx() { _vuADDAx(&VU0); }
void VU0MI_ADDAy() { _vuADDAy(&VU0); }
void VU0MI_ADDAz() { _vuADDAz(&VU0); }
void VU0MI_ADDAw() { _vuADDAw(&VU0); }
void VU0MI_SUB() { _vuSUB(&VU0); }
void VU0MI_SUBi() { _vuSUBi(&VU0); }
void VU0MI_SUBq() { _vuSUBq(&VU0); }
void VU0MI_SUBx() { _vuSUBx(&VU0); }
void VU0MI_SUBy() { _vuSUBy(&VU0); }
void VU0MI_SUBz() { _vuSUBz(&VU0); }
void VU0MI_SUBw() { _vuSUBw(&VU0); }
void VU0MI_SUBA() { _vuSUBA(&VU0); }
void VU0MI_SUBAi() { _vuSUBAi(&VU0); }
void VU0MI_SUBAq() { _vuSUBAq(&VU0); }
void VU0MI_SUBAx() { _vuSUBAx(&VU0); }
void VU0MI_SUBAy() { _vuSUBAy(&VU0); }
void VU0MI_SUBAz() { _vuSUBAz(&VU0); }
void VU0MI_SUBAw() { _vuSUBAw(&VU0); }
void VU0MI_MUL() { _vuMUL(&VU0); }
void VU0MI_MULi() { _vuMULi(&VU0); }
void VU0MI_MULq() { _vuMULq(&VU0); }
void VU0MI_MULx() { _vuMULx(&VU0); }
void VU0MI_MULy() { _vuMULy(&VU0); }
void VU0MI_MULz() { _vuMULz(&VU0); }
void VU0MI_MULw() { _vuMULw(&VU0); }
void VU0MI_MULA() { _vuMULA(&VU0); }
void VU0MI_MULAi() { _vuMULAi(&VU0); }
void VU0MI_MULAq() { _vuMULAq(&VU0); }
void VU0MI_MULAx() { _vuMULAx(&VU0); }
void VU0MI_MULAy() { _vuMULAy(&VU0); }
void VU0MI_MULAz() { _vuMULAz(&VU0); }
void VU0MI_MULAw() { _vuMULAw(&VU0); }
void VU0MI_MADD() { _vuMADD(&VU0); }
void VU0MI_MADDi() { _vuMADDi(&VU0); }
void VU0MI_MADDq() { _vuMADDq(&VU0); }
void VU0MI_MADDx() { _vuMADDx(&VU0); }
void VU0MI_MADDy() { _vuMADDy(&VU0); }
void VU0MI_MADDz() { _vuMADDz(&VU0); }
void VU0MI_MADDw() { _vuMADDw(&VU0); }
void VU0MI_MADDA() { _vuMADDA(&VU0); }
void VU0MI_MADDAi() { _vuMADDAi(&VU0); }
void VU0MI_MADDAq() { _vuMADDAq(&VU0); }
void VU0MI_MADDAx() { _vuMADDAx(&VU0); }
void VU0MI_MADDAy() { _vuMADDAy(&VU0); }
void VU0MI_MADDAz() { _vuMADDAz(&VU0); }
void VU0MI_MADDAw() { _vuMADDAw(&VU0); }
void VU0MI_MSUB() { _vuMSUB(&VU0); }
void VU0MI_MSUBi() { _vuMSUBi(&VU0); }
void VU0MI_MSUBq() { _vuMSUBq(&VU0); }
void VU0MI_MSUBx() { _vuMSUBx(&VU0); }
void VU0MI_MSUBy() { _vuMSUBy(&VU0); }
void VU0MI_MSUBz() { _vuMSUBz(&VU0); }
void VU0MI_MSUBw() { _vuMSUBw(&VU0); }
void VU0MI_MSUBA() { _vuMSUBA(&VU0); }
void VU0MI_MSUBAi() { _vuMSUBAi(&VU0); }
void VU0MI_MSUBAq() { _vuMSUBAq(&VU0); }
void VU0MI_MSUBAx() { _vuMSUBAx(&VU0); }
void VU0MI_MSUBAy() { _vuMSUBAy(&VU0); }
void VU0MI_MSUBAz() { _vuMSUBAz(&VU0); }
void VU0MI_MSUBAw() { _vuMSUBAw(&VU0); }
void VU0MI_MAX() { _vuMAX(&VU0); }
void VU0MI_MAXi() { _vuMAXi(&VU0); }
void VU0MI_MAXx() { _vuMAXx(&VU0); }
void VU0MI_MAXy() { _vuMAXy(&VU0); }
void VU0MI_MAXz() { _vuMAXz(&VU0); }
void VU0MI_MAXw() { _vuMAXw(&VU0); }
void VU0MI_MINI() { _vuMINI(&VU0); }
void VU0MI_MINIi() { _vuMINIi(&VU0); }
void VU0MI_MINIx() { _vuMINIx(&VU0); }
void VU0MI_MINIy() { _vuMINIy(&VU0); }
void VU0MI_MINIz() { _vuMINIz(&VU0); }
void VU0MI_MINIw() { _vuMINIw(&VU0); }
void VU0MI_OPMULA() { _vuOPMULA(&VU0); }
void VU0MI_OPMSUB() { _vuOPMSUB(&VU0); }
void VU0MI_NOP() { _vuNOP(&VU0); }
void VU0MI_FTOI0() { _vuFTOI0(&VU0); }
void VU0MI_FTOI4() { _vuFTOI4(&VU0); }
void VU0MI_FTOI12() { _vuFTOI12(&VU0); }
void VU0MI_FTOI15() { _vuFTOI15(&VU0); }
void VU0MI_ITOF0() { _vuITOF0(&VU0); }
void VU0MI_ITOF4() { _vuITOF4(&VU0); }
void VU0MI_ITOF12() { _vuITOF12(&VU0); }
void VU0MI_ITOF15() { _vuITOF15(&VU0); }
void VU0MI_CLIP() { _vuCLIP(&VU0); }
/*****************************************/
/* VU Micromode Lower instructions */
/*****************************************/
void VU0MI_DIV() { _vuDIV(&VU0); }
void VU0MI_SQRT() { _vuSQRT(&VU0); }
void VU0MI_RSQRT() { _vuRSQRT(&VU0); }
void VU0MI_IADD() { _vuIADD(&VU0); }
void VU0MI_IADDI() { _vuIADDI(&VU0); }
void VU0MI_IADDIU() { _vuIADDIU(&VU0); }
void VU0MI_IAND() { _vuIAND(&VU0); }
void VU0MI_IOR() { _vuIOR(&VU0); }
void VU0MI_ISUB() { _vuISUB(&VU0); }
void VU0MI_ISUBIU() { _vuISUBIU(&VU0); }
void VU0MI_MOVE() { _vuMOVE(&VU0); }
void VU0MI_MFIR() { _vuMFIR(&VU0); }
void VU0MI_MTIR() { _vuMTIR(&VU0); }
void VU0MI_MR32() { _vuMR32(&VU0); }
void VU0MI_LQ() { _vuLQ(&VU0); }
void VU0MI_LQD() { _vuLQD(&VU0); }
void VU0MI_LQI() { _vuLQI(&VU0); }
void VU0MI_SQ() { _vuSQ(&VU0); }
void VU0MI_SQD() { _vuSQD(&VU0); }
void VU0MI_SQI() { _vuSQI(&VU0); }
void VU0MI_ILW() { _vuILW(&VU0); }
void VU0MI_ISW() { _vuISW(&VU0); }
void VU0MI_ILWR() { _vuILWR(&VU0); }
void VU0MI_ISWR() { _vuISWR(&VU0); }
void VU0MI_RINIT() { _vuRINIT(&VU0); }
void VU0MI_RGET() { _vuRGET(&VU0); }
void VU0MI_RNEXT() { _vuRNEXT(&VU0); }
void VU0MI_RXOR() { _vuRXOR(&VU0); }
void VU0MI_WAITQ() { _vuWAITQ(&VU0); }
void VU0MI_FSAND() { _vuFSAND(&VU0); }
void VU0MI_FSEQ() { _vuFSEQ(&VU0); }
void VU0MI_FSOR() { _vuFSOR(&VU0); }
void VU0MI_FSSET() { _vuFSSET(&VU0); }
void VU0MI_FMAND() { _vuFMAND(&VU0); }
void VU0MI_FMEQ() { _vuFMEQ(&VU0); }
void VU0MI_FMOR() { _vuFMOR(&VU0); }
void VU0MI_FCAND() { _vuFCAND(&VU0); }
void VU0MI_FCEQ() { _vuFCEQ(&VU0); }
void VU0MI_FCOR() { _vuFCOR(&VU0); }
void VU0MI_FCSET() { _vuFCSET(&VU0); }
void VU0MI_FCGET() { _vuFCGET(&VU0); }
void VU0MI_IBEQ() { _vuIBEQ(&VU0); }
void VU0MI_IBGEZ() { _vuIBGEZ(&VU0); }
void VU0MI_IBGTZ() { _vuIBGTZ(&VU0); }
void VU0MI_IBLTZ() { _vuIBLTZ(&VU0); }
void VU0MI_IBLEZ() { _vuIBLEZ(&VU0); }
void VU0MI_IBNE() { _vuIBNE(&VU0); }
void VU0MI_B() { _vuB(&VU0); }
void VU0MI_BAL() { _vuBAL(&VU0); }
void VU0MI_JR() { _vuJR(&VU0); }
void VU0MI_JALR() { _vuJALR(&VU0); }
void VU0MI_MFP() { _vuMFP(&VU0); }
void VU0MI_WAITP() { _vuWAITP(&VU0); }
void VU0MI_ESADD() { _vuESADD(&VU0); }
void VU0MI_ERSADD() { _vuERSADD(&VU0); }
void VU0MI_ELENG() { _vuELENG(&VU0); }
void VU0MI_ERLENG() { _vuERLENG(&VU0); }
void VU0MI_EATANxy() { _vuEATANxy(&VU0); }
void VU0MI_EATANxz() { _vuEATANxz(&VU0); }
void VU0MI_ESUM() { _vuESUM(&VU0); }
void VU0MI_ERCPR() { _vuERCPR(&VU0); }
void VU0MI_ESQRT() { _vuESQRT(&VU0); }
void VU0MI_ERSQRT() { _vuERSQRT(&VU0); }
void VU0MI_ESIN() { _vuESIN(&VU0); }
void VU0MI_EATAN() { _vuEATAN(&VU0); }
void VU0MI_EEXP() { _vuEEXP(&VU0); }
void VU0MI_XITOP() { _vuXITOP(&VU0); }
/****************************************/
/* VU Micromode Upper instructions */
/****************************************/
void VU0regsMI_ABS(_VURegsNum *VUregsn) { _vuRegsABS(&VU0, VUregsn); }
void VU0regsMI_ADD(_VURegsNum *VUregsn) { _vuRegsADD(&VU0, VUregsn); }
void VU0regsMI_ADDi(_VURegsNum *VUregsn) { _vuRegsADDi(&VU0, VUregsn); }
void VU0regsMI_ADDq(_VURegsNum *VUregsn) { _vuRegsADDq(&VU0, VUregsn); }
void VU0regsMI_ADDx(_VURegsNum *VUregsn) { _vuRegsADDx(&VU0, VUregsn); }
void VU0regsMI_ADDy(_VURegsNum *VUregsn) { _vuRegsADDy(&VU0, VUregsn); }
void VU0regsMI_ADDz(_VURegsNum *VUregsn) { _vuRegsADDz(&VU0, VUregsn); }
void VU0regsMI_ADDw(_VURegsNum *VUregsn) { _vuRegsADDw(&VU0, VUregsn); }
void VU0regsMI_ADDA(_VURegsNum *VUregsn) { _vuRegsADDA(&VU0, VUregsn); }
void VU0regsMI_ADDAi(_VURegsNum *VUregsn) { _vuRegsADDAi(&VU0, VUregsn); }
void VU0regsMI_ADDAq(_VURegsNum *VUregsn) { _vuRegsADDAq(&VU0, VUregsn); }
void VU0regsMI_ADDAx(_VURegsNum *VUregsn) { _vuRegsADDAx(&VU0, VUregsn); }
void VU0regsMI_ADDAy(_VURegsNum *VUregsn) { _vuRegsADDAy(&VU0, VUregsn); }
void VU0regsMI_ADDAz(_VURegsNum *VUregsn) { _vuRegsADDAz(&VU0, VUregsn); }
void VU0regsMI_ADDAw(_VURegsNum *VUregsn) { _vuRegsADDAw(&VU0, VUregsn); }
void VU0regsMI_SUB(_VURegsNum *VUregsn) { _vuRegsSUB(&VU0, VUregsn); }
void VU0regsMI_SUBi(_VURegsNum *VUregsn) { _vuRegsSUBi(&VU0, VUregsn); }
void VU0regsMI_SUBq(_VURegsNum *VUregsn) { _vuRegsSUBq(&VU0, VUregsn); }
void VU0regsMI_SUBx(_VURegsNum *VUregsn) { _vuRegsSUBx(&VU0, VUregsn); }
void VU0regsMI_SUBy(_VURegsNum *VUregsn) { _vuRegsSUBy(&VU0, VUregsn); }
void VU0regsMI_SUBz(_VURegsNum *VUregsn) { _vuRegsSUBz(&VU0, VUregsn); }
void VU0regsMI_SUBw(_VURegsNum *VUregsn) { _vuRegsSUBw(&VU0, VUregsn); }
void VU0regsMI_SUBA(_VURegsNum *VUregsn) { _vuRegsSUBA(&VU0, VUregsn); }
void VU0regsMI_SUBAi(_VURegsNum *VUregsn) { _vuRegsSUBAi(&VU0, VUregsn); }
void VU0regsMI_SUBAq(_VURegsNum *VUregsn) { _vuRegsSUBAq(&VU0, VUregsn); }
void VU0regsMI_SUBAx(_VURegsNum *VUregsn) { _vuRegsSUBAx(&VU0, VUregsn); }
void VU0regsMI_SUBAy(_VURegsNum *VUregsn) { _vuRegsSUBAy(&VU0, VUregsn); }
void VU0regsMI_SUBAz(_VURegsNum *VUregsn) { _vuRegsSUBAz(&VU0, VUregsn); }
void VU0regsMI_SUBAw(_VURegsNum *VUregsn) { _vuRegsSUBAw(&VU0, VUregsn); }
void VU0regsMI_MUL(_VURegsNum *VUregsn) { _vuRegsMUL(&VU0, VUregsn); }
void VU0regsMI_MULi(_VURegsNum *VUregsn) { _vuRegsMULi(&VU0, VUregsn); }
void VU0regsMI_MULq(_VURegsNum *VUregsn) { _vuRegsMULq(&VU0, VUregsn); }
void VU0regsMI_MULx(_VURegsNum *VUregsn) { _vuRegsMULx(&VU0, VUregsn); }
void VU0regsMI_MULy(_VURegsNum *VUregsn) { _vuRegsMULy(&VU0, VUregsn); }
void VU0regsMI_MULz(_VURegsNum *VUregsn) { _vuRegsMULz(&VU0, VUregsn); }
void VU0regsMI_MULw(_VURegsNum *VUregsn) { _vuRegsMULw(&VU0, VUregsn); }
void VU0regsMI_MULA(_VURegsNum *VUregsn) { _vuRegsMULA(&VU0, VUregsn); }
void VU0regsMI_MULAi(_VURegsNum *VUregsn) { _vuRegsMULAi(&VU0, VUregsn); }
void VU0regsMI_MULAq(_VURegsNum *VUregsn) { _vuRegsMULAq(&VU0, VUregsn); }
void VU0regsMI_MULAx(_VURegsNum *VUregsn) { _vuRegsMULAx(&VU0, VUregsn); }
void VU0regsMI_MULAy(_VURegsNum *VUregsn) { _vuRegsMULAy(&VU0, VUregsn); }
void VU0regsMI_MULAz(_VURegsNum *VUregsn) { _vuRegsMULAz(&VU0, VUregsn); }
void VU0regsMI_MULAw(_VURegsNum *VUregsn) { _vuRegsMULAw(&VU0, VUregsn); }
void VU0regsMI_MADD(_VURegsNum *VUregsn) { _vuRegsMADD(&VU0, VUregsn); }
void VU0regsMI_MADDi(_VURegsNum *VUregsn) { _vuRegsMADDi(&VU0, VUregsn); }
void VU0regsMI_MADDq(_VURegsNum *VUregsn) { _vuRegsMADDq(&VU0, VUregsn); }
void VU0regsMI_MADDx(_VURegsNum *VUregsn) { _vuRegsMADDx(&VU0, VUregsn); }
void VU0regsMI_MADDy(_VURegsNum *VUregsn) { _vuRegsMADDy(&VU0, VUregsn); }
void VU0regsMI_MADDz(_VURegsNum *VUregsn) { _vuRegsMADDz(&VU0, VUregsn); }
void VU0regsMI_MADDw(_VURegsNum *VUregsn) { _vuRegsMADDw(&VU0, VUregsn); }
void VU0regsMI_MADDA(_VURegsNum *VUregsn) { _vuRegsMADDA(&VU0, VUregsn); }
void VU0regsMI_MADDAi(_VURegsNum *VUregsn) { _vuRegsMADDAi(&VU0, VUregsn); }
void VU0regsMI_MADDAq(_VURegsNum *VUregsn) { _vuRegsMADDAq(&VU0, VUregsn); }
void VU0regsMI_MADDAx(_VURegsNum *VUregsn) { _vuRegsMADDAx(&VU0, VUregsn); }
void VU0regsMI_MADDAy(_VURegsNum *VUregsn) { _vuRegsMADDAy(&VU0, VUregsn); }
void VU0regsMI_MADDAz(_VURegsNum *VUregsn) { _vuRegsMADDAz(&VU0, VUregsn); }
void VU0regsMI_MADDAw(_VURegsNum *VUregsn) { _vuRegsMADDAw(&VU0, VUregsn); }
void VU0regsMI_MSUB(_VURegsNum *VUregsn) { _vuRegsMSUB(&VU0, VUregsn); }
void VU0regsMI_MSUBi(_VURegsNum *VUregsn) { _vuRegsMSUBi(&VU0, VUregsn); }
void VU0regsMI_MSUBq(_VURegsNum *VUregsn) { _vuRegsMSUBq(&VU0, VUregsn); }
void VU0regsMI_MSUBx(_VURegsNum *VUregsn) { _vuRegsMSUBx(&VU0, VUregsn); }
void VU0regsMI_MSUBy(_VURegsNum *VUregsn) { _vuRegsMSUBy(&VU0, VUregsn); }
void VU0regsMI_MSUBz(_VURegsNum *VUregsn) { _vuRegsMSUBz(&VU0, VUregsn); }
void VU0regsMI_MSUBw(_VURegsNum *VUregsn) { _vuRegsMSUBw(&VU0, VUregsn); }
void VU0regsMI_MSUBA(_VURegsNum *VUregsn) { _vuRegsMSUBA(&VU0, VUregsn); }
void VU0regsMI_MSUBAi(_VURegsNum *VUregsn) { _vuRegsMSUBAi(&VU0, VUregsn); }
void VU0regsMI_MSUBAq(_VURegsNum *VUregsn) { _vuRegsMSUBAq(&VU0, VUregsn); }
void VU0regsMI_MSUBAx(_VURegsNum *VUregsn) { _vuRegsMSUBAx(&VU0, VUregsn); }
void VU0regsMI_MSUBAy(_VURegsNum *VUregsn) { _vuRegsMSUBAy(&VU0, VUregsn); }
void VU0regsMI_MSUBAz(_VURegsNum *VUregsn) { _vuRegsMSUBAz(&VU0, VUregsn); }
void VU0regsMI_MSUBAw(_VURegsNum *VUregsn) { _vuRegsMSUBAw(&VU0, VUregsn); }
void VU0regsMI_MAX(_VURegsNum *VUregsn) { _vuRegsMAX(&VU0, VUregsn); }
void VU0regsMI_MAXi(_VURegsNum *VUregsn) { _vuRegsMAXi(&VU0, VUregsn); }
void VU0regsMI_MAXx(_VURegsNum *VUregsn) { _vuRegsMAXx(&VU0, VUregsn); }
void VU0regsMI_MAXy(_VURegsNum *VUregsn) { _vuRegsMAXy(&VU0, VUregsn); }
void VU0regsMI_MAXz(_VURegsNum *VUregsn) { _vuRegsMAXz(&VU0, VUregsn); }
void VU0regsMI_MAXw(_VURegsNum *VUregsn) { _vuRegsMAXw(&VU0, VUregsn); }
void VU0regsMI_MINI(_VURegsNum *VUregsn) { _vuRegsMINI(&VU0, VUregsn); }
void VU0regsMI_MINIi(_VURegsNum *VUregsn) { _vuRegsMINIi(&VU0, VUregsn); }
void VU0regsMI_MINIx(_VURegsNum *VUregsn) { _vuRegsMINIx(&VU0, VUregsn); }
void VU0regsMI_MINIy(_VURegsNum *VUregsn) { _vuRegsMINIy(&VU0, VUregsn); }
void VU0regsMI_MINIz(_VURegsNum *VUregsn) { _vuRegsMINIz(&VU0, VUregsn); }
void VU0regsMI_MINIw(_VURegsNum *VUregsn) { _vuRegsMINIw(&VU0, VUregsn); }
void VU0regsMI_OPMULA(_VURegsNum *VUregsn) { _vuRegsOPMULA(&VU0, VUregsn); }
void VU0regsMI_OPMSUB(_VURegsNum *VUregsn) { _vuRegsOPMSUB(&VU0, VUregsn); }
void VU0regsMI_NOP(_VURegsNum *VUregsn) { _vuRegsNOP(&VU0, VUregsn); }
void VU0regsMI_FTOI0(_VURegsNum *VUregsn) { _vuRegsFTOI0(&VU0, VUregsn); }
void VU0regsMI_FTOI4(_VURegsNum *VUregsn) { _vuRegsFTOI4(&VU0, VUregsn); }
void VU0regsMI_FTOI12(_VURegsNum *VUregsn) { _vuRegsFTOI12(&VU0, VUregsn); }
void VU0regsMI_FTOI15(_VURegsNum *VUregsn) { _vuRegsFTOI15(&VU0, VUregsn); }
void VU0regsMI_ITOF0(_VURegsNum *VUregsn) { _vuRegsITOF0(&VU0, VUregsn); }
void VU0regsMI_ITOF4(_VURegsNum *VUregsn) { _vuRegsITOF4(&VU0, VUregsn); }
void VU0regsMI_ITOF12(_VURegsNum *VUregsn) { _vuRegsITOF12(&VU0, VUregsn); }
void VU0regsMI_ITOF15(_VURegsNum *VUregsn) { _vuRegsITOF15(&VU0, VUregsn); }
void VU0regsMI_CLIP(_VURegsNum *VUregsn) { _vuRegsCLIP(&VU0, VUregsn); }
/*****************************************/
/* VU Micromode Lower instructions */
/*****************************************/
void VU0regsMI_DIV(_VURegsNum *VUregsn) { _vuRegsDIV(&VU0, VUregsn); }
void VU0regsMI_SQRT(_VURegsNum *VUregsn) { _vuRegsSQRT(&VU0, VUregsn); }
void VU0regsMI_RSQRT(_VURegsNum *VUregsn) { _vuRegsRSQRT(&VU0, VUregsn); }
void VU0regsMI_IADD(_VURegsNum *VUregsn) { _vuRegsIADD(&VU0, VUregsn); }
void VU0regsMI_IADDI(_VURegsNum *VUregsn) { _vuRegsIADDI(&VU0, VUregsn); }
void VU0regsMI_IADDIU(_VURegsNum *VUregsn) { _vuRegsIADDIU(&VU0, VUregsn); }
void VU0regsMI_IAND(_VURegsNum *VUregsn) { _vuRegsIAND(&VU0, VUregsn); }
void VU0regsMI_IOR(_VURegsNum *VUregsn) { _vuRegsIOR(&VU0, VUregsn); }
void VU0regsMI_ISUB(_VURegsNum *VUregsn) { _vuRegsISUB(&VU0, VUregsn); }
void VU0regsMI_ISUBIU(_VURegsNum *VUregsn) { _vuRegsISUBIU(&VU0, VUregsn); }
void VU0regsMI_MOVE(_VURegsNum *VUregsn) { _vuRegsMOVE(&VU0, VUregsn); }
void VU0regsMI_MFIR(_VURegsNum *VUregsn) { _vuRegsMFIR(&VU0, VUregsn); }
void VU0regsMI_MTIR(_VURegsNum *VUregsn) { _vuRegsMTIR(&VU0, VUregsn); }
void VU0regsMI_MR32(_VURegsNum *VUregsn) { _vuRegsMR32(&VU0, VUregsn); }
void VU0regsMI_LQ(_VURegsNum *VUregsn) { _vuRegsLQ(&VU0, VUregsn); }
void VU0regsMI_LQD(_VURegsNum *VUregsn) { _vuRegsLQD(&VU0, VUregsn); }
void VU0regsMI_LQI(_VURegsNum *VUregsn) { _vuRegsLQI(&VU0, VUregsn); }
void VU0regsMI_SQ(_VURegsNum *VUregsn) { _vuRegsSQ(&VU0, VUregsn); }
void VU0regsMI_SQD(_VURegsNum *VUregsn) { _vuRegsSQD(&VU0, VUregsn); }
void VU0regsMI_SQI(_VURegsNum *VUregsn) { _vuRegsSQI(&VU0, VUregsn); }
void VU0regsMI_ILW(_VURegsNum *VUregsn) { _vuRegsILW(&VU0, VUregsn); }
void VU0regsMI_ISW(_VURegsNum *VUregsn) { _vuRegsISW(&VU0, VUregsn); }
void VU0regsMI_ILWR(_VURegsNum *VUregsn) { _vuRegsILWR(&VU0, VUregsn); }
void VU0regsMI_ISWR(_VURegsNum *VUregsn) { _vuRegsISWR(&VU0, VUregsn); }
void VU0regsMI_RINIT(_VURegsNum *VUregsn) { _vuRegsRINIT(&VU0, VUregsn); }
void VU0regsMI_RGET(_VURegsNum *VUregsn) { _vuRegsRGET(&VU0, VUregsn); }
void VU0regsMI_RNEXT(_VURegsNum *VUregsn) { _vuRegsRNEXT(&VU0, VUregsn); }
void VU0regsMI_RXOR(_VURegsNum *VUregsn) { _vuRegsRXOR(&VU0, VUregsn); }
void VU0regsMI_WAITQ(_VURegsNum *VUregsn) { _vuRegsWAITQ(&VU0, VUregsn); }
void VU0regsMI_FSAND(_VURegsNum *VUregsn) { _vuRegsFSAND(&VU0, VUregsn); }
void VU0regsMI_FSEQ(_VURegsNum *VUregsn) { _vuRegsFSEQ(&VU0, VUregsn); }
void VU0regsMI_FSOR(_VURegsNum *VUregsn) { _vuRegsFSOR(&VU0, VUregsn); }
void VU0regsMI_FSSET(_VURegsNum *VUregsn) { _vuRegsFSSET(&VU0, VUregsn); }
void VU0regsMI_FMAND(_VURegsNum *VUregsn) { _vuRegsFMAND(&VU0, VUregsn); }
void VU0regsMI_FMEQ(_VURegsNum *VUregsn) { _vuRegsFMEQ(&VU0, VUregsn); }
void VU0regsMI_FMOR(_VURegsNum *VUregsn) { _vuRegsFMOR(&VU0, VUregsn); }
void VU0regsMI_FCAND(_VURegsNum *VUregsn) { _vuRegsFCAND(&VU0, VUregsn); }
void VU0regsMI_FCEQ(_VURegsNum *VUregsn) { _vuRegsFCEQ(&VU0, VUregsn); }
void VU0regsMI_FCOR(_VURegsNum *VUregsn) { _vuRegsFCOR(&VU0, VUregsn); }
void VU0regsMI_FCSET(_VURegsNum *VUregsn) { _vuRegsFCSET(&VU0, VUregsn); }
void VU0regsMI_FCGET(_VURegsNum *VUregsn) { _vuRegsFCGET(&VU0, VUregsn); }
void VU0regsMI_IBEQ(_VURegsNum *VUregsn) { _vuRegsIBEQ(&VU0, VUregsn); }
void VU0regsMI_IBGEZ(_VURegsNum *VUregsn) { _vuRegsIBGEZ(&VU0, VUregsn); }
void VU0regsMI_IBGTZ(_VURegsNum *VUregsn) { _vuRegsIBGTZ(&VU0, VUregsn); }
void VU0regsMI_IBLTZ(_VURegsNum *VUregsn) { _vuRegsIBLTZ(&VU0, VUregsn); }
void VU0regsMI_IBLEZ(_VURegsNum *VUregsn) { _vuRegsIBLEZ(&VU0, VUregsn); }
void VU0regsMI_IBNE(_VURegsNum *VUregsn) { _vuRegsIBNE(&VU0, VUregsn); }
void VU0regsMI_B(_VURegsNum *VUregsn) { _vuRegsB(&VU0, VUregsn); }
void VU0regsMI_BAL(_VURegsNum *VUregsn) { _vuRegsBAL(&VU0, VUregsn); }
void VU0regsMI_JR(_VURegsNum *VUregsn) { _vuRegsJR(&VU0, VUregsn); }
void VU0regsMI_JALR(_VURegsNum *VUregsn) { _vuRegsJALR(&VU0, VUregsn); }
void VU0regsMI_MFP(_VURegsNum *VUregsn) { _vuRegsMFP(&VU0, VUregsn); }
void VU0regsMI_WAITP(_VURegsNum *VUregsn) { _vuRegsWAITP(&VU0, VUregsn); }
void VU0regsMI_ESADD(_VURegsNum *VUregsn) { _vuRegsESADD(&VU0, VUregsn); }
void VU0regsMI_ERSADD(_VURegsNum *VUregsn) { _vuRegsERSADD(&VU0, VUregsn); }
void VU0regsMI_ELENG(_VURegsNum *VUregsn) { _vuRegsELENG(&VU0, VUregsn); }
void VU0regsMI_ERLENG(_VURegsNum *VUregsn) { _vuRegsERLENG(&VU0, VUregsn); }
void VU0regsMI_EATANxy(_VURegsNum *VUregsn) { _vuRegsEATANxy(&VU0, VUregsn); }
void VU0regsMI_EATANxz(_VURegsNum *VUregsn) { _vuRegsEATANxz(&VU0, VUregsn); }
void VU0regsMI_ESUM(_VURegsNum *VUregsn) { _vuRegsESUM(&VU0, VUregsn); }
void VU0regsMI_ERCPR(_VURegsNum *VUregsn) { _vuRegsERCPR(&VU0, VUregsn); }
void VU0regsMI_ESQRT(_VURegsNum *VUregsn) { _vuRegsESQRT(&VU0, VUregsn); }
void VU0regsMI_ERSQRT(_VURegsNum *VUregsn) { _vuRegsERSQRT(&VU0, VUregsn); }
void VU0regsMI_ESIN(_VURegsNum *VUregsn) { _vuRegsESIN(&VU0, VUregsn); }
void VU0regsMI_EATAN(_VURegsNum *VUregsn) { _vuRegsEATAN(&VU0, VUregsn); }
void VU0regsMI_EEXP(_VURegsNum *VUregsn) { _vuRegsEEXP(&VU0, VUregsn); }
void VU0regsMI_XITOP(_VURegsNum *VUregsn) { _vuRegsXITOP(&VU0, VUregsn); }
void VU0regsMI_XGKICK(_VURegsNum *VUregsn) { _vuRegsXGKICK(&VU0, VUregsn); }
void VU0regsMI_XTOP(_VURegsNum *VUregsn) { _vuRegsXTOP(&VU0, VUregsn); }

View File

@ -21,15 +21,13 @@
extern void _vuFlushAll(VURegs* VU); extern void _vuFlushAll(VURegs* VU);
_vuTables(VU0, VU0); static void _vu0ExecUpper(VURegs* VU, u32 *ptr) {
void _vu0ExecUpper(VURegs* VU, u32 *ptr) {
VU->code = ptr[1]; VU->code = ptr[1];
IdebugUPPER(VU0); IdebugUPPER(VU0);
VU0_UPPER_OPCODE[VU->code & 0x3f](); VU0_UPPER_OPCODE[VU->code & 0x3f]();
} }
void _vu0ExecLower(VURegs* VU, u32 *ptr) { static void _vu0ExecLower(VURegs* VU, u32 *ptr) {
VU->code = ptr[0]; VU->code = ptr[0];
IdebugLOWER(VU0); IdebugLOWER(VU0);
VU0_LOWER_OPCODE[VU->code >> 25](); VU0_LOWER_OPCODE[VU->code >> 25]();
@ -49,15 +47,6 @@ static void _vu0Exec(VURegs* VU)
int vireg; int vireg;
int discard=0; int discard=0;
if(VU0.VI[REG_TPC].UL >= VU0.maxmicro){
#ifdef CPU_LOG
Console.WriteLn("VU0 memory overflow!!: %x", VU->VI[REG_TPC].UL);
#endif
VU0.VI[REG_VPU_STAT].UL&= ~0x1;
VU->cycle++;
return;
}
ptr = (u32*)&VU->Micro[VU->VI[REG_TPC].UL]; ptr = (u32*)&VU->Micro[VU->VI[REG_TPC].UL];
VU->VI[REG_TPC].UL+=8; VU->VI[REG_TPC].UL+=8;
@ -166,21 +155,15 @@ static void _vu0Exec(VURegs* VU)
if( VU->ebit-- == 1 ) { if( VU->ebit-- == 1 ) {
_vuFlushAll(VU); _vuFlushAll(VU);
VU0.VI[REG_VPU_STAT].UL&= ~0x1; /* E flag */ VU0.VI[REG_VPU_STAT].UL&= ~0x1; /* E flag */
vif0Regs->stat.VEW = false; vif0Regs.stat.VEW = false;
} }
} }
} }
void vu0Exec(VURegs* VU) void vu0Exec(VURegs* VU)
{ {
if (VU->VI[REG_TPC].UL >= VU->maxmicro) { VU0.VI[REG_TPC].UL &= VU0_PROGMASK;
#ifdef CPU_LOG
Console.Warning("VU0 memory overflow!!: %x", VU->VI[REG_TPC].UL);
#endif
VU0.VI[REG_VPU_STAT].UL&= ~0x1;
} else {
_vu0Exec(VU); _vu0Exec(VU);
}
VU->cycle++; VU->cycle++;
if (VU->VI[0].UL != 0) DbgCon.Error("VI[0] != 0!!!!\n"); if (VU->VI[0].UL != 0) DbgCon.Error("VI[0] != 0!!!!\n");

View File

@ -24,8 +24,6 @@
#include "VUmicro.h" #include "VUmicro.h"
VURegs* g_pVU1;
#ifdef PCSX2_DEBUG #ifdef PCSX2_DEBUG
u32 vudump = 0; u32 vudump = 0;
#endif #endif
@ -37,7 +35,7 @@ void vu1ResetRegs()
{ {
VU0.VI[REG_VPU_STAT].UL &= ~0xff00; // stop vu1 VU0.VI[REG_VPU_STAT].UL &= ~0xff00; // stop vu1
VU0.VI[REG_FBRST].UL &= ~0xff00; // stop vu1 VU0.VI[REG_FBRST].UL &= ~0xff00; // stop vu1
vif1Regs->stat.VEW = false; vif1Regs.stat.VEW = false;
} }
void vu1Finish() { void vu1Finish() {
@ -58,373 +56,9 @@ void __fastcall vu1ExecMicro(u32 addr)
VU0.VI[REG_VPU_STAT].UL &= ~0xFF00; VU0.VI[REG_VPU_STAT].UL &= ~0xFF00;
VU0.VI[REG_VPU_STAT].UL |= 0x0100; VU0.VI[REG_VPU_STAT].UL |= 0x0100;
vif1Regs->stat.VEW = true; vif1Regs.stat.VEW = true;
if ((s32)addr != -1) VU1.VI[REG_TPC].UL = addr; if ((s32)addr != -1) VU1.VI[REG_TPC].UL = addr;
_vuExecMicroDebug(VU1); _vuExecMicroDebug(VU1);
CpuVU1->Execute(vu1RunCycles); CpuVU1->Execute(vu1RunCycles);
} }
_vuRegsTables(VU1, VU1regs);
void VU1unknown() {
//assert(0);
CPU_LOG("Unknown VU micromode opcode called");
}
void VU1regsunknown(_VURegsNum *VUregsn) {
//assert(0);
CPU_LOG("Unknown VU micromode opcode called");
}
/****************************************/
/* VU Micromode Upper instructions */
/****************************************/
void VU1MI_ABS() { _vuABS(&VU1); }
void VU1MI_ADD() { _vuADD(&VU1); }
void VU1MI_ADDi() { _vuADDi(&VU1); }
void VU1MI_ADDq() { _vuADDq(&VU1); }
void VU1MI_ADDx() { _vuADDx(&VU1); }
void VU1MI_ADDy() { _vuADDy(&VU1); }
void VU1MI_ADDz() { _vuADDz(&VU1); }
void VU1MI_ADDw() { _vuADDw(&VU1); }
void VU1MI_ADDA() { _vuADDA(&VU1); }
void VU1MI_ADDAi() { _vuADDAi(&VU1); }
void VU1MI_ADDAq() { _vuADDAq(&VU1); }
void VU1MI_ADDAx() { _vuADDAx(&VU1); }
void VU1MI_ADDAy() { _vuADDAy(&VU1); }
void VU1MI_ADDAz() { _vuADDAz(&VU1); }
void VU1MI_ADDAw() { _vuADDAw(&VU1); }
void VU1MI_SUB() { _vuSUB(&VU1); }
void VU1MI_SUBi() { _vuSUBi(&VU1); }
void VU1MI_SUBq() { _vuSUBq(&VU1); }
void VU1MI_SUBx() { _vuSUBx(&VU1); }
void VU1MI_SUBy() { _vuSUBy(&VU1); }
void VU1MI_SUBz() { _vuSUBz(&VU1); }
void VU1MI_SUBw() { _vuSUBw(&VU1); }
void VU1MI_SUBA() { _vuSUBA(&VU1); }
void VU1MI_SUBAi() { _vuSUBAi(&VU1); }
void VU1MI_SUBAq() { _vuSUBAq(&VU1); }
void VU1MI_SUBAx() { _vuSUBAx(&VU1); }
void VU1MI_SUBAy() { _vuSUBAy(&VU1); }
void VU1MI_SUBAz() { _vuSUBAz(&VU1); }
void VU1MI_SUBAw() { _vuSUBAw(&VU1); }
void VU1MI_MUL() { _vuMUL(&VU1); }
void VU1MI_MULi() { _vuMULi(&VU1); }
void VU1MI_MULq() { _vuMULq(&VU1); }
void VU1MI_MULx() { _vuMULx(&VU1); }
void VU1MI_MULy() { _vuMULy(&VU1); }
void VU1MI_MULz() { _vuMULz(&VU1); }
void VU1MI_MULw() { _vuMULw(&VU1); }
void VU1MI_MULA() { _vuMULA(&VU1); }
void VU1MI_MULAi() { _vuMULAi(&VU1); }
void VU1MI_MULAq() { _vuMULAq(&VU1); }
void VU1MI_MULAx() { _vuMULAx(&VU1); }
void VU1MI_MULAy() { _vuMULAy(&VU1); }
void VU1MI_MULAz() { _vuMULAz(&VU1); }
void VU1MI_MULAw() { _vuMULAw(&VU1); }
void VU1MI_MADD() { _vuMADD(&VU1); }
void VU1MI_MADDi() { _vuMADDi(&VU1); }
void VU1MI_MADDq() { _vuMADDq(&VU1); }
void VU1MI_MADDx() { _vuMADDx(&VU1); }
void VU1MI_MADDy() { _vuMADDy(&VU1); }
void VU1MI_MADDz() { _vuMADDz(&VU1); }
void VU1MI_MADDw() { _vuMADDw(&VU1); }
void VU1MI_MADDA() { _vuMADDA(&VU1); }
void VU1MI_MADDAi() { _vuMADDAi(&VU1); }
void VU1MI_MADDAq() { _vuMADDAq(&VU1); }
void VU1MI_MADDAx() { _vuMADDAx(&VU1); }
void VU1MI_MADDAy() { _vuMADDAy(&VU1); }
void VU1MI_MADDAz() { _vuMADDAz(&VU1); }
void VU1MI_MADDAw() { _vuMADDAw(&VU1); }
void VU1MI_MSUB() { _vuMSUB(&VU1); }
void VU1MI_MSUBi() { _vuMSUBi(&VU1); }
void VU1MI_MSUBq() { _vuMSUBq(&VU1); }
void VU1MI_MSUBx() { _vuMSUBx(&VU1); }
void VU1MI_MSUBy() { _vuMSUBy(&VU1); }
void VU1MI_MSUBz() { _vuMSUBz(&VU1); }
void VU1MI_MSUBw() { _vuMSUBw(&VU1); }
void VU1MI_MSUBA() { _vuMSUBA(&VU1); }
void VU1MI_MSUBAi() { _vuMSUBAi(&VU1); }
void VU1MI_MSUBAq() { _vuMSUBAq(&VU1); }
void VU1MI_MSUBAx() { _vuMSUBAx(&VU1); }
void VU1MI_MSUBAy() { _vuMSUBAy(&VU1); }
void VU1MI_MSUBAz() { _vuMSUBAz(&VU1); }
void VU1MI_MSUBAw() { _vuMSUBAw(&VU1); }
void VU1MI_MAX() { _vuMAX(&VU1); }
void VU1MI_MAXi() { _vuMAXi(&VU1); }
void VU1MI_MAXx() { _vuMAXx(&VU1); }
void VU1MI_MAXy() { _vuMAXy(&VU1); }
void VU1MI_MAXz() { _vuMAXz(&VU1); }
void VU1MI_MAXw() { _vuMAXw(&VU1); }
void VU1MI_MINI() { _vuMINI(&VU1); }
void VU1MI_MINIi() { _vuMINIi(&VU1); }
void VU1MI_MINIx() { _vuMINIx(&VU1); }
void VU1MI_MINIy() { _vuMINIy(&VU1); }
void VU1MI_MINIz() { _vuMINIz(&VU1); }
void VU1MI_MINIw() { _vuMINIw(&VU1); }
void VU1MI_OPMULA() { _vuOPMULA(&VU1); }
void VU1MI_OPMSUB() { _vuOPMSUB(&VU1); }
void VU1MI_NOP() { _vuNOP(&VU1); }
void VU1MI_FTOI0() { _vuFTOI0(&VU1); }
void VU1MI_FTOI4() { _vuFTOI4(&VU1); }
void VU1MI_FTOI12() { _vuFTOI12(&VU1); }
void VU1MI_FTOI15() { _vuFTOI15(&VU1); }
void VU1MI_ITOF0() { _vuITOF0(&VU1); }
void VU1MI_ITOF4() { _vuITOF4(&VU1); }
void VU1MI_ITOF12() { _vuITOF12(&VU1); }
void VU1MI_ITOF15() { _vuITOF15(&VU1); }
void VU1MI_CLIP() { _vuCLIP(&VU1); }
/*****************************************/
/* VU Micromode Lower instructions */
/*****************************************/
void VU1MI_DIV() { _vuDIV(&VU1); }
void VU1MI_SQRT() { _vuSQRT(&VU1); }
void VU1MI_RSQRT() { _vuRSQRT(&VU1); }
void VU1MI_IADD() { _vuIADD(&VU1); }
void VU1MI_IADDI() { _vuIADDI(&VU1); }
void VU1MI_IADDIU() { _vuIADDIU(&VU1); }
void VU1MI_IAND() { _vuIAND(&VU1); }
void VU1MI_IOR() { _vuIOR(&VU1); }
void VU1MI_ISUB() { _vuISUB(&VU1); }
void VU1MI_ISUBIU() { _vuISUBIU(&VU1); }
void VU1MI_MOVE() { _vuMOVE(&VU1); }
void VU1MI_MFIR() { _vuMFIR(&VU1); }
void VU1MI_MTIR() { _vuMTIR(&VU1); }
void VU1MI_MR32() { _vuMR32(&VU1); }
void VU1MI_LQ() { _vuLQ(&VU1); }
void VU1MI_LQD() { _vuLQD(&VU1); }
void VU1MI_LQI() { _vuLQI(&VU1); }
void VU1MI_SQ() { _vuSQ(&VU1); }
void VU1MI_SQD() { _vuSQD(&VU1); }
void VU1MI_SQI() { _vuSQI(&VU1); }
void VU1MI_ILW() { _vuILW(&VU1); }
void VU1MI_ISW() { _vuISW(&VU1); }
void VU1MI_ILWR() { _vuILWR(&VU1); }
void VU1MI_ISWR() { _vuISWR(&VU1); }
void VU1MI_RINIT() { _vuRINIT(&VU1); }
void VU1MI_RGET() { _vuRGET(&VU1); }
void VU1MI_RNEXT() { _vuRNEXT(&VU1); }
void VU1MI_RXOR() { _vuRXOR(&VU1); }
void VU1MI_WAITQ() { _vuWAITQ(&VU1); }
void VU1MI_FSAND() { _vuFSAND(&VU1); }
void VU1MI_FSEQ() { _vuFSEQ(&VU1); }
void VU1MI_FSOR() { _vuFSOR(&VU1); }
void VU1MI_FSSET() { _vuFSSET(&VU1); }
void VU1MI_FMAND() { _vuFMAND(&VU1); }
void VU1MI_FMEQ() { _vuFMEQ(&VU1); }
void VU1MI_FMOR() { _vuFMOR(&VU1); }
void VU1MI_FCAND() { _vuFCAND(&VU1); }
void VU1MI_FCEQ() { _vuFCEQ(&VU1); }
void VU1MI_FCOR() { _vuFCOR(&VU1); }
void VU1MI_FCSET() { _vuFCSET(&VU1); }
void VU1MI_FCGET() { _vuFCGET(&VU1); }
void VU1MI_IBEQ() { _vuIBEQ(&VU1); }
void VU1MI_IBGEZ() { _vuIBGEZ(&VU1); }
void VU1MI_IBGTZ() { _vuIBGTZ(&VU1); }
void VU1MI_IBLTZ() { _vuIBLTZ(&VU1); }
void VU1MI_IBLEZ() { _vuIBLEZ(&VU1); }
void VU1MI_IBNE() { _vuIBNE(&VU1); }
void VU1MI_B() { _vuB(&VU1); }
void VU1MI_BAL() { _vuBAL(&VU1); }
void VU1MI_JR() { _vuJR(&VU1); }
void VU1MI_JALR() { _vuJALR(&VU1); }
void VU1MI_MFP() { _vuMFP(&VU1); }
void VU1MI_WAITP() { _vuWAITP(&VU1); }
void VU1MI_ESADD() { _vuESADD(&VU1); }
void VU1MI_ERSADD() { _vuERSADD(&VU1); }
void VU1MI_ELENG() { _vuELENG(&VU1); }
void VU1MI_ERLENG() { _vuERLENG(&VU1); }
void VU1MI_EATANxy() { _vuEATANxy(&VU1); }
void VU1MI_EATANxz() { _vuEATANxz(&VU1); }
void VU1MI_ESUM() { _vuESUM(&VU1); }
void VU1MI_ERCPR() { _vuERCPR(&VU1); }
void VU1MI_ESQRT() { _vuESQRT(&VU1); }
void VU1MI_ERSQRT() { _vuERSQRT(&VU1); }
void VU1MI_ESIN() { _vuESIN(&VU1); }
void VU1MI_EATAN() { _vuEATAN(&VU1); }
void VU1MI_EEXP() { _vuEEXP(&VU1); }
void VU1MI_XITOP() { _vuXITOP(&VU1); }
void VU1MI_XGKICK() { _vuXGKICK(&VU1); }
void VU1MI_XTOP() { _vuXTOP(&VU1); }
/****************************************/
/* VU Micromode Upper instructions */
/****************************************/
void VU1regsMI_ABS(_VURegsNum *VUregsn) { _vuRegsABS(&VU1, VUregsn); }
void VU1regsMI_ADD(_VURegsNum *VUregsn) { _vuRegsADD(&VU1, VUregsn); }
void VU1regsMI_ADDi(_VURegsNum *VUregsn) { _vuRegsADDi(&VU1, VUregsn); }
void VU1regsMI_ADDq(_VURegsNum *VUregsn) { _vuRegsADDq(&VU1, VUregsn); }
void VU1regsMI_ADDx(_VURegsNum *VUregsn) { _vuRegsADDx(&VU1, VUregsn); }
void VU1regsMI_ADDy(_VURegsNum *VUregsn) { _vuRegsADDy(&VU1, VUregsn); }
void VU1regsMI_ADDz(_VURegsNum *VUregsn) { _vuRegsADDz(&VU1, VUregsn); }
void VU1regsMI_ADDw(_VURegsNum *VUregsn) { _vuRegsADDw(&VU1, VUregsn); }
void VU1regsMI_ADDA(_VURegsNum *VUregsn) { _vuRegsADDA(&VU1, VUregsn); }
void VU1regsMI_ADDAi(_VURegsNum *VUregsn) { _vuRegsADDAi(&VU1, VUregsn); }
void VU1regsMI_ADDAq(_VURegsNum *VUregsn) { _vuRegsADDAq(&VU1, VUregsn); }
void VU1regsMI_ADDAx(_VURegsNum *VUregsn) { _vuRegsADDAx(&VU1, VUregsn); }
void VU1regsMI_ADDAy(_VURegsNum *VUregsn) { _vuRegsADDAy(&VU1, VUregsn); }
void VU1regsMI_ADDAz(_VURegsNum *VUregsn) { _vuRegsADDAz(&VU1, VUregsn); }
void VU1regsMI_ADDAw(_VURegsNum *VUregsn) { _vuRegsADDAw(&VU1, VUregsn); }
void VU1regsMI_SUB(_VURegsNum *VUregsn) { _vuRegsSUB(&VU1, VUregsn); }
void VU1regsMI_SUBi(_VURegsNum *VUregsn) { _vuRegsSUBi(&VU1, VUregsn); }
void VU1regsMI_SUBq(_VURegsNum *VUregsn) { _vuRegsSUBq(&VU1, VUregsn); }
void VU1regsMI_SUBx(_VURegsNum *VUregsn) { _vuRegsSUBx(&VU1, VUregsn); }
void VU1regsMI_SUBy(_VURegsNum *VUregsn) { _vuRegsSUBy(&VU1, VUregsn); }
void VU1regsMI_SUBz(_VURegsNum *VUregsn) { _vuRegsSUBz(&VU1, VUregsn); }
void VU1regsMI_SUBw(_VURegsNum *VUregsn) { _vuRegsSUBw(&VU1, VUregsn); }
void VU1regsMI_SUBA(_VURegsNum *VUregsn) { _vuRegsSUBA(&VU1, VUregsn); }
void VU1regsMI_SUBAi(_VURegsNum *VUregsn) { _vuRegsSUBAi(&VU1, VUregsn); }
void VU1regsMI_SUBAq(_VURegsNum *VUregsn) { _vuRegsSUBAq(&VU1, VUregsn); }
void VU1regsMI_SUBAx(_VURegsNum *VUregsn) { _vuRegsSUBAx(&VU1, VUregsn); }
void VU1regsMI_SUBAy(_VURegsNum *VUregsn) { _vuRegsSUBAy(&VU1, VUregsn); }
void VU1regsMI_SUBAz(_VURegsNum *VUregsn) { _vuRegsSUBAz(&VU1, VUregsn); }
void VU1regsMI_SUBAw(_VURegsNum *VUregsn) { _vuRegsSUBAw(&VU1, VUregsn); }
void VU1regsMI_MUL(_VURegsNum *VUregsn) { _vuRegsMUL(&VU1, VUregsn); }
void VU1regsMI_MULi(_VURegsNum *VUregsn) { _vuRegsMULi(&VU1, VUregsn); }
void VU1regsMI_MULq(_VURegsNum *VUregsn) { _vuRegsMULq(&VU1, VUregsn); }
void VU1regsMI_MULx(_VURegsNum *VUregsn) { _vuRegsMULx(&VU1, VUregsn); }
void VU1regsMI_MULy(_VURegsNum *VUregsn) { _vuRegsMULy(&VU1, VUregsn); }
void VU1regsMI_MULz(_VURegsNum *VUregsn) { _vuRegsMULz(&VU1, VUregsn); }
void VU1regsMI_MULw(_VURegsNum *VUregsn) { _vuRegsMULw(&VU1, VUregsn); }
void VU1regsMI_MULA(_VURegsNum *VUregsn) { _vuRegsMULA(&VU1, VUregsn); }
void VU1regsMI_MULAi(_VURegsNum *VUregsn) { _vuRegsMULAi(&VU1, VUregsn); }
void VU1regsMI_MULAq(_VURegsNum *VUregsn) { _vuRegsMULAq(&VU1, VUregsn); }
void VU1regsMI_MULAx(_VURegsNum *VUregsn) { _vuRegsMULAx(&VU1, VUregsn); }
void VU1regsMI_MULAy(_VURegsNum *VUregsn) { _vuRegsMULAy(&VU1, VUregsn); }
void VU1regsMI_MULAz(_VURegsNum *VUregsn) { _vuRegsMULAz(&VU1, VUregsn); }
void VU1regsMI_MULAw(_VURegsNum *VUregsn) { _vuRegsMULAw(&VU1, VUregsn); }
void VU1regsMI_MADD(_VURegsNum *VUregsn) { _vuRegsMADD(&VU1, VUregsn); }
void VU1regsMI_MADDi(_VURegsNum *VUregsn) { _vuRegsMADDi(&VU1, VUregsn); }
void VU1regsMI_MADDq(_VURegsNum *VUregsn) { _vuRegsMADDq(&VU1, VUregsn); }
void VU1regsMI_MADDx(_VURegsNum *VUregsn) { _vuRegsMADDx(&VU1, VUregsn); }
void VU1regsMI_MADDy(_VURegsNum *VUregsn) { _vuRegsMADDy(&VU1, VUregsn); }
void VU1regsMI_MADDz(_VURegsNum *VUregsn) { _vuRegsMADDz(&VU1, VUregsn); }
void VU1regsMI_MADDw(_VURegsNum *VUregsn) { _vuRegsMADDw(&VU1, VUregsn); }
void VU1regsMI_MADDA(_VURegsNum *VUregsn) { _vuRegsMADDA(&VU1, VUregsn); }
void VU1regsMI_MADDAi(_VURegsNum *VUregsn) { _vuRegsMADDAi(&VU1, VUregsn); }
void VU1regsMI_MADDAq(_VURegsNum *VUregsn) { _vuRegsMADDAq(&VU1, VUregsn); }
void VU1regsMI_MADDAx(_VURegsNum *VUregsn) { _vuRegsMADDAx(&VU1, VUregsn); }
void VU1regsMI_MADDAy(_VURegsNum *VUregsn) { _vuRegsMADDAy(&VU1, VUregsn); }
void VU1regsMI_MADDAz(_VURegsNum *VUregsn) { _vuRegsMADDAz(&VU1, VUregsn); }
void VU1regsMI_MADDAw(_VURegsNum *VUregsn) { _vuRegsMADDAw(&VU1, VUregsn); }
void VU1regsMI_MSUB(_VURegsNum *VUregsn) { _vuRegsMSUB(&VU1, VUregsn); }
void VU1regsMI_MSUBi(_VURegsNum *VUregsn) { _vuRegsMSUBi(&VU1, VUregsn); }
void VU1regsMI_MSUBq(_VURegsNum *VUregsn) { _vuRegsMSUBq(&VU1, VUregsn); }
void VU1regsMI_MSUBx(_VURegsNum *VUregsn) { _vuRegsMSUBx(&VU1, VUregsn); }
void VU1regsMI_MSUBy(_VURegsNum *VUregsn) { _vuRegsMSUBy(&VU1, VUregsn); }
void VU1regsMI_MSUBz(_VURegsNum *VUregsn) { _vuRegsMSUBz(&VU1, VUregsn); }
void VU1regsMI_MSUBw(_VURegsNum *VUregsn) { _vuRegsMSUBw(&VU1, VUregsn); }
void VU1regsMI_MSUBA(_VURegsNum *VUregsn) { _vuRegsMSUBA(&VU1, VUregsn); }
void VU1regsMI_MSUBAi(_VURegsNum *VUregsn) { _vuRegsMSUBAi(&VU1, VUregsn); }
void VU1regsMI_MSUBAq(_VURegsNum *VUregsn) { _vuRegsMSUBAq(&VU1, VUregsn); }
void VU1regsMI_MSUBAx(_VURegsNum *VUregsn) { _vuRegsMSUBAx(&VU1, VUregsn); }
void VU1regsMI_MSUBAy(_VURegsNum *VUregsn) { _vuRegsMSUBAy(&VU1, VUregsn); }
void VU1regsMI_MSUBAz(_VURegsNum *VUregsn) { _vuRegsMSUBAz(&VU1, VUregsn); }
void VU1regsMI_MSUBAw(_VURegsNum *VUregsn) { _vuRegsMSUBAw(&VU1, VUregsn); }
void VU1regsMI_MAX(_VURegsNum *VUregsn) { _vuRegsMAX(&VU1, VUregsn); }
void VU1regsMI_MAXi(_VURegsNum *VUregsn) { _vuRegsMAXi(&VU1, VUregsn); }
void VU1regsMI_MAXx(_VURegsNum *VUregsn) { _vuRegsMAXx(&VU1, VUregsn); }
void VU1regsMI_MAXy(_VURegsNum *VUregsn) { _vuRegsMAXy(&VU1, VUregsn); }
void VU1regsMI_MAXz(_VURegsNum *VUregsn) { _vuRegsMAXz(&VU1, VUregsn); }
void VU1regsMI_MAXw(_VURegsNum *VUregsn) { _vuRegsMAXw(&VU1, VUregsn); }
void VU1regsMI_MINI(_VURegsNum *VUregsn) { _vuRegsMINI(&VU1, VUregsn); }
void VU1regsMI_MINIi(_VURegsNum *VUregsn) { _vuRegsMINIi(&VU1, VUregsn); }
void VU1regsMI_MINIx(_VURegsNum *VUregsn) { _vuRegsMINIx(&VU1, VUregsn); }
void VU1regsMI_MINIy(_VURegsNum *VUregsn) { _vuRegsMINIy(&VU1, VUregsn); }
void VU1regsMI_MINIz(_VURegsNum *VUregsn) { _vuRegsMINIz(&VU1, VUregsn); }
void VU1regsMI_MINIw(_VURegsNum *VUregsn) { _vuRegsMINIw(&VU1, VUregsn); }
void VU1regsMI_OPMULA(_VURegsNum *VUregsn) { _vuRegsOPMULA(&VU1, VUregsn); }
void VU1regsMI_OPMSUB(_VURegsNum *VUregsn) { _vuRegsOPMSUB(&VU1, VUregsn); }
void VU1regsMI_NOP(_VURegsNum *VUregsn) { _vuRegsNOP(&VU1, VUregsn); }
void VU1regsMI_FTOI0(_VURegsNum *VUregsn) { _vuRegsFTOI0(&VU1, VUregsn); }
void VU1regsMI_FTOI4(_VURegsNum *VUregsn) { _vuRegsFTOI4(&VU1, VUregsn); }
void VU1regsMI_FTOI12(_VURegsNum *VUregsn) { _vuRegsFTOI12(&VU1, VUregsn); }
void VU1regsMI_FTOI15(_VURegsNum *VUregsn) { _vuRegsFTOI15(&VU1, VUregsn); }
void VU1regsMI_ITOF0(_VURegsNum *VUregsn) { _vuRegsITOF0(&VU1, VUregsn); }
void VU1regsMI_ITOF4(_VURegsNum *VUregsn) { _vuRegsITOF4(&VU1, VUregsn); }
void VU1regsMI_ITOF12(_VURegsNum *VUregsn) { _vuRegsITOF12(&VU1, VUregsn); }
void VU1regsMI_ITOF15(_VURegsNum *VUregsn) { _vuRegsITOF15(&VU1, VUregsn); }
void VU1regsMI_CLIP(_VURegsNum *VUregsn) { _vuRegsCLIP(&VU1, VUregsn); }
/*****************************************/
/* VU Micromode Lower instructions */
/*****************************************/
void VU1regsMI_DIV(_VURegsNum *VUregsn) { _vuRegsDIV(&VU1, VUregsn); }
void VU1regsMI_SQRT(_VURegsNum *VUregsn) { _vuRegsSQRT(&VU1, VUregsn); }
void VU1regsMI_RSQRT(_VURegsNum *VUregsn) { _vuRegsRSQRT(&VU1, VUregsn); }
void VU1regsMI_IADD(_VURegsNum *VUregsn) { _vuRegsIADD(&VU1, VUregsn); }
void VU1regsMI_IADDI(_VURegsNum *VUregsn) { _vuRegsIADDI(&VU1, VUregsn); }
void VU1regsMI_IADDIU(_VURegsNum *VUregsn) { _vuRegsIADDIU(&VU1, VUregsn); }
void VU1regsMI_IAND(_VURegsNum *VUregsn) { _vuRegsIAND(&VU1, VUregsn); }
void VU1regsMI_IOR(_VURegsNum *VUregsn) { _vuRegsIOR(&VU1, VUregsn); }
void VU1regsMI_ISUB(_VURegsNum *VUregsn) { _vuRegsISUB(&VU1, VUregsn); }
void VU1regsMI_ISUBIU(_VURegsNum *VUregsn) { _vuRegsISUBIU(&VU1, VUregsn); }
void VU1regsMI_MOVE(_VURegsNum *VUregsn) { _vuRegsMOVE(&VU1, VUregsn); }
void VU1regsMI_MFIR(_VURegsNum *VUregsn) { _vuRegsMFIR(&VU1, VUregsn); }
void VU1regsMI_MTIR(_VURegsNum *VUregsn) { _vuRegsMTIR(&VU1, VUregsn); }
void VU1regsMI_MR32(_VURegsNum *VUregsn) { _vuRegsMR32(&VU1, VUregsn); }
void VU1regsMI_LQ(_VURegsNum *VUregsn) { _vuRegsLQ(&VU1, VUregsn); }
void VU1regsMI_LQD(_VURegsNum *VUregsn) { _vuRegsLQD(&VU1, VUregsn); }
void VU1regsMI_LQI(_VURegsNum *VUregsn) { _vuRegsLQI(&VU1, VUregsn); }
void VU1regsMI_SQ(_VURegsNum *VUregsn) { _vuRegsSQ(&VU1, VUregsn); }
void VU1regsMI_SQD(_VURegsNum *VUregsn) { _vuRegsSQD(&VU1, VUregsn); }
void VU1regsMI_SQI(_VURegsNum *VUregsn) { _vuRegsSQI(&VU1, VUregsn); }
void VU1regsMI_ILW(_VURegsNum *VUregsn) { _vuRegsILW(&VU1, VUregsn); }
void VU1regsMI_ISW(_VURegsNum *VUregsn) { _vuRegsISW(&VU1, VUregsn); }
void VU1regsMI_ILWR(_VURegsNum *VUregsn) { _vuRegsILWR(&VU1, VUregsn); }
void VU1regsMI_ISWR(_VURegsNum *VUregsn) { _vuRegsISWR(&VU1, VUregsn); }
void VU1regsMI_RINIT(_VURegsNum *VUregsn) { _vuRegsRINIT(&VU1, VUregsn); }
void VU1regsMI_RGET(_VURegsNum *VUregsn) { _vuRegsRGET(&VU1, VUregsn); }
void VU1regsMI_RNEXT(_VURegsNum *VUregsn) { _vuRegsRNEXT(&VU1, VUregsn); }
void VU1regsMI_RXOR(_VURegsNum *VUregsn) { _vuRegsRXOR(&VU1, VUregsn); }
void VU1regsMI_WAITQ(_VURegsNum *VUregsn) { _vuRegsWAITQ(&VU1, VUregsn); }
void VU1regsMI_FSAND(_VURegsNum *VUregsn) { _vuRegsFSAND(&VU1, VUregsn); }
void VU1regsMI_FSEQ(_VURegsNum *VUregsn) { _vuRegsFSEQ(&VU1, VUregsn); }
void VU1regsMI_FSOR(_VURegsNum *VUregsn) { _vuRegsFSOR(&VU1, VUregsn); }
void VU1regsMI_FSSET(_VURegsNum *VUregsn) { _vuRegsFSSET(&VU1, VUregsn); }
void VU1regsMI_FMAND(_VURegsNum *VUregsn) { _vuRegsFMAND(&VU1, VUregsn); }
void VU1regsMI_FMEQ(_VURegsNum *VUregsn) { _vuRegsFMEQ(&VU1, VUregsn); }
void VU1regsMI_FMOR(_VURegsNum *VUregsn) { _vuRegsFMOR(&VU1, VUregsn); }
void VU1regsMI_FCAND(_VURegsNum *VUregsn) { _vuRegsFCAND(&VU1, VUregsn); }
void VU1regsMI_FCEQ(_VURegsNum *VUregsn) { _vuRegsFCEQ(&VU1, VUregsn); }
void VU1regsMI_FCOR(_VURegsNum *VUregsn) { _vuRegsFCOR(&VU1, VUregsn); }
void VU1regsMI_FCSET(_VURegsNum *VUregsn) { _vuRegsFCSET(&VU1, VUregsn); }
void VU1regsMI_FCGET(_VURegsNum *VUregsn) { _vuRegsFCGET(&VU1, VUregsn); }
void VU1regsMI_IBEQ(_VURegsNum *VUregsn) { _vuRegsIBEQ(&VU1, VUregsn); }
void VU1regsMI_IBGEZ(_VURegsNum *VUregsn) { _vuRegsIBGEZ(&VU1, VUregsn); }
void VU1regsMI_IBGTZ(_VURegsNum *VUregsn) { _vuRegsIBGTZ(&VU1, VUregsn); }
void VU1regsMI_IBLTZ(_VURegsNum *VUregsn) { _vuRegsIBLTZ(&VU1, VUregsn); }
void VU1regsMI_IBLEZ(_VURegsNum *VUregsn) { _vuRegsIBLEZ(&VU1, VUregsn); }
void VU1regsMI_IBNE(_VURegsNum *VUregsn) { _vuRegsIBNE(&VU1, VUregsn); }
void VU1regsMI_B(_VURegsNum *VUregsn) { _vuRegsB(&VU1, VUregsn); }
void VU1regsMI_BAL(_VURegsNum *VUregsn) { _vuRegsBAL(&VU1, VUregsn); }
void VU1regsMI_JR(_VURegsNum *VUregsn) { _vuRegsJR(&VU1, VUregsn); }
void VU1regsMI_JALR(_VURegsNum *VUregsn) { _vuRegsJALR(&VU1, VUregsn); }
void VU1regsMI_MFP(_VURegsNum *VUregsn) { _vuRegsMFP(&VU1, VUregsn); }
void VU1regsMI_WAITP(_VURegsNum *VUregsn) { _vuRegsWAITP(&VU1, VUregsn); }
void VU1regsMI_ESADD(_VURegsNum *VUregsn) { _vuRegsESADD(&VU1, VUregsn); }
void VU1regsMI_ERSADD(_VURegsNum *VUregsn) { _vuRegsERSADD(&VU1, VUregsn); }
void VU1regsMI_ELENG(_VURegsNum *VUregsn) { _vuRegsELENG(&VU1, VUregsn); }
void VU1regsMI_ERLENG(_VURegsNum *VUregsn) { _vuRegsERLENG(&VU1, VUregsn); }
void VU1regsMI_EATANxy(_VURegsNum *VUregsn) { _vuRegsEATANxy(&VU1, VUregsn); }
void VU1regsMI_EATANxz(_VURegsNum *VUregsn) { _vuRegsEATANxz(&VU1, VUregsn); }
void VU1regsMI_ESUM(_VURegsNum *VUregsn) { _vuRegsESUM(&VU1, VUregsn); }
void VU1regsMI_ERCPR(_VURegsNum *VUregsn) { _vuRegsERCPR(&VU1, VUregsn); }
void VU1regsMI_ESQRT(_VURegsNum *VUregsn) { _vuRegsESQRT(&VU1, VUregsn); }
void VU1regsMI_ERSQRT(_VURegsNum *VUregsn) { _vuRegsERSQRT(&VU1, VUregsn); }
void VU1regsMI_ESIN(_VURegsNum *VUregsn) { _vuRegsESIN(&VU1, VUregsn); }
void VU1regsMI_EATAN(_VURegsNum *VUregsn) { _vuRegsEATAN(&VU1, VUregsn); }
void VU1regsMI_EEXP(_VURegsNum *VUregsn) { _vuRegsEEXP(&VU1, VUregsn); }
void VU1regsMI_XITOP(_VURegsNum *VUregsn) { _vuRegsXITOP(&VU1, VUregsn); }
void VU1regsMI_XGKICK(_VURegsNum *VUregsn) { _vuRegsXGKICK(&VU1, VUregsn); }
void VU1regsMI_XTOP(_VURegsNum *VUregsn) { _vuRegsXTOP(&VU1, VUregsn); }

View File

@ -21,8 +21,6 @@
extern void _vuFlushAll(VURegs* VU); extern void _vuFlushAll(VURegs* VU);
_vuTables(VU1, VU1);
void _vu1ExecUpper(VURegs* VU, u32 *ptr) { void _vu1ExecUpper(VURegs* VU, u32 *ptr) {
VU->code = ptr[1]; VU->code = ptr[1];
IdebugUPPER(VU1); IdebugUPPER(VU1);
@ -50,13 +48,6 @@ static void _vu1Exec(VURegs* VU)
int vireg; int vireg;
int discard=0; int discard=0;
if(VU->VI[REG_TPC].UL >= VU->maxmicro){
CPU_LOG("VU1 memory overflow!!: %x", VU->VI[REG_TPC].UL);
VU->VI[REG_TPC].UL &= 0x3FFF;
/*VU0.VI[REG_VPU_STAT].UL&= ~0x100;
VU->cycle++;
return;*/
}
ptr = (u32*)&VU->Micro[VU->VI[REG_TPC].UL]; ptr = (u32*)&VU->Micro[VU->VI[REG_TPC].UL];
VU->VI[REG_TPC].UL+=8; VU->VI[REG_TPC].UL+=8;
@ -159,7 +150,7 @@ static void _vu1Exec(VURegs* VU)
if( VU->ebit-- == 1 ) { if( VU->ebit-- == 1 ) {
_vuFlushAll(VU); _vuFlushAll(VU);
VU0.VI[REG_VPU_STAT].UL &= ~0x100; VU0.VI[REG_VPU_STAT].UL &= ~0x100;
vif1Regs->stat.VEW = false; vif1Regs.stat.VEW = false;
} }
} }
} }
@ -184,6 +175,7 @@ InterpVU1::InterpVU1()
void InterpVU1::Step() void InterpVU1::Step()
{ {
VU1.VI[REG_TPC].UL &= VU1_PROGMASK;
vu1Exec( &VU1 ); vu1Exec( &VU1 );
} }
@ -192,11 +184,11 @@ void InterpVU1::Execute(u32 cycles)
for (int i = (int)cycles; i > 0 ; i--) { for (int i = (int)cycles; i > 0 ; i--) {
if (!(VU0.VI[REG_VPU_STAT].UL & 0x100)) { if (!(VU0.VI[REG_VPU_STAT].UL & 0x100)) {
if (VU1.branch || VU1.ebit) { if (VU1.branch || VU1.ebit) {
vu1Exec(&VU1); // run branch delay slot? Step(); // run branch delay slot?
} }
break; break;
} }
vu1Exec(&VU1); Step();
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -18,10 +18,12 @@
#include "Common.h" #include "Common.h"
#include "VUmicro.h" #include "VUmicro.h"
__aligned16 VURegs vuRegs[2];
static u8* m_vuAllMem = NULL; static u8* m_vuAllMem = NULL;
static const uint m_vuMemSize = static const uint m_vuMemSize =
0x1000 + // VU0micro memory 0x1000 + // VU0micro memory
0x4000+0x800 + // VU0 memory and VU1 registers 0x4000 + // VU0 memory
0x4000 + // VU1 memory 0x4000 + // VU1 memory
0x4000; 0x4000;
@ -33,12 +35,9 @@ void vuMicroMemAlloc()
if( m_vuAllMem == NULL ) if( m_vuAllMem == NULL )
throw Exception::OutOfMemory( L"VU0 and VU1 on-chip memory" ); throw Exception::OutOfMemory( L"VU0 and VU1 on-chip memory" );
pxAssume( sizeof( VURegs ) <= 0x800 );
u8* curpos = m_vuAllMem; u8* curpos = m_vuAllMem;
VU0.Micro = curpos; curpos += 0x1000; VU0.Micro = curpos; curpos += 0x1000;
VU0.Mem = curpos; curpos += 0x4000; VU0.Mem = curpos; curpos += 0x4000;
g_pVU1 = (VURegs*)curpos; curpos += 0x800;
VU1.Micro = curpos; curpos += 0x4000; VU1.Micro = curpos; curpos += 0x4000;
VU1.Mem = curpos; VU1.Mem = curpos;
//curpos += 0x4000; //curpos += 0x4000;
@ -50,7 +49,6 @@ void vuMicroMemShutdown()
vtlb_free( m_vuAllMem, m_vuMemSize ); vtlb_free( m_vuAllMem, m_vuMemSize );
m_vuAllMem = NULL; m_vuAllMem = NULL;
g_pVU1 = NULL;
} }
void vuMicroMemReset() void vuMicroMemReset()
@ -72,17 +70,6 @@ void vuMicroMemReset()
memzero_ptr<4*1024>(VU0.Mem); memzero_ptr<4*1024>(VU0.Mem);
memzero_ptr<4*1024>(VU0.Micro); memzero_ptr<4*1024>(VU0.Micro);
/* this is kinda tricky, maxmem is set to 0x4400 here,
tho it's not 100% accurate, since the mem goes from
0x0000 - 0x1000 (Mem) and 0x4000 - 0x4400 (VU1 Regs),
i guess it shouldn't be a problem,
at least hope so :) (linuz)
*/
VU0.maxmem = 0x4800-4; //We are allocating 0x800 for vu1 reg's
VU0.maxmicro = 0x1000-4;
VU0.vuExec = vu0Exec;
VU0.vifRegs = vif0Regs;
// === VU1 Initialization === // === VU1 Initialization ===
memzero(VU1.ACC); memzero(VU1.ACC);
memzero(VU1.VF); memzero(VU1.VF);
@ -94,13 +81,6 @@ void vuMicroMemReset()
VU1.VI[0].UL = 0; VU1.VI[0].UL = 0;
memzero_ptr<16*1024>(VU1.Mem); memzero_ptr<16*1024>(VU1.Mem);
memzero_ptr<16*1024>(VU1.Micro); memzero_ptr<16*1024>(VU1.Micro);
VU1.maxmem = 0x4000-4;//16*1024-4;
VU1.maxmicro = 0x4000-4;
// VU1.VF = (VECTOR*)(VU0.Mem + 0x4000);
// VU1.VI = (REG_VI*)(VU0.Mem + 0x4200);
VU1.vuExec = vu1Exec;
VU1.vifRegs = vif1Regs;
} }
void SaveStateBase::vuMicroFreeze() void SaveStateBase::vuMicroFreeze()

File diff suppressed because it is too large Load Diff

View File

@ -27,354 +27,35 @@
#define MAC_Reset( VU ) VU->VI[REG_MAC_FLAG].UL = VU->VI[REG_MAC_FLAG].UL & (~0xFFFF) #define MAC_Reset( VU ) VU->VI[REG_MAC_FLAG].UL = VU->VI[REG_MAC_FLAG].UL & (~0xFFFF)
struct _VURegsNum {
u8 pipe; // if 0xff, COP2
u8 VFwrite;
u8 VFwxyzw;
u8 VFr0xyzw;
u8 VFr1xyzw;
u8 VFread0;
u8 VFread1;
u32 VIwrite;
u32 VIread;
int cycles;
};
#define __vuRegsCall __fastcall
typedef void __vuRegsCall FnType_VuRegsN(_VURegsNum *VUregsn);
typedef FnType_VuRegsN* Fnptr_VuRegsN;
extern __aligned16 const Fnptr_Void VU0_LOWER_OPCODE[128];
extern __aligned16 const Fnptr_Void VU0_UPPER_OPCODE[64];
extern __aligned16 const Fnptr_VuRegsN VU0regs_LOWER_OPCODE[128];
extern __aligned16 const Fnptr_VuRegsN VU0regs_UPPER_OPCODE[64];
extern __aligned16 const Fnptr_Void VU1_LOWER_OPCODE[128];
extern __aligned16 const Fnptr_Void VU1_UPPER_OPCODE[64];
extern __aligned16 const Fnptr_VuRegsN VU1regs_LOWER_OPCODE[128];
extern __aligned16 const Fnptr_VuRegsN VU1regs_UPPER_OPCODE[64];
extern void _vuTestPipes(VURegs * VU); extern void _vuTestPipes(VURegs * VU);
extern void _vuTestUpperStalls(VURegs * VU, _VURegsNum *VUregsn); extern void _vuTestUpperStalls(VURegs * VU, _VURegsNum *VUregsn);
extern void _vuTestLowerStalls(VURegs * VU, _VURegsNum *VUregsn); extern void _vuTestLowerStalls(VURegs * VU, _VURegsNum *VUregsn);
extern void _vuAddUpperStalls(VURegs * VU, _VURegsNum *VUregsn); extern void _vuAddUpperStalls(VURegs * VU, _VURegsNum *VUregsn);
extern void _vuAddLowerStalls(VURegs * VU, _VURegsNum *VUregsn); extern void _vuAddLowerStalls(VURegs * VU, _VURegsNum *VUregsn);
/******************************/
/* VU Upper instructions */
/******************************/
void _vuABS(VURegs * VU);
void _vuADD(VURegs * VU);
void _vuADDi(VURegs * VU);
void _vuADDq(VURegs * VU);
void _vuADDx(VURegs * VU);
void _vuADDy(VURegs * VU);
void _vuADDz(VURegs * VU);
void _vuADDw(VURegs * VU);
void _vuADDA(VURegs * VU);
void _vuADDAi(VURegs * VU);
void _vuADDAq(VURegs * VU);
void _vuADDAx(VURegs * VU);
void _vuADDAy(VURegs * VU);
void _vuADDAz(VURegs * VU);
void _vuADDAw(VURegs * VU);
void _vuSUB(VURegs * VU);
void _vuSUBi(VURegs * VU);
void _vuSUBq(VURegs * VU);
void _vuSUBx(VURegs * VU);
void _vuSUBy(VURegs * VU);
void _vuSUBz(VURegs * VU);
void _vuSUBw(VURegs * VU);
void _vuSUBA(VURegs * VU);
void _vuSUBAi(VURegs * VU);
void _vuSUBAq(VURegs * VU);
void _vuSUBAx(VURegs * VU);
void _vuSUBAy(VURegs * VU);
void _vuSUBAz(VURegs * VU);
void _vuSUBAw(VURegs * VU);
void _vuMUL(VURegs * VU);
void _vuMULi(VURegs * VU);
void _vuMULq(VURegs * VU);
void _vuMULx(VURegs * VU);
void _vuMULy(VURegs * VU);
void _vuMULz(VURegs * VU);
void _vuMULw(VURegs * VU);
void _vuMULA(VURegs * VU);
void _vuMULAi(VURegs * VU);
void _vuMULAq(VURegs * VU);
void _vuMULAx(VURegs * VU);
void _vuMULAy(VURegs * VU);
void _vuMULAz(VURegs * VU);
void _vuMULAw(VURegs * VU);
void _vuMADD(VURegs * VU) ;
void _vuMADDi(VURegs * VU);
void _vuMADDq(VURegs * VU);
void _vuMADDx(VURegs * VU);
void _vuMADDy(VURegs * VU);
void _vuMADDz(VURegs * VU);
void _vuMADDw(VURegs * VU);
void _vuMADDA(VURegs * VU);
void _vuMADDAi(VURegs * VU);
void _vuMADDAq(VURegs * VU);
void _vuMADDAx(VURegs * VU);
void _vuMADDAy(VURegs * VU);
void _vuMADDAz(VURegs * VU);
void _vuMADDAw(VURegs * VU);
void _vuMSUB(VURegs * VU);
void _vuMSUBi(VURegs * VU);
void _vuMSUBq(VURegs * VU);
void _vuMSUBx(VURegs * VU);
void _vuMSUBy(VURegs * VU);
void _vuMSUBz(VURegs * VU) ;
void _vuMSUBw(VURegs * VU) ;
void _vuMSUBA(VURegs * VU);
void _vuMSUBAi(VURegs * VU);
void _vuMSUBAq(VURegs * VU);
void _vuMSUBAx(VURegs * VU);
void _vuMSUBAy(VURegs * VU);
void _vuMSUBAz(VURegs * VU);
void _vuMSUBAw(VURegs * VU);
void _vuMAX(VURegs * VU);
void _vuMAXi(VURegs * VU);
void _vuMAXx(VURegs * VU);
void _vuMAXy(VURegs * VU);
void _vuMAXz(VURegs * VU);
void _vuMAXw(VURegs * VU);
void _vuMINI(VURegs * VU);
void _vuMINIi(VURegs * VU);
void _vuMINIx(VURegs * VU);
void _vuMINIy(VURegs * VU);
void _vuMINIz(VURegs * VU);
void _vuMINIw(VURegs * VU);
void _vuOPMULA(VURegs * VU);
void _vuOPMSUB(VURegs * VU);
void _vuNOP(VURegs * VU);
void _vuFTOI0(VURegs * VU);
void _vuFTOI4(VURegs * VU);
void _vuFTOI12(VURegs * VU);
void _vuFTOI15(VURegs * VU);
void _vuITOF0(VURegs * VU) ;
void _vuITOF4(VURegs * VU) ;
void _vuITOF12(VURegs * VU);
void _vuITOF15(VURegs * VU);
void _vuCLIP(VURegs * VU);
/******************************/
/* VU Lower instructions */
/******************************/
void _vuDIV(VURegs * VU);
void _vuSQRT(VURegs * VU);
void _vuRSQRT(VURegs * VU);
void _vuIADDI(VURegs * VU);
void _vuIADDIU(VURegs * VU);
void _vuIADD(VURegs * VU);
void _vuIAND(VURegs * VU);
void _vuIOR(VURegs * VU);
void _vuISUB(VURegs * VU);
void _vuISUBIU(VURegs * VU);
void _vuMOVE(VURegs * VU);
void _vuMFIR(VURegs * VU);
void _vuMTIR(VURegs * VU);
void _vuMR32(VURegs * VU);
void _vuLQ(VURegs * VU) ;
void _vuLQD(VURegs * VU);
void _vuLQI(VURegs * VU);
void _vuSQ(VURegs * VU);
void _vuSQD(VURegs * VU);
void _vuSQI(VURegs * VU);
void _vuILW(VURegs * VU);
void _vuISW(VURegs * VU);
void _vuILWR(VURegs * VU);
void _vuISWR(VURegs * VU);
void _vuLOI(VURegs * VU);
void _vuRINIT(VURegs * VU);
void _vuRGET(VURegs * VU);
void _vuRNEXT(VURegs * VU);
void _vuRXOR(VURegs * VU);
void _vuWAITQ(VURegs * VU);
void _vuFSAND(VURegs * VU);
void _vuFSEQ(VURegs * VU);
void _vuFSOR(VURegs * VU);
void _vuFSSET(VURegs * VU);
void _vuFMAND(VURegs * VU);
void _vuFMEQ(VURegs * VU);
void _vuFMOR(VURegs * VU);
void _vuFCAND(VURegs * VU);
void _vuFCEQ(VURegs * VU);
void _vuFCOR(VURegs * VU);
void _vuFCSET(VURegs * VU);
void _vuFCGET(VURegs * VU);
void _vuIBEQ(VURegs * VU);
void _vuIBGEZ(VURegs * VU);
void _vuIBGTZ(VURegs * VU);
void _vuIBLEZ(VURegs * VU);
void _vuIBLTZ(VURegs * VU);
void _vuIBNE(VURegs * VU);
void _vuB(VURegs * VU);
void _vuBAL(VURegs * VU);
void _vuJR(VURegs * VU);
void _vuJALR(VURegs * VU);
void _vuMFP(VURegs * VU);
void _vuWAITP(VURegs * VU);
void _vuESADD(VURegs * VU);
void _vuERSADD(VURegs * VU);
void _vuELENG(VURegs * VU);
void _vuERLENG(VURegs * VU);
void _vuEATANxy(VURegs * VU);
void _vuEATANxz(VURegs * VU);
void _vuESUM(VURegs * VU);
void _vuERCPR(VURegs * VU);
void _vuESQRT(VURegs * VU);
void _vuERSQRT(VURegs * VU);
void _vuESIN(VURegs * VU);
void _vuEATAN(VURegs * VU);
void _vuEEXP(VURegs * VU);
void _vuXITOP(VURegs * VU);
void _vuXGKICK(VURegs * VU);
void _vuXTOP(VURegs * VU);
/******************************/
/* VU Upper instructions */
/******************************/
void _vuRegsABS(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsADD(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsADDi(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsADDq(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsADDx(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsADDy(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsADDz(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsADDw(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsADDA(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsADDAi(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsADDAq(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsADDAx(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsADDAy(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsADDAz(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsADDAw(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsSUB(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsSUBi(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsSUBq(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsSUBx(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsSUBy(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsSUBz(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsSUBw(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsSUBA(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsSUBAi(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsSUBAq(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsSUBAx(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsSUBAy(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsSUBAz(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsSUBAw(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsMUL(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsMULi(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsMULq(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsMULx(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsMULy(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsMULz(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsMULw(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsMULA(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsMULAi(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsMULAq(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsMULAx(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsMULAy(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsMULAz(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsMULAw(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsMADD(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsMADDi(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsMADDq(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsMADDx(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsMADDy(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsMADDz(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsMADDw(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsMADDA(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsMADDAi(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsMADDAq(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsMADDAx(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsMADDAy(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsMADDAz(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsMADDAw(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsMSUB(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsMSUBi(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsMSUBq(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsMSUBx(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsMSUBy(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsMSUBz(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsMSUBw(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsMSUBA(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsMSUBAi(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsMSUBAq(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsMSUBAx(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsMSUBAy(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsMSUBAz(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsMSUBAw(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsMAX(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsMAXi(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsMAXx(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsMAXy(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsMAXz(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsMAXw(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsMINI(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsMINIi(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsMINIx(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsMINIy(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsMINIz(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsMINIw(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsOPMULA(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsOPMSUB(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsNOP(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsFTOI0(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsFTOI4(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsFTOI12(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsFTOI15(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsITOF0(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsITOF4(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsITOF12(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsITOF15(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsCLIP(VURegs * VU, _VURegsNum *VUregsn);
/******************************/
/* VU Lower instructions */
/******************************/
void _vuRegsDIV(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsSQRT(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsRSQRT(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsIADDI(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsIADDIU(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsIADD(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsIAND(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsIOR(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsISUB(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsISUBIU(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsMOVE(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsMFIR(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsMTIR(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsMR32(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsLQ(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsLQD(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsLQI(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsSQ(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsSQD(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsSQI(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsILW(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsISW(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsILWR(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsISWR(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsLOI(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsRINIT(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsRGET(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsRNEXT(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsRXOR(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsWAITQ(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsFSAND(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsFSEQ(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsFSOR(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsFSSET(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsFMAND(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsFMEQ(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsFMOR(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsFCAND(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsFCEQ(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsFCOR(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsFCSET(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsFCGET(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsIBEQ(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsIBGEZ(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsIBGTZ(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsIBLEZ(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsIBLTZ(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsIBNE(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsB(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsBAL(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsJR(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsJALR(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsMFP(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsWAITP(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsESADD(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsERSADD(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsELENG(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsERLENG(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsEATANxy(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsEATANxz(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsESUM(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsERCPR(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsESQRT(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsERSQRT(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsESIN(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsEATAN(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsEEXP(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsXITOP(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsXGKICK(VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsXTOP(VURegs * VU, _VURegsNum *VUregsn);

View File

@ -29,13 +29,13 @@ void vif0Reset()
{ {
/* Reset the whole VIF, meaning the internal pcsx2 vars and all the registers */ /* Reset the whole VIF, meaning the internal pcsx2 vars and all the registers */
memzero(vif0); memzero(vif0);
memzero(*vif0Regs); memzero(vif0Regs);
psHu64(VIF0_FIFO) = 0; psHu64(VIF0_FIFO) = 0;
psHu64(VIF0_FIFO + 8) = 0; psHu64(VIF0_FIFO + 8) = 0;
vif0Regs->stat.VPS = VPS_IDLE; vif0Regs.stat.VPS = VPS_IDLE;
vif0Regs->stat.FQC = 0; vif0Regs.stat.FQC = 0;
vif0.done = false; vif0.done = false;
@ -46,13 +46,13 @@ void vif1Reset()
{ {
/* Reset the whole VIF, meaning the internal pcsx2 vars, and all the registers */ /* Reset the whole VIF, meaning the internal pcsx2 vars, and all the registers */
memzero(vif1); memzero(vif1);
memzero(*vif1Regs); memzero(vif1Regs);
psHu64(VIF1_FIFO) = 0; psHu64(VIF1_FIFO) = 0;
psHu64(VIF1_FIFO + 8) = 0; psHu64(VIF1_FIFO + 8) = 0;
vif1Regs->stat.VPS = VPS_IDLE; vif1Regs.stat.VPS = VPS_IDLE;
vif1Regs->stat.FQC = 0; // FQC=0 vif1Regs.stat.FQC = 0; // FQC=0
vif1.done = false; vif1.done = false;
cpuRegs.interrupt &= ~((1 << 1) | (1 << 10)); //Stop all vif1 DMA's cpuRegs.interrupt &= ~((1 << 1) | (1 << 10)); //Stop all vif1 DMA's
@ -91,16 +91,16 @@ __fi void vif0FBRST(u32 value) {
if (value & 0x1) // Reset Vif. if (value & 0x1) // Reset Vif.
{ {
//Console.WriteLn("Vif0 Reset %x", vif0Regs->stat._u32); //Console.WriteLn("Vif0 Reset %x", vif0Regs.stat._u32);
memzero(vif0); memzero(vif0);
vif0ch->qwc = 0; //? vif0ch.qwc = 0; //?
cpuRegs.interrupt &= ~1; //Stop all vif0 DMA's cpuRegs.interrupt &= ~1; //Stop all vif0 DMA's
psHu64(VIF0_FIFO) = 0; psHu64(VIF0_FIFO) = 0;
psHu64(VIF0_FIFO + 8) = 0; psHu64(VIF0_FIFO + 8) = 0;
vif0.done = false; vif0.done = false;
vif0Regs->err.reset(); vif0Regs.err.reset();
vif0Regs->stat.clear_flags(VIF0_STAT_FQC | VIF0_STAT_INT | VIF0_STAT_VSS | VIF0_STAT_VIS | VIF0_STAT_VFS | VIF0_STAT_VPS); // FQC=0 vif0Regs.stat.clear_flags(VIF0_STAT_FQC | VIF0_STAT_INT | VIF0_STAT_VSS | VIF0_STAT_VIS | VIF0_STAT_VFS | VIF0_STAT_VPS); // FQC=0
} }
/* Fixme: Forcebreaks are pretty unknown for operation, presumption is it just stops it what its doing /* Fixme: Forcebreaks are pretty unknown for operation, presumption is it just stops it what its doing
@ -109,8 +109,8 @@ __fi void vif0FBRST(u32 value) {
{ {
/* I guess we should stop the VIF dma here, but not 100% sure (linuz) */ /* I guess we should stop the VIF dma here, but not 100% sure (linuz) */
cpuRegs.interrupt &= ~1; //Stop all vif0 DMA's cpuRegs.interrupt &= ~1; //Stop all vif0 DMA's
vif0Regs->stat.VFS = true; vif0Regs.stat.VFS = true;
vif0Regs->stat.VPS = VPS_IDLE; vif0Regs.stat.VPS = VPS_IDLE;
Console.WriteLn("vif0 force break"); Console.WriteLn("vif0 force break");
} }
@ -118,8 +118,8 @@ __fi void vif0FBRST(u32 value) {
{ {
// Not completely sure about this, can't remember what game, used this, but 'draining' the VIF helped it, instead of // Not completely sure about this, can't remember what game, used this, but 'draining' the VIF helped it, instead of
// just stoppin the VIF (linuz). // just stoppin the VIF (linuz).
vif0Regs->stat.VSS = true; vif0Regs.stat.VSS = true;
vif0Regs->stat.VPS = VPS_IDLE; vif0Regs.stat.VPS = VPS_IDLE;
vif0.vifstalled = true; vif0.vifstalled = true;
} }
@ -128,10 +128,10 @@ __fi void vif0FBRST(u32 value) {
bool cancel = false; bool cancel = false;
/* Cancel stall, first check if there is a stall to cancel, and then clear VIF0_STAT VSS|VFS|VIS|INT|ER0|ER1 bits */ /* Cancel stall, first check if there is a stall to cancel, and then clear VIF0_STAT VSS|VFS|VIS|INT|ER0|ER1 bits */
if (vif0Regs->stat.test(VIF0_STAT_VSS | VIF0_STAT_VIS | VIF0_STAT_VFS)) if (vif0Regs.stat.test(VIF0_STAT_VSS | VIF0_STAT_VIS | VIF0_STAT_VFS))
cancel = true; cancel = true;
vif0Regs->stat.clear_flags(VIF0_STAT_VSS | VIF0_STAT_VFS | VIF0_STAT_VIS | vif0Regs.stat.clear_flags(VIF0_STAT_VSS | VIF0_STAT_VFS | VIF0_STAT_VIS |
VIF0_STAT_INT | VIF0_STAT_ER0 | VIF0_STAT_ER1); VIF0_STAT_INT | VIF0_STAT_ER0 | VIF0_STAT_ER1);
if (cancel) if (cancel)
{ {
@ -140,8 +140,8 @@ __fi void vif0FBRST(u32 value) {
g_vifCycles = 0; g_vifCycles = 0;
// loop necessary for spiderman // loop necessary for spiderman
//vif0ch->chcr.STR = true; //vif0ch.chcr.STR = true;
if(vif0ch->chcr.STR) CPU_INT(DMAC_VIF0, 0); // Gets the timing right - Flatout if(vif0ch.chcr.STR) CPU_INT(DMAC_VIF0, 0); // Gets the timing right - Flatout
} }
} }
} }
@ -154,29 +154,29 @@ __fi void vif1FBRST(u32 value) {
{ {
memzero(vif1); memzero(vif1);
//cpuRegs.interrupt &= ~((1 << 1) | (1 << 10)); //Stop all vif1 DMA's //cpuRegs.interrupt &= ~((1 << 1) | (1 << 10)); //Stop all vif1 DMA's
vif1ch->qwc -= min((int)vif1ch->qwc, 16); //? vif1ch.qwc -= min((int)vif1ch.qwc, 16); //?
psHu64(VIF1_FIFO) = 0; psHu64(VIF1_FIFO) = 0;
psHu64(VIF1_FIFO + 8) = 0; psHu64(VIF1_FIFO + 8) = 0;
//vif1.done = false; //vif1.done = false;
//DevCon.Warning("VIF FBRST Reset MSK = %x", vif1Regs->mskpath3); //DevCon.Warning("VIF FBRST Reset MSK = %x", vif1Regs.mskpath3);
if(vif1Regs->mskpath3 == 1 && GSTransferStatus.PTH3 == STOPPED_MODE && gif->chcr.STR == true) if(vif1Regs.mskpath3 == 1 && GSTransferStatus.PTH3 == STOPPED_MODE && gifch.chcr.STR == true)
{ {
//DevCon.Warning("VIF Path3 Resume on FBRST MSK = %x", vif1Regs->mskpath3); //DevCon.Warning("VIF Path3 Resume on FBRST MSK = %x", vif1Regs.mskpath3);
gsInterrupt(); gsInterrupt();
vif1Regs->mskpath3 = false; vif1Regs.mskpath3 = false;
gifRegs->stat.M3P = 0; gifRegs.stat.M3P = 0;
} }
vif1Regs->mskpath3 = false; vif1Regs.mskpath3 = false;
gifRegs->stat.M3P = 0; gifRegs.stat.M3P = 0;
vif1Regs->err.reset(); vif1Regs.err.reset();
vif1.inprogress = 0; vif1.inprogress = 0;
vif1.cmd = 0; vif1.cmd = 0;
vif1.vifstalled = false; vif1.vifstalled = false;
vif1Regs->stat.FQC = 0; vif1Regs.stat.FQC = 0;
vif1Regs->stat.clear_flags(VIF1_STAT_FDR | VIF1_STAT_INT | VIF1_STAT_VSS | VIF1_STAT_VIS | VIF1_STAT_VFS | VIF1_STAT_VPS); vif1Regs.stat.clear_flags(VIF1_STAT_FDR | VIF1_STAT_INT | VIF1_STAT_VSS | VIF1_STAT_VIS | VIF1_STAT_VFS | VIF1_STAT_VPS);
} }
/* Fixme: Forcebreaks are pretty unknown for operation, presumption is it just stops it what its doing /* Fixme: Forcebreaks are pretty unknown for operation, presumption is it just stops it what its doing
@ -185,8 +185,8 @@ __fi void vif1FBRST(u32 value) {
if (FBRST(value).FBK) // Forcebreak Vif. if (FBRST(value).FBK) // Forcebreak Vif.
{ {
/* I guess we should stop the VIF dma here, but not 100% sure (linuz) */ /* I guess we should stop the VIF dma here, but not 100% sure (linuz) */
vif1Regs->stat.VFS = true; vif1Regs.stat.VFS = true;
vif1Regs->stat.VPS = VPS_IDLE; vif1Regs.stat.VPS = VPS_IDLE;
cpuRegs.interrupt &= ~((1 << 1) | (1 << 10)); //Stop all vif1 DMA's cpuRegs.interrupt &= ~((1 << 1) | (1 << 10)); //Stop all vif1 DMA's
Console.WriteLn("vif1 force break"); Console.WriteLn("vif1 force break");
} }
@ -195,8 +195,8 @@ __fi void vif1FBRST(u32 value) {
{ {
// Not completely sure about this, can't remember what game used this, but 'draining' the VIF helped it, instead of // Not completely sure about this, can't remember what game used this, but 'draining' the VIF helped it, instead of
// just stoppin the VIF (linuz). // just stoppin the VIF (linuz).
vif1Regs->stat.VSS = true; vif1Regs.stat.VSS = true;
vif1Regs->stat.VPS = VPS_IDLE; vif1Regs.stat.VPS = VPS_IDLE;
cpuRegs.interrupt &= ~((1 << 1) | (1 << 10)); //Stop all vif1 DMA's cpuRegs.interrupt &= ~((1 << 1) | (1 << 10)); //Stop all vif1 DMA's
vif1.vifstalled = true; vif1.vifstalled = true;
} }
@ -206,12 +206,12 @@ __fi void vif1FBRST(u32 value) {
bool cancel = false; bool cancel = false;
/* Cancel stall, first check if there is a stall to cancel, and then clear VIF1_STAT VSS|VFS|VIS|INT|ER0|ER1 bits */ /* Cancel stall, first check if there is a stall to cancel, and then clear VIF1_STAT VSS|VFS|VIS|INT|ER0|ER1 bits */
if (vif1Regs->stat.test(VIF1_STAT_VSS | VIF1_STAT_VIS | VIF1_STAT_VFS)) if (vif1Regs.stat.test(VIF1_STAT_VSS | VIF1_STAT_VIS | VIF1_STAT_VFS))
{ {
cancel = true; cancel = true;
} }
vif1Regs->stat.clear_flags(VIF1_STAT_VSS | VIF1_STAT_VFS | VIF1_STAT_VIS | vif1Regs.stat.clear_flags(VIF1_STAT_VSS | VIF1_STAT_VFS | VIF1_STAT_VIS |
VIF1_STAT_INT | VIF1_STAT_ER0 | VIF1_STAT_ER1); VIF1_STAT_INT | VIF1_STAT_ER0 | VIF1_STAT_ER1);
if (cancel) if (cancel)
@ -220,22 +220,22 @@ __fi void vif1FBRST(u32 value) {
{ {
g_vifCycles = 0; g_vifCycles = 0;
// loop necessary for spiderman // loop necessary for spiderman
switch(dmacRegs->ctrl.MFD) switch(dmacRegs.ctrl.MFD)
{ {
case MFD_VIF1: case MFD_VIF1:
//Console.WriteLn("MFIFO Stall"); //Console.WriteLn("MFIFO Stall");
if(vif1ch->chcr.STR == true) CPU_INT(DMAC_MFIFO_VIF, 0); if(vif1ch.chcr.STR == true) CPU_INT(DMAC_MFIFO_VIF, 0);
break; break;
case NO_MFD: case NO_MFD:
case MFD_RESERVED: case MFD_RESERVED:
case MFD_GIF: // Wonder if this should be with VIF? case MFD_GIF: // Wonder if this should be with VIF?
// Gets the timing right - Flatout // Gets the timing right - Flatout
if(vif1ch->chcr.STR == true) CPU_INT(DMAC_VIF1, 0); if(vif1ch.chcr.STR == true) CPU_INT(DMAC_VIF1, 0);
break; break;
} }
//vif1ch->chcr.STR = true; //vif1ch.chcr.STR = true;
} }
} }
} }
@ -245,16 +245,16 @@ __fi void vif1STAT(u32 value) {
VIF_LOG("VIF1_STAT write32 0x%8.8x", value); VIF_LOG("VIF1_STAT write32 0x%8.8x", value);
/* Only FDR bit is writable, so mask the rest */ /* Only FDR bit is writable, so mask the rest */
if ((vif1Regs->stat.FDR) ^ ((tVIF_STAT&)value).FDR) { if ((vif1Regs.stat.FDR) ^ ((tVIF_STAT&)value).FDR) {
// different so can't be stalled // different so can't be stalled
if (vif1Regs->stat.test(VIF1_STAT_INT | VIF1_STAT_VSS | VIF1_STAT_VIS | VIF1_STAT_VFS)) { if (vif1Regs.stat.test(VIF1_STAT_INT | VIF1_STAT_VSS | VIF1_STAT_VIS | VIF1_STAT_VFS)) {
DevCon.WriteLn("changing dir when vif1 fifo stalled"); DevCon.WriteLn("changing dir when vif1 fifo stalled");
} }
} }
vif1Regs->stat.FDR = VIF_STAT(value).FDR; vif1Regs.stat.FDR = VIF_STAT(value).FDR;
if (vif1Regs->stat.FDR) // Vif transferring to memory. if (vif1Regs.stat.FDR) // Vif transferring to memory.
{ {
// Hack but it checks this is true before transfer? (fatal frame) // Hack but it checks this is true before transfer? (fatal frame)
// Update Refraction: Use of this function has been investigated and understood. // Update Refraction: Use of this function has been investigated and understood.
@ -263,7 +263,7 @@ __fi void vif1STAT(u32 value) {
// As far as the GS is concerned, the transfer starts as soon as TRXDIR is accessed, which is why fatal frame // As far as the GS is concerned, the transfer starts as soon as TRXDIR is accessed, which is why fatal frame
// was expecting data, the GS should already be sending it over (buffering in the FIFO) // was expecting data, the GS should already be sending it over (buffering in the FIFO)
vif1Regs->stat.FQC = min((u32)16, vif1.GSLastDownloadSize); vif1Regs.stat.FQC = min((u32)16, vif1.GSLastDownloadSize);
//Console.Warning("Reversing VIF Transfer for %x QWC", vif1.GSLastDownloadSize); //Console.Warning("Reversing VIF Transfer for %x QWC", vif1.GSLastDownloadSize);
} }
@ -271,69 +271,65 @@ __fi void vif1STAT(u32 value) {
{ {
//Sometimes the value from the GS is bigger than vif wanted, so it just sets it back and cancels it. //Sometimes the value from the GS is bigger than vif wanted, so it just sets it back and cancels it.
//Other times it can read it off ;) //Other times it can read it off ;)
vif1Regs->stat.FQC = 0; vif1Regs.stat.FQC = 0;
} }
} }
#define caseVif(x) (idx ? VIF1_##x : VIF0_##x) #define caseVif(x) (idx ? VIF1_##x : VIF0_##x)
_vifT void vifWrite32(u32 mem, u32 value) { // returns FALSE if no writeback is needed (or writeback is handled internally)
// returns TRUE if the caller should writeback the value to the eeHw register map.
_vifT __fi bool vifWrite32(u32 mem, u32 value) {
switch (mem) { switch (mem) {
case caseVif(MARK): case caseVif(MARK):
VIF_LOG("VIF%d_MARK write32 0x%8.8x", idx, value); VIF_LOG("VIF%d_MARK write32 0x%8.8x", idx, value);
vifXRegs->stat.MRK = false; vifXRegs.stat.MRK = false;
vifXRegs->mark = value; //vifXRegs.mark = value;
break; break;
case caseVif(FBRST): case caseVif(FBRST):
if (!idx) vif0FBRST(value); if (!idx) vif0FBRST(value);
else vif1FBRST(value); else vif1FBRST(value);
break; return false;
case caseVif(ERR):
VIF_LOG("VIF%d_ERR write32 0x%8.8x", idx, value);
vifXRegs->err.write(value);
break;
case caseVif(STAT): case caseVif(STAT):
if (idx) { // Only Vif1 does this stuff? if (idx) { // Only Vif1 does this stuff?
vif1STAT(value); vif1STAT(value);
} }
else { return false;
Console.WriteLn("Unknown Vif%d write to %x", idx, mem);
psHu32(mem) = value;
}
break;
case caseVif(ERR):
case caseVif(MODE): case caseVif(MODE):
vifXRegs->mode = value; // standard register writes -- handled by caller.
break; break;
case caseVif(R0): case caseVif(ROW0):
case caseVif(R1): case caseVif(ROW1):
case caseVif(R2): case caseVif(ROW2):
case caseVif(R3): case caseVif(ROW3):
if (!idx) g_vifmask.Row0[ (mem>>4)&3 ] = value; // Here's a neat way to obfuscate code. This is a super-fancy-complicated version
else g_vifmask.Row1[ (mem>>4)&3 ] = value; // of a standard psHu32(mem) = value; writeback. Handled by caller for us, thanks! --air
((u32*)&vifXRegs->r0) [((mem>>4)&3)*4] = value; //if (!idx) g_vifmask.Row0[ (mem>>4)&3 ] = value;
//else g_vifmask.Row1[ (mem>>4)&3 ] = value;
//((u32*)&vifXRegs.r0) [((mem>>4)&3)*4] = value;
break; break;
case caseVif(C0): case caseVif(COL0):
case caseVif(C1): case caseVif(COL1):
case caseVif(C2): case caseVif(COL2):
case caseVif(C3): case caseVif(COL3):
if (!idx) g_vifmask.Col0[ (mem>>4)&3 ] = value; // Here's a neat way to obfuscate code. This is a super-fancy-complicated version
else g_vifmask.Col1[ (mem>>4)&3 ] = value; // of a standard psHu32(mem) = value; writeback. Handled by caller for us, thanks! --air
((u32*)&vifXRegs->c0) [((mem>>4)&3)*4] = value; //if (!idx) g_vifmask.Col0[ (mem>>4)&3 ] = value;
break; //else g_vifmask.Col1[ (mem>>4)&3 ] = value;
//((u32*)&vifXRegs.c0) [((mem>>4)&3)*4] = value;
default:
Console.WriteLn("Unknown Vif%d write to %x", idx, mem);
psHu32(mem) = value;
break; break;
} }
/* Other registers are read-only so do nothing for them */
// fall-through case: issue standard writeback behavior.
return true;
} }
void vif0Write32(u32 mem, u32 value) { vifWrite32<0>(mem, value); }
void vif1Write32(u32 mem, u32 value) { vifWrite32<1>(mem, value); } template bool vifWrite32<0>(u32 mem, u32 value);
template bool vifWrite32<1>(u32 mem, u32 value);

View File

@ -15,6 +15,7 @@
#pragma once #pragma once
#include "MemoryTypes.h"
#include "R5900.h" #include "R5900.h"
enum vif0_stat_flags enum vif0_stat_flags
@ -214,10 +215,8 @@ struct VIFregisters {
extern VIFregisters *vifRegs; extern VIFregisters *vifRegs;
#define vif0RegsRef ((VIFregisters&)eeMem->HW[0x3800]) static VIFregisters& vif0Regs = (VIFregisters&)eeHw[0x3800];
#define vif1RegsRef ((VIFregisters&)eeMem->HW[0x3c00]) static VIFregisters& vif1Regs = (VIFregisters&)eeHw[0x3C00];
#define vif0Regs (&vif0RegsRef)
#define vif1Regs (&vif1RegsRef)
#define _vifT template <int idx> #define _vifT template <int idx>
#define GetVifX (idx ? (vif1) : (vif0)) #define GetVifX (idx ? (vif1) : (vif0))

View File

@ -54,28 +54,28 @@ bool _VIF0chain()
{ {
u32 *pMem; u32 *pMem;
if (vif0ch->qwc == 0) if (vif0ch.qwc == 0)
{ {
vif0.inprogress = 0; vif0.inprogress = 0;
return true; return true;
} }
pMem = (u32*)dmaGetAddr(vif0ch->madr, false); pMem = (u32*)dmaGetAddr(vif0ch.madr, false);
if (pMem == NULL) if (pMem == NULL)
{ {
vif0.cmd = 0; vif0.cmd = 0;
vif0.tag.size = 0; vif0.tag.size = 0;
vif0ch->qwc = 0; vif0ch.qwc = 0;
return true; return true;
} }
VIF_LOG("VIF0chain size=%d, madr=%lx, tadr=%lx", VIF_LOG("VIF0chain size=%d, madr=%lx, tadr=%lx",
vif0ch->qwc, vif0ch->madr, vif0ch->tadr); vif0ch.qwc, vif0ch.madr, vif0ch.tadr);
if (vif0.vifstalled) if (vif0.vifstalled)
return VIF0transfer(pMem + vif0.irqoffset, vif0ch->qwc * 4 - vif0.irqoffset); return VIF0transfer(pMem + vif0.irqoffset, vif0ch.qwc * 4 - vif0.irqoffset);
else else
return VIF0transfer(pMem, vif0ch->qwc * 4); return VIF0transfer(pMem, vif0ch.qwc * 4);
} }
__fi void vif0SetupTransfer() __fi void vif0SetupTransfer()
@ -91,21 +91,21 @@ __fi void vif0SetupTransfer()
break; break;
case VIF_CHAIN_MODE: case VIF_CHAIN_MODE:
ptag = dmaGetAddr(vif0ch->tadr, false); //Set memory pointer to TADR ptag = dmaGetAddr(vif0ch.tadr, false); //Set memory pointer to TADR
if (!(vif0ch->transfer("vif0 Tag", ptag))) return; if (!(vif0ch.transfer("vif0 Tag", ptag))) return;
vif0ch->madr = ptag[1]._u32; //MADR = ADDR field + SPR vif0ch.madr = ptag[1]._u32; //MADR = ADDR field + SPR
g_vifCycles += 1; // Add 1 g_vifCycles from the QW read for the tag g_vifCycles += 1; // Add 1 g_vifCycles from the QW read for the tag
// Transfer dma tag if tte is set // Transfer dma tag if tte is set
VIF_LOG("vif0 Tag %8.8x_%8.8x size=%d, id=%d, madr=%lx, tadr=%lx", VIF_LOG("vif0 Tag %8.8x_%8.8x size=%d, id=%d, madr=%lx, tadr=%lx",
ptag[1]._u32, ptag[0]._u32, vif0ch->qwc, ptag->ID, vif0ch->madr, vif0ch->tadr); ptag[1]._u32, ptag[0]._u32, vif0ch.qwc, ptag->ID, vif0ch.madr, vif0ch.tadr);
vif0.inprogress = 0; vif0.inprogress = 0;
if (vif0ch->chcr.TTE) if (vif0ch.chcr.TTE)
{ {
bool ret; bool ret;
@ -124,9 +124,9 @@ __fi void vif0SetupTransfer()
vif0.irqoffset = 0; vif0.irqoffset = 0;
vif0.done |= hwDmacSrcChainWithStack(vif0ch, ptag->ID); vif0.done |= hwDmacSrcChainWithStack(vif0ch, ptag->ID);
if(vif0ch->qwc > 0) vif0.inprogress = 1; if(vif0ch.qwc > 0) vif0.inprogress = 1;
//Check TIE bit of CHCR and IRQ bit of tag //Check TIE bit of CHCR and IRQ bit of tag
if (vif0ch->chcr.TIE && ptag->IRQ) if (vif0ch.chcr.TIE && ptag->IRQ)
{ {
VIF_LOG("dmaIrq Set"); VIF_LOG("dmaIrq Set");
@ -144,29 +144,29 @@ __fi void vif0Interrupt()
g_vifCycles = 0; g_vifCycles = 0;
if (!(vif0ch->chcr.STR)) Console.WriteLn("vif0 running when CHCR == %x", vif0ch->chcr._u32); if (!(vif0ch.chcr.STR)) Console.WriteLn("vif0 running when CHCR == %x", vif0ch.chcr._u32);
if (vif0.cmd) if (vif0.cmd)
{ {
if(vif0.done == true && vif0ch->qwc == 0) vif0Regs->stat.VPS = VPS_WAITING; if(vif0.done == true && vif0ch.qwc == 0) vif0Regs.stat.VPS = VPS_WAITING;
} }
else else
{ {
vif0Regs->stat.VPS = VPS_IDLE; vif0Regs.stat.VPS = VPS_IDLE;
} }
if (vif0.irq && vif0.tag.size == 0) if (vif0.irq && vif0.tag.size == 0)
{ {
vif0Regs->stat.INT = true; vif0Regs.stat.INT = true;
hwIntcIrq(VIF0intc); hwIntcIrq(VIF0intc);
--vif0.irq; --vif0.irq;
if (vif0Regs->stat.test(VIF0_STAT_VSS | VIF0_STAT_VIS | VIF0_STAT_VFS)) if (vif0Regs.stat.test(VIF0_STAT_VSS | VIF0_STAT_VIS | VIF0_STAT_VFS))
{ {
vif0Regs->stat.FQC = 0; vif0Regs.stat.FQC = 0;
// One game doesn't like vif stalling at end, can't remember what. Spiderman isn't keen on it tho // One game doesn't like vif stalling at end, can't remember what. Spiderman isn't keen on it tho
//vif0ch->chcr.STR = false; //vif0ch.chcr.STR = false;
if(vif0ch->qwc > 0 || !vif0.done) return; if(vif0ch.qwc > 0 || !vif0.done) return;
} }
} }
@ -180,7 +180,7 @@ __fi void vif0Interrupt()
if (!vif0.done) if (!vif0.done)
{ {
if (!(dmacRegs->ctrl.DMAE)) if (!(dmacRegs.ctrl.DMAE))
{ {
Console.WriteLn("vif0 dma masked"); Console.WriteLn("vif0 dma masked");
return; return;
@ -199,22 +199,22 @@ __fi void vif0Interrupt()
return; //Dont want to end if vif is stalled. return; //Dont want to end if vif is stalled.
} }
#ifdef PCSX2_DEVBUILD #ifdef PCSX2_DEVBUILD
if (vif0ch->qwc > 0) Console.WriteLn("vif0 Ending with %x QWC left"); if (vif0ch.qwc > 0) Console.WriteLn("vif0 Ending with %x QWC left");
if (vif0.cmd != 0) Console.WriteLn("vif0.cmd still set %x tag size %x", vif0.cmd, vif0.tag.size); if (vif0.cmd != 0) Console.WriteLn("vif0.cmd still set %x tag size %x", vif0.cmd, vif0.tag.size);
#endif #endif
vif0ch->chcr.STR = false; vif0ch.chcr.STR = false;
g_vifCycles = 0; g_vifCycles = 0;
hwDmacIrq(DMAC_VIF0); hwDmacIrq(DMAC_VIF0);
vif0Regs->stat.FQC = 0; vif0Regs.stat.FQC = 0;
} }
void dmaVIF0() void dmaVIF0()
{ {
VIF_LOG("dmaVIF0 chcr = %lx, madr = %lx, qwc = %lx\n" VIF_LOG("dmaVIF0 chcr = %lx, madr = %lx, qwc = %lx\n"
" tadr = %lx, asr0 = %lx, asr1 = %lx", " tadr = %lx, asr0 = %lx, asr1 = %lx",
vif0ch->chcr._u32, vif0ch->madr, vif0ch->qwc, vif0ch.chcr._u32, vif0ch.madr, vif0ch.qwc,
vif0ch->tadr, vif0ch->asr0, vif0ch->asr1); vif0ch.tadr, vif0ch.asr0, vif0ch.asr1);
g_vifCycles = 0; g_vifCycles = 0;
g_vu0Cycles = 0; g_vu0Cycles = 0;
@ -224,18 +224,18 @@ void dmaVIF0()
vif0.inprogress = 0; vif0.inprogress = 0;
vif0.done = false;*/ vif0.done = false;*/
if ((vif0ch->chcr.MOD == NORMAL_MODE) || vif0ch->qwc > 0) // Normal Mode if ((vif0ch.chcr.MOD == NORMAL_MODE) || vif0ch.qwc > 0) // Normal Mode
{ {
vif0.dmamode = VIF_NORMAL_TO_MEM_MODE; vif0.dmamode = VIF_NORMAL_TO_MEM_MODE;
vif0.done = false; vif0.done = false;
if(vif0ch->chcr.MOD == CHAIN_MODE && vif0ch->qwc > 0) if(vif0ch.chcr.MOD == CHAIN_MODE && vif0ch.qwc > 0)
{ {
vif0.dmamode = VIF_CHAIN_MODE; vif0.dmamode = VIF_CHAIN_MODE;
DevCon.Warning(L"VIF0 QWC on Chain CHCR " + vif0ch->chcr.desc()); DevCon.Warning(L"VIF0 QWC on Chain CHCR " + vif0ch.chcr.desc());
if ((vif0ch->chcr.tag().ID == TAG_REFE) || (vif0ch->chcr.tag().ID == TAG_END)) if ((vif0ch.chcr.tag().ID == TAG_REFE) || (vif0ch.chcr.tag().ID == TAG_END))
{ {
vif0.done = true; vif0.done = true;
} }
@ -247,7 +247,7 @@ void dmaVIF0()
vif0.done = false; vif0.done = false;
} }
vif0Regs->stat.FQC = min((u16)0x8, vif0ch->qwc); vif0Regs.stat.FQC = min((u16)0x8, vif0ch.qwc);
//Using a delay as Beyond Good and Evil does the DMA twice with 2 different TADR's (no checks in the middle, all one block of code), //Using a delay as Beyond Good and Evil does the DMA twice with 2 different TADR's (no checks in the middle, all one block of code),
//the first bit it sends isnt required for it to work. //the first bit it sends isnt required for it to work.

View File

@ -46,10 +46,10 @@ __fi void vif1FLUSH()
//DevCon.Warning("VIF1 adding %x cycles", (VU1.cycle - _cycles) * BIAS); //DevCon.Warning("VIF1 adding %x cycles", (VU1.cycle - _cycles) * BIAS);
g_vifCycles += (VU1.cycle - _cycles) * BIAS; g_vifCycles += (VU1.cycle - _cycles) * BIAS;
} }
if(gifRegs->stat.P1Q && ((vif1.cmd & 0x7f) != 0x14) && ((vif1.cmd & 0x7f) != 0x17)) if(gifRegs.stat.P1Q && ((vif1.cmd & 0x7f) != 0x14) && ((vif1.cmd & 0x7f) != 0x17))
{ {
vif1.vifstalled = true; vif1.vifstalled = true;
vif1Regs->stat.VGW = true; vif1Regs.stat.VGW = true;
vif1.GifWaitState = 2; vif1.GifWaitState = 2;
} }
@ -58,16 +58,16 @@ __fi void vif1FLUSH()
void vif1TransferToMemory() void vif1TransferToMemory()
{ {
u32 size; u32 size;
u64* pMem = (u64*)dmaGetAddr(vif1ch->madr, false); u64* pMem = (u64*)dmaGetAddr(vif1ch.madr, false);
// VIF from gsMemory // VIF from gsMemory
if (pMem == NULL) //Is vif0ptag empty? if (pMem == NULL) //Is vif0ptag empty?
{ {
Console.WriteLn("Vif1 Tag BUSERR"); Console.WriteLn("Vif1 Tag BUSERR");
dmacRegs->stat.BEIS = true; //Bus Error dmacRegs.stat.BEIS = true; //Bus Error
vif1Regs->stat.FQC = 0; vif1Regs.stat.FQC = 0;
vif1ch->qwc = 0; vif1ch.qwc = 0;
vif1.done = true; vif1.done = true;
CPU_INT(DMAC_VIF1, 0); CPU_INT(DMAC_VIF1, 0);
return; //An error has occurred. return; //An error has occurred.
@ -76,8 +76,8 @@ void vif1TransferToMemory()
// MTGS concerns: The MTGS is inherently disagreeable with the idea of downloading // 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 // stuff from the GS. The *only* way to handle this case safely is to flush the GS
// completely and execute the transfer there-after. // completely and execute the transfer there-after.
//Console.Warning("Real QWC %x", vif1ch->qwc); //Console.Warning("Real QWC %x", vif1ch.qwc);
size = min((u32)vif1ch->qwc, vif1.GSLastDownloadSize); size = min((u32)vif1ch.qwc, vif1.GSLastDownloadSize);
if (GSreadFIFO2 == NULL) if (GSreadFIFO2 == NULL)
{ {
@ -90,10 +90,10 @@ void vif1TransferToMemory()
pMem[1] = psHu64(VIF1_FIFO + 8); pMem[1] = psHu64(VIF1_FIFO + 8);
pMem += 2; pMem += 2;
} }
if(vif1ch->qwc > vif1.GSLastDownloadSize) if(vif1ch.qwc > vif1.GSLastDownloadSize)
{ {
DevCon.Warning("GS Transfer < VIF QWC, Clearing end of space"); DevCon.Warning("GS Transfer < VIF QWC, Clearing end of space");
for (size = vif1ch->qwc - vif1.GSLastDownloadSize; size > 0; --size) for (size = vif1ch.qwc - vif1.GSLastDownloadSize; size > 0; --size)
{ {
psHu64(VIF1_FIFO) = 0; psHu64(VIF1_FIFO) = 0;
psHu64(VIF1_FIFO + 8) = 0; psHu64(VIF1_FIFO + 8) = 0;
@ -112,10 +112,10 @@ void vif1TransferToMemory()
psHu64(VIF1_FIFO) = pMem[2*size-2]; psHu64(VIF1_FIFO) = pMem[2*size-2];
psHu64(VIF1_FIFO + 8) = pMem[2*size-1]; psHu64(VIF1_FIFO + 8) = pMem[2*size-1];
pMem += size * 2; pMem += size * 2;
if(vif1ch->qwc > vif1.GSLastDownloadSize) if(vif1ch.qwc > vif1.GSLastDownloadSize)
{ {
DevCon.Warning("GS Transfer < VIF QWC, Clearing end of space"); DevCon.Warning("GS Transfer < VIF QWC, Clearing end of space");
for (size = vif1ch->qwc - vif1.GSLastDownloadSize; size > 0; --size) for (size = vif1ch.qwc - vif1.GSLastDownloadSize; size > 0; --size)
{ {
psHu64(VIF1_FIFO) = 0; psHu64(VIF1_FIFO) = 0;
psHu64(VIF1_FIFO + 8) = 0; psHu64(VIF1_FIFO + 8) = 0;
@ -127,27 +127,27 @@ void vif1TransferToMemory()
} }
g_vifCycles += vif1ch->qwc * 2; g_vifCycles += vif1ch.qwc * 2;
vif1ch->madr += vif1ch->qwc * 16; // mgs3 scene changes vif1ch.madr += vif1ch.qwc * 16; // mgs3 scene changes
if(vif1.GSLastDownloadSize >= vif1ch->qwc) if(vif1.GSLastDownloadSize >= vif1ch.qwc)
{ {
vif1.GSLastDownloadSize -= vif1ch->qwc; vif1.GSLastDownloadSize -= vif1ch.qwc;
vif1Regs->stat.FQC = min((u32)16, vif1.GSLastDownloadSize); vif1Regs.stat.FQC = min((u32)16, vif1.GSLastDownloadSize);
} }
else else
{ {
vif1Regs->stat.FQC = 0; vif1Regs.stat.FQC = 0;
vif1.GSLastDownloadSize = 0; vif1.GSLastDownloadSize = 0;
} }
vif1ch->qwc = 0; vif1ch.qwc = 0;
} }
bool _VIF1chain() bool _VIF1chain()
{ {
u32 *pMem; u32 *pMem;
if (vif1ch->qwc == 0) if (vif1ch.qwc == 0)
{ {
vif1.inprogress &= ~1; vif1.inprogress &= ~1;
vif1.irqoffset = 0; vif1.irqoffset = 0;
@ -162,28 +162,27 @@ bool _VIF1chain()
return true; return true;
} }
pMem = (u32*)dmaGetAddr(vif1ch->madr, !vif1ch->chcr.DIR); pMem = (u32*)dmaGetAddr(vif1ch.madr, !vif1ch.chcr.DIR);
if (pMem == NULL) if (pMem == NULL)
{ {
vif1.cmd = 0; vif1.cmd = 0;
vif1.tag.size = 0; vif1.tag.size = 0;
vif1ch->qwc = 0; vif1ch.qwc = 0;
return true; return true;
} }
VIF_LOG("VIF1chain size=%d, madr=%lx, tadr=%lx", VIF_LOG("VIF1chain size=%d, madr=%lx, tadr=%lx",
vif1ch->qwc, vif1ch->madr, vif1ch->tadr); vif1ch.qwc, vif1ch.madr, vif1ch.tadr);
if (vif1.vifstalled) if (vif1.vifstalled)
return VIF1transfer(pMem + vif1.irqoffset, vif1ch->qwc * 4 - vif1.irqoffset); return VIF1transfer(pMem + vif1.irqoffset, vif1ch.qwc * 4 - vif1.irqoffset);
else else
return VIF1transfer(pMem, vif1ch->qwc * 4); return VIF1transfer(pMem, vif1ch.qwc * 4);
} }
__fi void vif1SetupTransfer() __fi void vif1SetupTransfer()
{ {
tDMA_TAG *ptag; tDMA_TAG *ptag;
DMACh& vif1c = (DMACh&)eeMem->HW[0x9000];
switch (vif1.dmamode) switch (vif1.dmamode)
{ {
@ -195,20 +194,20 @@ __fi void vif1SetupTransfer()
break; break;
case VIF_CHAIN_MODE: case VIF_CHAIN_MODE:
ptag = dmaGetAddr(vif1c.tadr, false); //Set memory pointer to TADR ptag = dmaGetAddr(vif1ch.tadr, false); //Set memory pointer to TADR
if (!(vif1c.transfer("Vif1 Tag", ptag))) return; if (!(vif1ch.transfer("Vif1 Tag", ptag))) return;
vif1c.madr = ptag[1]._u32; //MADR = ADDR field + SPR vif1ch.madr = ptag[1]._u32; //MADR = ADDR field + SPR
g_vifCycles += 1; // Add 1 g_vifCycles from the QW read for the tag g_vifCycles += 1; // Add 1 g_vifCycles from the QW read for the tag
VIF_LOG("VIF1 Tag %8.8x_%8.8x size=%d, id=%d, madr=%lx, tadr=%lx", VIF_LOG("VIF1 Tag %8.8x_%8.8x size=%d, id=%d, madr=%lx, tadr=%lx",
ptag[1]._u32, ptag[0]._u32, vif1c.qwc, ptag->ID, vif1c.madr, vif1c.tadr); ptag[1]._u32, ptag[0]._u32, vif1ch.qwc, ptag->ID, vif1ch.madr, vif1ch.tadr);
if (!vif1.done && ((dmacRegs->ctrl.STD == STD_VIF1) && (ptag->ID == TAG_REFS))) // STD == VIF1 if (!vif1.done && ((dmacRegs.ctrl.STD == STD_VIF1) && (ptag->ID == TAG_REFS))) // STD == VIF1
{ {
// there are still bugs, need to also check if gif->madr +16*qwc >= stadr, if not, stall // there are still bugs, need to also check if gif->madr +16*qwc >= stadr, if not, stall
if ((vif1c.madr + vif1c.qwc * 16) >= dmacRegs->stadr.ADDR) if ((vif1ch.madr + vif1ch.qwc * 16) >= dmacRegs.stadr.ADDR)
{ {
// stalled // stalled
hwDmacIrq(DMAC_STALL_SIS); hwDmacIrq(DMAC_STALL_SIS);
@ -219,7 +218,7 @@ __fi void vif1SetupTransfer()
vif1.inprogress &= ~1; vif1.inprogress &= ~1;
if (vif1c.chcr.TTE) if (vif1ch.chcr.TTE)
{ {
// Transfer dma tag if tte is set // Transfer dma tag if tte is set
@ -243,10 +242,10 @@ __fi void vif1SetupTransfer()
vif1.done |= hwDmacSrcChainWithStack(vif1ch, ptag->ID); vif1.done |= hwDmacSrcChainWithStack(vif1ch, ptag->ID);
if(vif1c.qwc > 0) vif1.inprogress |= 1; if(vif1ch.qwc > 0) vif1.inprogress |= 1;
//Check TIE bit of CHCR and IRQ bit of tag //Check TIE bit of CHCR and IRQ bit of tag
if (vif1c.chcr.TIE && ptag->IRQ) if (vif1ch.chcr.TIE && ptag->IRQ)
{ {
VIF_LOG("dmaIrq Set"); VIF_LOG("dmaIrq Set");
@ -262,73 +261,73 @@ extern bool SIGNAL_IMR_Pending;
bool CheckPath2GIF(EE_EventType channel) bool CheckPath2GIF(EE_EventType channel)
{ {
if ((vif1Regs->stat.VGW)) if ((vif1Regs.stat.VGW))
{ {
if( vif1.GifWaitState == 0 ) //DIRECT/HL Check if( vif1.GifWaitState == 0 ) //DIRECT/HL Check
{ {
if(GSTransferStatus.PTH3 < IDLE_MODE || gifRegs->stat.P1Q) if(GSTransferStatus.PTH3 < IDLE_MODE || gifRegs.stat.P1Q)
{ {
if(gifRegs->stat.IMT && GSTransferStatus.PTH3 <= IMAGE_MODE && (vif1.cmd & 0x7f) == 0x50 && gifRegs->stat.P1Q == false) if(gifRegs.stat.IMT && GSTransferStatus.PTH3 <= IMAGE_MODE && (vif1.cmd & 0x7f) == 0x50 && gifRegs.stat.P1Q == false)
{ {
vif1Regs->stat.VGW = false; vif1Regs.stat.VGW = false;
} }
else else
{ {
//DevCon.Warning("VIF1-0 stall P1Q %x P2Q %x APATH %x PTH3 %x vif1cmd %x", gifRegs->stat.P1Q, gifRegs->stat.P2Q, gifRegs->stat.APATH, GSTransferStatus.PTH3, vif1.cmd); //DevCon.Warning("VIF1-0 stall P1Q %x P2Q %x APATH %x PTH3 %x vif1cmd %x", gifRegs.stat.P1Q, gifRegs.stat.P2Q, gifRegs.stat.APATH, GSTransferStatus.PTH3, vif1.cmd);
CPU_INT(channel, 128); CPU_INT(channel, 128);
return false; return false;
} }
} }
else else
{ {
vif1Regs->stat.VGW = false; vif1Regs.stat.VGW = false;
} }
} }
else if( vif1.GifWaitState == 1 ) // Else we're flushing path3 :), but of course waiting for the microprogram to finish else if( vif1.GifWaitState == 1 ) // Else we're flushing path3 :), but of course waiting for the microprogram to finish
{ {
if (gifRegs->stat.P1Q) if (gifRegs.stat.P1Q)
{ {
//DevCon.Warning("VIF1-1 stall P1Q %x P2Q %x APATH %x PTH3 %x vif1cmd %x", gifRegs->stat.P1Q, gifRegs->stat.P2Q, gifRegs->stat.APATH, GSTransferStatus.PTH3, vif1.cmd); //DevCon.Warning("VIF1-1 stall P1Q %x P2Q %x APATH %x PTH3 %x vif1cmd %x", gifRegs.stat.P1Q, gifRegs.stat.P2Q, gifRegs.stat.APATH, GSTransferStatus.PTH3, vif1.cmd);
CPU_INT(channel, 128); CPU_INT(channel, 128);
return false; return false;
} }
if (GSTransferStatus.PTH3 < IDLE_MODE) if (GSTransferStatus.PTH3 < IDLE_MODE)
{ {
//DevCon.Warning("VIF1-11 stall P1Q %x P2Q %x APATH %x PTH3 %x vif1cmd %x", gifRegs->stat.P1Q, gifRegs->stat.P2Q, gifRegs->stat.APATH, GSTransferStatus.PTH3, vif1.cmd); //DevCon.Warning("VIF1-11 stall P1Q %x P2Q %x APATH %x PTH3 %x vif1cmd %x", gifRegs.stat.P1Q, gifRegs.stat.P2Q, gifRegs.stat.APATH, GSTransferStatus.PTH3, vif1.cmd);
//DevCon.Warning("PTH3 %x P1Q %x P3Q %x IP3 %x", GSTransferStatus.PTH3, gifRegs->stat.P1Q, gifRegs->stat.P3Q, gifRegs->stat.IP3 ); //DevCon.Warning("PTH3 %x P1Q %x P3Q %x IP3 %x", GSTransferStatus.PTH3, gifRegs.stat.P1Q, gifRegs.stat.P3Q, gifRegs.stat.IP3 );
CPU_INT(channel, 8); CPU_INT(channel, 8);
return false; return false;
} }
else else
{ {
vif1Regs->stat.VGW = false; vif1Regs.stat.VGW = false;
} }
} }
else if( vif1.GifWaitState == 3 ) // Else we're flushing path3 :), but of course waiting for the microprogram to finish else if( vif1.GifWaitState == 3 ) // Else we're flushing path3 :), but of course waiting for the microprogram to finish
{ {
if (gifRegs->ctrl.PSE) if (gifRegs.ctrl.PSE)
{ {
//DevCon.Warning("VIF1-1 stall P1Q %x P2Q %x APATH %x PTH3 %x vif1cmd %x", gifRegs->stat.P1Q, gifRegs->stat.P2Q, gifRegs->stat.APATH, GSTransferStatus.PTH3, vif1.cmd); //DevCon.Warning("VIF1-1 stall P1Q %x P2Q %x APATH %x PTH3 %x vif1cmd %x", gifRegs.stat.P1Q, gifRegs.stat.P2Q, gifRegs.stat.APATH, GSTransferStatus.PTH3, vif1.cmd);
CPU_INT(channel, 128); CPU_INT(channel, 128);
return false; return false;
} }
else else
{ {
vif1Regs->stat.VGW = false; vif1Regs.stat.VGW = false;
} }
} }
else //Normal Flush else //Normal Flush
{ {
if (gifRegs->stat.P1Q) if (gifRegs.stat.P1Q)
{ {
//DevCon.Warning("VIF1-2 stall P1Q %x P2Q %x APATH %x PTH3 %x vif1cmd %x", gifRegs->stat.P1Q, gifRegs->stat.P2Q, gifRegs->stat.APATH, GSTransferStatus.PTH3, vif1.cmd); //DevCon.Warning("VIF1-2 stall P1Q %x P2Q %x APATH %x PTH3 %x vif1cmd %x", gifRegs.stat.P1Q, gifRegs.stat.P2Q, gifRegs.stat.APATH, GSTransferStatus.PTH3, vif1.cmd);
CPU_INT(channel, 128); CPU_INT(channel, 128);
return false; return false;
} }
else else
{ {
vif1Regs->stat.VGW = false; vif1Regs.stat.VGW = false;
} }
} }
} }
@ -346,11 +345,11 @@ __fi void vif1Interrupt()
g_vifCycles = 0; g_vifCycles = 0;
if(GSTransferStatus.PTH2 == STOPPED_MODE && gifRegs->stat.APATH == GIF_APATH2) if(GSTransferStatus.PTH2 == STOPPED_MODE && gifRegs.stat.APATH == GIF_APATH2)
{ {
gifRegs->stat.OPH = false; gifRegs.stat.OPH = false;
gifRegs->stat.APATH = GIF_APATH_IDLE; gifRegs.stat.APATH = GIF_APATH_IDLE;
if(gifRegs->stat.P1Q) gsPath1Interrupt(); if(gifRegs.stat.P1Q) gsPath1Interrupt();
} }
if (schedulepath3msk & 0x10) if (schedulepath3msk & 0x10)
@ -360,48 +359,48 @@ __fi void vif1Interrupt()
return; return;
} }
//Some games (Fahrenheit being one) start vif first, let it loop through blankness while it sets MFIFO mode, so we need to check it here. //Some games (Fahrenheit being one) start vif first, let it loop through blankness while it sets MFIFO mode, so we need to check it here.
if (dmacRegs->ctrl.MFD == MFD_VIF1) if (dmacRegs.ctrl.MFD == MFD_VIF1)
{ {
//Console.WriteLn("VIFMFIFO\n"); //Console.WriteLn("VIFMFIFO\n");
// Test changed because the Final Fantasy 12 opening somehow has the tag in *Undefined* mode, which is not in the documentation that I saw. // Test changed because the Final Fantasy 12 opening somehow has the tag in *Undefined* mode, which is not in the documentation that I saw.
if (vif1ch->chcr.MOD == NORMAL_MODE) Console.WriteLn("MFIFO mode is normal (which isn't normal here)! %x", vif1ch->chcr._u32); if (vif1ch.chcr.MOD == NORMAL_MODE) Console.WriteLn("MFIFO mode is normal (which isn't normal here)! %x", vif1ch.chcr._u32);
vif1Regs->stat.FQC = min((u16)0x10, vif1ch->qwc); vif1Regs.stat.FQC = min((u16)0x10, vif1ch.qwc);
vifMFIFOInterrupt(); vifMFIFOInterrupt();
return; return;
} }
//We need to check the direction, if it is downloading from the GS, we handle that separately (KH2 for testing) //We need to check the direction, if it is downloading from the GS, we handle that separately (KH2 for testing)
if (vif1ch->chcr.DIR) if (vif1ch.chcr.DIR)
{ {
if (!CheckPath2GIF(DMAC_VIF1)) return; if (!CheckPath2GIF(DMAC_VIF1)) return;
vif1Regs->stat.FQC = min(vif1ch->qwc, (u16)16); vif1Regs.stat.FQC = min(vif1ch.qwc, (u16)16);
//Simulated GS transfer time done, clear the flags //Simulated GS transfer time done, clear the flags
} }
if (!vif1ch->chcr.STR) Console.WriteLn("Vif1 running when CHCR == %x", vif1ch->chcr._u32); if (!vif1ch.chcr.STR) Console.WriteLn("Vif1 running when CHCR == %x", vif1ch.chcr._u32);
if (vif1.cmd) if (vif1.cmd)
{ {
if (vif1.done && (vif1ch->qwc == 0)) vif1Regs->stat.VPS = VPS_WAITING; if (vif1.done && (vif1ch.qwc == 0)) vif1Regs.stat.VPS = VPS_WAITING;
} }
else else
{ {
vif1Regs->stat.VPS = VPS_IDLE; vif1Regs.stat.VPS = VPS_IDLE;
} }
if (vif1.irq && vif1.tag.size == 0) if (vif1.irq && vif1.tag.size == 0)
{ {
vif1Regs->stat.INT = true; vif1Regs.stat.INT = true;
hwIntcIrq(VIF1intc); hwIntcIrq(VIF1intc);
--vif1.irq; --vif1.irq;
if (vif1Regs->stat.test(VIF1_STAT_VSS | VIF1_STAT_VIS | VIF1_STAT_VFS)) if (vif1Regs.stat.test(VIF1_STAT_VSS | VIF1_STAT_VIS | VIF1_STAT_VFS))
{ {
//vif1Regs->stat.FQC = 0; //vif1Regs.stat.FQC = 0;
//NFSHPS stalls when the whole packet has gone across (it stalls in the last 32bit cmd) //NFSHPS stalls when the whole packet has gone across (it stalls in the last 32bit cmd)
//In this case VIF will end //In this case VIF will end
if(vif1ch->qwc > 0 || !vif1.done) return; if(vif1ch.qwc > 0 || !vif1.done) return;
} }
} }
@ -410,7 +409,7 @@ __fi void vif1Interrupt()
_VIF1chain(); _VIF1chain();
// VIF_NORMAL_FROM_MEM_MODE is a very slow operation. // VIF_NORMAL_FROM_MEM_MODE is a very slow operation.
// Timesplitters 2 depends on this beeing a bit higher than 128. // Timesplitters 2 depends on this beeing a bit higher than 128.
if (vif1ch->chcr.DIR) vif1Regs->stat.FQC = min(vif1ch->qwc, (u16)16); if (vif1ch.chcr.DIR) vif1Regs.stat.FQC = min(vif1ch.qwc, (u16)16);
// Refraction - Removing voodoo timings for now, completely messes a lot of Path3 masked games. // Refraction - Removing voodoo timings for now, completely messes a lot of Path3 masked games.
/*if (vif1.dmamode == VIF_NORMAL_FROM_MEM_MODE ) CPU_INT(DMAC_VIF1, 1024); /*if (vif1.dmamode == VIF_NORMAL_FROM_MEM_MODE ) CPU_INT(DMAC_VIF1, 1024);
else */CPU_INT(DMAC_VIF1, g_vifCycles /*VifCycleVoodoo*/); else */CPU_INT(DMAC_VIF1, g_vifCycles /*VifCycleVoodoo*/);
@ -420,14 +419,14 @@ __fi void vif1Interrupt()
if (!vif1.done) if (!vif1.done)
{ {
if (!(dmacRegs->ctrl.DMAE)) if (!(dmacRegs.ctrl.DMAE))
{ {
Console.WriteLn("vif1 dma masked"); Console.WriteLn("vif1 dma masked");
return; return;
} }
if ((vif1.inprogress & 0x1) == 0) vif1SetupTransfer(); if ((vif1.inprogress & 0x1) == 0) vif1SetupTransfer();
if (vif1ch->chcr.DIR) vif1Regs->stat.FQC = min(vif1ch->qwc, (u16)16); if (vif1ch.chcr.DIR) vif1Regs.stat.FQC = min(vif1ch.qwc, (u16)16);
CPU_INT(DMAC_VIF1, g_vifCycles); CPU_INT(DMAC_VIF1, g_vifCycles);
return; return;
} }
@ -439,17 +438,17 @@ __fi void vif1Interrupt()
return; //Dont want to end if vif is stalled. return; //Dont want to end if vif is stalled.
} }
#ifdef PCSX2_DEVBUILD #ifdef PCSX2_DEVBUILD
if (vif1ch->qwc > 0) Console.WriteLn("VIF1 Ending with %x QWC left", vif1ch->qwc); if (vif1ch.qwc > 0) Console.WriteLn("VIF1 Ending with %x QWC left", vif1ch.qwc);
if (vif1.cmd != 0) Console.WriteLn("vif1.cmd still set %x tag size %x", vif1.cmd, vif1.tag.size); if (vif1.cmd != 0) Console.WriteLn("vif1.cmd still set %x tag size %x", vif1.cmd, vif1.tag.size);
#endif #endif
if((vif1ch->chcr.DIR == VIF_NORMAL_TO_MEM_MODE) && vif1.GSLastDownloadSize <= 16) if((vif1ch.chcr.DIR == VIF_NORMAL_TO_MEM_MODE) && vif1.GSLastDownloadSize <= 16)
{ {
//Reverse fifo has finished and nothing is left, so lets clear the outputting flag //Reverse fifo has finished and nothing is left, so lets clear the outputting flag
gifRegs->stat.OPH = false; gifRegs.stat.OPH = false;
} }
vif1ch->chcr.STR = false; vif1ch.chcr.STR = false;
vif1.vifstalled = false; vif1.vifstalled = false;
g_vifCycles = 0; g_vifCycles = 0;
g_vu1Cycles = 0; g_vu1Cycles = 0;
@ -462,8 +461,8 @@ void dmaVIF1()
{ {
VIF_LOG("dmaVIF1 chcr = %lx, madr = %lx, qwc = %lx\n" VIF_LOG("dmaVIF1 chcr = %lx, madr = %lx, qwc = %lx\n"
" tadr = %lx, asr0 = %lx, asr1 = %lx", " tadr = %lx, asr0 = %lx, asr1 = %lx",
vif1ch->chcr._u32, vif1ch->madr, vif1ch->qwc, vif1ch.chcr._u32, vif1ch.madr, vif1ch.qwc,
vif1ch->tadr, vif1ch->asr0, vif1ch->asr1); vif1ch.tadr, vif1ch.asr0, vif1ch.asr1);
// vif1.done = false; // vif1.done = false;
@ -475,19 +474,19 @@ void dmaVIF1()
g_vu1Cycles = 0; g_vu1Cycles = 0;
#ifdef PCSX2_DEVBUILD #ifdef PCSX2_DEVBUILD
if (dmacRegs->ctrl.STD == STD_VIF1) if (dmacRegs.ctrl.STD == STD_VIF1)
{ {
//DevCon.WriteLn("VIF Stall Control Source = %x, Drain = %x", (psHu32(0xe000) >> 4) & 0x3, (psHu32(0xe000) >> 6) & 0x3); //DevCon.WriteLn("VIF Stall Control Source = %x, Drain = %x", (psHu32(0xe000) >> 4) & 0x3, (psHu32(0xe000) >> 6) & 0x3);
} }
#endif #endif
if ((vif1ch->chcr.MOD == NORMAL_MODE) || vif1ch->qwc > 0) // Normal Mode if ((vif1ch.chcr.MOD == NORMAL_MODE) || vif1ch.qwc > 0) // Normal Mode
{ {
if (dmacRegs->ctrl.STD == STD_VIF1) if (dmacRegs.ctrl.STD == STD_VIF1)
Console.WriteLn("DMA Stall Control on VIF1 normal"); Console.WriteLn("DMA Stall Control on VIF1 normal");
if (vif1ch->chcr.DIR) // to Memory if (vif1ch.chcr.DIR) // to Memory
vif1.dmamode = VIF_NORMAL_FROM_MEM_MODE; vif1.dmamode = VIF_NORMAL_FROM_MEM_MODE;
else else
vif1.dmamode = VIF_NORMAL_TO_MEM_MODE; vif1.dmamode = VIF_NORMAL_TO_MEM_MODE;
@ -495,12 +494,12 @@ void dmaVIF1()
vif1.done = false; vif1.done = false;
// ignore tag if it's a GS download (Def Jam Fight for NY) // ignore tag if it's a GS download (Def Jam Fight for NY)
if(vif1ch->chcr.MOD == CHAIN_MODE && vif1.dmamode != VIF_NORMAL_TO_MEM_MODE) if(vif1ch.chcr.MOD == CHAIN_MODE && vif1.dmamode != VIF_NORMAL_TO_MEM_MODE)
{ {
vif1.dmamode = VIF_CHAIN_MODE; vif1.dmamode = VIF_CHAIN_MODE;
DevCon.Warning(L"VIF1 QWC on Chain CHCR " + vif1ch->chcr.desc()); DevCon.Warning(L"VIF1 QWC on Chain CHCR " + vif1ch.chcr.desc());
if ((vif1ch->chcr.tag().ID == TAG_REFE) || (vif1ch->chcr.tag().ID == TAG_END)) if ((vif1ch.chcr.tag().ID == TAG_REFE) || (vif1ch.chcr.tag().ID == TAG_END))
{ {
vif1.done = true; vif1.done = true;
} }
@ -512,7 +511,7 @@ void dmaVIF1()
vif1.done = false; vif1.done = false;
} }
if (vif1ch->chcr.DIR) vif1Regs->stat.FQC = min((u16)0x10, vif1ch->qwc); if (vif1ch.chcr.DIR) vif1Regs.stat.FQC = min((u16)0x10, vif1ch.qwc);
// Chain Mode // Chain Mode
CPU_INT(DMAC_VIF1, 4); CPU_INT(DMAC_VIF1, 4);

View File

@ -33,26 +33,26 @@ extern u32 g_vifCycles;
static u32 qwctag(u32 mask) static u32 qwctag(u32 mask)
{ {
return (dmacRegs->rbor.ADDR + (mask & dmacRegs->rbsr.RMSK)); return (dmacRegs.rbor.ADDR + (mask & dmacRegs.rbsr.RMSK));
} }
static __fi bool mfifoVIF1rbTransfer() static __fi bool mfifoVIF1rbTransfer()
{ {
u32 maddr = dmacRegs->rbor.ADDR; u32 maddr = dmacRegs.rbor.ADDR;
u32 msize = dmacRegs->rbor.ADDR + dmacRegs->rbsr.RMSK + 16; u32 msize = dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16;
u16 mfifoqwc = std::min(vif1ch->qwc, vifqwc); u16 mfifoqwc = std::min(vif1ch.qwc, vifqwc);
u32 *src; u32 *src;
bool ret; bool ret;
/* Check if the transfer should wrap around the ring buffer */ /* Check if the transfer should wrap around the ring buffer */
if ((vif1ch->madr + (mfifoqwc << 4)) > (msize)) if ((vif1ch.madr + (mfifoqwc << 4)) > (msize))
{ {
int s1 = ((msize) - vif1ch->madr) >> 2; int s1 = ((msize) - vif1ch.madr) >> 2;
SPR_LOG("Split MFIFO"); SPR_LOG("Split MFIFO");
/* it does, so first copy 's1' bytes from 'addr' to 'data' */ /* it does, so first copy 's1' bytes from 'addr' to 'data' */
src = (u32*)PSM(vif1ch->madr); src = (u32*)PSM(vif1ch.madr);
if (src == NULL) return false; if (src == NULL) return false;
if (vif1.vifstalled) if (vif1.vifstalled)
@ -60,18 +60,18 @@ static __fi bool mfifoVIF1rbTransfer()
else else
ret = VIF1transfer(src, s1); ret = VIF1transfer(src, s1);
vif1ch->madr = qwctag(vif1ch->madr); vif1ch.madr = qwctag(vif1ch.madr);
if (ret) if (ret)
{ {
/* and second copy 's2' bytes from 'maddr' to '&data[s1]' */ /* and second copy 's2' bytes from 'maddr' to '&data[s1]' */
vif1ch->madr = maddr; vif1ch.madr = maddr;
src = (u32*)PSM(maddr); src = (u32*)PSM(maddr);
if (src == NULL) return false; if (src == NULL) return false;
VIF1transfer(src, ((mfifoqwc << 2) - s1)); VIF1transfer(src, ((mfifoqwc << 2) - s1));
} }
vif1ch->madr = qwctag(vif1ch->madr); vif1ch.madr = qwctag(vif1ch.madr);
} }
else else
@ -79,7 +79,7 @@ static __fi bool mfifoVIF1rbTransfer()
SPR_LOG("Direct MFIFO"); SPR_LOG("Direct MFIFO");
/* it doesn't, so just transfer 'qwc*4' words */ /* it doesn't, so just transfer 'qwc*4' words */
src = (u32*)PSM(vif1ch->madr); src = (u32*)PSM(vif1ch.madr);
if (src == NULL) return false; if (src == NULL) return false;
if (vif1.vifstalled) if (vif1.vifstalled)
@ -87,7 +87,7 @@ static __fi bool mfifoVIF1rbTransfer()
else else
ret = VIF1transfer(src, mfifoqwc << 2); ret = VIF1transfer(src, mfifoqwc << 2);
vif1ch->madr = qwctag(vif1ch->madr); vif1ch.madr = qwctag(vif1ch.madr);
} }
return ret; return ret;
@ -96,25 +96,25 @@ static __fi bool mfifoVIF1rbTransfer()
static __fi void mfifo_VIF1chain() static __fi void mfifo_VIF1chain()
{ {
/* Is QWC = 0? if so there is nothing to transfer */ /* Is QWC = 0? if so there is nothing to transfer */
if ((vif1ch->qwc == 0)) if ((vif1ch.qwc == 0))
{ {
vif1.inprogress &= ~1; vif1.inprogress &= ~1;
return; return;
} }
if (vif1ch->madr >= dmacRegs->rbor.ADDR && if (vif1ch.madr >= dmacRegs.rbor.ADDR &&
vif1ch->madr <= (dmacRegs->rbor.ADDR + dmacRegs->rbsr.RMSK)) vif1ch.madr <= (dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK))
{ {
//Need to exit on mfifo locations, if the madr is matching the madr of spr, we dont have any data left :( //Need to exit on mfifo locations, if the madr is matching the madr of spr, we dont have any data left :(
u16 startqwc = vif1ch->qwc; u16 startqwc = vif1ch.qwc;
mfifoVIF1rbTransfer(); mfifoVIF1rbTransfer();
vifqwc -= startqwc - vif1ch->qwc; vifqwc -= startqwc - vif1ch.qwc;
} }
else else
{ {
tDMA_TAG *pMem = dmaGetAddr(vif1ch->madr, !vif1ch->chcr.DIR); tDMA_TAG *pMem = dmaGetAddr(vif1ch.madr, !vif1ch.chcr.DIR);
SPR_LOG("Non-MFIFO Location"); SPR_LOG("Non-MFIFO Location");
//No need to exit on non-mfifo as it is indirect anyway, so it can be transferring this while spr refills the mfifo //No need to exit on non-mfifo as it is indirect anyway, so it can be transferring this while spr refills the mfifo
@ -122,9 +122,9 @@ static __fi void mfifo_VIF1chain()
if (pMem == NULL) return; if (pMem == NULL) return;
if (vif1.vifstalled) if (vif1.vifstalled)
VIF1transfer((u32*)pMem + vif1.irqoffset, vif1ch->qwc * 4 - vif1.irqoffset); VIF1transfer((u32*)pMem + vif1.irqoffset, vif1ch.qwc * 4 - vif1.irqoffset);
else else
VIF1transfer((u32*)pMem, vif1ch->qwc << 2); VIF1transfer((u32*)pMem, vif1ch.qwc << 2);
} }
} }
@ -139,23 +139,23 @@ void mfifoVIF1transfer(int qwc)
if (qwc > 0) if (qwc > 0)
{ {
vifqwc += qwc; vifqwc += qwc;
SPR_LOG("Added %x qw to mfifo, total now %x - Vif CHCR %x Stalled %x done %x", qwc, vifqwc, vif1ch->chcr._u32, vif1.vifstalled, vif1.done); SPR_LOG("Added %x qw to mfifo, total now %x - Vif CHCR %x Stalled %x done %x", qwc, vifqwc, vif1ch.chcr._u32, vif1.vifstalled, vif1.done);
if (vif1.inprogress & 0x10) if (vif1.inprogress & 0x10)
{ {
if(vif1ch->chcr.STR == true)CPU_INT(DMAC_MFIFO_VIF, 4); if(vif1ch.chcr.STR == true)CPU_INT(DMAC_MFIFO_VIF, 4);
vif1Regs->stat.FQC = 0x10; // FQC=16 vif1Regs.stat.FQC = 0x10; // FQC=16
} }
vif1.inprogress &= ~0x10; vif1.inprogress &= ~0x10;
return; return;
} }
if (vif1ch->qwc == 0 && vifqwc > 0) if (vif1ch.qwc == 0 && vifqwc > 0)
{ {
ptag = dmaGetAddr(vif1ch->tadr, false); ptag = dmaGetAddr(vif1ch.tadr, false);
if (vif1ch->chcr.TTE) if (vif1ch.chcr.TTE)
{ {
bool ret; bool ret;
@ -173,62 +173,62 @@ void mfifoVIF1transfer(int qwc)
vif1.irqoffset = 0; vif1.irqoffset = 0;
vif1ch->unsafeTransfer(ptag); vif1ch.unsafeTransfer(ptag);
vif1ch->madr = ptag[1]._u32; vif1ch.madr = ptag[1]._u32;
vifqwc--; vifqwc--;
SPR_LOG("dmaChain %8.8x_%8.8x size=%d, id=%d, madr=%lx, tadr=%lx mfifo qwc = %x spr0 madr = %x", SPR_LOG("dmaChain %8.8x_%8.8x size=%d, id=%d, madr=%lx, tadr=%lx mfifo qwc = %x spr0 madr = %x",
ptag[1]._u32, ptag[0]._u32, vif1ch->qwc, ptag->ID, vif1ch->madr, vif1ch->tadr, vifqwc, spr0->madr); ptag[1]._u32, ptag[0]._u32, vif1ch.qwc, ptag->ID, vif1ch.madr, vif1ch.tadr, vifqwc, spr0ch.madr);
switch (ptag->ID) switch (ptag->ID)
{ {
case TAG_REFE: // Refe - Transfer Packet According to ADDR field case TAG_REFE: // Refe - Transfer Packet According to ADDR field
vif1ch->tadr = qwctag(vif1ch->tadr + 16); vif1ch.tadr = qwctag(vif1ch.tadr + 16);
vif1.done = true; //End Transfer vif1.done = true; //End Transfer
break; break;
case TAG_CNT: // CNT - Transfer QWC following the tag. case TAG_CNT: // CNT - Transfer QWC following the tag.
vif1ch->madr = qwctag(vif1ch->tadr + 16); //Set MADR to QW after Tag vif1ch.madr = qwctag(vif1ch.tadr + 16); //Set MADR to QW after Tag
vif1ch->tadr = qwctag(vif1ch->madr + (vif1ch->qwc << 4)); //Set TADR to QW following the data vif1ch.tadr = qwctag(vif1ch.madr + (vif1ch.qwc << 4)); //Set TADR to QW following the data
vif1.done = false; vif1.done = false;
break; break;
case TAG_NEXT: // Next - Transfer QWC following tag. TADR = ADDR case TAG_NEXT: // Next - Transfer QWC following tag. TADR = ADDR
{ {
int temp = vif1ch->madr; //Temporarily Store ADDR int temp = vif1ch.madr; //Temporarily Store ADDR
vif1ch->madr = qwctag(vif1ch->tadr + 16); //Set MADR to QW following the tag vif1ch.madr = qwctag(vif1ch.tadr + 16); //Set MADR to QW following the tag
vif1ch->tadr = temp; //Copy temporarily stored ADDR to Tag vif1ch.tadr = temp; //Copy temporarily stored ADDR to Tag
if ((temp & dmacRegs->rbsr.RMSK) != dmacRegs->rbor.ADDR) Console.WriteLn("Next tag = %x outside ring %x size %x", temp, psHu32(DMAC_RBOR), psHu32(DMAC_RBSR)); if ((temp & dmacRegs.rbsr.RMSK) != dmacRegs.rbor.ADDR) Console.WriteLn("Next tag = %x outside ring %x size %x", temp, psHu32(DMAC_RBOR), psHu32(DMAC_RBSR));
vif1.done = false; vif1.done = false;
break; break;
} }
case TAG_REF: // Ref - Transfer QWC from ADDR field case TAG_REF: // Ref - Transfer QWC from ADDR field
case TAG_REFS: // Refs - Transfer QWC from ADDR field (Stall Control) case TAG_REFS: // Refs - Transfer QWC from ADDR field (Stall Control)
vif1ch->tadr = qwctag(vif1ch->tadr + 16); //Set TADR to next tag vif1ch.tadr = qwctag(vif1ch.tadr + 16); //Set TADR to next tag
vif1.done = false; vif1.done = false;
break; break;
case TAG_END: // End - Transfer QWC following the tag case TAG_END: // End - Transfer QWC following the tag
vif1ch->madr = qwctag(vif1ch->tadr + 16); //Set MADR to data following the tag vif1ch.madr = qwctag(vif1ch.tadr + 16); //Set MADR to data following the tag
vif1ch->tadr = qwctag(vif1ch->madr + (vif1ch->qwc << 4)); //Set TADR to QW following the data vif1ch.tadr = qwctag(vif1ch.madr + (vif1ch.qwc << 4)); //Set TADR to QW following the data
vif1.done = true; //End Transfer vif1.done = true; //End Transfer
break; break;
} }
if (vif1ch->chcr.TIE && ptag->IRQ) if (vif1ch.chcr.TIE && ptag->IRQ)
{ {
VIF_LOG("dmaIrq Set"); VIF_LOG("dmaIrq Set");
vif1.done = true; vif1.done = true;
} }
vif1Regs->stat.FQC = min(vif1ch->qwc, (u16)16); vif1Regs.stat.FQC = min(vif1ch.qwc, (u16)16);
vif1.inprogress |= 1; vif1.inprogress |= 1;
} }
SPR_LOG("mfifoVIF1transfer end %x madr %x, tadr %x vifqwc %x", vif1ch->chcr._u32, vif1ch->madr, vif1ch->tadr, vifqwc); SPR_LOG("mfifoVIF1transfer end %x madr %x, tadr %x vifqwc %x", vif1ch.chcr._u32, vif1ch.madr, vif1ch.tadr, vifqwc);
} }
void vifMFIFOInterrupt() void vifMFIFOInterrupt()
@ -236,52 +236,52 @@ void vifMFIFOInterrupt()
g_vifCycles = 0; g_vifCycles = 0;
VIF_LOG("vif mfifo interrupt"); VIF_LOG("vif mfifo interrupt");
if(GSTransferStatus.PTH2 == STOPPED_MODE && gifRegs->stat.APATH == GIF_APATH2) if(GSTransferStatus.PTH2 == STOPPED_MODE && gifRegs.stat.APATH == GIF_APATH2)
{ {
GSTransferStatus.PTH2 = STOPPED_MODE; GSTransferStatus.PTH2 = STOPPED_MODE;
if(gifRegs->stat.DIR == 0)gifRegs->stat.OPH = false; if(gifRegs.stat.DIR == 0)gifRegs.stat.OPH = false;
gifRegs->stat.APATH = GIF_APATH_IDLE; gifRegs.stat.APATH = GIF_APATH_IDLE;
if(gifRegs->stat.P1Q) gsPath1Interrupt(); if(gifRegs.stat.P1Q) gsPath1Interrupt();
/*gifRegs->stat.APATH = GIF_APATH_IDLE; /*gifRegs.stat.APATH = GIF_APATH_IDLE;
if(gifRegs->stat.DIR == 0)gifRegs->stat.OPH = false;*/ if(gifRegs.stat.DIR == 0)gifRegs.stat.OPH = false;*/
} }
if (schedulepath3msk & 0x10) Vif1MskPath3(); if (schedulepath3msk & 0x10) Vif1MskPath3();
if(vif1ch->chcr.DIR && CheckPath2GIF(DMAC_MFIFO_VIF) == false) return; if(vif1ch.chcr.DIR && CheckPath2GIF(DMAC_MFIFO_VIF) == false) return;
//We need to check the direction, if it is downloading from the GS, we handle that seperately (KH2 for testing) //We need to check the direction, if it is downloading from the GS, we handle that seperately (KH2 for testing)
//Simulated GS transfer time done, clear the flags //Simulated GS transfer time done, clear the flags
if (vif1.cmd) if (vif1.cmd)
{ {
if(vif1.done == true && vif1ch->qwc == 0) vif1Regs->stat.VPS = VPS_WAITING; if(vif1.done == true && vif1ch.qwc == 0) vif1Regs.stat.VPS = VPS_WAITING;
} }
else else
{ {
vif1Regs->stat.VPS = VPS_IDLE; vif1Regs.stat.VPS = VPS_IDLE;
} }
if (vif1.irq && vif1.tag.size == 0) if (vif1.irq && vif1.tag.size == 0)
{ {
vif1Regs->stat.INT = true; vif1Regs.stat.INT = true;
hwIntcIrq(INTC_VIF1); hwIntcIrq(INTC_VIF1);
--vif1.irq; --vif1.irq;
if (vif1Regs->stat.test(VIF1_STAT_VSS | VIF1_STAT_VIS | VIF1_STAT_VFS)) if (vif1Regs.stat.test(VIF1_STAT_VSS | VIF1_STAT_VIS | VIF1_STAT_VFS))
{ {
/*vif1Regs->stat.FQC = 0; // FQC=0 /*vif1Regs.stat.FQC = 0; // FQC=0
vif1ch->chcr.STR = false;*/ vif1ch.chcr.STR = false;*/
if(vif1ch->qwc > 0 || !vif1.done) return; if(vif1ch.qwc > 0 || !vif1.done) return;
} }
} }
if (vif1.done == false || vif1ch->qwc) if (vif1.done == false || vif1ch.qwc)
{ {
switch(vif1.inprogress & 1) switch(vif1.inprogress & 1)
{ {
case 0: //Set up transfer case 0: //Set up transfer
if (vif1ch->tadr == spr0->madr) if (vif1ch.tadr == spr0ch.madr)
{ {
// Console.WriteLn("Empty 1"); // Console.WriteLn("Empty 1");
vifqwc = 0; vifqwc = 0;
@ -290,7 +290,7 @@ void vifMFIFOInterrupt()
hwDmacIrq(DMAC_MFIFO_EMPTY); hwDmacIrq(DMAC_MFIFO_EMPTY);
vif1.inprogress |= 0x10; vif1.inprogress |= 0x10;
} }
vif1Regs->stat.FQC = 0; vif1Regs.stat.FQC = 0;
return; return;
} }
@ -310,7 +310,7 @@ void vifMFIFOInterrupt()
//FF7 Dirge of Cerberus seems to like the mfifo to tell it when it's empty, even if it's ending. //FF7 Dirge of Cerberus seems to like the mfifo to tell it when it's empty, even if it's ending.
//Doesn't seem to care about the vif1 dma interrupting (possibly disabled the interrupt?) //Doesn't seem to care about the vif1 dma interrupting (possibly disabled the interrupt?)
if (vif1ch->tadr == spr0->madr) if (vif1ch.tadr == spr0ch.madr)
{ {
vifqwc = 0; vifqwc = 0;
if((vif1.inprogress & 0x10) == 0) if((vif1.inprogress & 0x10) == 0)
@ -322,9 +322,9 @@ void vifMFIFOInterrupt()
vif1.vifstalled = false; vif1.vifstalled = false;
vif1.done = 1; vif1.done = 1;
g_vifCycles = 0; g_vifCycles = 0;
vif1ch->chcr.STR = false; vif1ch.chcr.STR = false;
hwDmacIrq(DMAC_VIF1); hwDmacIrq(DMAC_VIF1);
VIF_LOG("vif mfifo dma end"); VIF_LOG("vif mfifo dma end");
vif1Regs->stat.FQC = 0; vif1Regs.stat.FQC = 0;
} }

View File

@ -39,32 +39,33 @@ static __fi void vifFlush(int idx) {
static __fi void vuExecMicro(int idx, u32 addr) { static __fi void vuExecMicro(int idx, u32 addr) {
VURegs* VU = nVif[idx].VU; VURegs* VU = nVif[idx].VU;
VIFregisters& vifRegs = VU->GetVifRegs();
int startcycles = 0; int startcycles = 0;
//vifFlush(idx); //vifFlush(idx);
//if(vifX.vifstalled == true) return; //if(vifX.vifstalled == true) return;
if (VU->vifRegs->itops > (idx ? 0x3ffu : 0xffu)) { if (vifRegs.itops > (idx ? 0x3ffu : 0xffu)) {
Console.WriteLn("VIF%d ITOP overrun! %x", idx, VU->vifRegs->itops); Console.WriteLn("VIF%d ITOP overrun! %x", idx, vifRegs.itops);
VU->vifRegs->itops &= (idx ? 0x3ffu : 0xffu); vifRegs.itops &= (idx ? 0x3ffu : 0xffu);
} }
VU->vifRegs->itop = VU->vifRegs->itops; vifRegs.itop = vifRegs.itops;
if (idx) { if (idx) {
// in case we're handling a VIF1 execMicro, set the top with the tops value // in case we're handling a VIF1 execMicro, set the top with the tops value
VU->vifRegs->top = VU->vifRegs->tops & 0x3ff; vifRegs.top = vifRegs.tops & 0x3ff;
// is DBF flag set in VIF_STAT? // is DBF flag set in VIF_STAT?
if (VU->vifRegs->stat.DBF) { if (vifRegs.stat.DBF) {
// it is, so set tops with base, and clear the stat DBF flag // it is, so set tops with base, and clear the stat DBF flag
VU->vifRegs->tops = VU->vifRegs->base; vifRegs.tops = vifRegs.base;
VU->vifRegs->stat.DBF = false; vifRegs.stat.DBF = false;
} }
else { else {
// it is not, so set tops with base + offset, and set stat DBF flag // it is not, so set tops with base + offset, and set stat DBF flag
VU->vifRegs->tops = VU->vifRegs->base + VU->vifRegs->ofst; vifRegs.tops = vifRegs.base + vifRegs.ofst;
VU->vifRegs->stat.DBF = true; vifRegs.stat.DBF = true;
} }
} }
@ -84,16 +85,16 @@ u8 schedulepath3msk = 0;
void Vif1MskPath3() { void Vif1MskPath3() {
vif1Regs->mskpath3 = schedulepath3msk & 0x1; vif1Regs.mskpath3 = schedulepath3msk & 0x1;
GIF_LOG("VIF MSKPATH3 %x gif str %x path3 status %x", vif1Regs->mskpath3, gif->chcr.STR, GSTransferStatus.PTH3); GIF_LOG("VIF MSKPATH3 %x gif str %x path3 status %x", vif1Regs.mskpath3, gifch.chcr.STR, GSTransferStatus.PTH3);
gifRegs->stat.M3P = vif1Regs->mskpath3; gifRegs.stat.M3P = vif1Regs.mskpath3;
if (!vif1Regs->mskpath3) if (!vif1Regs.mskpath3)
{ {
//if(GSTransferStatus.PTH3 > TRANSFER_MODE && gif->chcr.STR) GSTransferStatus.PTH3 = TRANSFER_MODE; //if(GSTransferStatus.PTH3 > TRANSFER_MODE && gif->chcr.STR) GSTransferStatus.PTH3 = TRANSFER_MODE;
//DevCon.Warning("Mask off"); //DevCon.Warning("Mask off");
//if(GSTransferStatus.PTH3 >= PENDINGSTOP_MODE) GSTransferStatus.PTH3 = IDLE_MODE; //if(GSTransferStatus.PTH3 >= PENDINGSTOP_MODE) GSTransferStatus.PTH3 = IDLE_MODE;
if(gifRegs->stat.P3Q) if(gifRegs.stat.P3Q)
{ {
gsInterrupt();//gsInterrupt(); gsInterrupt();//gsInterrupt();
} }
@ -109,7 +110,7 @@ void Vif1MskPath3() {
vifOp(vifCode_Base) { vifOp(vifCode_Base) {
vif1Only(); vif1Only();
pass1 { vif1Regs->base = vif1Regs->code & 0x3ff; vif1.cmd = 0; } pass1 { vif1Regs.base = vif1Regs.code & 0x3ff; vif1.cmd = 0; }
pass3 { VifCodeLog("Base"); } pass3 { VifCodeLog("Base"); }
return 0; return 0;
} }
@ -119,15 +120,15 @@ extern bool SIGNAL_IMR_Pending;
template<int idx> __fi int _vifCode_Direct(int pass, const u8* data, bool isDirectHL) { template<int idx> __fi int _vifCode_Direct(int pass, const u8* data, bool isDirectHL) {
pass1 { pass1 {
vif1Only(); vif1Only();
int vifImm = (u16)vif1Regs->code; int vifImm = (u16)vif1Regs.code;
vif1.tag.size = vifImm ? (vifImm*4) : (65536*4); vif1.tag.size = vifImm ? (vifImm*4) : (65536*4);
vif1.vifstalled = true; vif1.vifstalled = true;
gifRegs->stat.P2Q = true; gifRegs.stat.P2Q = true;
if (gifRegs->stat.PSE) // temporarily stop if (gifRegs.stat.PSE) // temporarily stop
{ {
Console.WriteLn("Gif dma temp paused? VIF DIRECT"); Console.WriteLn("Gif dma temp paused? VIF DIRECT");
vif1.GifWaitState = 3; vif1.GifWaitState = 3;
vif1Regs->stat.VGW = true; vif1Regs.stat.VGW = true;
} }
//Should cause this to split here to try and time PATH3 right. //Should cause this to split here to try and time PATH3 right.
return 0; return 0;
@ -135,18 +136,18 @@ template<int idx> __fi int _vifCode_Direct(int pass, const u8* data, bool isDire
pass2 { pass2 {
vif1Only(); vif1Only();
if (GSTransferStatus.PTH3 < IDLE_MODE || gifRegs->stat.P1Q == true) if (GSTransferStatus.PTH3 < IDLE_MODE || gifRegs.stat.P1Q == true)
{ {
if(gifRegs->stat.APATH == GIF_APATH2 || ((GSTransferStatus.PTH3 <= IMAGE_MODE && gifRegs->stat.IMT && (vif1.cmd & 0x7f) == 0x50)) && gifRegs->stat.P1Q == false) if(gifRegs.stat.APATH == GIF_APATH2 || ((GSTransferStatus.PTH3 <= IMAGE_MODE && gifRegs.stat.IMT && (vif1.cmd & 0x7f) == 0x50)) && gifRegs.stat.P1Q == false)
{ {
//Do nothing, allow it //Do nothing, allow it
vif1Regs->stat.VGW = false; vif1Regs.stat.VGW = false;
//if(gifRegs->stat.APATH != GIF_APATH2)DevCon.Warning("Continue DIRECT/HL %x P3 %x APATH %x P1Q %x", vif1.cmd, GSTransferStatus.PTH3, gifRegs->stat.APATH, gifRegs->stat.P1Q); //if(gifRegs.stat.APATH != GIF_APATH2)DevCon.Warning("Continue DIRECT/HL %x P3 %x APATH %x P1Q %x", vif1.cmd, GSTransferStatus.PTH3, gifRegs.stat.APATH, gifRegs.stat.P1Q);
} }
else else
{ {
//DevCon.Warning("Stall DIRECT/HL %x P3 %x APATH %x P1Q %x", vif1.cmd, GSTransferStatus.PTH3, gifRegs->stat.APATH, gifRegs->stat.P1Q); //DevCon.Warning("Stall DIRECT/HL %x P3 %x APATH %x P1Q %x", vif1.cmd, GSTransferStatus.PTH3, gifRegs.stat.APATH, gifRegs.stat.P1Q);
vif1Regs->stat.VGW = true; // PATH3 is in image mode (DIRECTHL), or busy (BOTH no IMT) vif1Regs.stat.VGW = true; // PATH3 is in image mode (DIRECTHL), or busy (BOTH no IMT)
vif1.GifWaitState = 0; vif1.GifWaitState = 0;
vif1.vifstalled = true; vif1.vifstalled = true;
return 0; return 0;
@ -158,19 +159,19 @@ template<int idx> __fi int _vifCode_Direct(int pass, const u8* data, bool isDire
vif1.vifstalled = true; vif1.vifstalled = true;
return 0; return 0;
} }
if (gifRegs->stat.PSE) // temporarily stop if (gifRegs.stat.PSE) // temporarily stop
{ {
Console.WriteLn("Gif dma temp paused? VIF DIRECT"); Console.WriteLn("Gif dma temp paused? VIF DIRECT");
vif1.GifWaitState = 3; vif1.GifWaitState = 3;
vif1.vifstalled = true; vif1.vifstalled = true;
vif1Regs->stat.VGW = true; vif1Regs.stat.VGW = true;
return 0; return 0;
} }
// HACK ATTACK! // HACK ATTACK!
// we shouldn't be clearing the queue flag here at all. Ideally, the queue statuses // we shouldn't be clearing the queue flag here at all. Ideally, the queue statuses
// should be checked, handled, and cleared from the EOP check in GIFPath only. --air // should be checked, handled, and cleared from the EOP check in GIFPath only. --air
gifRegs->stat.clear_flags(GIF_STAT_P2Q); gifRegs.stat.clear_flags(GIF_STAT_P2Q);
uint minSize = aMin(vif1.vifpacketsize, vif1.tag.size); uint minSize = aMin(vif1.vifpacketsize, vif1.tag.size);
uint ret; uint ret;
@ -259,12 +260,12 @@ vifOp(vifCode_FlushA) {
pass1 { pass1 {
vifFlush(idx); vifFlush(idx);
// Gif is already transferring so wait for it. // Gif is already transferring so wait for it.
if (gifRegs->stat.P1Q || GSTransferStatus.PTH3 <= PENDINGSTOP_MODE) { if (gifRegs.stat.P1Q || GSTransferStatus.PTH3 <= PENDINGSTOP_MODE) {
//DevCon.Warning("VIF FlushA Wait MSK = %x", vif1Regs->mskpath3); //DevCon.Warning("VIF FlushA Wait MSK = %x", vif1Regs.mskpath3);
// //
//DevCon.WriteLn("FlushA path3 Wait! PTH3 MD %x STR %x", GSTransferStatus.PTH3, gif->chcr.STR); //DevCon.WriteLn("FlushA path3 Wait! PTH3 MD %x STR %x", GSTransferStatus.PTH3, gif->chcr.STR);
vif1Regs->stat.VGW = true; vif1Regs.stat.VGW = true;
vifX.GifWaitState = 1; vifX.GifWaitState = 1;
vifX.vifstalled = true; vifX.vifstalled = true;
} // else DevCon.WriteLn("FlushA path3 no Wait! PTH3 MD %x STR %x", GSTransferStatus.PTH3, gif->chcr.STR); } // else DevCon.WriteLn("FlushA path3 no Wait! PTH3 MD %x STR %x", GSTransferStatus.PTH3, gif->chcr.STR);
@ -284,7 +285,7 @@ vifOp(vifCode_FlushE) {
} }
vifOp(vifCode_ITop) { vifOp(vifCode_ITop) {
pass1 { vifXRegs->itops = vifXRegs->code & 0x3ff; GetVifX.cmd = 0; } pass1 { vifXRegs.itops = vifXRegs.code & 0x3ff; GetVifX.cmd = 0; }
pass3 { VifCodeLog("ITop"); } pass3 { VifCodeLog("ITop"); }
return 0; return 0;
} }
@ -292,8 +293,8 @@ vifOp(vifCode_ITop) {
vifOp(vifCode_Mark) { vifOp(vifCode_Mark) {
vifStruct& vifX = GetVifX; vifStruct& vifX = GetVifX;
pass1 { pass1 {
vifXRegs->mark = (u16)vifXRegs->code; vifXRegs.mark = (u16)vifXRegs.code;
vifXRegs->stat.MRK = true; vifXRegs.stat.MRK = true;
vifX.cmd = 0; vifX.cmd = 0;
} }
pass3 { VifCodeLog("Mark"); } pass3 { VifCodeLog("Mark"); }
@ -316,8 +317,8 @@ static __fi void _vifCode_MPG(int idx, u32 addr, const u32 *data, int size) {
vifOp(vifCode_MPG) { vifOp(vifCode_MPG) {
vifStruct& vifX = GetVifX; vifStruct& vifX = GetVifX;
pass1 { pass1 {
int vifNum = (u8)(vifXRegs->code >> 16); int vifNum = (u8)(vifXRegs.code >> 16);
vifX.tag.addr = (u16)(vifXRegs->code << 3) & (idx ? 0x3fff : 0xfff); vifX.tag.addr = (u16)(vifXRegs.code << 3) & (idx ? 0x3fff : 0xfff);
vifX.tag.size = vifNum ? (vifNum*2) : 512; vifX.tag.size = vifNum ? (vifNum*2) : 512;
//vifFlush(idx); //vifFlush(idx);
return 1; return 1;
@ -349,14 +350,14 @@ vifOp(vifCode_MPG) {
vifOp(vifCode_MSCAL) { vifOp(vifCode_MSCAL) {
vifStruct& vifX = GetVifX; vifStruct& vifX = GetVifX;
pass1 { vifFlush(idx); vuExecMicro(idx, (u16)(vifXRegs->code) << 3); vifX.cmd = 0;} pass1 { vifFlush(idx); vuExecMicro(idx, (u16)(vifXRegs.code) << 3); vifX.cmd = 0;}
pass3 { VifCodeLog("MSCAL"); } pass3 { VifCodeLog("MSCAL"); }
return 0; return 0;
} }
vifOp(vifCode_MSCALF) { vifOp(vifCode_MSCALF) {
vifStruct& vifX = GetVifX; vifStruct& vifX = GetVifX;
pass1 { vifFlush(idx); vuExecMicro(idx, (u16)(vifXRegs->code) << 3); vifX.cmd = 0; } pass1 { vifFlush(idx); vuExecMicro(idx, (u16)(vifXRegs.code) << 3); vifX.cmd = 0; }
pass3 { VifCodeLog("MSCALF"); } pass3 { VifCodeLog("MSCALF"); }
return 0; return 0;
} }
@ -372,12 +373,12 @@ vifOp(vifCode_MSCNT) {
vifOp(vifCode_MskPath3) { vifOp(vifCode_MskPath3) {
vif1Only(); vif1Only();
pass1 { pass1 {
if (vif1ch->chcr.STR && vif1.lastcmd != 0x13) { if (vif1ch.chcr.STR && vif1.lastcmd != 0x13) {
schedulepath3msk = 0x10 | ((vif1Regs->code >> 15) & 0x1); schedulepath3msk = 0x10 | ((vif1Regs.code >> 15) & 0x1);
vif1.vifstalled = true; vif1.vifstalled = true;
} }
else { else {
schedulepath3msk = (vif1Regs->code >> 15) & 0x1; schedulepath3msk = (vif1Regs.code >> 15) & 0x1;
Vif1MskPath3(); Vif1MskPath3();
} }
vif1.cmd = 0; vif1.cmd = 0;
@ -397,9 +398,9 @@ vifOp(vifCode_Null) {
vifStruct& vifX = GetVifX; vifStruct& vifX = GetVifX;
pass1 { pass1 {
// if ME1, then force the vif to interrupt // if ME1, then force the vif to interrupt
if (!(vifXRegs->err.ME1)) { // Ignore vifcode and tag mismatch error if (!(vifXRegs.err.ME1)) { // Ignore vifcode and tag mismatch error
Console.WriteLn("Vif%d: Unknown VifCmd! [%x]", idx, vifX.cmd); Console.WriteLn("Vif%d: Unknown VifCmd! [%x]", idx, vifX.cmd);
vifXRegs->stat.ER1 = true; vifXRegs.stat.ER1 = true;
vifX.vifstalled = true; vifX.vifstalled = true;
//vifX.irq++; //vifX.irq++;
} }
@ -413,9 +414,9 @@ vifOp(vifCode_Null) {
vifOp(vifCode_Offset) { vifOp(vifCode_Offset) {
vif1Only(); vif1Only();
pass1 { pass1 {
vif1Regs->stat.DBF = false; vif1Regs.stat.DBF = false;
vif1Regs->ofst = vif1Regs->code & 0x3ff; vif1Regs.ofst = vif1Regs.code & 0x3ff;
vif1Regs->tops = vif1Regs->base; vif1Regs.tops = vif1Regs.base;
vif1.cmd = 0; vif1.cmd = 0;
} }
pass3 { VifCodeLog("Offset"); } pass3 { VifCodeLog("Offset"); }
@ -462,7 +463,7 @@ vifOp(vifCode_STCol) {
} }
pass2 { pass2 {
u32* cols = idx ? g_vifmask.Col1 : g_vifmask.Col0; u32* cols = idx ? g_vifmask.Col1 : g_vifmask.Col0;
u32* pmem1 = &vifXRegs->c0 + (vifX.tag.addr << 2); u32* pmem1 = &vifXRegs.c0 + (vifX.tag.addr << 2);
u32* pmem2 = cols + vifX.tag.addr; u32* pmem2 = cols + vifX.tag.addr;
return _vifCode_STColRow<idx>(data, pmem1, pmem2); return _vifCode_STColRow<idx>(data, pmem1, pmem2);
} }
@ -480,7 +481,7 @@ vifOp(vifCode_STRow) {
} }
pass2 { pass2 {
u32* rows = idx ? g_vifmask.Row1 : g_vifmask.Row0; u32* rows = idx ? g_vifmask.Row1 : g_vifmask.Row0;
u32* pmem1 = &vifXRegs->r0 + (vifX.tag.addr << 2); u32* pmem1 = &vifXRegs.r0 + (vifX.tag.addr << 2);
u32* pmem2 = rows + vifX.tag.addr; u32* pmem2 = rows + vifX.tag.addr;
return _vifCode_STColRow<idx>(data, pmem1, pmem2); return _vifCode_STColRow<idx>(data, pmem1, pmem2);
} }
@ -491,8 +492,8 @@ vifOp(vifCode_STRow) {
vifOp(vifCode_STCycl) { vifOp(vifCode_STCycl) {
vifStruct& vifX = GetVifX; vifStruct& vifX = GetVifX;
pass1 { pass1 {
vifXRegs->cycle.cl = (u8)(vifXRegs->code); vifXRegs.cycle.cl = (u8)(vifXRegs.code);
vifXRegs->cycle.wl = (u8)(vifXRegs->code >> 8); vifXRegs.cycle.wl = (u8)(vifXRegs.code >> 8);
vifX.cmd = 0; vifX.cmd = 0;
} }
pass3 { VifCodeLog("STCycl"); } pass3 { VifCodeLog("STCycl"); }
@ -502,13 +503,13 @@ vifOp(vifCode_STCycl) {
vifOp(vifCode_STMask) { vifOp(vifCode_STMask) {
vifStruct& vifX = GetVifX; vifStruct& vifX = GetVifX;
pass1 { vifX.tag.size = 1; } pass1 { vifX.tag.size = 1; }
pass2 { vifXRegs->mask = data[0]; vifX.tag.size = 0; vifX.cmd = 0; } pass2 { vifXRegs.mask = data[0]; vifX.tag.size = 0; vifX.cmd = 0; }
pass3 { VifCodeLog("STMask"); } pass3 { VifCodeLog("STMask"); }
return 1; return 1;
} }
vifOp(vifCode_STMod) { vifOp(vifCode_STMod) {
pass1 { vifXRegs->mode = vifXRegs->code & 0x3; GetVifX.cmd = 0; } pass1 { vifXRegs.mode = vifXRegs.code & 0x3; GetVifX.cmd = 0; }
pass3 { VifCodeLog("STMod"); } pass3 { VifCodeLog("STMod"); }
return 0; return 0;
} }

View File

@ -14,6 +14,8 @@
*/ */
#pragma once #pragma once
#include "Vif.h"
#include "Vif_Unpack.h" #include "Vif_Unpack.h"
struct vifCode { struct vifCode {
@ -84,13 +86,13 @@ extern vifStruct* vif;
extern vifStruct vif0, vif1; extern vifStruct vif0, vif1;
extern u8 schedulepath3msk; extern u8 schedulepath3msk;
_vifT extern bool vifWrite32(u32 mem, u32 value);
extern void vif0Interrupt(); extern void vif0Interrupt();
extern void vif0Write32(u32 mem, u32 value);
extern void vif0Reset(); extern void vif0Reset();
extern void vif1Interrupt(); extern void vif1Interrupt();
extern void Vif1MskPath3(); extern void Vif1MskPath3();
extern void vif1Write32(u32 mem, u32 value);
extern void vif1Reset(); extern void vif1Reset();
typedef int __fastcall FnType_VifCmdHandler(int pass, const u32 *data); typedef int __fastcall FnType_VifCmdHandler(int pass, const u32 *data);

View File

@ -24,7 +24,7 @@
// Doesn't stall if the next vifCode is the Mark command // Doesn't stall if the next vifCode is the Mark command
_vifT bool runMark(u32* &data) { _vifT bool runMark(u32* &data) {
if (((vifXRegs->code >> 24) & 0x7f) == 0x7) { if (((vifXRegs.code >> 24) & 0x7f) == 0x7) {
Console.WriteLn("Vif%d: Running Mark with I-bit", idx); Console.WriteLn("Vif%d: Running Mark with I-bit", idx);
return 1; // No Stall? return 1; // No Stall?
} }
@ -34,7 +34,7 @@ _vifT bool runMark(u32* &data) {
// Returns 1 if i-bit && finished vifcode && i-bit not masked // Returns 1 if i-bit && finished vifcode && i-bit not masked
_vifT bool analyzeIbit(u32* &data, int iBit) { _vifT bool analyzeIbit(u32* &data, int iBit) {
vifStruct& vifX = GetVifX; vifStruct& vifX = GetVifX;
if (iBit && !vifX.cmd && !vifXRegs->err.MII) { if (iBit && !vifX.cmd && !vifXRegs.err.MII) {
//DevCon.WriteLn("Vif I-Bit IRQ"); //DevCon.WriteLn("Vif I-Bit IRQ");
vifX.irq++; vifX.irq++;
@ -75,14 +75,14 @@ _vifT void vifTransferLoop(u32* &data) {
u32& pSize = vifX.vifpacketsize; u32& pSize = vifX.vifpacketsize;
int iBit = vifX.cmd >> 7; int iBit = vifX.cmd >> 7;
vifXRegs->stat.VPS |= VPS_TRANSFERRING; vifXRegs.stat.VPS |= VPS_TRANSFERRING;
vifXRegs->stat.ER1 = false; vifXRegs.stat.ER1 = false;
while (pSize > 0 && !vifX.vifstalled) { while (pSize > 0 && !vifX.vifstalled) {
if(!vifX.cmd) { // Get new VifCode if(!vifX.cmd) { // Get new VifCode
vifX.lastcmd = (vifXRegs->code >> 24) & 0x7f; vifX.lastcmd = (vifXRegs.code >> 24) & 0x7f;
vifXRegs->code = data[0]; vifXRegs.code = data[0];
vifX.cmd = data[0] >> 24; vifX.cmd = data[0] >> 24;
iBit = data[0] >> 31; iBit = data[0] >> 31;
@ -135,20 +135,20 @@ _vifT static __fi bool vifTransfer(u32 *data, int size) {
transferred = transferred >> 2; transferred = transferred >> 2;
vifXch->madr +=(transferred << 4); vifXch.madr +=(transferred << 4);
vifXch->qwc -= transferred; vifXch.qwc -= transferred;
if (!vifXch->qwc && !vifX.irqoffset) vifX.inprogress &= ~0x1; if (!vifXch.qwc && !vifX.irqoffset) vifX.inprogress &= ~0x1;
if (vifX.irq && vifX.cmd == 0) { if (vifX.irq && vifX.cmd == 0) {
//DevCon.WriteLn("Vif IRQ!"); //DevCon.WriteLn("Vif IRQ!");
if(((vifXRegs->code >> 24) & 0x7f) != 0x7) if(((vifXRegs.code >> 24) & 0x7f) != 0x7)
{ {
vifX.vifstalled = true; vifX.vifstalled = true;
vifXRegs->stat.VIS = true; // Note: commenting this out fixes WALL-E? vifXRegs.stat.VIS = true; // Note: commenting this out fixes WALL-E?
} }
if (!vifXch->qwc && !vifX.irqoffset) vifX.inprogress &= ~1; if (!vifXch.qwc && !vifX.irqoffset) vifX.inprogress &= ~1;
return false; return false;
} }

View File

@ -302,8 +302,8 @@ _vifT void vifUnpackSetup(const u32 *data) {
vifStruct& vifX = GetVifX; vifStruct& vifX = GetVifX;
if ((vifXRegs->cycle.wl == 0) && (vifXRegs->cycle.wl < vifXRegs->cycle.cl)) { if ((vifXRegs.cycle.wl == 0) && (vifXRegs.cycle.wl < vifXRegs.cycle.cl)) {
Console.WriteLn("Vif%d CL %d, WL %d", idx, vifXRegs->cycle.cl, vifXRegs->cycle.wl); Console.WriteLn("Vif%d CL %d, WL %d", idx, vifXRegs.cycle.cl, vifXRegs.cycle.wl);
vifX.cmd = 0; vifX.cmd = 0;
return; // Skipping write and 0 write-cycles, so do nothing! return; // Skipping write and 0 write-cycles, so do nothing!
} }
@ -311,33 +311,33 @@ _vifT void vifUnpackSetup(const u32 *data) {
//if (!idx) vif0FLUSH(); // Only VU0? //if (!idx) vif0FLUSH(); // Only VU0?
vifX.usn = (vifXRegs->code >> 14) & 0x01; vifX.usn = (vifXRegs.code >> 14) & 0x01;
int vifNum = (vifXRegs->code >> 16) & 0xff; int vifNum = (vifXRegs.code >> 16) & 0xff;
if (vifNum == 0) vifNum = 256; if (vifNum == 0) vifNum = 256;
vifXRegs->num = vifNum; vifXRegs.num = vifNum;
if (vifXRegs->cycle.wl <= vifXRegs->cycle.cl) { if (vifXRegs.cycle.wl <= vifXRegs.cycle.cl) {
if (!idx) vif0.tag.size = ((vifNum * VIFfuncTable[ vif0.cmd & 0xf ].gsize) + 3) >> 2; if (!idx) vif0.tag.size = ((vifNum * VIFfuncTable[ vif0.cmd & 0xf ].gsize) + 3) >> 2;
else vif1.tag.size = ((vifNum * VIFfuncTable[ vif1.cmd & 0xf ].gsize) + 3) >> 2; else vif1.tag.size = ((vifNum * VIFfuncTable[ vif1.cmd & 0xf ].gsize) + 3) >> 2;
} }
else { else {
int n = vifXRegs->cycle.cl * (vifNum / vifXRegs->cycle.wl) + int n = vifXRegs.cycle.cl * (vifNum / vifXRegs.cycle.wl) +
_limit(vifNum % vifXRegs->cycle.wl, vifXRegs->cycle.cl); _limit(vifNum % vifXRegs.cycle.wl, vifXRegs.cycle.cl);
if (!idx) vif0.tag.size = ((n * VIFfuncTable[ vif0.cmd & 0xf ].gsize) + 3) >> 2; if (!idx) vif0.tag.size = ((n * VIFfuncTable[ vif0.cmd & 0xf ].gsize) + 3) >> 2;
else vif1.tag.size = ((n * VIFfuncTable[ vif1.cmd & 0xf ].gsize) + 3) >> 2; else vif1.tag.size = ((n * VIFfuncTable[ vif1.cmd & 0xf ].gsize) + 3) >> 2;
} }
u32 addr = vifXRegs->code; u32 addr = vifXRegs.code;
if (idx && ((addr>>15)&1)) addr += vif1Regs->tops; if (idx && ((addr>>15)&1)) addr += vif1Regs.tops;
vifX.tag.addr = (addr<<4) & (idx ? 0x3ff0 : 0xff0); vifX.tag.addr = (addr<<4) & (idx ? 0x3ff0 : 0xff0);
VIF_LOG("Unpack VIF%x, QWC %x tagsize %x", idx, vifNum, vif0.tag.size); VIF_LOG("Unpack VIF%x, QWC %x tagsize %x", idx, vifNum, vif0.tag.size);
vifX.cl = 0; vifX.cl = 0;
vifX.tag.cmd = vifX.cmd; vifX.tag.cmd = vifX.cmd;
vifXRegs->offset = 0; vifXRegs.offset = 0;
} }
template void vifUnpackSetup<0>(const u32 *data); template void vifUnpackSetup<0>(const u32 *data);

View File

@ -26,12 +26,12 @@ template<const u32 VIFdmanum> void VIFunpack(u32 *data, vifCode *v, u32 size) {
if (VIFdmanum == 0) { if (VIFdmanum == 0) {
VU = &VU0; VU = &VU0;
vifRegs = vif0Regs; vifRegs = &vif0Regs;
vif = &vif0; vif = &vif0;
} }
else { else {
VU = &VU1; VU = &VU1;
vifRegs = vif1Regs; vifRegs = &vif1Regs;
vif = &vif1; vif = &vif1;
} }

View File

@ -993,7 +993,7 @@ void Pcsx2App::ProgramLog_PostEvent( wxEvent& evt )
static void __concall ConsoleToFile_Newline() static void __concall ConsoleToFile_Newline()
{ {
#ifdef __LINUX__ #ifdef __LINUX__
if (g_Conf->EmuOptions.ConsoleToStdio) ConsoleWriter_Stdout.Newline(); if ((g_Conf) && (g_Conf->EmuOptions.ConsoleToStdio)) ConsoleWriter_Stdout.Newline();
#endif #endif
#ifdef __LINUX__ #ifdef __LINUX__
@ -1006,7 +1006,7 @@ static void __concall ConsoleToFile_Newline()
static void __concall ConsoleToFile_DoWrite( const wxString& fmt ) static void __concall ConsoleToFile_DoWrite( const wxString& fmt )
{ {
#ifdef __LINUX__ #ifdef __LINUX__
if (g_Conf->EmuOptions.ConsoleToStdio) ConsoleWriter_Stdout.WriteRaw(fmt); if ((g_Conf) && (g_Conf->EmuOptions.ConsoleToStdio)) ConsoleWriter_Stdout.WriteRaw(fmt);
#endif #endif
px_fputs( emuLog, fmt.ToUTF8() ); px_fputs( emuLog, fmt.ToUTF8() );

View File

@ -358,7 +358,7 @@ static __fi void gsHandler(const u8* pMem)
// games must take care to ensure transfer rectangles are exact multiples of a qword // games must take care to ensure transfer rectangles are exact multiples of a qword
vif1.GSLastDownloadSize = vif1.TRXREG.RRW * vif1.TRXREG.RRH * bpp >> 7; vif1.GSLastDownloadSize = vif1.TRXREG.RRW * vif1.TRXREG.RRH * bpp >> 7;
//DevCon.Warning("GS download in progress"); //DevCon.Warning("GS download in progress");
gifRegs->stat.OPH = true; gifRegs.stat.OPH = true;
} }
} }
if (reg >= 0x60) if (reg >= 0x60)
@ -602,7 +602,7 @@ __fi int GIFPath::CopyTag(const u128* pMem128, u32 size)
else GSTransferStatus.PTH2 = TRANSFER_MODE; else GSTransferStatus.PTH2 = TRANSFER_MODE;
break; break;
case GIF_PATH_3: case GIF_PATH_3:
if(vif1Regs->mskpath3 == 1 && GSTransferStatus.PTH3 == STOPPED_MODE) if(vif1Regs.mskpath3 == 1 && GSTransferStatus.PTH3 == STOPPED_MODE)
{ {
GSTransferStatus.PTH3 = IDLE_MODE; GSTransferStatus.PTH3 = IDLE_MODE;
@ -618,8 +618,8 @@ __fi int GIFPath::CopyTag(const u128* pMem128, u32 size)
} }
if(GSTransferStatus.PTH3 < PENDINGSTOP_MODE || pathidx != 2) if(GSTransferStatus.PTH3 < PENDINGSTOP_MODE || pathidx != 2)
{ {
gifRegs->stat.OPH = true; gifRegs.stat.OPH = true;
gifRegs->stat.APATH = pathidx + 1; gifRegs.stat.APATH = pathidx + 1;
} }
if(pathidx == GIF_PATH_3) if(pathidx == GIF_PATH_3)
@ -645,8 +645,8 @@ __fi int GIFPath::CopyTag(const u128* pMem128, u32 size)
break; break;
} }
gifRegs->stat.APATH = pathidx + 1; gifRegs.stat.APATH = pathidx + 1;
gifRegs->stat.OPH = true; gifRegs.stat.OPH = true;
switch(tag.FLG) { switch(tag.FLG) {
case GIF_FLG_PACKED: case GIF_FLG_PACKED:
@ -809,10 +809,10 @@ __fi int GIFPath::CopyTag(const u128* pMem128, u32 size)
// FINISH is *not* a per-path register, and it seems to pretty clearly indicate that all active // FINISH is *not* a per-path register, and it seems to pretty clearly indicate that all active
// drawing *and* image transfer actions must be finished before the IRQ raises. // drawing *and* image transfer actions must be finished before the IRQ raises.
if(gifRegs->stat.P1Q || gifRegs->stat.P2Q || gifRegs->stat.P3Q) if(gifRegs.stat.P1Q || gifRegs.stat.P2Q || gifRegs.stat.P3Q)
{ {
//GH3 and possibly others have path data queued waiting for another path to finish! we need to check they are done too //GH3 and possibly others have path data queued waiting for another path to finish! we need to check they are done too
//DevCon.Warning("Early FINISH signal! P1 %x P2 %x P3 %x", gifRegs->stat.P1Q, gifRegs->stat.P2Q, gifRegs->stat.P3Q); //DevCon.Warning("Early FINISH signal! P1 %x P2 %x P3 %x", gifRegs.stat.P1Q, gifRegs.stat.P2Q, gifRegs.stat.P3Q);
} }
else if (!(GSIMR&0x200) && !s_gifPath.path[0].IsActive() && !s_gifPath.path[1].IsActive() && !s_gifPath.path[2].IsActive()) else if (!(GSIMR&0x200) && !s_gifPath.path[0].IsActive() && !s_gifPath.path[1].IsActive() && !s_gifPath.path[2].IsActive())
{ {
@ -835,8 +835,8 @@ __fi int GIFPath::CopyTag(const u128* pMem128, u32 size)
if (tag.EOP && nloop == 0) { if (tag.EOP && nloop == 0) {
/*if(gifRegs->stat.DIR == 0)gifRegs->stat.OPH = false; /*if(gifRegs.stat.DIR == 0)gifRegs.stat.OPH = false;
gifRegs->stat.APATH = GIF_APATH_IDLE;*/ gifRegs.stat.APATH = GIF_APATH_IDLE;*/
switch(pathidx) switch(pathidx)
{ {
case GIF_PATH_1: case GIF_PATH_1:
@ -849,10 +849,10 @@ __fi int GIFPath::CopyTag(const u128* pMem128, u32 size)
//For huge chunks we may have delay problems, so we need to stall it till the interrupt, else we get desync (Lemmings) //For huge chunks we may have delay problems, so we need to stall it till the interrupt, else we get desync (Lemmings)
if(size > 8) GSTransferStatus.PTH3 = PENDINGSTOP_MODE; if(size > 8) GSTransferStatus.PTH3 = PENDINGSTOP_MODE;
else GSTransferStatus.PTH3 = STOPPED_MODE; else GSTransferStatus.PTH3 = STOPPED_MODE;
if (gif->chcr.STR) { //Make sure we are really doing a DMA and not using FIFO if (gifch.chcr.STR) { //Make sure we are really doing a DMA and not using FIFO
//GIF_LOG("Path3 end EOP %x NLOOP %x Status %x", tag.EOP, nloop, GSTransferStatus.PTH3); //GIF_LOG("Path3 end EOP %x NLOOP %x Status %x", tag.EOP, nloop, GSTransferStatus.PTH3);
gif->madr += size * 16; gifch.madr += size * 16;
gif->qwc -= size; gifch.qwc -= size;
} }
break; break;
} }
@ -860,10 +860,10 @@ __fi int GIFPath::CopyTag(const u128* pMem128, u32 size)
else if(pathidx == 2) else if(pathidx == 2)
{ {
//if(nloop <= 16 && GSTransferStatus.PTH3 == IMAGE_MODE)GSTransferStatus.PTH3 = PENDINGIMAGE_MODE; //if(nloop <= 16 && GSTransferStatus.PTH3 == IMAGE_MODE)GSTransferStatus.PTH3 = PENDINGIMAGE_MODE;
if (gif->chcr.STR) { //Make sure we are really doing a DMA and not using FIFO if (gifch.chcr.STR) { //Make sure we are really doing a DMA and not using FIFO
//GIF_LOG("Path3 end EOP %x NLOOP %x Status %x", tag.EOP, nloop, GSTransferStatus.PTH3); //GIF_LOG("Path3 end EOP %x NLOOP %x Status %x", tag.EOP, nloop, GSTransferStatus.PTH3);
gif->madr += size * 16; gifch.madr += size * 16;
gif->qwc -= size; gifch.qwc -= size;
} }
} }

79
pcsx2/ps2/HwInternal.h Normal file
View File

@ -0,0 +1,79 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2010 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 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 PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "Hw.h"
// --------------------------------------------------------------------------------------
// IsPageFor() / iswitch() / icase() [macros!]
// --------------------------------------------------------------------------------------
// Page-granulated switch helpers: In order for the compiler to optimize hardware register
// handlers, which dispatch registers along a series of switches, the compiler needs to know
// that the case entry applies to the current page only. Under MSVC, I tried all manners of
// bitmasks against the templated page value, and this was the only one that worked:
//
// Note: MSVC 2008 actually fails to optimize "switch" properly due to being overly aggressive
// about trying to use its clever BSP-tree logic for long switches. It adds the BSP tree logic,
// even though most of the "tree" is empty (resulting in several compare/jumps that do nothing).
// Explained: Even though only one or two of the switch entires are valid, MSVC will still
// compile in its BSP tree check (which divides the switch into 2 or 4 ranges of values). Three
// of the ranges just link to "RET", while the fourth range contains the handler for the one
// register operation contained in the templated page.
#define IsPageFor(_mem) ((page<<12) == (_mem&(0xf<<12)))
#define icase(ugh) if(IsPageFor(ugh) && (mem==ugh))
#define iswitch(mem)
// hw read functions
template< uint page > extern mem8_t __fastcall hwRead8 (u32 mem);
template< uint page > extern mem16_t __fastcall hwRead16 (u32 mem);
template< uint page > extern mem32_t __fastcall hwRead32 (u32 mem);
template< uint page > extern void __fastcall hwRead64 (u32 mem, mem64_t* out );
template< uint page > extern void __fastcall hwRead128(u32 mem, mem128_t* out);
// Internal hwRead32 which does not log reads, used by hwWrite8/16 to perform
// read-modify-write operations.
template< uint page, bool intcstathack >
extern mem32_t __fastcall _hwRead32(u32 mem);
extern mem16_t __fastcall hwRead16_page_0F_INTC_HACK(u32 mem);
extern mem32_t __fastcall hwRead32_page_0F_INTC_HACK(u32 mem);
// hw write functions
template<uint page> extern void __fastcall hwWrite8 (u32 mem, u8 value);
template<uint page> extern void __fastcall hwWrite16 (u32 mem, u16 value);
template<uint page> extern void __fastcall hwWrite32 (u32 mem, mem32_t value);
template<uint page> extern void __fastcall hwWrite64 (u32 mem, const mem64_t* srcval);
template<uint page> extern void __fastcall hwWrite128(u32 mem, const mem128_t* srcval);
// --------------------------------------------------------------------------------------
// Hardware FIFOs (128 bit access only!)
// --------------------------------------------------------------------------------------
// VIF0 -- 0x10004000 -- eeHw[0x4000]
// VIF1 -- 0x10005000 -- eeHw[0x5000]
// GIF -- 0x10006000 -- eeHw[0x6000]
// IPUout -- 0x10007000 -- eeHw[0x7000]
// IPUin -- 0x10007010 -- eeHw[0x7010]
extern void __fastcall ReadFIFO_VIF1(mem128_t* out);
extern void __fastcall ReadFIFO_IPUout(mem128_t* out);
extern void __fastcall WriteFIFO_VIF0(const mem128_t* value);
extern void __fastcall WriteFIFO_VIF1(const mem128_t* value);
extern void __fastcall WriteFIFO_GIF(const mem128_t* value);
extern void __fastcall WriteFIFO_IPUin(const mem128_t* value);

View File

@ -51,28 +51,28 @@ mem8_t __fastcall iopHwRead8_Page1( u32 addr )
default: default:
if( masked_addr >= 0x100 && masked_addr < 0x130 ) if( masked_addr >= 0x100 && masked_addr < 0x130 )
{ {
DevCon.Warning( "HwRead8 from Counter16 [ignored], addr 0x%08x = 0x%02x", addr, psxHu8(addr) ); DevCon.Warning( "HwRead8 from Counter16 [ignored] @ 0x%08x = 0x%02x", addr, psxHu8(addr) );
ret = psxHu8( addr ); ret = psxHu8( addr );
} }
else if( masked_addr >= 0x480 && masked_addr < 0x4a0 ) else if( masked_addr >= 0x480 && masked_addr < 0x4a0 )
{ {
DevCon.Warning( "HwRead8 from Counter32 [ignored], addr 0x%08x = 0x%02x", addr, psxHu8(addr) ); DevCon.Warning( "HwRead8 from Counter32 [ignored] @ 0x%08x = 0x%02x", addr, psxHu8(addr) );
ret = psxHu8( addr ); ret = psxHu8( addr );
} }
else if( (masked_addr >= pgmsk(HW_USB_START)) && (masked_addr < pgmsk(HW_USB_END)) ) else if( (masked_addr >= pgmsk(HW_USB_START)) && (masked_addr < pgmsk(HW_USB_END)) )
{ {
ret = USBread8( addr ); ret = USBread8( addr );
PSXHW_LOG( "HwRead8 from USB, addr 0x%08x = 0x%02x", addr, ret ); PSXHW_LOG( "HwRead8 from USB @ 0x%08x = 0x%02x", addr, ret );
} }
else else
{ {
ret = psxHu8(addr); ret = psxHu8(addr);
PSXUnkHW_LOG( "HwRead8 from Unknown, addr 0x%08x = 0x%02x", addr, ret ); PSXUnkHW_LOG( "HwRead8 from Unknown @ 0x%08x = 0x%02x", addr, ret );
} }
return ret; return ret;
} }
IopHwTraceLog<mem8_t>( addr, ret, "Read" ); IopHwTraceLog<mem8_t>( addr, ret, true );
return ret; return ret;
} }
@ -89,7 +89,7 @@ mem8_t __fastcall iopHwRead8_Page3( u32 addr )
else else
ret = psxHu8( addr ); ret = psxHu8( addr );
IopHwTraceLog<mem8_t>( addr, ret, "Read" ); IopHwTraceLog<mem8_t>( addr, ret, true );
return ret; return ret;
} }
@ -107,7 +107,7 @@ mem8_t __fastcall iopHwRead8_Page8( u32 addr )
else else
ret = psxHu8( addr ); ret = psxHu8( addr );
IopHwTraceLog<mem8_t>( addr, ret, "Read" ); IopHwTraceLog<mem8_t>( addr, ret, true );
return ret; return ret;
} }
@ -216,7 +216,7 @@ static __fi T _HwRead_16or32_Page1( u32 addr )
ret = SPU2read( addr ); ret = SPU2read( addr );
else else
{ {
DevCon.Warning( "HwRead32 from SPU2? (addr=0x%08X) .. What manner of trickery is this?!", addr ); DbgCon.Warning( "HwRead32 from SPU2? @ 0x%08X .. What manner of trickery is this?!", addr );
ret = psxHu32(addr); ret = psxHu32(addr);
} }
} }
@ -320,7 +320,7 @@ static __fi T _HwRead_16or32_Page1( u32 addr )
} }
} }
IopHwTraceLog<T>( addr, ret, "Read" ); IopHwTraceLog<T>( addr, ret, true );
return ret; return ret;
} }
@ -343,7 +343,7 @@ mem16_t __fastcall iopHwRead16_Page3( u32 addr )
jASSUME( (addr >> 12) == 0x1f803 ); jASSUME( (addr >> 12) == 0x1f803 );
mem16_t ret = psxHu16(addr); mem16_t ret = psxHu16(addr);
IopHwTraceLog<mem16_t>( addr, ret, "Read" ); IopHwTraceLog<mem16_t>( addr, ret, true );
return ret; return ret;
} }
@ -355,7 +355,7 @@ mem16_t __fastcall iopHwRead16_Page8( u32 addr )
jASSUME( (addr >> 12) == 0x1f808 ); jASSUME( (addr >> 12) == 0x1f808 );
mem16_t ret = psxHu16(addr); mem16_t ret = psxHu16(addr);
IopHwTraceLog<mem16_t>( addr, ret, "Read" ); IopHwTraceLog<mem16_t>( addr, ret, true );
return ret; return ret;
} }
@ -373,7 +373,7 @@ mem32_t __fastcall iopHwRead32_Page3( u32 addr )
// all addresses are assumed to be prefixed with 0x1f803xxx: // all addresses are assumed to be prefixed with 0x1f803xxx:
jASSUME( (addr >> 12) == 0x1f803 ); jASSUME( (addr >> 12) == 0x1f803 );
const mem32_t ret = psxHu32(addr); const mem32_t ret = psxHu32(addr);
IopHwTraceLog<mem32_t>( addr, ret, "Read" ); IopHwTraceLog<mem32_t>( addr, ret, true );
return ret; return ret;
} }
@ -437,7 +437,7 @@ mem32_t __fastcall iopHwRead32_Page8( u32 addr )
} }
else ret = psxHu32(addr); else ret = psxHu32(addr);
IopHwTraceLog<mem32_t>( addr, ret, "Read" ); IopHwTraceLog<mem32_t>( addr, ret, true );
return ret; return ret;
} }

View File

@ -33,7 +33,7 @@ template< typename T >
static __fi void _generic_write( u32 addr, T val ) static __fi void _generic_write( u32 addr, T val )
{ {
//int bitsize = (sizeof(T) == 1) ? 8 : ( (sizeof(T) == 2) ? 16 : 32 ); //int bitsize = (sizeof(T) == 1) ? 8 : ( (sizeof(T) == 2) ? 16 : 32 );
IopHwTraceLog<T>( addr, val, "Write" ); IopHwTraceLog<T>( addr, val, false );
psxHu(addr) = val; psxHu(addr) = val;
} }
@ -49,7 +49,7 @@ static __fi T _generic_read( u32 addr )
//int bitsize = (sizeof(T) == 1) ? 8 : ( (sizeof(T) == 2) ? 16 : 32 ); //int bitsize = (sizeof(T) == 1) ? 8 : ( (sizeof(T) == 2) ? 16 : 32 );
T ret = psxHu(addr); T ret = psxHu(addr);
IopHwTraceLog<T>( addr, ret, "Read" ); IopHwTraceLog<T>( addr, ret, true );
return ret; return ret;
} }
@ -84,12 +84,12 @@ void __fastcall iopHwWrite8_Page1( u32 addr, mem8_t val )
default: default:
if( masked_addr >= 0x100 && masked_addr < 0x130 ) if( masked_addr >= 0x100 && masked_addr < 0x130 )
{ {
DevCon.Warning( "HwWrite8 to Counter16 [ignored], addr 0x%08x = 0x%02x", addr, psxHu8(addr) ); DbgCon.Warning( "HwWrite8 to Counter16 [ignored] @ addr 0x%08x = 0x%02x", addr, psxHu8(addr) );
psxHu8( addr ) = val; psxHu8( addr ) = val;
} }
else if( masked_addr >= 0x480 && masked_addr < 0x4a0 ) else if( masked_addr >= 0x480 && masked_addr < 0x4a0 )
{ {
DevCon.Warning( "HwWrite8 to Counter32 [ignored], addr 0x%08x = 0x%02x", addr, psxHu8(addr) ); DbgCon.Warning( "HwWrite8 to Counter32 [ignored] @ addr 0x%08x = 0x%02x", addr, psxHu8(addr) );
psxHu8( addr ) = val; psxHu8( addr ) = val;
} }
else if( (masked_addr >= pgmsk(HW_USB_START)) && (masked_addr < pgmsk(HW_USB_END)) ) else if( (masked_addr >= pgmsk(HW_USB_START)) && (masked_addr < pgmsk(HW_USB_END)) )
@ -103,7 +103,7 @@ void __fastcall iopHwWrite8_Page1( u32 addr, mem8_t val )
break; break;
} }
IopHwTraceLog<mem8_t>( addr, val, "Write" ); IopHwTraceLog<mem8_t>( addr, val, false );
} }
void __fastcall iopHwWrite8_Page3( u32 addr, mem8_t val ) void __fastcall iopHwWrite8_Page3( u32 addr, mem8_t val )
@ -137,7 +137,7 @@ void __fastcall iopHwWrite8_Page3( u32 addr, mem8_t val )
} }
psxHu8( addr ) = val; psxHu8( addr ) = val;
IopHwTraceLog<mem8_t>( addr, val, "Write" ); IopHwTraceLog<mem8_t>( addr, val, false );
} }
void __fastcall iopHwWrite8_Page8( u32 addr, mem8_t val ) void __fastcall iopHwWrite8_Page8( u32 addr, mem8_t val )
@ -150,7 +150,7 @@ void __fastcall iopHwWrite8_Page8( u32 addr, mem8_t val )
else else
psxHu8( addr ) = val; psxHu8( addr ) = val;
IopHwTraceLog<mem8_t>( addr, val, "Write" ); IopHwTraceLog<mem8_t>( addr, val, false );
} }
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
@ -244,7 +244,7 @@ static __fi void _HwWrite_16or32_Page1( u32 addr, T val )
SPU2write( addr, val ); SPU2write( addr, val );
else else
{ {
DevCon.Warning( "HwWrite32 to SPU2? (addr=0x%08X) .. What manner of trickery is this?!", addr ); DbgCon.Warning( "HwWrite32 to SPU2? @ 0x%08X .. What manner of trickery is this?!", addr );
//psxHu(addr) = val; //psxHu(addr) = val;
} }
} }
@ -481,7 +481,7 @@ static __fi void _HwWrite_16or32_Page1( u32 addr, T val )
} }
} }
IopHwTraceLog<T>( addr, val, "Write" ); IopHwTraceLog<T>( addr, val, false );
} }
@ -497,7 +497,7 @@ void __fastcall iopHwWrite16_Page3( u32 addr, mem16_t val )
// all addresses are assumed to be prefixed with 0x1f803xxx: // all addresses are assumed to be prefixed with 0x1f803xxx:
pxAssert( (addr >> 12) == 0x1f803 ); pxAssert( (addr >> 12) == 0x1f803 );
psxHu16(addr) = val; psxHu16(addr) = val;
IopHwTraceLog<mem16_t>( addr, val, "Write" ); IopHwTraceLog<mem16_t>( addr, val, false );
} }
void __fastcall iopHwWrite16_Page8( u32 addr, mem16_t val ) void __fastcall iopHwWrite16_Page8( u32 addr, mem16_t val )
@ -505,7 +505,7 @@ void __fastcall iopHwWrite16_Page8( u32 addr, mem16_t val )
// all addresses are assumed to be prefixed with 0x1f808xxx: // all addresses are assumed to be prefixed with 0x1f808xxx:
pxAssert( (addr >> 12) == 0x1f808 ); pxAssert( (addr >> 12) == 0x1f808 );
psxHu16(addr) = val; psxHu16(addr) = val;
IopHwTraceLog<mem16_t>( addr, val, "Write" ); IopHwTraceLog<mem16_t>( addr, val, false );
} }
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
@ -520,7 +520,7 @@ void __fastcall iopHwWrite32_Page3( u32 addr, mem32_t val )
// all addresses are assumed to be prefixed with 0x1f803xxx: // all addresses are assumed to be prefixed with 0x1f803xxx:
pxAssert( (addr >> 12) == 0x1f803 ); pxAssert( (addr >> 12) == 0x1f803 );
psxHu16(addr) = val; psxHu16(addr) = val;
IopHwTraceLog<mem32_t>( addr, val, "Write" ); IopHwTraceLog<mem32_t>( addr, val, false );
} }
void __fastcall iopHwWrite32_Page8( u32 addr, mem32_t val ) void __fastcall iopHwWrite32_Page8( u32 addr, mem32_t val )
@ -567,7 +567,7 @@ void __fastcall iopHwWrite32_Page8( u32 addr, mem32_t val )
} }
else psxHu32(addr) = val; else psxHu32(addr) = val;
IopHwTraceLog<mem32_t>( addr, val, "Write" ); IopHwTraceLog<mem32_t>( addr, val, false );
} }
} }

View File

@ -38,7 +38,7 @@ namespace Internal {
// //
template< typename T> template< typename T>
static __ri const char* _log_GetIopHwName( u32 addr, T val ) static __ri const char* _ioplog_GetHwName( u32 addr, T val )
{ {
switch( addr ) switch( addr )
{ {
@ -200,20 +200,31 @@ static __ri const char* _log_GetIopHwName( u32 addr, T val )
} }
template< typename T> template< typename T>
static __ri void IopHwTraceLog( u32 addr, T val, const char* modestr ) static __ri void IopHwTraceLog( u32 addr, T val, bool mode )
{ {
if( !EmuConfig.Trace.IOP.m_EnableRegisters ) return; if (!IsDevBuild) return;
if (!EmuConfig.Trace.IOP.m_EnableRegisters) return;
static char *temp = "Hw%s%d from %s, addr 0x%08x = 0x%0*x"; FastFormatAscii valStr;
FastFormatAscii labelStr;
labelStr.Write("Hw%s%u", mode ? "Read" : "Write", sizeof (T) * 8);
// Replace the * above with the operand size (this ensures nicely formatted switch( sizeof (T) )
// zero-fill hex values): {
temp[(sizeof temp)-3] = '0' + (sizeof(T)*2); case 1: valStr.Write("0x%02x", val); break;
case 2: valStr.Write("0x%04x", val); break;
case 4: valStr.Write("0x%08x", val); break;
if( const char* regname = _log_GetIopHwName<T>( addr, val ) ) case 8: valStr.Write("0x%08x.%08x", ((u32*)&val)[1], ((u32*)&val)[0]); break;
PSXHW_LOG( temp, modestr, (sizeof (T)) * 8, regname, addr, val ); case 16: ((u128&)val).WriteTo(valStr);
}
static const char* temp = "%-12s @ 0x%08X/%-16s %s %s";
if( const char* regname = _ioplog_GetHwName<T>( addr, val ) )
PSXHW_LOG( temp, labelStr.c_str(), addr, regname, mode ? "->" : "<-", valStr.c_str() );
else else
PSXUnkHW_LOG( temp, modestr, (sizeof (T)) * 8, "Unknown", addr, val ); PSXUnkHW_LOG( temp, labelStr.c_str(), addr, "Unknown", mode ? "->" : "<-", valStr.c_str() );
} }
} }; } };

437
pcsx2/ps2/LegacyDmac.cpp Normal file
View File

@ -0,0 +1,437 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2010 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 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 PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include "PrecompiledHeader.h"
#include "Common.h"
#include "Hardware.h"
#include "IPU/IPUdma.h"
#include "ps2/HwInternal.h"
bool DMACh::transfer(const char *s, tDMA_TAG* ptag)
{
if (ptag == NULL) // Is ptag empty?
{
throwBusError(s);
return false;
}
chcrTransfer(ptag);
qwcTransfer(ptag);
return true;
}
void DMACh::unsafeTransfer(tDMA_TAG* ptag)
{
chcrTransfer(ptag);
qwcTransfer(ptag);
}
tDMA_TAG *DMACh::getAddr(u32 addr, u32 num, bool write)
{
tDMA_TAG *ptr = dmaGetAddr(addr, write);
if (ptr == NULL)
{
throwBusError("dmaGetAddr");
setDmacStat(num);
chcr.STR = false;
}
return ptr;
}
tDMA_TAG *DMACh::DMAtransfer(u32 addr, u32 num)
{
tDMA_TAG *tag = getAddr(addr, num, false);
if (tag == NULL) return NULL;
chcrTransfer(tag);
qwcTransfer(tag);
return tag;
}
tDMA_TAG DMACh::dma_tag()
{
return chcr.tag();
}
wxString DMACh::cmq_to_str() const
{
return wxsFormat(L"chcr = %lx, madr = %lx, qwc = %lx", chcr._u32, madr, qwc);
}
wxString DMACh::cmqt_to_str() const
{
return wxsFormat(L"chcr = %lx, madr = %lx, qwc = %lx, tadr = %1x", chcr._u32, madr, qwc, tadr);
}
__fi void throwBusError(const char *s)
{
Console.Error("%s BUSERR", s);
dmacRegs.stat.BEIS = true;
}
__fi void setDmacStat(u32 num)
{
dmacRegs.stat.set_flags(1 << num);
}
// Note: Dma addresses are guaranteed to be aligned to 16 bytes (128 bits)
__fi tDMA_TAG *SPRdmaGetAddr(u32 addr, bool write)
{
// if (addr & 0xf) { DMA_LOG("*PCSX2*: DMA address not 128bit aligned: %8.8x", addr); }
//For some reason Getaway references SPR Memory from itself using SPR0, oh well, let it i guess...
if((addr & 0x70000000) == 0x70000000)
{
return (tDMA_TAG*)&eeMem->Scratch[addr & 0x3ff0];
}
// FIXME: Why??? DMA uses physical addresses
addr &= 0x1ffffff0;
if (addr < Ps2MemSize::Base)
{
return (tDMA_TAG*)&eeMem->Main[addr];
}
else if (addr < 0x10000000)
{
return (tDMA_TAG*)(write ? eeMem->ZeroWrite : eeMem->ZeroRead);
}
else if ((addr >= 0x11004000) && (addr < 0x11010000))
{
//Access for VU Memory
return (tDMA_TAG*)vtlb_GetPhyPtr(addr & 0x1FFFFFF0);
}
else
{
Console.Error( "*PCSX2*: DMA error: %8.8x", addr);
return NULL;
}
}
// Note: Dma addresses are guaranteed to be aligned to 16 bytes (128 bits)
__ri tDMA_TAG *dmaGetAddr(u32 addr, bool write)
{
// if (addr & 0xf) { DMA_LOG("*PCSX2*: DMA address not 128bit aligned: %8.8x", addr); }
if (DMA_TAG(addr).SPR) return (tDMA_TAG*)&eeMem->Scratch[addr & 0x3ff0];
// FIXME: Why??? DMA uses physical addresses
addr &= 0x1ffffff0;
if (addr < Ps2MemSize::Base)
{
return (tDMA_TAG*)&eeMem->Main[addr];
}
else if (addr < 0x10000000)
{
return (tDMA_TAG*)(write ? eeMem->ZeroWrite : eeMem->ZeroRead);
}
else if (addr < 0x10004000)
{
// Secret scratchpad address for DMA = end of maximum main memory?
//Console.Warning("Writing to the scratchpad without the SPR flag set!");
return (tDMA_TAG*)&eeMem->Scratch[addr & 0x3ff0];
}
else
{
Console.Error( "*PCSX2*: DMA error: %8.8x", addr);
return NULL;
}
}
// Returns true if the DMA is enabled and executed successfully. Returns false if execution
// was blocked (DMAE or master DMA enabler).
static bool QuickDmaExec( void (*func)(), u32 mem)
{
bool ret = false;
DMACh& reg = (DMACh&)psHu32(mem);
if (reg.chcr.STR && dmacRegs.ctrl.DMAE && !psHu8(DMAC_ENABLER+2))
{
func();
ret = true;
}
return ret;
}
static tDMAC_QUEUE QueuedDMA(0);
static u32 oldvalue = 0;
static void StartQueuedDMA()
{
if (QueuedDMA.VIF0) { DMA_LOG("Resuming DMA for VIF0"); QueuedDMA.VIF0 = !QuickDmaExec(dmaVIF0, D0_CHCR); }
if (QueuedDMA.VIF1) { DMA_LOG("Resuming DMA for VIF1"); QueuedDMA.VIF1 = !QuickDmaExec(dmaVIF1, D1_CHCR); }
if (QueuedDMA.GIF ) { DMA_LOG("Resuming DMA for GIF" ); QueuedDMA.GIF = !QuickDmaExec(dmaGIF , D2_CHCR); }
if (QueuedDMA.IPU0) { DMA_LOG("Resuming DMA for IPU0"); QueuedDMA.IPU0 = !QuickDmaExec(dmaIPU0, D3_CHCR); }
if (QueuedDMA.IPU1) { DMA_LOG("Resuming DMA for IPU1"); QueuedDMA.IPU1 = !QuickDmaExec(dmaIPU1, D4_CHCR); }
if (QueuedDMA.SIF0) { DMA_LOG("Resuming DMA for SIF0"); QueuedDMA.SIF0 = !QuickDmaExec(dmaSIF0, D5_CHCR); }
if (QueuedDMA.SIF1) { DMA_LOG("Resuming DMA for SIF1"); QueuedDMA.SIF1 = !QuickDmaExec(dmaSIF1, D6_CHCR); }
if (QueuedDMA.SIF2) { DMA_LOG("Resuming DMA for SIF2"); QueuedDMA.SIF2 = !QuickDmaExec(dmaSIF2, D7_CHCR); }
if (QueuedDMA.SPR0) { DMA_LOG("Resuming DMA for SPR0"); QueuedDMA.SPR0 = !QuickDmaExec(dmaSPR0, D8_CHCR); }
if (QueuedDMA.SPR1) { DMA_LOG("Resuming DMA for SPR1"); QueuedDMA.SPR1 = !QuickDmaExec(dmaSPR1, D9_CHCR); }
}
static __ri void DmaExec( void (*func)(), u32 mem, u32 value )
{
DMACh& reg = (DMACh&)psHu32(mem);
tDMA_CHCR chcr(value);
//It's invalid for the hardware to write a DMA while it is active, not without Suspending the DMAC
if (reg.chcr.STR)
{
const uint channel = ChannelNumber(mem);
if(psHu8(DMAC_ENABLER+2) == 1) //DMA is suspended so we can allow writes to anything
{
//If it stops the DMA, we need to clear any pending interrupts so the DMA doesnt continue.
if(chcr.STR == 0)
{
//DevCon.Warning(L"32bit %s DMA Stopped on Suspend", ChcrName(mem));
if(channel == 1)
{
cpuClearInt( 10 );
QueuedDMA._u16 &= ~(1 << 10); //Clear any queued DMA requests for this channel
}
else if(channel == 2)
{
cpuClearInt( 11 );
QueuedDMA._u16 &= ~(1 << 11); //Clear any queued DMA requests for this channel
}
cpuClearInt( channel );
QueuedDMA._u16 &= ~(1 << channel); //Clear any queued DMA requests for this channel
}
//Sanity Check for possible future bug fix0rs ;p
//Spams on Persona 4 opening.
//if(reg.chcr.TAG != chcr.TAG) DevCon.Warning(L"32bit CHCR Tag on %s changed to %x from %x QWC = %x Channel Active", ChcrName(mem), chcr.TAG, reg.chcr.TAG, reg.qwc);
//Here we update the LOWER CHCR, if a chain is stopped half way through, it can be manipulated in to a different mode
//But we need to preserve the existing tag for now
reg.chcr.set((reg.chcr.TAG << 16) | chcr.lower());
return;
}
else //Else the DMA is running (Not Suspended), so we cant touch it!
{
//As the manual states "Fields other than STR can only be written to when the DMA is stopped"
//Also "The DMA may not stop properly just by writing 0 to STR"
//So the presumption is that STR can be written to (ala force stop the DMA) but nothing else
if(chcr.STR == 0)
{
//DevCon.Warning(L"32bit Force Stopping %s (Current CHCR %x) while DMA active", ChcrName(mem), reg.chcr._u32, chcr._u32);
reg.chcr.STR = 0;
//We need to clear any existing DMA loops that are in progress else they will continue!
if(channel == 1)
{
cpuClearInt( 10 );
QueuedDMA._u16 &= ~(1 << 10); //Clear any queued DMA requests for this channel
}
else if(channel == 2)
{
cpuClearInt( 11 );
QueuedDMA._u16 &= ~(1 << 11); //Clear any queued DMA requests for this channel
}
cpuClearInt( channel );
QueuedDMA._u16 &= ~(1 << channel); //Clear any queued DMA requests for this channel
}
//else DevCon.Warning(L"32bit Attempted to change %s CHCR (Currently %x) with %x while DMA active, ignoring QWC = %x", ChcrName(mem), reg.chcr._u32, chcr._u32, reg.qwc);
return;
}
}
//if(reg.chcr.TAG != chcr.TAG && chcr.MOD == CHAIN_MODE) DevCon.Warning(L"32bit CHCR Tag on %s changed to %x from %x QWC = %x Channel Not Active", ChcrName(mem), chcr.TAG, reg.chcr.TAG, reg.qwc);
reg.chcr.set(value);
if (reg.chcr.STR && dmacRegs.ctrl.DMAE && !psHu8(DMAC_ENABLER+2))
{
func();
}
else if(reg.chcr.STR)
{
//DevCon.Warning(L"32bit %s DMA Start while DMAC Disabled\n", ChcrName(mem));
QueuedDMA._u16 |= (1 << ChannelNumber(mem)); //Queue the DMA up to be started then the DMA's are Enabled and or the Suspend is lifted
} //else QueuedDMA._u16 &~= (1 << ChannelNumber(mem)); //
}
template< uint page >
__fi u32 dmacRead32( u32 mem )
{
// Fixme: OPH hack. Toggle the flag on each GIF_STAT access. (rama)
if (IsPageFor(mem) && (mem == GIF_STAT) && CHECK_OPHFLAGHACK)
{
gifRegs.stat.OPH = !gifRegs.stat.OPH;
}
return psHu32(mem);
}
// Returns TRUE if the caller should do writeback of the register to eeHw; false if the
// register has no writeback, or if the writeback is handled internally.
template< uint page >
__fi bool dmacWrite32( u32 mem, mem32_t& value )
{
iswitch(mem) {
icase(D0_CHCR) // dma0 - vif0
{
DMA_LOG("VIF0dma EXECUTE, value=0x%x", value);
DmaExec(dmaVIF0, mem, value);
return false;
}
icase(D1_CHCR) // dma1 - vif1 - chcr
{
DMA_LOG("VIF1dma EXECUTE, value=0x%x", value);
DmaExec(dmaVIF1, mem, value);
return false;
}
icase(D2_CHCR) // dma2 - gif
{
DMA_LOG("GIFdma EXECUTE, value=0x%x", value);
DmaExec(dmaGIF, mem, value);
return false;
}
icase(D3_CHCR) // dma3 - fromIPU
{
DMA_LOG("IPU0dma EXECUTE, value=0x%x\n", value);
DmaExec(dmaIPU0, mem, value);
return false;
}
icase(D4_CHCR) // dma4 - toIPU
{
DMA_LOG("IPU1dma EXECUTE, value=0x%x\n", value);
DmaExec(dmaIPU1, mem, value);
return false;
}
icase(D5_CHCR) // dma5 - sif0
{
DMA_LOG("SIF0dma EXECUTE, value=0x%x", value);
DmaExec(dmaSIF0, mem, value);
return false;
}
icase(D6_CHCR) // dma6 - sif1
{
DMA_LOG("SIF1dma EXECUTE, value=0x%x", value);
DmaExec(dmaSIF1, mem, value);
return false;
}
icase(D7_CHCR) // dma7 - sif2
{
DMA_LOG("SIF2dma EXECUTE, value=0x%x", value);
DmaExec(dmaSIF2, mem, value);
return false;
}
icase(D8_CHCR) // dma8 - fromSPR
{
DMA_LOG("SPR0dma EXECUTE (fromSPR), value=0x%x", value);
DmaExec(dmaSPR0, mem, value);
return false;
}
icase(D9_CHCR) // dma9 - toSPR
{
DMA_LOG("SPR1dma EXECUTE (toSPR), value=0x%x", value);
DmaExec(dmaSPR1, mem, value);
return false;
}
icase(DMAC_CTRL)
{
u32 oldvalue = psHu32(mem);
HW_LOG("DMAC_CTRL Write 32bit %x", value);
psHu32(mem) = value;
//Check for DMAS that were started while the DMAC was disabled
if (((oldvalue & 0x1) == 0) && ((value & 0x1) == 1))
{
if (!QueuedDMA.empty()) StartQueuedDMA();
}
if ((oldvalue & 0x30) != (value & 0x30))
{
DevCon.Warning("32bit Stall Source Changed to %x", (value & 0x30) >> 4);
}
if ((oldvalue & 0xC0) != (value & 0xC0))
{
DevCon.Warning("32bit Stall Destination Changed to %x", (value & 0xC0) >> 4);
}
return false;
}
icase(DMAC_STAT)
{
HW_LOG("DMAC_STAT Write 32bit %x", value);
// lower 16 bits: clear on 1
// upper 16 bits: reverse on 1
psHu16(0xe010) &= ~(value & 0xffff);
psHu16(0xe012) ^= (u16)(value >> 16);
cpuTestDMACInts();
return false;
}
icase(DMAC_ENABLEW)
{
HW_LOG("DMAC_ENABLEW Write 32bit %lx", value);
oldvalue = psHu8(DMAC_ENABLEW + 2);
psHu32(DMAC_ENABLEW) = value;
psHu32(DMAC_ENABLER) = value;
if (((oldvalue & 0x1) == 1) && (((value >> 16) & 0x1) == 0))
{
if (!QueuedDMA.empty()) StartQueuedDMA();
}
return false;
}
}
// fall-through: use the default writeback provided by caller.
return true;
}
template u32 dmacRead32<0x03>( u32 mem );
template bool dmacWrite32<0x00>( u32 mem, mem32_t& value );
template bool dmacWrite32<0x01>( u32 mem, mem32_t& value );
template bool dmacWrite32<0x02>( u32 mem, mem32_t& value );
template bool dmacWrite32<0x03>( u32 mem, mem32_t& value );
template bool dmacWrite32<0x04>( u32 mem, mem32_t& value );
template bool dmacWrite32<0x05>( u32 mem, mem32_t& value );
template bool dmacWrite32<0x06>( u32 mem, mem32_t& value );
template bool dmacWrite32<0x07>( u32 mem, mem32_t& value );
template bool dmacWrite32<0x08>( u32 mem, mem32_t& value );
template bool dmacWrite32<0x09>( u32 mem, mem32_t& value );
template bool dmacWrite32<0x0a>( u32 mem, mem32_t& value );
template bool dmacWrite32<0x0b>( u32 mem, mem32_t& value );
template bool dmacWrite32<0x0c>( u32 mem, mem32_t& value );
template bool dmacWrite32<0x0d>( u32 mem, mem32_t& value );
template bool dmacWrite32<0x0e>( u32 mem, mem32_t& value );
template bool dmacWrite32<0x0f>( u32 mem, mem32_t& value );

268
pcsx2/ps2/eeHwTraceLog.inl Normal file
View File

@ -0,0 +1,268 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2010 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 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 PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
template< typename T>
static __ri const char* _eelog_GetHwName( u32 addr, T val )
{
#define EasyCase(label) case label: return #label
switch( addr )
{
// Counters!
EasyCase(RCNT0_COUNT);
EasyCase(RCNT0_MODE);
EasyCase(RCNT0_TARGET);
EasyCase(RCNT0_HOLD);
EasyCase(RCNT1_COUNT);
EasyCase(RCNT1_MODE);
EasyCase(RCNT1_TARGET);
EasyCase(RCNT1_HOLD);
EasyCase(RCNT2_COUNT);
EasyCase(RCNT2_MODE);
EasyCase(RCNT2_TARGET);
EasyCase(RCNT3_COUNT);
EasyCase(RCNT3_MODE);
EasyCase(RCNT3_TARGET);
// IPU!
EasyCase(IPU_CMD);
EasyCase(IPU_CTRL);
EasyCase(IPU_BP);
EasyCase(IPU_TOP);
// GIF!
EasyCase(GIF_CTRL);
EasyCase(GIF_MODE);
EasyCase(GIF_STAT);
EasyCase(GIF_TAG0);
EasyCase(GIF_TAG1);
EasyCase(GIF_TAG2);
EasyCase(GIF_TAG3);
EasyCase(GIF_CNT);
EasyCase(GIF_P3CNT);
EasyCase(GIF_P3TAG);
// VIF!
EasyCase(VIF0_STAT);
EasyCase(VIF0_FBRST);
EasyCase(VIF0_ERR);
EasyCase(VIF0_MARK);
EasyCase(VIF0_CYCLE);
EasyCase(VIF0_MODE);
EasyCase(VIF0_NUM);
EasyCase(VIF0_MASK);
EasyCase(VIF0_CODE);
EasyCase(VIF0_ITOPS);
EasyCase(VIF0_ITOP);
EasyCase(VIF0_TOP);
EasyCase(VIF0_ROW0);
EasyCase(VIF0_ROW1);
EasyCase(VIF0_ROW2);
EasyCase(VIF0_ROW3);
EasyCase(VIF0_COL0);
EasyCase(VIF0_COL1);
EasyCase(VIF0_COL2);
EasyCase(VIF0_COL3);
EasyCase(VIF1_STAT);
EasyCase(VIF1_FBRST);
EasyCase(VIF1_ERR);
EasyCase(VIF1_MARK);
EasyCase(VIF1_CYCLE);
EasyCase(VIF1_MODE);
EasyCase(VIF1_NUM);
EasyCase(VIF1_MASK);
EasyCase(VIF1_CODE);
EasyCase(VIF1_ITOPS);
EasyCase(VIF1_BASE);
EasyCase(VIF1_OFST);
EasyCase(VIF1_TOPS);
EasyCase(VIF1_ITOP);
EasyCase(VIF1_TOP);
EasyCase(VIF1_ROW0);
EasyCase(VIF1_ROW1);
EasyCase(VIF1_ROW2);
EasyCase(VIF1_ROW3);
EasyCase(VIF1_COL0);
EasyCase(VIF1_COL1);
EasyCase(VIF1_COL2);
EasyCase(VIF1_COL3);
// VIF DMA!
EasyCase(VIF0_CHCR);
EasyCase(VIF0_MADR);
EasyCase(VIF0_QWC);
EasyCase(VIF0_TADR);
EasyCase(VIF0_ASR0);
EasyCase(VIF0_ASR1);
EasyCase(VIF1_CHCR);
EasyCase(VIF1_QWC);
EasyCase(VIF1_TADR);
EasyCase(VIF1_ASR0);
EasyCase(VIF1_ASR1);
// GIF DMA!
EasyCase(GIF_CHCR);
EasyCase(GIF_MADR);
EasyCase(GIF_QWC);
EasyCase(GIF_TADR);
EasyCase(GIF_ASR0);
EasyCase(GIF_ASR1);
// IPU DMA!
EasyCase(fromIPU_CHCR);
EasyCase(fromIPU_MADR);
EasyCase(fromIPU_QWC);
EasyCase(fromIPU_TADR);
EasyCase(toIPU_CHCR);
EasyCase(toIPU_MADR);
EasyCase(toIPU_QWC);
EasyCase(toIPU_TADR);
// SIF DMA!
EasyCase(SIF0_CHCR);
EasyCase(SIF0_MADR);
EasyCase(SIF0_QWC);
EasyCase(SIF1_CHCR);
EasyCase(SIF1_MADR);
EasyCase(SIF1_QWC);
EasyCase(SIF2_CHCR);
EasyCase(SIF2_MADR);
EasyCase(SIF2_QWC);
// Scratchpad DMA! (SPRdma)
EasyCase(fromSPR_CHCR);
EasyCase(fromSPR_MADR);
EasyCase(fromSPR_QWC);
EasyCase(toSPR_CHCR);
EasyCase(toSPR_MADR);
EasyCase(toSPR_QWC);
// DMAC!
EasyCase(DMAC_CTRL);
EasyCase(DMAC_STAT);
EasyCase(DMAC_PCR);
EasyCase(DMAC_SQWC);
EasyCase(DMAC_RBSR);
EasyCase(DMAC_RBOR);
EasyCase(DMAC_STADR);
EasyCase(DMAC_ENABLER);
EasyCase(DMAC_ENABLEW);
// INTC!
EasyCase(INTC_STAT);
EasyCase(INTC_MASK);
// SIO
EasyCase(SIO_LCR);
EasyCase(SIO_LSR);
EasyCase(SIO_IER);
EasyCase(SIO_ISR);
EasyCase(SIO_FCR);
EasyCase(SIO_BGR);
EasyCase(SIO_TXFIFO);
EasyCase(SIO_RXFIFO);
// SBUS (terribly mysterious!)
EasyCase(SBUS_F200);
EasyCase(SBUS_F210);
EasyCase(SBUS_F220);
EasyCase(SBUS_F230);
EasyCase(SBUS_F240);
EasyCase(SBUS_F250);
EasyCase(SBUS_F260);
// MCH (vaguely mysterious!)
EasyCase(MCH_RICM);
EasyCase(MCH_DRD);
}
#define EasyZone(zone) \
if ((addr >= EEMemoryMap::zone##_Start) && (addr < EEMemoryMap::zone##_End)) return #zone
#define EasyZoneR(zone) \
EasyZone(zone) "_reserved"
// Nothing discovered/handled : Check for "zoned" registers -- registers mirrored
// across large sections of memory (FIFOs mainly).
EasyZone(VIF0_FIFO); EasyZone(VIF1_FIFO); EasyZone(GIF_FIFO);
if( (addr >= EEMemoryMap::IPU_FIFO_Start) && (addr < EEMemoryMap::IPU_FIFO_End) )
{
return (addr & 0x10) ? "IPUin_FIFO" : "IPUout_FIFO";
}
// Check for "reserved" regions -- registers that most likely discard writes and
// return 0 when read. To assist in having useful logs, we determine the general
// "zone" of the register address and return the zone name in the unknown string.
EasyZoneR(RCNT0); EasyZoneR(RCNT1);
EasyZoneR(RCNT2); EasyZoneR(RCNT3);
EasyZoneR(IPU); EasyZoneR(GIF);
EasyZoneR(VIF0); EasyZoneR(VIF1);
EasyZoneR(VIF0dma); EasyZoneR(VIF1dma);
EasyZoneR(GIFdma); EasyZoneR(fromIPU); EasyZoneR(toIPU);
EasyZoneR(SIF0dma); EasyZoneR(SIF1dma); EasyZoneR(SIF2dma);
EasyZoneR(fromSPR); EasyZoneR(toSPR);
EasyZoneR(DMAC); EasyZoneR(INTC);
EasyZoneR(SIO); EasyZoneR(SBUS);
EasyZoneR(MCH); EasyZoneR(DMACext);
// If we get this far it's an *unknown* register; plain and simple.
return NULL; //"Unknown";
}
template< typename T>
static __ri void eeHwTraceLog( u32 addr, T val, bool mode )
{
if (!IsDevBuild) return;
if (!EmuConfig.Trace.EE.m_EnableRegisters) return;
FastFormatAscii valStr;
FastFormatAscii labelStr;
labelStr.Write("Hw%s%u", mode ? "Read" : "Write", sizeof (T) * 8);
switch( sizeof(T) )
{
case 1: valStr.Write("0x%02x", val); break;
case 2: valStr.Write("0x%04x", val); break;
case 4: valStr.Write("0x%08x", val); break;
case 8: valStr.Write("0x%08x.%08x", ((u32*)&val)[1], ((u32*)&val)[0]); break;
case 16: ((u128&)val).WriteTo(valStr);
}
static const char* temp = "%-12s @ 0x%08X/%-16s %s %s";
if( const char* regname = _eelog_GetHwName<T>( addr, val ) )
HW_LOG( temp, labelStr.c_str(), addr, regname, mode ? "->" : "<-", valStr.c_str() );
else
UnknownHW_LOG( temp, labelStr.c_str(), addr, "Unknown", mode ? "->" : "<-", valStr.c_str() );
}

View File

@ -126,10 +126,6 @@ void __fastcall vtlb_memRead128(u32 mem, mem128_t *out)
((vtlbMemR128FP*)vtlbdata.RWFT[4][0][hand])(paddr, out); ((vtlbMemR128FP*)vtlbdata.RWFT[4][0][hand])(paddr, out);
} }
} }
void __fastcall vtlb_memRead128(u32 mem, u64 (&out)[2])
{
vtlb_memRead128(mem, (mem128_t*)out);
}
template< typename DataType > template< typename DataType >
void __fastcall vtlb_memWrite(u32 addr, DataType data) void __fastcall vtlb_memWrite(u32 addr, DataType data)
@ -159,6 +155,7 @@ void __fastcall vtlb_memWrite(u32 addr, DataType data)
} }
} }
} }
void __fastcall vtlb_memWrite64(u32 mem, const mem64_t* value) void __fastcall vtlb_memWrite64(u32 mem, const mem64_t* value)
{ {
u32 vmv=vtlbdata.vmap[mem>>VTLB_PAGE_BITS]; u32 vmv=vtlbdata.vmap[mem>>VTLB_PAGE_BITS];
@ -197,11 +194,6 @@ void __fastcall vtlb_memWrite128(u32 mem, const mem128_t *value)
} }
} }
void __fastcall vtlb_memWrite128(u32 mem, const u64 (&out)[2])
{
vtlb_memWrite128(mem, (const mem128_t*)out);
}
template mem8_t vtlb_memRead<mem8_t>(u32 mem); template mem8_t vtlb_memRead<mem8_t>(u32 mem);
template mem16_t vtlb_memRead<mem16_t>(u32 mem); template mem16_t vtlb_memRead<mem16_t>(u32 mem);
template mem32_t vtlb_memRead<mem32_t>(u32 mem); template mem32_t vtlb_memRead<mem32_t>(u32 mem);

View File

@ -71,13 +71,11 @@ template< typename DataType >
extern DataType __fastcall vtlb_memRead(u32 mem); extern DataType __fastcall vtlb_memRead(u32 mem);
extern void __fastcall vtlb_memRead64(u32 mem, mem64_t *out); extern void __fastcall vtlb_memRead64(u32 mem, mem64_t *out);
extern void __fastcall vtlb_memRead128(u32 mem, mem128_t *out); extern void __fastcall vtlb_memRead128(u32 mem, mem128_t *out);
extern void __fastcall vtlb_memRead128(u32 mem, u64 (&out)[2]);
template< typename DataType > template< typename DataType >
extern void __fastcall vtlb_memWrite(u32 mem, DataType value); extern void __fastcall vtlb_memWrite(u32 mem, DataType value);
extern void __fastcall vtlb_memWrite64(u32 mem, const mem64_t* value); extern void __fastcall vtlb_memWrite64(u32 mem, const mem64_t* value);
extern void __fastcall vtlb_memWrite128(u32 mem, const mem128_t* value); extern void __fastcall vtlb_memWrite128(u32 mem, const mem128_t* value);
extern void __fastcall vtlb_memWrite128(u32 mem, const u64 (&value)[2]);
extern void vtlb_DynGenWrite(u32 sz); extern void vtlb_DynGenWrite(u32 sz);
extern void vtlb_DynGenRead32(u32 bits, bool sign); extern void vtlb_DynGenRead32(u32 bits, bool sign);

View File

@ -33,14 +33,14 @@ s32 PrepareEERead()
"\n\tread tag: %x %x %x %x", hw_dma(9).madr, hw_dma(9).tadr, sif0.iop.counter, sif0words, sif0data, "\n\tread tag: %x %x %x %x", hw_dma(9).madr, hw_dma(9).tadr, sif0.iop.counter, sif0words, sif0data,
tag[0], tag[1], tag[2], tag[3]); tag[0], tag[1], tag[2], tag[3]);
sif0dma->unsafeTransfer(((tDMA_TAG*)(tag))); sif0dma.unsafeTransfer(((tDMA_TAG*)(tag)));
sif0dma->madr = tag[1]; sif0dma.madr = tag[1];
tDMA_TAG ptag(tag[0]); tDMA_TAG ptag(tag[0]);
SIF_LOG("SIF0 EE dest chain tag madr:%08X qwc:%04X id:%X irq:%d(%08X_%08X)", SIF_LOG("SIF0 EE dest chain tag madr:%08X qwc:%04X id:%X irq:%d(%08X_%08X)",
sif0dma->madr, sif0dma->qwc, ptag.ID, ptag.IRQ, tag[1], tag[0]); sif0dma.madr, sif0dma.qwc, ptag.ID, ptag.IRQ, tag[1], tag[0]);
if (sif0dma->chcr.TIE && ptag.IRQ) if (sif0dma.chcr.TIE && ptag.IRQ)
{ {
//Console.WriteLn("SIF0 TIE"); //Console.WriteLn("SIF0 TIE");
sif0.ee.end = true; sif0.ee.end = true;
@ -50,13 +50,13 @@ s32 PrepareEERead()
{ {
case TAG_REFE: case TAG_REFE:
sif0.ee.end = true; sif0.ee.end = true;
if (dmacRegs->ctrl.STS != NO_STS) if (dmacRegs.ctrl.STS != NO_STS)
dmacRegs->stadr.ADDR = sif0dma->madr + (sif0dma->qwc * 16); dmacRegs.stadr.ADDR = sif0dma.madr + (sif0dma.qwc * 16);
break; break;
case TAG_REFS: case TAG_REFS:
if (dmacRegs->ctrl.STS != NO_STS) if (dmacRegs.ctrl.STS != NO_STS)
dmacRegs->stadr.ADDR = sif0dma->madr + (sif0dma->qwc * 16); dmacRegs.stadr.ADDR = sif0dma.madr + (sif0dma.qwc * 16);
break; break;
case TAG_END: case TAG_END:
@ -91,7 +91,7 @@ s32 DoSifRead(u32 iopAvailable)
SIF_LOG("Write IOP to EE: +++++++++++ %lX of %lX", transferSizeWords, sif0.iop.counter); SIF_LOG("Write IOP to EE: +++++++++++ %lX of %lX", transferSizeWords, sif0.iop.counter);
tDMA_TAG *ptag = sif0dma->getAddr(sif0dma->madr, DMAC_SIF0, true); tDMA_TAG *ptag = sif0dma.getAddr(sif0dma.madr, DMAC_SIF0, true);
if (ptag == NULL) if (ptag == NULL)
{ {
DevCon.Warning("Write IOP to EE: ptag == NULL"); DevCon.Warning("Write IOP to EE: ptag == NULL");
@ -101,11 +101,11 @@ s32 DoSifRead(u32 iopAvailable)
memcpy((u32*)ptag, (u32*)iopPhysMem(hw_dma(9).madr), transferSizeBytes); memcpy((u32*)ptag, (u32*)iopPhysMem(hw_dma(9).madr), transferSizeBytes);
// Clearing handled by vtlb memory protection and manual blocks. // Clearing handled by vtlb memory protection and manual blocks.
//Cpu->Clear(sif0dma->madr, readSize*4); //Cpu->Clear(sif0dma.madr, readSize*4);
sif0dma->madr += transferSizeBytes; sif0dma.madr += transferSizeBytes;
sif0.ee.cycles += transferSizeQWords * 2; sif0.ee.cycles += transferSizeQWords * 2;
sif0dma->qwc -= transferSizeQWords; sif0dma.qwc -= transferSizeQWords;
return transferSizeBytes; return transferSizeBytes;
} }

View File

@ -513,6 +513,10 @@
RelativePath="..\..\Dmac.h" RelativePath="..\..\Dmac.h"
> >
</File> </File>
<File
RelativePath="..\..\ps2\eeHwTraceLog.inl"
>
</File>
<File <File
RelativePath="..\..\FiFo.cpp" RelativePath="..\..\FiFo.cpp"
> >
@ -529,6 +533,10 @@
RelativePath="..\..\Hw.h" RelativePath="..\..\Hw.h"
> >
</File> </File>
<File
RelativePath="..\..\ps2\HwInternal.h"
>
</File>
<File <File
RelativePath="..\..\HwRead.cpp" RelativePath="..\..\HwRead.cpp"
> >
@ -749,6 +757,10 @@
<Filter <Filter
Name="DMAC" Name="DMAC"
> >
<File
RelativePath="..\..\ps2\LegacyDmac.cpp"
>
</File>
<Filter <Filter
Name="Sif" Name="Sif"
> >
@ -1318,6 +1330,14 @@
RelativePath="..\..\Ipu\IPU_Fifo.h" RelativePath="..\..\Ipu\IPU_Fifo.h"
> >
</File> </File>
<File
RelativePath="..\..\IPU\IPUdma.cpp"
>
</File>
<File
RelativePath="..\..\IPU\IPUdma.h"
>
</File>
<File <File
RelativePath="..\..\Ipu\yuv2rgb.cpp" RelativePath="..\..\Ipu\yuv2rgb.cpp"
> >

View File

@ -670,7 +670,7 @@ void psxRecompileCodeConst1(R3000AFNPTR constcode, R3000AFNPTR_INFO noconstcode)
const char *funcname = irxImportFuncname(libname, index); const char *funcname = irxImportFuncname(libname, index);
irxDEBUG debug = irxImportDebug(libname, index); irxDEBUG debug = irxImportDebug(libname, index);
if (SysTrace.IOP.Bios.IsActive()) { if (SysTraceActive(IOP.Bios)) {
xMOV(ecx, (uptr)libname); xMOV(ecx, (uptr)libname);
xMOV(edx, index); xMOV(edx, index);
xPUSH((uptr)funcname); xPUSH((uptr)funcname);

View File

@ -21,11 +21,6 @@
#include "iR5900.h" #include "iR5900.h"
#ifdef _WIN32
//#pragma warning(disable:4244)
//#pragma warning(disable:4761)
#endif
namespace R5900 { namespace R5900 {
namespace Dynarec { namespace Dynarec {
namespace OpcodeImpl namespace OpcodeImpl

View File

@ -19,6 +19,21 @@
#include "Common.h" #include "Common.h"
#include "microVU.h" #include "microVU.h"
// Include all the *.inl files (Needed because C++ sucks with templates and *.cpp files)
#include "microVU_Clamp.inl"
#include "microVU_Misc.inl"
#include "microVU_Log.inl"
#include "microVU_Analyze.inl"
#include "microVU_Alloc.inl"
#include "microVU_Upper.inl"
#include "microVU_Lower.inl"
#include "microVU_Tables.inl"
#include "microVU_Flags.inl"
#include "microVU_Branch.inl"
#include "microVU_Compile.inl"
#include "microVU_Execute.inl"
#include "microVU_Macro.inl"
//------------------------------------------------------------------ //------------------------------------------------------------------
// Micro VU - Global Variables // Micro VU - Global Variables
//------------------------------------------------------------------ //------------------------------------------------------------------
@ -70,107 +85,93 @@ static __fi void mVUthrowHardwareDeficiency(const wxChar* extFail, int vuIndex)
} }
// Only run this once per VU! ;) // Only run this once per VU! ;)
static __ri void mVUinit(int vuIndex) { void microVU::init(uint vuIndex) {
if(!x86caps.hasMultimediaExtensions) mVUthrowHardwareDeficiency( L"MMX", vuIndex ); if(!x86caps.hasMultimediaExtensions) mVUthrowHardwareDeficiency( L"MMX", vuIndex );
if(!x86caps.hasStreamingSIMDExtensions) mVUthrowHardwareDeficiency( L"SSE", vuIndex ); if(!x86caps.hasStreamingSIMDExtensions) mVUthrowHardwareDeficiency( L"SSE", vuIndex );
if(!x86caps.hasStreamingSIMD2Extensions) mVUthrowHardwareDeficiency( L"SSE2", vuIndex ); if(!x86caps.hasStreamingSIMD2Extensions) mVUthrowHardwareDeficiency( L"SSE2", vuIndex );
microVU* mVU = mVUx; memzero(prog);
memzero(mVU->prog);
mVU->index = vuIndex; index = vuIndex;
mVU->cop2 = 0; cop2 = 0;
mVU->vuMemSize = (vuIndex ? 0x4000 : 0x1000); vuMemSize = (index ? 0x4000 : 0x1000);
mVU->microMemSize = (vuIndex ? 0x4000 : 0x1000); microMemSize = (index ? 0x4000 : 0x1000);
mVU->progSize = (vuIndex ? 0x4000 : 0x1000) / 4; progSize = (index ? 0x4000 : 0x1000) / 4;
mVU->progMemMask = mVU->progSize-1; progMemMask = progSize-1;
mVU->dispCache = NULL; dispCache = NULL;
mVU->cache = NULL; cache = NULL;
mVU->cacheSize = mVUcacheSize; cacheSize = mVUcacheSize;
mVU->regAlloc = new microRegAlloc(); regAlloc = new microRegAlloc(index);
for (u32 i = 0; i < (mVU->progSize / 2); i++) { for (u32 i = 0; i < (progSize / 2); i++) {
mVU->prog.prog[i] = new deque<microProgram*>(); prog.prog[i] = new deque<microProgram*>();
} }
mVU->dispCache = SysMmapEx(0, mVUdispCacheSize, 0, (mVU->index ? "Micro VU1 Dispatcher" : "Micro VU0 Dispatcher")); dispCache = SysMmapEx(0, mVUdispCacheSize, 0, (index ? "Micro VU1 Dispatcher" : "Micro VU0 Dispatcher"));
if (!mVU->dispCache) throw Exception::OutOfMemory( mVU->index ? L"Micro VU1 Dispatcher" : L"Micro VU0 Dispatcher" ); if (!dispCache) throw Exception::OutOfMemory( index ? L"Micro VU1 Dispatcher" : L"Micro VU0 Dispatcher" );
memset(mVU->dispCache, 0xcc, mVUdispCacheSize); memset(dispCache, 0xcc, mVUdispCacheSize);
// Allocates rec-cache and calls mVUreset() // Allocates rec-cache and calls mVUreset()
mVUresizeCache(mVU, mVU->cacheSize + mVUcacheSafeZone); mVUresizeCache(this, cacheSize + mVUcacheSafeZone);
//if (vuIndex) gen_memcpy_vibes(); //if (vuIndex) gen_memcpy_vibes();
} }
// Resets Rec Data // Resets Rec Data
// If vuRegsPtr is NUL, the current regs pointer assigned to the VU compiler is assumed. void microVU::reset() {
static __fi void mVUreset(mV, VURegs* vuRegsPtr) {
static bool dispatchersGenerated = false; x86SetPtr(dispCache);
mVUdispatcherA(this);
if (!vuRegsPtr) vuRegsPtr = mVU->regs; mVUdispatcherB(this);
if (!dispatchersGenerated || (mVU->regs != vuRegsPtr))
{
// Setup Entrance/Exit Points
// These must be rebuilt whenever the vuRegsPtr has changed.
dispatchersGenerated = true;
mVU->regs = vuRegsPtr;
x86SetPtr(mVU->dispCache);
mVUdispatcherA(mVU);
mVUdispatcherB(mVU);
mVUemitSearch(); mVUemitSearch();
}
// Clear All Program Data // Clear All Program Data
//memset(&mVU->prog, 0, sizeof(mVU->prog)); //memset(&prog, 0, sizeof(prog));
memset(&mVU->prog.lpState, 0, sizeof(mVU->prog.lpState)); memset(&prog.lpState, 0, sizeof(prog.lpState));
if (IsDevBuild) { // Release builds shouldn't need this if (IsDevBuild) { // Release builds shouldn't need this
memset(mVU->cache, 0xcc, mVU->cacheSize); memset(cache, 0xcc, cacheSize);
} }
// Program Variables // Program Variables
mVU->prog.cleared = 1; prog.cleared = 1;
mVU->prog.isSame = -1; prog.isSame = -1;
mVU->prog.cur = NULL; prog.cur = NULL;
mVU->prog.total = 0; prog.total = 0;
mVU->prog.curFrame = 0; prog.curFrame = 0;
// Setup Dynarec Cache Limits for Each Program // Setup Dynarec Cache Limits for Each Program
u8* z = mVU->cache; u8* z = cache;
mVU->prog.x86start = z; prog.x86start = z;
mVU->prog.x86ptr = z; prog.x86ptr = z;
mVU->prog.x86end = (u8*)((uptr)z + (uptr)(mVU->cacheSize - mVUcacheSafeZone)); // "Safe Zone" prog.x86end = (u8*)((uptr)z + (uptr)(cacheSize - mVUcacheSafeZone)); // "Safe Zone"
for (u32 i = 0; i < (mVU->progSize / 2); i++) { for (u32 i = 0; i < (progSize / 2); i++) {
deque<microProgram*>::iterator it(mVU->prog.prog[i]->begin()); deque<microProgram*>::iterator it(prog.prog[i]->begin());
for ( ; it != mVU->prog.prog[i]->end(); ++it) { for ( ; it != prog.prog[i]->end(); ++it) {
if (!isVU1) mVUdeleteProg<0>(it[0]); if (index) mVUdeleteProg<1>(it[0]);
else mVUdeleteProg<1>(it[0]); else mVUdeleteProg<0>(it[0]);
} }
mVU->prog.prog[i]->clear(); prog.prog[i]->clear();
mVU->prog.quick[i].block = NULL; prog.quick[i].block = NULL;
mVU->prog.quick[i].prog = NULL; prog.quick[i].prog = NULL;
} }
} }
// Free Allocated Resources // Free Allocated Resources
static __fi void mVUclose(mV) { void microVU::close() {
if (mVU->dispCache) { HostSys::Munmap(mVU->dispCache, mVUdispCacheSize); mVU->dispCache = NULL; } if (dispCache) { HostSys::Munmap(dispCache, mVUdispCacheSize); dispCache = NULL; }
if (mVU->cache) { HostSys::Munmap(mVU->cache, mVU->cacheSize); mVU->cache = NULL; } if (cache) { HostSys::Munmap(cache, cacheSize); cache = NULL; }
// Delete Programs and Block Managers // Delete Programs and Block Managers
for (u32 i = 0; i < (mVU->progSize / 2); i++) { for (u32 i = 0; i < (progSize / 2); i++) {
deque<microProgram*>::iterator it(mVU->prog.prog[i]->begin()); deque<microProgram*>::iterator it(prog.prog[i]->begin());
for ( ; it != mVU->prog.prog[i]->end(); ++it) { for ( ; it != prog.prog[i]->end(); ++it) {
if (!isVU1) mVUdeleteProg<0>(it[0]); if (index) mVUdeleteProg<1>(it[0]);
else mVUdeleteProg<1>(it[0]); else mVUdeleteProg<0>(it[0]);
} }
safe_delete(mVU->prog.prog[i]); safe_delete(prog.prog[i]);
} }
} }
@ -181,7 +182,7 @@ static void mVUresizeCache(mV, u32 size) {
// We can't grow the rec any larger, so just reset it and start over. // We can't grow the rec any larger, so just reset it and start over.
//(if we don't reset, the rec will eventually crash) //(if we don't reset, the rec will eventually crash)
Console.WriteLn(Color_Magenta, "microVU%d: Cannot grow cache, size limit reached! [%dmb]. Resetting rec.", mVU->index, mVU->cacheSize/_1mb); Console.WriteLn(Color_Magenta, "microVU%d: Cannot grow cache, size limit reached! [%dmb]. Resetting rec.", mVU->index, mVU->cacheSize/_1mb);
mVUreset(mVU); mVU->reset();
return; return;
} }
size = mVUcacheMaxSize; size = mVUcacheMaxSize;
@ -191,7 +192,7 @@ static void mVUresizeCache(mV, u32 size) {
u8* cache = SysMmapEx(0, size, 0, (mVU->index ? "Micro VU1 RecCache" : "Micro VU0 RecCache")); u8* cache = SysMmapEx(0, size, 0, (mVU->index ? "Micro VU1 RecCache" : "Micro VU0 RecCache"));
if(!cache && !mVU->cache) throw Exception::OutOfMemory( wxsFormat( L"Micro VU%d recompiled code cache", mVU->index) ); if(!cache && !mVU->cache) throw Exception::OutOfMemory( wxsFormat( L"Micro VU%d recompiled code cache", mVU->index) );
if(!cache) { Console.Error("microVU%d Error - Cache Resize Failed...", mVU->index); mVUreset(mVU); return; } if(!cache) { Console.Error("microVU%d Error - Cache Resize Failed...", mVU->index); mVU->reset(); return; }
if (mVU->cache) { if (mVU->cache) {
HostSys::Munmap(mVU->cache, mVU->cacheSize); HostSys::Munmap(mVU->cache, mVU->cacheSize);
ProfilerTerminateSource(isVU1?"mVU1 Rec":"mVU0 Rec"); ProfilerTerminateSource(isVU1?"mVU1 Rec":"mVU0 Rec");
@ -200,7 +201,7 @@ static void mVUresizeCache(mV, u32 size) {
mVU->cache = cache; mVU->cache = cache;
mVU->cacheSize = size; mVU->cacheSize = size;
ProfilerRegisterSource(isVU1?"mVU1 Rec":"mVU0 Rec", mVU->cache, mVU->cacheSize); ProfilerRegisterSource(isVU1?"mVU1 Rec":"mVU0 Rec", mVU->cache, mVU->cacheSize);
mVUreset(mVU); mVU->reset();
} }
// Clears Block Data in specified range // Clears Block Data in specified range
@ -254,8 +255,8 @@ _mVUt __fi microProgram* mVUcreateProg(int startPC) {
// Caches Micro Program // Caches Micro Program
_mVUt __fi void mVUcacheProg(microProgram& prog) { _mVUt __fi void mVUcacheProg(microProgram& prog) {
microVU* mVU = mVUx; microVU* mVU = mVUx;
if (!vuIndex) memcpy_const(prog.data, mVU->regs->Micro, 0x1000); if (!vuIndex) memcpy_const(prog.data, mVU->regs().Micro, 0x1000);
else memcpy_const(prog.data, mVU->regs->Micro, 0x4000); else memcpy_const(prog.data, mVU->regs().Micro, 0x4000);
mVUdumpProg(prog); mVUdumpProg(prog);
} }
@ -265,17 +266,17 @@ _mVUt __fi bool mVUcmpPartial(microProgram& prog) {
deque<microRange>::const_iterator it(prog.ranges->begin()); deque<microRange>::const_iterator it(prog.ranges->begin());
for ( ; it != prog.ranges->end(); ++it) { for ( ; it != prog.ranges->end(); ++it) {
if((it[0].start<0)||(it[0].end<0)) { DevCon.Error("microVU%d: Negative Range![%d][%d]", mVU->index, it[0].start, it[0].end); } if((it[0].start<0)||(it[0].end<0)) { DevCon.Error("microVU%d: Negative Range![%d][%d]", mVU->index, it[0].start, it[0].end); }
if (memcmp_mmx(cmpOffset(prog.data), cmpOffset(mVU->regs->Micro), ((it[0].end + 8) - it[0].start))) { if (memcmp_mmx(cmpOffset(prog.data), cmpOffset(mVU->regs().Micro), ((it[0].end + 8) - it[0].start))) {
return 0; return 0;
} }
} }
return 1; return 1;
} }
// Compare Cached microProgram to mVU->regs->Micro // Compare Cached microProgram to mVU->regs().Micro
_mVUt __fi bool mVUcmpProg(microProgram& prog, const bool cmpWholeProg) { _mVUt __fi bool mVUcmpProg(microProgram& prog, const bool cmpWholeProg) {
microVU* mVU = mVUx; microVU* mVU = mVUx;
if ((cmpWholeProg && !memcmp_mmx((u8*)prog.data, mVU->regs->Micro, mVU->microMemSize)) if ((cmpWholeProg && !memcmp_mmx((u8*)prog.data, mVU->regs().Micro, mVU->microMemSize))
|| (!cmpWholeProg && mVUcmpPartial<vuIndex>(prog))) { || (!cmpWholeProg && mVUcmpPartial<vuIndex>(prog))) {
mVU->prog.cleared = 0; mVU->prog.cleared = 0;
mVU->prog.cur = &prog; mVU->prog.cur = &prog;
@ -334,14 +335,14 @@ void recMicroVU0::Allocate() {
if(!m_AllocCount) { if(!m_AllocCount) {
m_AllocCount++; m_AllocCount++;
if (AtomicExchange(mvu0_allocated, 1) == 0) if (AtomicExchange(mvu0_allocated, 1) == 0)
mVUinit(0); microVU0.init(0);
} }
} }
void recMicroVU1::Allocate() { void recMicroVU1::Allocate() {
if(!m_AllocCount) { if(!m_AllocCount) {
m_AllocCount++; m_AllocCount++;
if (AtomicExchange(mvu1_allocated, 1) == 0) if (AtomicExchange(mvu1_allocated, 1) == 0)
mVUinit(1); microVU1.init(1);
} }
} }
@ -349,24 +350,24 @@ void recMicroVU0::Shutdown() throw() {
if (m_AllocCount > 0) { if (m_AllocCount > 0) {
m_AllocCount--; m_AllocCount--;
if (AtomicExchange(mvu0_allocated, 0) == 1) if (AtomicExchange(mvu0_allocated, 0) == 1)
mVUclose(&microVU0); microVU0.close();
} }
} }
void recMicroVU1::Shutdown() throw() { void recMicroVU1::Shutdown() throw() {
if (m_AllocCount > 0) { if (m_AllocCount > 0) {
m_AllocCount--; m_AllocCount--;
if (AtomicExchange(mvu1_allocated, 0) == 1) if (AtomicExchange(mvu1_allocated, 0) == 1)
mVUclose(&microVU1); microVU1.close();
} }
} }
void recMicroVU0::Reset() { void recMicroVU0::Reset() {
if(!pxAssertDev(m_AllocCount, "MicroVU0 CPU Provider has not been allocated prior to reset!")) return; if(!pxAssertDev(m_AllocCount, "MicroVU0 CPU Provider has not been allocated prior to reset!")) return;
mVUreset(&microVU0, &VU0); microVU0.reset();
} }
void recMicroVU1::Reset() { void recMicroVU1::Reset() {
if(!pxAssertDev(m_AllocCount, "MicroVU1 CPU Provider has not been allocated prior to reset!")) return; if(!pxAssertDev(m_AllocCount, "MicroVU1 CPU Provider has not been allocated prior to reset!")) return;
mVUreset(&microVU1, &VU1); microVU1.reset();
} }
void recMicroVU0::Execute(u32 cycles) { void recMicroVU0::Execute(u32 cycles) {

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