mirror of https://github.com/PCSX2/pcsx2.git
wxgui: synced with trunk (to acquire new CDVD/ISO api)
git-svn-id: http://pcsx2.googlecode.com/svn/branches/wxgui@1558 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
commit
3751c928d3
2
build.rb
2
build.rb
|
@ -22,7 +22,7 @@ $pcsx2_prefix = " --prefix #{$main_dir}"
|
|||
$plugins_prefix = " --prefix #{$plugin_install_dir}"
|
||||
|
||||
$plugin_list=["CDVDnull", "dev9null", "FWnull", "USBnull", "SPU2null", "zerogs", "zzogl", "zeropad", "zerospu2", "PeopsSPU2", "CDVDiso", "CDVDisoEFP", "CDVDlinuz"]
|
||||
$full_plugin_list=["CDVDnull", "dev9null", "FWnull", "USBnull", "SPU2null", "zerogs", "zzogl", "zeropad", "zerospu2", "PeopsSPU2", "CDVDiso", "CDVDisoEFP", "CDVDlinuz","GSnull","PadNull","wxpad"]
|
||||
$full_plugin_list=["CDVDnull", "dev9null", "FWnull", "USBnull", "SPU2null", "zerogs", "zzogl", "zeropad", "zerospu2", "PeopsSPU2", "CDVDiso", "CDVDisoEFP", "CDVDlinuz","GSnull","PadNull","onepad"]
|
||||
|
||||
$pcsx2_build_types = {
|
||||
"dev" => " --enable-devbuild ",
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
-- clean_msvc.cmd
|
||||
--
|
||||
-- This batch file cleans up some files that MSVC's Clean/Rebuild commands tend to miss.
|
||||
-- In particular the .ilk and .pdb files are known to get corrupted and cause all sorts of odd
|
||||
-- linker errors, and the .ncb files can also get corrupted and cause intellisense breakges.
|
||||
--
|
||||
-- Safety: This tool should be pretty safe. None of the files it deletes are important. That
|
||||
-- is, they're all files MSVC just rebuilds automatically next time you run/recompile. But even
|
||||
-- so, don't go running this batch file in your root c:\ folder. It's probably not a wise action.
|
||||
-- Enjoy. :)
|
||||
|
||||
del /s *.ncb;*.ilk;*.pdb;*.bsc;*.sbr
|
|
@ -393,6 +393,17 @@ void CALLBACK CDVDabout();
|
|||
s32 CALLBACK CDVDtest();
|
||||
void CALLBACK CDVDnewDiskCB(void (*callback)());
|
||||
|
||||
// new funcs
|
||||
|
||||
// read a track directly
|
||||
s32 CALLBACK CDVDreadSector(u8* buffer, s32 lsn, int mode);
|
||||
|
||||
// improved getBuffer
|
||||
s32 CALLBACK CDVDgetBuffer2(u8* buffer);
|
||||
|
||||
// tool function
|
||||
s32 CALLBACK CDVDgetDualInfo(s32* dualType, u32* _layer1start);
|
||||
|
||||
#endif
|
||||
|
||||
/* DEV9 plugin API */
|
||||
|
@ -521,6 +532,7 @@ typedef void (CALLBACK* _GSprintf)(int timeout, char *fmt, ...);
|
|||
typedef void (CALLBACK* _GSsetBaseMem)(void*);
|
||||
typedef void (CALLBACK* _GSsetGameCRC)(int, int);
|
||||
typedef void (CALLBACK* _GSsetFrameSkip)(int frameskip);
|
||||
typedef void (CALLBACK* _GSsetFrameLimit)(int limit);
|
||||
typedef int (CALLBACK* _GSsetupRecording)(int, void*);
|
||||
typedef void (CALLBACK* _GSreset)();
|
||||
typedef void (CALLBACK* _GSwriteCSR)(u32 value);
|
||||
|
@ -615,12 +627,16 @@ typedef s32 (CALLBACK* _CDVDgetDiskType)();
|
|||
typedef s32 (CALLBACK* _CDVDgetTrayStatus)();
|
||||
typedef s32 (CALLBACK* _CDVDctrlTrayOpen)();
|
||||
typedef s32 (CALLBACK* _CDVDctrlTrayClose)();
|
||||
typedef s32 (CALLBACK* _CDVDreadSector)(u8* buffer, u32 lsn, int mode);
|
||||
typedef s32 (CALLBACK* _CDVDgetBuffer2)(u8* buffer);
|
||||
typedef s32 (CALLBACK* _CDVDgetDualInfo)(s32* dualType, u32* _layer1start);
|
||||
|
||||
typedef void (CALLBACK* _CDVDconfigure)();
|
||||
typedef s32 (CALLBACK* _CDVDtest)();
|
||||
typedef void (CALLBACK* _CDVDabout)();
|
||||
typedef void (CALLBACK* _CDVDnewDiskCB)(void (*callback)());
|
||||
|
||||
|
||||
// DEV9
|
||||
// NOTE: The read/write functions CANNOT use XMM/MMX regs
|
||||
// If you want to use them, need to save and restore current ones
|
||||
|
@ -710,6 +726,7 @@ extern _GSprintf GSprintf;
|
|||
extern _GSsetBaseMem GSsetBaseMem;
|
||||
extern _GSsetGameCRC GSsetGameCRC;
|
||||
extern _GSsetFrameSkip GSsetFrameSkip;
|
||||
extern _GSsetFrameLimit GSsetFrameLimit;
|
||||
extern _GSsetupRecording GSsetupRecording;
|
||||
extern _GSreset GSreset;
|
||||
extern _GSwriteCSR GSwriteCSR;
|
||||
|
@ -802,25 +819,35 @@ extern _SPU2test SPU2test;
|
|||
extern _SPU2about SPU2about;
|
||||
|
||||
// CDVD
|
||||
extern _CDVDinit CDVDinit;
|
||||
extern _CDVDopen CDVDopen;
|
||||
extern _CDVDclose CDVDclose;
|
||||
extern _CDVDshutdown CDVDshutdown;
|
||||
extern _CDVDreadTrack CDVDreadTrack;
|
||||
extern _CDVDgetBuffer CDVDgetBuffer;
|
||||
extern _CDVDreadSubQ CDVDreadSubQ;
|
||||
extern _CDVDgetTN CDVDgetTN;
|
||||
extern _CDVDgetTD CDVDgetTD;
|
||||
extern _CDVDgetTOC CDVDgetTOC;
|
||||
extern _CDVDgetDiskType CDVDgetDiskType;
|
||||
extern _CDVDgetTrayStatus CDVDgetTrayStatus;
|
||||
extern _CDVDctrlTrayOpen CDVDctrlTrayOpen;
|
||||
extern _CDVDctrlTrayClose CDVDctrlTrayClose;
|
||||
struct CDVDplugin {
|
||||
_CDVDinit init;
|
||||
_CDVDopen open;
|
||||
_CDVDclose close;
|
||||
_CDVDshutdown shutdown;
|
||||
_CDVDreadTrack readTrack;
|
||||
_CDVDgetBuffer getBuffer;
|
||||
_CDVDreadSubQ readSubQ;
|
||||
_CDVDgetTN getTN;
|
||||
_CDVDgetTD getTD;
|
||||
_CDVDgetTOC getTOC;
|
||||
_CDVDgetDiskType getDiskType;
|
||||
_CDVDgetTrayStatus getTrayStatus;
|
||||
_CDVDctrlTrayOpen ctrlTrayOpen;
|
||||
_CDVDctrlTrayClose ctrlTrayClose;
|
||||
|
||||
extern _CDVDconfigure CDVDconfigure;
|
||||
extern _CDVDtest CDVDtest;
|
||||
extern _CDVDabout CDVDabout;
|
||||
extern _CDVDnewDiskCB CDVDnewDiskCB;
|
||||
_CDVDconfigure configure;
|
||||
_CDVDtest test;
|
||||
_CDVDabout about;
|
||||
_CDVDnewDiskCB newDiskCB;
|
||||
|
||||
// special functions, not in external interface yet
|
||||
_CDVDreadSector readSector;
|
||||
_CDVDgetBuffer2 getBuffer2;
|
||||
_CDVDgetDualInfo getDualInfo;
|
||||
|
||||
int* initCount;
|
||||
};
|
||||
extern CDVDplugin CDVD_plugin; // _plugin because of
|
||||
|
||||
// DEV9
|
||||
extern _DEV9init DEV9init;
|
||||
|
|
|
@ -167,7 +167,7 @@ public:
|
|||
struct Hacks_t {
|
||||
int EECycleRate;
|
||||
bool IOPCycleDouble;
|
||||
bool WaitCycleExt;
|
||||
//bool WaitCycleExt;
|
||||
bool INTCSTATSlow;
|
||||
bool IdleLoopFF;
|
||||
int VUCycleSteal;
|
||||
|
@ -183,6 +183,8 @@ public:
|
|||
u32 sseVUMXCSR;
|
||||
u32 eeOptions;
|
||||
u32 vuOptions;
|
||||
|
||||
int Blockdump;
|
||||
};
|
||||
|
||||
extern PcsxConfig Config;
|
||||
|
|
|
@ -47,26 +47,35 @@
|
|||
// alignment of the stack at compile time, so I'm forced to use movups to store and
|
||||
// retrieve xmm0.
|
||||
|
||||
// MSVC Template Issue:
|
||||
// MSVC treats int template parameters like macro insertions. That is, if you have a
|
||||
// a template parameter in the form of "func<10-5>()", MSVC inserts 10-5 into the
|
||||
// templated function, causing order-of-operation problems (sigh). The normal fix would
|
||||
// be to assign the template parameter to a static const int inside each function, but that
|
||||
// won't fly with the enums optimization. So in order to fix the problem I define a macro
|
||||
// that encapsulates the template parameter inside parenthesis for us:
|
||||
|
||||
#define MZFbytes (_bytes)
|
||||
|
||||
// This is an implementation of the memzero_ptr fast memset routine (for zero-clears only).
|
||||
template< size_t bytes >
|
||||
template< size_t _bytes >
|
||||
static __forceinline void memzero_ptr( void *dest )
|
||||
{
|
||||
if( bytes == 0 ) return;
|
||||
if( MZFbytes == 0 ) return;
|
||||
|
||||
// This function only works on 32-bit alignments. For anything else we just fall back
|
||||
// on the compiler-provided implementation of memset...
|
||||
|
||||
if( (bytes & 0x3) != 0 )
|
||||
if( (MZFbytes & 0x3) != 0 )
|
||||
{
|
||||
memset( dest, 0, bytes );
|
||||
memset( dest, 0, MZFbytes );
|
||||
return;
|
||||
}
|
||||
|
||||
enum
|
||||
{
|
||||
remainder = bytes & 127,
|
||||
bytes128 = bytes / 128
|
||||
remainder = MZFbytes & 127,
|
||||
bytes128 = MZFbytes / 128
|
||||
};
|
||||
|
||||
// Initial check -- if the length is not a multiple of 16 then fall back on
|
||||
|
@ -74,7 +83,7 @@ static __forceinline void memzero_ptr( void *dest )
|
|||
// manner isn't necessary in pcsx2 (meaning they aren't used in speed-critical
|
||||
// scenarios).
|
||||
|
||||
if( (bytes & 0xf) == 0 )
|
||||
if( (MZFbytes & 0xf) == 0 )
|
||||
{
|
||||
u64 _xmm_backup[2];
|
||||
|
||||
|
@ -177,12 +186,12 @@ static __forceinline void memzero_ptr( void *dest )
|
|||
}
|
||||
|
||||
// This function only works on 32-bit alignments.
|
||||
jASSUME( (bytes & 0x3) == 0 );
|
||||
jASSUME( (MZFbytes & 0x3) == 0 );
|
||||
jASSUME( ((uptr)dest & 0x3) == 0 );
|
||||
|
||||
enum
|
||||
{
|
||||
remdat = bytes>>2
|
||||
remdat = MZFbytes >> 2
|
||||
};
|
||||
|
||||
// This case statement handles 5 special-case sizes (small blocks)
|
||||
|
@ -247,28 +256,28 @@ static __forceinline void memzero_ptr( void *dest )
|
|||
}
|
||||
|
||||
// An optimized memset for 8 bit destination data.
|
||||
template< u8 data, size_t bytes >
|
||||
template< u8 data, size_t _bytes >
|
||||
static __forceinline void memset_8( void *dest )
|
||||
{
|
||||
if( bytes == 0 ) return;
|
||||
if( MZFbytes == 0 ) return;
|
||||
|
||||
if( (bytes & 0x3) != 0 )
|
||||
if( (MZFbytes & 0x3) != 0 )
|
||||
{
|
||||
// unaligned data length. No point in doing an optimized inline version (too complicated!)
|
||||
// So fall back on the compiler implementation:
|
||||
|
||||
memset( dest, data, bytes );
|
||||
memset( dest, data, MZFbytes );
|
||||
return;
|
||||
}
|
||||
|
||||
//u64 _xmm_backup[2];
|
||||
|
||||
/*static const size_t remainder = bytes & 127;
|
||||
static const size_t bytes128 = bytes / 128;
|
||||
/*static const size_t remainder = MZFbytes & 127;
|
||||
static const size_t bytes128 = MZFbytes / 128;
|
||||
if( bytes128 > 32 )
|
||||
{
|
||||
// This function only works on 128-bit alignments.
|
||||
jASSUME( (bytes & 0xf) == 0 );
|
||||
jASSUME( (MZFbytes & 0xf) == 0 );
|
||||
jASSUME( ((uptr)dest & 0xf) == 0 );
|
||||
|
||||
__asm
|
||||
|
@ -313,11 +322,11 @@ static __forceinline void memset_8( void *dest )
|
|||
}*/
|
||||
|
||||
// This function only works on 32-bit alignments of data copied.
|
||||
jASSUME( (bytes & 0x3) == 0 );
|
||||
jASSUME( (MZFbytes & 0x3) == 0 );
|
||||
|
||||
enum
|
||||
{
|
||||
remdat = bytes>>2,
|
||||
remdat = MZFbytes >> 2,
|
||||
data32 = data + (data<<8) + (data<<16) + (data<<24)
|
||||
};
|
||||
|
||||
|
@ -381,31 +390,31 @@ static __forceinline void memset_8( void *dest )
|
|||
}
|
||||
}
|
||||
|
||||
template< u16 data, size_t bytes >
|
||||
template< u16 data, size_t _bytes >
|
||||
static __forceinline void memset_16( void *dest )
|
||||
{
|
||||
if( bytes == 0 ) return;
|
||||
if( MZFbytes == 0 ) return;
|
||||
|
||||
if( (bytes & 0x1) != 0 )
|
||||
if( (MZFbytes & 0x1) != 0 )
|
||||
throw Exception::LogicError( "Invalid parameter passed to memset_16 - data length is not a multiple of 16 or 32 bits." );
|
||||
|
||||
if( (bytes & 0x3) != 0 )
|
||||
if( (MZFbytes & 0x3) != 0 )
|
||||
{
|
||||
// Unaligned data length. No point in doing an optimized inline version (too complicated with
|
||||
// remainders and such).
|
||||
|
||||
_memset16_unaligned( dest, data, bytes );
|
||||
_memset16_unaligned( dest, data, MZFbytes );
|
||||
return;
|
||||
}
|
||||
|
||||
//u64 _xmm_backup[2];
|
||||
|
||||
// This function only works on 32-bit alignments of data copied.
|
||||
jASSUME( (bytes & 0x3) == 0 );
|
||||
jASSUME( (MZFbytes & 0x3) == 0 );
|
||||
|
||||
enum
|
||||
{
|
||||
remdat = bytes>>2,
|
||||
remdat = MZFbytes >> 2,
|
||||
data32 = data + (data<<16)
|
||||
};
|
||||
|
||||
|
@ -469,12 +478,12 @@ static __forceinline void memset_16( void *dest )
|
|||
}
|
||||
}
|
||||
|
||||
template< u32 data, size_t bytes >
|
||||
template< u32 data, size_t MZFbytes >
|
||||
static __forceinline void memset_32( void *dest )
|
||||
{
|
||||
if( bytes == 0 ) return;
|
||||
if( MZFbytes == 0 ) return;
|
||||
|
||||
if( (bytes & 0x3) != 0 )
|
||||
if( (MZFbytes & 0x3) != 0 )
|
||||
throw Exception::LogicError( "Invalid parameter passed to memset_32 - data length is not a multiple of 32 bits." );
|
||||
|
||||
|
||||
|
@ -484,11 +493,11 @@ static __forceinline void memset_32( void *dest )
|
|||
// If the data length is not a factor of 32 bits, the C++ optimizing compiler will
|
||||
// probably just generate mysteriously broken code in Release builds. ;)
|
||||
|
||||
jASSUME( (bytes & 0x3) == 0 );
|
||||
jASSUME( (MZFbytes & 0x3) == 0 );
|
||||
|
||||
enum
|
||||
{
|
||||
remdat = bytes>>2,
|
||||
remdat = MZFbytes>>2,
|
||||
data32 = data
|
||||
};
|
||||
|
||||
|
@ -582,3 +591,4 @@ static __forceinline void memset32_obj( T& object )
|
|||
memset_32<data, sizeof(T)>( &object );
|
||||
}
|
||||
|
||||
#undef MZFbytes
|
||||
|
|
|
@ -1344,11 +1344,11 @@ extern void SSSE3_PABSD_XMM_to_XMM(x86SSERegType to, x86SSERegType from);
|
|||
#ifndef _MM_MK_INSERTPS_NDX
|
||||
#define _MM_MK_INSERTPS_NDX(srcField, dstField, zeroMask) (((srcField)<<6) | ((dstField)<<4) | (zeroMask))
|
||||
#endif
|
||||
|
||||
extern void SSE4_DPPS_XMM_to_XMM(x86SSERegType to, x86SSERegType from, u8 imm8);
|
||||
extern void SSE4_DPPS_M128_to_XMM(x86SSERegType to, uptr from, u8 imm8);
|
||||
extern void SSE4_INSERTPS_XMM_to_XMM(x86SSERegType to, x86SSERegType from, u8 imm8);
|
||||
extern void SSE4_EXTRACTPS_XMM_to_R32(x86IntRegType to, x86SSERegType from, u8 imm8);
|
||||
extern void SSE4_EXTRACTPS_XMM_to_M32(uptr to, x86SSERegType from, u8 imm8);
|
||||
extern void SSE4_BLENDPS_XMM_to_XMM(x86SSERegType to, x86SSERegType from, u8 imm8);
|
||||
extern void SSE4_BLENDVPS_XMM_to_XMM(x86SSERegType to, x86SSERegType from);
|
||||
extern void SSE4_BLENDVPS_M128_to_XMM(x86SSERegType to, uptr from);
|
||||
|
|
|
@ -364,6 +364,7 @@ emitterT void SSE4_PINSRD_R32_to_XMM(x86SSERegType to, x86IntRegType from, u8 im
|
|||
|
||||
emitterT void SSE4_INSERTPS_XMM_to_XMM(x86SSERegType to, x86SSERegType from, u8 imm8) { xINSERTPS( xRegisterSSE(to), xRegisterSSE(from), imm8 ); }
|
||||
emitterT void SSE4_EXTRACTPS_XMM_to_R32(x86IntRegType to, x86SSERegType from, u8 imm8) { xEXTRACTPS( xRegister32(to), xRegisterSSE(from), imm8 ); }
|
||||
emitterT void SSE4_EXTRACTPS_XMM_to_M32(uptr to, x86SSERegType from, u8 imm8) { xEXTRACTPS( (u32*)to, xRegisterSSE(from), imm8 ); }
|
||||
|
||||
emitterT void SSE4_DPPS_XMM_to_XMM(x86SSERegType to, x86SSERegType from, u8 imm8) { xDP.PS( xRegisterSSE(to), xRegisterSSE(from), imm8 ); }
|
||||
emitterT void SSE4_DPPS_M128_to_XMM(x86SSERegType to, uptr from, u8 imm8) { xDP.PS( xRegisterSSE(to), (void*)from, imm8 ); }
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
Instruction for installations:
|
||||
|
||||
Install NSIS (tested with 2.45)
|
||||
Install NSIS Script Advanced Uninstall Log NSIS Header (you can find it opn NSIS wiki)
|
||||
Create a folder
|
||||
Put the nsis script in said folder
|
||||
Put vcredist_x86.exe in said folder
|
||||
Put the pcsx2 folder in said folder (warning, leave only the files you want in the installer. All files from the pcsx2 folder will be added to the installer )
|
||||
Edit the NSIS script with a text editor, changing the installer name and putting the correct name for the menu item (2 times, both filename and link name)
|
||||
Compile the NSIS script
|
|
@ -0,0 +1,147 @@
|
|||
; Pcsx2 NSIS installer script
|
||||
; loosely based on a collection of examples and on information from the wikipedia
|
||||
|
||||
!define APP_NAME "Pcsx2 - A Playstation 2 Emulator"
|
||||
!define INSTDIR_REG_ROOT "HKLM"
|
||||
!define INSTDIR_REG_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APP_NAME}"
|
||||
|
||||
;--------------------------------
|
||||
;Include Modern UI 2 and advanced log uninstaller. all credits to the respective authors
|
||||
|
||||
!include "MUI2.nsh"
|
||||
!include "AdvUninstLog.nsh"
|
||||
|
||||
;--------------------------------
|
||||
|
||||
; The name of the installer
|
||||
Name "Pcsx2"
|
||||
|
||||
; The file to write. To change each release
|
||||
OutFile "Pcsx2-beta-1474-setup.exe"
|
||||
|
||||
; The default installation directory
|
||||
InstallDir "$PROGRAMFILES\Pcsx2"
|
||||
|
||||
; Registry key to check for directory (so if you install again, it will
|
||||
; overwrite the old one automatically)
|
||||
InstallDirRegKey HKLM "Software\Pcsx2" "Install_Dir"
|
||||
|
||||
; Request application privileges for Windows Vista
|
||||
RequestExecutionLevel admin
|
||||
|
||||
; Pages
|
||||
|
||||
!insertmacro UNATTENDED_UNINSTALL
|
||||
!define MUI_COMPONENTSPAGE_NODESC ;no decription is really necessary at this stage...
|
||||
!insertmacro MUI_PAGE_COMPONENTS
|
||||
!insertmacro MUI_PAGE_DIRECTORY
|
||||
!insertmacro MUI_PAGE_INSTFILES
|
||||
|
||||
!insertmacro MUI_UNPAGE_CONFIRM
|
||||
!insertmacro MUI_UNPAGE_COMPONENTS
|
||||
!insertmacro MUI_UNPAGE_INSTFILES
|
||||
|
||||
|
||||
;--------------------------------
|
||||
|
||||
; Basic section (emulation proper)
|
||||
Section "Pcsx2 (required)"
|
||||
|
||||
SectionIn RO
|
||||
|
||||
; Set output path to the installation directory.
|
||||
SetOutPath $INSTDIR
|
||||
|
||||
; Put file there. It's catched by the uninstaller script
|
||||
!insertmacro UNINSTALL.LOG_OPEN_INSTALL
|
||||
File /r "Pcsx2\"
|
||||
!insertmacro UNINSTALL.LOG_CLOSE_INSTALL
|
||||
|
||||
; Write the installation path into the registry
|
||||
WriteRegStr HKLM Software\Pcsx2 "Install_Dir" "$INSTDIR"
|
||||
|
||||
; Write the uninstall keys for Windows
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Pcsx2" "DisplayName" "Pcsx2 - Playstation 2 Emulator"
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Pcsx2" "UninstallString" '"$INSTDIR\uninstall.exe"'
|
||||
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Pcsx2" "NoModify" 1
|
||||
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Pcsx2" "NoRepair" 1
|
||||
WriteUninstaller "uninstall.exe"
|
||||
|
||||
SectionEnd
|
||||
|
||||
; Optional sections (can be disabled by the user)
|
||||
Section "Start Menu Shortcuts"
|
||||
|
||||
; Need to change name too, for each version
|
||||
CreateDirectory "$SMPROGRAMS\Pcsx2"
|
||||
CreateShortCut "$SMPROGRAMS\Pcsx2\Uninstall.lnk" "$INSTDIR\uninstall.exe" "" "$INSTDIR\uninstall.exe" 0
|
||||
CreateShortCut "$SMPROGRAMS\Pcsx2\Pcsx2.lnk" "$INSTDIR\pcsx2-beta-1474.exe" "" "$INSTDIR\pcsx2-beta-1474.exe" 0
|
||||
|
||||
SectionEnd
|
||||
|
||||
; Optional, but required if you don't already have it
|
||||
Section "Microsoft Visual C++ 2008 SP1 Redist(Required)"
|
||||
|
||||
SetOutPath $TEMP
|
||||
File "vcredist_x86.exe"
|
||||
ExecWait "$TEMP\vcredist_x86.exe"
|
||||
|
||||
SectionEnd
|
||||
|
||||
;--------------------------------
|
||||
|
||||
Function .onInit
|
||||
|
||||
;prepare log always within .onInit function
|
||||
!insertmacro UNINSTALL.LOG_PREPARE_INSTALL
|
||||
|
||||
FunctionEnd
|
||||
|
||||
|
||||
Function .onInstSuccess
|
||||
|
||||
;create/update log always within .onInstSuccess function
|
||||
!insertmacro UNINSTALL.LOG_UPDATE_INSTALL
|
||||
|
||||
FunctionEnd
|
||||
|
||||
;--------------------------------
|
||||
|
||||
|
||||
|
||||
; Uninstaller
|
||||
|
||||
Section "Un.Standard uninstallation (Leaves user created files untouched)"
|
||||
|
||||
; Remove registry keys
|
||||
DeleteRegKey HKLM Software\Microsoft\Windows\CurrentVersion\Uninstall\Pcsx2
|
||||
DeleteRegKey HKLM Software\Pcsx2
|
||||
|
||||
; Remove shortcuts, if any
|
||||
Delete "$SMPROGRAMS\Pcsx2\*.*"
|
||||
RMDir "$SMPROGRAMS\Pcsx2"
|
||||
|
||||
!insertmacro UNINSTALL.LOG_UNINSTALL "$INSTDIR"
|
||||
DeleteRegKey ${INSTDIR_REG_ROOT} "${INSTDIR_REG_KEY}"
|
||||
|
||||
SectionEnd
|
||||
|
||||
; This option lets you COMPLETELY uninstall by deleting the main folder. Caution! :)
|
||||
Section /o "Un.Complete Uninstall. WARNING, this will delete every file in the program folder"
|
||||
|
||||
MessageBox MB_YESNO "You have chosen to remove ALL files in the installation folder. This will remove all your saves, screenshots, patches and bios as well. Do you want to proceed?" IDYES true IDNO false
|
||||
true:
|
||||
Delete "$SMPROGRAMS\Pcsx2\*.*"
|
||||
RMDir "$SMPROGRAMS\Pcsx2"
|
||||
RMDir /r "$INSTDIR"
|
||||
DeleteRegKey ${INSTDIR_REG_ROOT} "${INSTDIR_REG_KEY}"
|
||||
false:
|
||||
|
||||
SectionEnd
|
||||
|
||||
Function UN.onInit
|
||||
|
||||
;begin uninstall, could be added on top of uninstall section instead
|
||||
!insertmacro UNINSTALL.LOG_BEGIN_UNINSTALL
|
||||
|
||||
FunctionEnd
|
3939
pcsx2/CDVD/CDVD.cpp
3939
pcsx2/CDVD/CDVD.cpp
File diff suppressed because it is too large
Load Diff
|
@ -18,7 +18,11 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "IopCommon.h"
|
||||
#include "CDVD/CDVDaccess.h"
|
||||
|
||||
extern char isoFileName[];
|
||||
|
||||
#define btoi(b) ((b)/16*10 + (b)%16) /* BCD to u_char */
|
||||
#define itob(i) ((i)/10*16 + (i)%10) /* u_char to BCD */
|
||||
|
@ -97,7 +101,11 @@ extern void cdvdActionInterrupt();
|
|||
extern void cdvdReadInterrupt();
|
||||
|
||||
// We really should not have a function with the exact same name as a callback except for case!
|
||||
extern void cdvdDetectDisk();
|
||||
extern void cdvdNewDiskCB();
|
||||
extern u8 cdvdRead(u8 key);
|
||||
extern void cdvdWrite(u8 key, u8 rt);
|
||||
|
||||
extern CDVDplugin CDVD;
|
||||
extern CDVDplugin ISO;
|
||||
extern CDVDplugin NODISC;
|
||||
|
|
|
@ -0,0 +1,534 @@
|
|||
/* Pcsx2 - Pc Ps2 Emulator
|
||||
* Copyright (C) 2002-2009 Pcsx2 Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include "PrecompiledHeader.h"
|
||||
|
||||
// TODO: fix this for linux! (hardcoded as _WIN32 only)
|
||||
#define ENABLE_TIMESTAMPS
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include <ctype.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "IopCommon.h"
|
||||
#include "IsoFStools.h"
|
||||
#include "IsoFSdrv.h"
|
||||
#include "CDVDisoReader.h"
|
||||
|
||||
static int diskTypeCached=-1;
|
||||
|
||||
int lastReadSize;
|
||||
static int plsn=0; // This never gets set, so it's always 0.
|
||||
|
||||
static isoFile *blockDumpFile;
|
||||
|
||||
/////////////////////////////////////////////////
|
||||
//
|
||||
// Disk Type detection stuff (from cdvdGigaherz)
|
||||
//
|
||||
|
||||
int CheckDiskTypeFS(int baseType)
|
||||
{
|
||||
int f;
|
||||
char buffer[256];//if a file is longer...it should be shorter :D
|
||||
char *pos;
|
||||
static struct TocEntry tocEntry;
|
||||
|
||||
IsoFS_init();
|
||||
|
||||
// check if the file exists
|
||||
if ((f=IsoFS_open("SYSTEM.CNF;1", 1)) >= 0)
|
||||
{
|
||||
int size = IsoFS_read(f, buffer, 256);
|
||||
IsoFS_close(f);
|
||||
|
||||
buffer[size]='\0';
|
||||
|
||||
pos = strstr(buffer, "BOOT2");
|
||||
if (pos == NULL)
|
||||
{
|
||||
pos = strstr(buffer, "BOOT");
|
||||
if (pos == NULL) return CDVD_TYPE_ILLEGAL;
|
||||
return CDVD_TYPE_PSCD;
|
||||
}
|
||||
return (baseType==CDVD_TYPE_DETCTCD) ? CDVD_TYPE_PS2CD : CDVD_TYPE_PS2DVD;
|
||||
}
|
||||
|
||||
if (IsoFS_findFile("PSX.EXE;1", &tocEntry) == TRUE)
|
||||
{
|
||||
return CDVD_TYPE_PSCD;
|
||||
}
|
||||
|
||||
if (IsoFS_findFile("VIDEO_TS/VIDEO_TS.IFO;1", &tocEntry) == TRUE)
|
||||
{
|
||||
return CDVD_TYPE_DVDV;
|
||||
}
|
||||
|
||||
return CDVD_TYPE_ILLEGAL; // << Only for discs which aren't ps2 at all.
|
||||
}
|
||||
|
||||
static char bleh[2352];
|
||||
|
||||
int FindDiskType(int mType)
|
||||
{
|
||||
int dataTracks = 0;
|
||||
int audioTracks = 0;
|
||||
|
||||
int iCDType = mType;
|
||||
|
||||
cdvdTN tn;
|
||||
|
||||
CDVD.getTN(&tn);
|
||||
|
||||
if (tn.strack != tn.etrack) // multitrack == CD.
|
||||
{
|
||||
iCDType = CDVD_TYPE_DETCTCD;
|
||||
}
|
||||
else if (mType < 0)
|
||||
{
|
||||
cdvdTD td;
|
||||
CDVD.getTD(0,&td);
|
||||
if (td.lsn > 452849)
|
||||
{
|
||||
iCDType = CDVD_TYPE_DETCTDVDS;
|
||||
}
|
||||
else if (DoCDVDreadSector((u8*)bleh,16,CDVD_MODE_2048) == 0)
|
||||
{
|
||||
struct cdVolDesc* volDesc=(struct cdVolDesc *)bleh;
|
||||
if (volDesc)
|
||||
{
|
||||
if(volDesc->rootToc.tocSize==2048)
|
||||
iCDType = CDVD_TYPE_DETCTCD;
|
||||
else
|
||||
iCDType = CDVD_TYPE_DETCTDVDS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (iCDType == CDVD_TYPE_DETCTDVDS)
|
||||
{
|
||||
s32 dlt = 0;
|
||||
u32 l1s = 0;
|
||||
|
||||
if(CDVD.getDualInfo(&dlt,&l1s)==0)
|
||||
{
|
||||
if (dlt > 0) iCDType = CDVD_TYPE_DETCTDVDD;
|
||||
}
|
||||
}
|
||||
|
||||
switch(iCDType)
|
||||
{
|
||||
case CDVD_TYPE_DETCTCD:
|
||||
Console::Status(" * CDVD Disk Open: CD, %d tracks (%d to %d):", params tn.etrack-tn.strack+1,tn.strack,tn.etrack);
|
||||
break;
|
||||
|
||||
case CDVD_TYPE_DETCTDVDS:
|
||||
Console::Status(" * CDVD Disk Open: DVD, Single layer or unknown:");
|
||||
break;
|
||||
|
||||
case CDVD_TYPE_DETCTDVDD:
|
||||
Console::Status(" * CDVD Disk Open: DVD, Double layer:");
|
||||
break;
|
||||
}
|
||||
|
||||
audioTracks = dataTracks = 0;
|
||||
for(int i = tn.strack; i <= tn.etrack; i++)
|
||||
{
|
||||
cdvdTD td,td2;
|
||||
CDVD.getTD(i,&td);
|
||||
|
||||
if (tn.etrack > i)
|
||||
CDVD.getTD(i+1,&td2);
|
||||
else
|
||||
CDVD.getTD(0,&td2);
|
||||
|
||||
int tlength = td2.lsn - td.lsn;
|
||||
|
||||
if (td.type == CDVD_AUDIO_TRACK)
|
||||
{
|
||||
audioTracks++;
|
||||
Console::Status(" * * Track %d: Audio (%d sectors)", params i,tlength);
|
||||
}
|
||||
else
|
||||
{
|
||||
dataTracks++;
|
||||
Console::Status(" * * Track %d: Data (Mode %d) (%d sectors)", params i,((td.type==CDVD_MODE1_TRACK)?1:2),tlength);
|
||||
}
|
||||
}
|
||||
|
||||
if (dataTracks > 0)
|
||||
{
|
||||
iCDType=CheckDiskTypeFS(iCDType);
|
||||
}
|
||||
|
||||
if (audioTracks > 0)
|
||||
{
|
||||
switch (iCDType)
|
||||
{
|
||||
case CDVD_TYPE_PS2CD:
|
||||
iCDType=CDVD_TYPE_PS2CDDA;
|
||||
break;
|
||||
case CDVD_TYPE_PSCD:
|
||||
iCDType=CDVD_TYPE_PSCDDA;
|
||||
break;
|
||||
default:
|
||||
iCDType=CDVD_TYPE_CDDA;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return iCDType;
|
||||
}
|
||||
|
||||
void DetectDiskType()
|
||||
{
|
||||
if (CDVD.getTrayStatus() == CDVD_TRAY_OPEN)
|
||||
{
|
||||
diskTypeCached = CDVD_TYPE_NODISC;
|
||||
return;
|
||||
}
|
||||
|
||||
int baseMediaType = CDVD.getDiskType();
|
||||
int mType = -1;
|
||||
|
||||
switch(baseMediaType) // Paranoid mode: do not trust the plugin's detection system to work correctly.
|
||||
{
|
||||
case CDVD_TYPE_CDDA:
|
||||
case CDVD_TYPE_PSCD:
|
||||
case CDVD_TYPE_PS2CD:
|
||||
case CDVD_TYPE_PSCDDA:
|
||||
case CDVD_TYPE_PS2CDDA:
|
||||
mType = CDVD_TYPE_DETCTCD;
|
||||
break;
|
||||
|
||||
case CDVD_TYPE_DVDV:
|
||||
case CDVD_TYPE_PS2DVD:
|
||||
mType = CDVD_TYPE_DETCTDVDS;
|
||||
break;
|
||||
|
||||
case CDVD_TYPE_DETCTDVDS:
|
||||
case CDVD_TYPE_DETCTDVDD:
|
||||
case CDVD_TYPE_DETCTCD:
|
||||
mType = baseMediaType;
|
||||
break;
|
||||
|
||||
case CDVD_TYPE_NODISC:
|
||||
diskTypeCached = CDVD_TYPE_NODISC;
|
||||
return;
|
||||
}
|
||||
|
||||
diskTypeCached = FindDiskType(mType);
|
||||
}
|
||||
|
||||
//
|
||||
/////////////////////////////////////////////////
|
||||
|
||||
s32 DoCDVDinit()
|
||||
{
|
||||
diskTypeCached = -1;
|
||||
|
||||
if(CDVD.initCount) *CDVD.initCount++; // used to handle the case where the plugin was inited at boot, but then iso takes over
|
||||
return CDVD.init();
|
||||
}
|
||||
|
||||
void DoCDVDshutdown()
|
||||
{
|
||||
if(CDVD.initCount) *CDVD.initCount--;
|
||||
CDVD.shutdown();
|
||||
}
|
||||
|
||||
s32 DoCDVDopen(const char* pTitleFilename)
|
||||
{
|
||||
int ret = CDVD.open(pTitleFilename);
|
||||
int cdtype = DoCDVDdetectDiskType();
|
||||
|
||||
if((Config.Blockdump)&&(cdtype != CDVD_TYPE_NODISC))
|
||||
{
|
||||
char fname_only[g_MaxPath];
|
||||
|
||||
if(CDVD.init == ISO.init)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
char fname[MAX_PATH], ext[g_MaxPath];
|
||||
_splitpath(isoFileName, NULL, NULL, fname, ext);
|
||||
_makepath(fname_only, NULL, NULL, fname, NULL);
|
||||
#else
|
||||
getcwd(fname_only, ArraySize(fname_only)); // Base it out of the current directory for now.
|
||||
strcat(fname_only, Path::GetFilenameWithoutExt(isoFileName).c_str());
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(fname_only, "Untitled");
|
||||
}
|
||||
|
||||
#ifdef ENABLE_TIMESTAMPS
|
||||
#ifdef _WIN32
|
||||
SYSTEMTIME time;
|
||||
GetLocalTime(&time);
|
||||
|
||||
sprintf(
|
||||
fname_only+strlen(fname_only),
|
||||
" (%04d-%02d-%02d %02d-%02d-%02d).dump",
|
||||
time.wYear, time.wMonth, time.wDay,
|
||||
time.wHour, time.wMinute, time.wSecond);
|
||||
#else
|
||||
time_t rawtime;
|
||||
struct tm * timeinfo;
|
||||
|
||||
time(&rawtime);
|
||||
timeinfo = localtime(&rawtime);
|
||||
|
||||
sprintf(
|
||||
fname_only+strlen(fname_only),
|
||||
" (%04d-%02d-%02d %02d-%02d-%02d).dump",
|
||||
timeinfo->tm_year + 1900, timeinfo->tm_mon, timeinfo->tm_mday,
|
||||
timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec);
|
||||
#endif
|
||||
#else
|
||||
strcat(fname_only, ".dump");
|
||||
#endif
|
||||
cdvdTD td;
|
||||
CDVD.getTD(0, &td);
|
||||
|
||||
int blockofs = 0;
|
||||
int blocksize = 0;
|
||||
int blocks = td.lsn;
|
||||
|
||||
switch(cdtype)
|
||||
{
|
||||
case CDVD_TYPE_PS2DVD:
|
||||
case CDVD_TYPE_DVDV:
|
||||
case CDVD_TYPE_DETCTDVDS:
|
||||
case CDVD_TYPE_DETCTDVDD:
|
||||
blockofs = 24;
|
||||
blocksize = 2048;
|
||||
break;
|
||||
|
||||
default:
|
||||
blockofs = 0;
|
||||
blocksize= 2352;
|
||||
break;
|
||||
}
|
||||
|
||||
blockDumpFile = isoCreate(fname_only, ISOFLAGS_BLOCKDUMP);
|
||||
if (blockDumpFile) isoSetFormat(blockDumpFile, blockofs, blocksize, blocks);
|
||||
}
|
||||
else
|
||||
{
|
||||
blockDumpFile = NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void DoCDVDclose()
|
||||
{
|
||||
if(blockDumpFile) isoClose(blockDumpFile);
|
||||
CDVD.close();
|
||||
}
|
||||
|
||||
s32 DoCDVDreadSector(u8* buffer, u32 lsn, int mode)
|
||||
{
|
||||
int ret = CDVD.readSector(buffer,lsn,mode);
|
||||
|
||||
if(ret==0)
|
||||
{
|
||||
if (blockDumpFile != NULL)
|
||||
{
|
||||
isoWriteBlock(blockDumpFile, buffer, plsn);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
s32 DoCDVDreadTrack(u32 lsn, int mode)
|
||||
{
|
||||
// TEMP: until all the plugins use the new CDVDgetBuffer style
|
||||
switch (mode)
|
||||
{
|
||||
case CDVD_MODE_2352:
|
||||
lastReadSize = 2352;
|
||||
break;
|
||||
case CDVD_MODE_2340:
|
||||
lastReadSize = 2340;
|
||||
break;
|
||||
case CDVD_MODE_2328:
|
||||
lastReadSize = 2328;
|
||||
break;
|
||||
case CDVD_MODE_2048:
|
||||
lastReadSize = 2048;
|
||||
break;
|
||||
}
|
||||
|
||||
//DevCon::Notice("CDVD readTrack(lsn=%d,mode=%d)",params lsn, lastReadSize);
|
||||
|
||||
return CDVD.readTrack(lsn,mode);
|
||||
}
|
||||
|
||||
// return can be NULL (for async modes)
|
||||
|
||||
s32 DoCDVDgetBuffer(u8* buffer)
|
||||
{
|
||||
int ret = CDVD.getBuffer2(buffer);
|
||||
|
||||
if (ret == 0)
|
||||
{
|
||||
if (blockDumpFile != NULL)
|
||||
{
|
||||
isoWriteBlock(blockDumpFile, buffer, plsn);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
s32 DoCDVDdetectDiskType()
|
||||
{
|
||||
if(diskTypeCached<0) DetectDiskType();
|
||||
|
||||
return diskTypeCached;
|
||||
}
|
||||
|
||||
void DoCDVDresetDiskTypeCache()
|
||||
{
|
||||
diskTypeCached = -1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
//
|
||||
// CDVD null interface for Run BIOS menu
|
||||
|
||||
|
||||
s32 CALLBACK NODISCinit()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 CALLBACK NODISCopen(const char* pTitle)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CALLBACK NODISCclose()
|
||||
{
|
||||
}
|
||||
|
||||
void CALLBACK NODISCshutdown()
|
||||
{
|
||||
}
|
||||
|
||||
s32 CALLBACK NODISCreadTrack(u32 lsn, int mode)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
// return can be NULL (for async modes)
|
||||
u8* CALLBACK NODISCgetBuffer()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
s32 CALLBACK NODISCreadSubQ(u32 lsn, cdvdSubQ* subq)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
s32 CALLBACK NODISCgetTN(cdvdTN *Buffer)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
s32 CALLBACK NODISCgetTD(u8 Track, cdvdTD *Buffer)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
s32 CALLBACK NODISCgetTOC(void* toc)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
s32 CALLBACK NODISCgetDiskType()
|
||||
{
|
||||
return CDVD_TYPE_NODISC;
|
||||
}
|
||||
|
||||
s32 CALLBACK NODISCgetTrayStatus()
|
||||
{
|
||||
return CDVD_TRAY_CLOSE;
|
||||
}
|
||||
|
||||
s32 CALLBACK NODISCdummyS32()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CALLBACK NODISCdummyVOID()
|
||||
{
|
||||
}
|
||||
|
||||
void CALLBACK NODISCnewDiskCB(void(CALLBACK*)())
|
||||
{
|
||||
}
|
||||
|
||||
s32 CALLBACK NODISCreadSector(u8* tempbuffer, u32 lsn, int mode)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
s32 CALLBACK NODISCgetBuffer2(u8* buffer)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
s32 CALLBACK NODISCgetDualInfo(s32* dualType, u32* _layer1start)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
CDVDplugin NODISC = {
|
||||
NODISCinit,
|
||||
NODISCopen,
|
||||
NODISCclose,
|
||||
NODISCshutdown,
|
||||
NODISCreadTrack,
|
||||
NODISCgetBuffer,
|
||||
NODISCreadSubQ,
|
||||
NODISCgetTN,
|
||||
NODISCgetTD,
|
||||
NODISCgetTOC,
|
||||
NODISCgetDiskType,
|
||||
NODISCgetTrayStatus,
|
||||
NODISCdummyS32,
|
||||
NODISCdummyS32,
|
||||
|
||||
NODISCdummyVOID,
|
||||
NODISCdummyS32,
|
||||
NODISCdummyVOID,
|
||||
NODISCnewDiskCB,
|
||||
|
||||
NODISCreadSector,
|
||||
NODISCgetBuffer2,
|
||||
NODISCgetDualInfo,
|
||||
|
||||
NULL
|
||||
};
|
|
@ -0,0 +1,34 @@
|
|||
/* Pcsx2 - Pc Ps2 Emulator
|
||||
* Copyright (C) 2002-2009 Pcsx2 Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef __CDVD_ACCESS_H__
|
||||
#define __CDVD_ACCESS_H__
|
||||
|
||||
extern s32 DoCDVDinit();
|
||||
extern s32 DoCDVDopen(const char* pTitleFilename);
|
||||
extern void DoCDVDclose();
|
||||
extern void DoCDVDshutdown();
|
||||
extern s32 DoCDVDreadSector(u8* buffer, u32 lsn, int mode);
|
||||
extern s32 DoCDVDreadTrack(u32 lsn, int mode);
|
||||
extern s32 DoCDVDgetBuffer(u8* buffer);
|
||||
extern s32 DoCDVDreadSubQ(u32 lsn, cdvdSubQ* subq);
|
||||
extern void DoCDVDnewDiskCB(void (*callback)());
|
||||
extern s32 DoCDVDdetectDiskType();
|
||||
extern void DoCDVDresetDiskTypeCache();
|
||||
|
||||
#endif /* __CDVD_H__ */
|
|
@ -0,0 +1,486 @@
|
|||
/* Pcsx2 - Pc Ps2 Emulator
|
||||
* Copyright (C) 2002-2009 Pcsx2 Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* Original code from libcdvd by Hiryu & Sjeep (C) 2002
|
||||
* Modified by Florin for PCSX2 emu
|
||||
* Fixed CdRead by linuzappz
|
||||
*/
|
||||
|
||||
#include "PrecompiledHeader.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "CDVDisoReader.h"
|
||||
|
||||
char isoFileName[g_MaxPath];
|
||||
|
||||
u8 *pbuffer;
|
||||
int cdtype;
|
||||
|
||||
static int psize;
|
||||
|
||||
isoFile *iso;
|
||||
|
||||
FILE *cdvdLog = NULL;
|
||||
|
||||
u8 cdbuffer[2352] = {0};
|
||||
|
||||
s32 msf_to_lba(u8 m, u8 s, u8 f)
|
||||
{
|
||||
u32 lsn;
|
||||
lsn = f;
|
||||
lsn += (s - 2) * 75;
|
||||
lsn += m * 75 * 60;
|
||||
return lsn;
|
||||
}
|
||||
|
||||
void lba_to_msf(s32 lba, u8* m, u8* s, u8* f)
|
||||
{
|
||||
lba += 150;
|
||||
*m = lba / (60 * 75);
|
||||
*s = (lba / 75) % 60;
|
||||
*f = lba % 75;
|
||||
}
|
||||
|
||||
//#define btoi(b) ((b)/16*10 + (b)%16) /* BCD to u_char */
|
||||
//#define itob(i) ((i)/10*16 + (i)%10) /* u_char to BCD */
|
||||
|
||||
|
||||
/*#ifdef PCSX2_DEBUG
|
||||
void __Log(char *fmt, ...)
|
||||
{
|
||||
va_list list;
|
||||
|
||||
if (cdvdLog == NULL) return;
|
||||
|
||||
va_start(list, fmt);
|
||||
vfprintf(cdvdLog, fmt, list);
|
||||
va_end(list);
|
||||
}
|
||||
#else
|
||||
#define __Log 0&&
|
||||
#endif*/
|
||||
|
||||
s32 CALLBACK ISOinit()
|
||||
{
|
||||
/*#ifdef PCSX2_DEBUG
|
||||
cdvdLog = fopen("logs/cdvdLog.txt", "w");
|
||||
if (cdvdLog == NULL)
|
||||
{
|
||||
cdvdLog = fopen("cdvdLog.txt", "w");
|
||||
if (cdvdLog == NULL)
|
||||
{
|
||||
Console::Error("Can't create cdvdLog.txt");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
setvbuf(cdvdLog, NULL, _IONBF, 0);*/
|
||||
CDVD_LOG("CDVDinit\n");
|
||||
/*#endif*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CALLBACK ISOshutdown()
|
||||
{
|
||||
/*#ifdef CDVD_LOG
|
||||
if (cdvdLog != NULL) fclose(cdvdLog);
|
||||
#endif*/
|
||||
}
|
||||
|
||||
s32 CALLBACK ISOopen(const char* pTitle)
|
||||
{
|
||||
//if (pTitle != NULL) strcpy(isoFileName, pTitle);
|
||||
|
||||
iso = isoOpen(isoFileName);
|
||||
if (iso == NULL)
|
||||
{
|
||||
Console::Error("Error loading %s\n", params isoFileName);
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (iso->type)
|
||||
{
|
||||
case ISOTYPE_DVD:
|
||||
cdtype = CDVD_TYPE_PS2DVD;
|
||||
break;
|
||||
case ISOTYPE_AUDIO:
|
||||
cdtype = CDVD_TYPE_CDDA;
|
||||
break;
|
||||
default:
|
||||
cdtype = CDVD_TYPE_PS2CD;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CALLBACK ISOclose()
|
||||
{
|
||||
isoClose(iso);
|
||||
}
|
||||
|
||||
s32 CALLBACK ISOreadSubQ(u32 lsn, cdvdSubQ* subq)
|
||||
{
|
||||
// fake it
|
||||
u8 min, sec, frm;
|
||||
subq->ctrl = 4;
|
||||
subq->mode = 1;
|
||||
subq->trackNum = itob(1);
|
||||
subq->trackIndex = itob(1);
|
||||
|
||||
lba_to_msf(lsn, &min, &sec, &frm);
|
||||
subq->trackM = itob(min);
|
||||
subq->trackS = itob(sec);
|
||||
subq->trackF = itob(frm);
|
||||
|
||||
subq->pad = 0;
|
||||
|
||||
lba_to_msf(lsn + (2*75), &min, &sec, &frm);
|
||||
subq->discM = itob(min);
|
||||
subq->discS = itob(sec);
|
||||
subq->discF = itob(frm);
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 CALLBACK ISOgetTN(cdvdTN *Buffer)
|
||||
{
|
||||
Buffer->strack = 1;
|
||||
Buffer->etrack = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 CALLBACK ISOgetTD(u8 Track, cdvdTD *Buffer)
|
||||
{
|
||||
if (Track == 0)
|
||||
{
|
||||
Buffer->lsn = iso->blocks;
|
||||
}
|
||||
else
|
||||
{
|
||||
Buffer->type = CDVD_MODE1_TRACK;
|
||||
Buffer->lsn = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static s32 layer1start = -1;
|
||||
|
||||
static void FindLayer1Start()
|
||||
{
|
||||
if ((layer1start == -1) && iso->blocks >= 2295104)
|
||||
{
|
||||
// search for it
|
||||
int off = iso->blockofs;
|
||||
u8 tempbuffer[2352];
|
||||
|
||||
Console::Status("CDVD ISO: searching for layer1...");
|
||||
//tempbuffer = (u8*)malloc(CD_FRAMESIZE_RAW);
|
||||
for (layer1start = (iso->blocks / 2 - 0x10) & ~0xf; layer1start < 0x200010; layer1start += 16)
|
||||
{
|
||||
isoReadBlock(iso, tempbuffer+off, layer1start);
|
||||
// CD001
|
||||
if ((tempbuffer[off+1] == 0x43) &&
|
||||
(tempbuffer[off+2] == 0x44) &&
|
||||
(tempbuffer[off+3] == 0x30) &&
|
||||
(tempbuffer[off+4] == 0x30) &&
|
||||
(tempbuffer[off+5] == 0x31)
|
||||
)
|
||||
break;
|
||||
}
|
||||
//free(tempbuffer);
|
||||
|
||||
if(layer1start == 0x200010)
|
||||
{
|
||||
Console::Status("Couldn't find second layer on dual layer... ignoring\n");
|
||||
layer1start=-2;
|
||||
}
|
||||
|
||||
if(layer1start>=0) Console::Status("found at 0x%8.8x\n", params layer1start);
|
||||
}
|
||||
}
|
||||
|
||||
s32 CALLBACK ISOgetDualInfo(s32* dualType, u32* _layer1start)
|
||||
{
|
||||
FindLayer1Start();
|
||||
|
||||
if(layer1start<0)
|
||||
{
|
||||
*dualType=0;
|
||||
*_layer1start = iso->blocks;
|
||||
}
|
||||
else
|
||||
{
|
||||
*dualType = 1;
|
||||
*_layer1start = layer1start;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
s32 CALLBACK ISOgetDiskType()
|
||||
{
|
||||
return cdtype;
|
||||
}
|
||||
|
||||
s32 CALLBACK ISOgetTOC(void* toc)
|
||||
{
|
||||
u8 type = ISOgetDiskType();
|
||||
u8* tocBuff = (u8*)toc;
|
||||
|
||||
//__Log("CDVDgetTOC\n");
|
||||
|
||||
if (type == CDVD_TYPE_DVDV || type == CDVD_TYPE_PS2DVD)
|
||||
{
|
||||
// get dvd structure format
|
||||
// scsi command 0x43
|
||||
memset(tocBuff, 0, 2048);
|
||||
|
||||
FindLayer1Start();
|
||||
|
||||
if (layer1start < 0)
|
||||
{
|
||||
// fake it
|
||||
tocBuff[ 0] = 0x04;
|
||||
tocBuff[ 1] = 0x02;
|
||||
tocBuff[ 2] = 0xF2;
|
||||
tocBuff[ 3] = 0x00;
|
||||
tocBuff[ 4] = 0x86;
|
||||
tocBuff[ 5] = 0x72;
|
||||
|
||||
tocBuff[16] = 0x00;
|
||||
tocBuff[17] = 0x03;
|
||||
tocBuff[18] = 0x00;
|
||||
tocBuff[19] = 0x00;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// dual sided
|
||||
tocBuff[ 0] = 0x24;
|
||||
tocBuff[ 1] = 0x02;
|
||||
tocBuff[ 2] = 0xF2;
|
||||
tocBuff[ 3] = 0x00;
|
||||
tocBuff[ 4] = 0x41;
|
||||
tocBuff[ 5] = 0x95;
|
||||
|
||||
tocBuff[14] = 0x60; // dual sided, ptp
|
||||
|
||||
tocBuff[16] = 0x00;
|
||||
tocBuff[17] = 0x03;
|
||||
tocBuff[18] = 0x00;
|
||||
tocBuff[19] = 0x00;
|
||||
|
||||
s32 l1s = layer1start + 0x30000 - 1;
|
||||
tocBuff[20] = (l1s >> 24);
|
||||
tocBuff[21] = (l1s >> 16) & 0xff;
|
||||
tocBuff[22] = (l1s >> 8) & 0xff;
|
||||
tocBuff[23] = (l1s >> 0) & 0xff;
|
||||
}
|
||||
}
|
||||
else if ((type == CDVD_TYPE_CDDA) || (type == CDVD_TYPE_PS2CDDA) ||
|
||||
(type == CDVD_TYPE_PS2CD) || (type == CDVD_TYPE_PSCDDA) || (type == CDVD_TYPE_PSCD))
|
||||
{
|
||||
// cd toc
|
||||
// (could be replaced by 1 command that reads the full toc)
|
||||
u8 min, sec, frm;
|
||||
s32 i, err;
|
||||
cdvdTN diskInfo;
|
||||
cdvdTD trackInfo;
|
||||
memset(tocBuff, 0, 1024);
|
||||
if (ISOgetTN(&diskInfo) == -1)
|
||||
{
|
||||
diskInfo.etrack = 0;
|
||||
diskInfo.strack = 1;
|
||||
}
|
||||
if (ISOgetTD(0, &trackInfo) == -1) trackInfo.lsn = 0;
|
||||
|
||||
tocBuff[0] = 0x41;
|
||||
tocBuff[1] = 0x00;
|
||||
|
||||
//Number of FirstTrack
|
||||
tocBuff[2] = 0xA0;
|
||||
tocBuff[7] = itob(diskInfo.strack);
|
||||
|
||||
//Number of LastTrack
|
||||
tocBuff[12] = 0xA1;
|
||||
tocBuff[17] = itob(diskInfo.etrack);
|
||||
|
||||
//DiskLength
|
||||
lba_to_msf(trackInfo.lsn, &min, &sec, &frm);
|
||||
tocBuff[22] = 0xA2;
|
||||
tocBuff[27] = itob(min);
|
||||
tocBuff[28] = itob(sec);
|
||||
|
||||
for (i = diskInfo.strack; i <= diskInfo.etrack; i++)
|
||||
{
|
||||
err = ISOgetTD(i, &trackInfo);
|
||||
lba_to_msf(trackInfo.lsn, &min, &sec, &frm);
|
||||
tocBuff[i*10+30] = trackInfo.type;
|
||||
tocBuff[i*10+32] = err == -1 ? 0 : itob(i); //number
|
||||
tocBuff[i*10+37] = itob(min);
|
||||
tocBuff[i*10+38] = itob(sec);
|
||||
tocBuff[i*10+39] = itob(frm);
|
||||
}
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 CALLBACK ISOreadSector(u8* tempbuffer, u32 lsn, int mode)
|
||||
{
|
||||
int _lsn = lsn;
|
||||
|
||||
if (_lsn < 0) lsn = iso->blocks + _lsn;
|
||||
if (lsn > iso->blocks) return -1;
|
||||
|
||||
if(mode == CDVD_MODE_2352)
|
||||
{
|
||||
isoReadBlock(iso, tempbuffer, lsn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
isoReadBlock(iso, cdbuffer + iso->blockofs, lsn);
|
||||
|
||||
pbuffer = cdbuffer;
|
||||
switch (mode)
|
||||
{
|
||||
case CDVD_MODE_2352:
|
||||
psize = 2352;
|
||||
break;
|
||||
case CDVD_MODE_2340:
|
||||
pbuffer += 12;
|
||||
psize = 2340;
|
||||
break;
|
||||
case CDVD_MODE_2328:
|
||||
pbuffer += 24;
|
||||
psize = 2328;
|
||||
break;
|
||||
case CDVD_MODE_2048:
|
||||
pbuffer += 24;
|
||||
psize = 2048;
|
||||
break;
|
||||
}
|
||||
|
||||
memcpy_fast(tempbuffer,pbuffer,psize);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 CALLBACK ISOreadTrack(u32 lsn, int mode)
|
||||
{
|
||||
int _lsn = lsn;
|
||||
|
||||
if (_lsn < 0) lsn = iso->blocks + _lsn;
|
||||
if (lsn > iso->blocks) return -1;
|
||||
|
||||
isoReadBlock(iso, cdbuffer + iso->blockofs, lsn);
|
||||
|
||||
pbuffer = cdbuffer;
|
||||
switch (mode)
|
||||
{
|
||||
case CDVD_MODE_2352:
|
||||
psize = 2352;
|
||||
break;
|
||||
case CDVD_MODE_2340:
|
||||
pbuffer += 12;
|
||||
psize = 2340;
|
||||
break;
|
||||
case CDVD_MODE_2328:
|
||||
pbuffer += 24;
|
||||
psize = 2328;
|
||||
break;
|
||||
case CDVD_MODE_2048:
|
||||
pbuffer += 24;
|
||||
psize = 2048;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 CALLBACK ISOgetBuffer2(u8* buffer)
|
||||
{
|
||||
memcpy_fast(buffer,pbuffer,psize);
|
||||
return 0;
|
||||
}
|
||||
|
||||
u8* CALLBACK ISOgetBuffer()
|
||||
{
|
||||
return pbuffer;
|
||||
}
|
||||
|
||||
s32 CALLBACK ISOgetTrayStatus()
|
||||
{
|
||||
return CDVD_TRAY_CLOSE;
|
||||
}
|
||||
|
||||
s32 CALLBACK ISOctrlTrayOpen()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
s32 CALLBACK ISOctrlTrayClose()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 CALLBACK ISOdummyS32()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CALLBACK ISOdummyVOID()
|
||||
{
|
||||
}
|
||||
|
||||
void CALLBACK ISOnewDiskCB(void(CALLBACK*)())
|
||||
{
|
||||
}
|
||||
|
||||
CDVDplugin ISO = {
|
||||
ISOinit,
|
||||
ISOopen,
|
||||
ISOclose,
|
||||
ISOshutdown,
|
||||
ISOreadTrack,
|
||||
ISOgetBuffer, // emu shouldn't use this one.
|
||||
ISOreadSubQ,
|
||||
ISOgetTN,
|
||||
ISOgetTD,
|
||||
ISOgetTOC,
|
||||
ISOgetDiskType,
|
||||
ISOdummyS32,
|
||||
ISOdummyS32,
|
||||
ISOdummyS32,
|
||||
|
||||
ISOdummyVOID,
|
||||
ISOdummyS32,
|
||||
ISOdummyVOID,
|
||||
ISOnewDiskCB,
|
||||
|
||||
ISOreadSector,
|
||||
ISOgetBuffer2,
|
||||
ISOgetDualInfo,
|
||||
|
||||
NULL
|
||||
};
|
|
@ -0,0 +1,48 @@
|
|||
/* Pcsx2 - Pc Ps2 Emulator
|
||||
* Copyright (C) 2002-2009 Pcsx2 Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef __CDVD_ISO_READER_H__
|
||||
#define __CDVD_ISO_READER_H__
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4018)
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "IopCommon.h"
|
||||
#include "IsoFStools.h"
|
||||
#include "IsoFileFormats.h"
|
||||
|
||||
//#define CDVD_LOG __Log
|
||||
|
||||
//#ifndef MAX_PATH
|
||||
//#define MAX_PATH 255
|
||||
//#endif
|
||||
|
||||
//extern FILE *cdvdLog;
|
||||
|
||||
//void __Log(char *fmt, ...);
|
||||
|
||||
//#define itob(i) ((i)/10*16 + (i)%10) /* u_char to BCD */
|
||||
//#define btoi(b) ((b)/16*10 + (b)%16) /* BCD to u_char */
|
||||
|
||||
extern char isoFileName[g_MaxPath];
|
||||
extern isoFile *iso;
|
||||
|
||||
#endif
|
|
@ -1,171 +0,0 @@
|
|||
/* Pcsx2 - Pc Ps2 Emulator
|
||||
* Copyright (C) 2002-2008 Pcsx2 Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
/*
|
||||
* Original code from libcdvd by Hiryu & Sjeep (C) 2002
|
||||
* Linux kernel headers
|
||||
* Modified by Florin for PCSX2 emu
|
||||
*/
|
||||
|
||||
#ifndef _CDVDLIB_H
|
||||
#define _CDVDLIB_H
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
// Macros for READ Data pattan
|
||||
#define CdSecS2048 0 // sector size 2048
|
||||
#define CdSecS2328 1 // sector size 2328
|
||||
#define CdSecS2340 2 // sector size 2340
|
||||
|
||||
//#define CD_FRAMESIZE_RAW1 (CD_FRAMESIZE_RAW-CD_SYNC_SIZE) /*2340*/
|
||||
//#define CD_FRAMESIZE_RAW0 (CD_FRAMESIZE_RAW-CD_SYNC_SIZE-CD_HEAD_SIZE) /*2336*/
|
||||
//#define CD_HEAD_SIZE 4 /* header (address) bytes per raw data frame */
|
||||
//#define CD_SUBHEAD_SIZE 8 /* subheader bytes per raw XA data frame */
|
||||
//#define CD_XA_HEAD (CD_HEAD_SIZE+CD_SUBHEAD_SIZE) /* "before data" part of raw XA frame */
|
||||
|
||||
/*
|
||||
* A CD-ROM physical sector size is 2048, 2052, 2056, 2324, 2332, 2336,
|
||||
* 2340, or 2352 bytes long.
|
||||
* Sector types of the standard CD-ROM data formats:
|
||||
*
|
||||
* format sector type user data size (bytes)
|
||||
* -----------------------------------------------------------------------------
|
||||
* 1 (Red Book) CD-DA 2352 (CD_FRAMESIZE_RAW)
|
||||
* 2 (Yellow Book) Mode1 Form1 2048 (CD_FRAMESIZE)
|
||||
* 3 (Yellow Book) Mode1 Form2 2336 (CD_FRAMESIZE_RAW0)
|
||||
* 4 (Green Book) Mode2 Form1 2048 (CD_FRAMESIZE)
|
||||
* 5 (Green Book) Mode2 Form2 2328 (2324+4 spare bytes)
|
||||
*
|
||||
*
|
||||
* The layout of the standard CD-ROM data formats:
|
||||
* -----------------------------------------------------------------------------
|
||||
* - audio (red): | audio_sample_bytes |
|
||||
* | 2352 |
|
||||
*
|
||||
* - data (yellow, mode1): | sync - head - data - EDC - zero - ECC |
|
||||
* | 12 - 4 - 2048 - 4 - 8 - 276 |
|
||||
*
|
||||
* - data (yellow, mode2): | sync - head - data |
|
||||
* | 12 - 4 - 2336 |
|
||||
*
|
||||
* - XA data (green, mode2 form1): | sync - head - sub - data - EDC - ECC |
|
||||
* | 12 - 4 - 8 - 2048 - 4 - 276 |
|
||||
*
|
||||
* - XA data (green, mode2 form2): | sync - head - sub - data - Spare |
|
||||
* | 12 - 4 - 8 - 2324 - 4 |
|
||||
*
|
||||
*/
|
||||
|
||||
// Macros for Spindle control
|
||||
#define CdSpinMax 0
|
||||
#define CdSpinNom 1 // Starts reading data at maximum rotational velocity and if a read error occurs, the rotational velocity is reduced.
|
||||
#define CdSpinStm 0 // Recommended stream rotation speed.
|
||||
|
||||
// Macros for TrayReq
|
||||
#define CdTrayOpen 0
|
||||
#define CdTrayClose 1
|
||||
#define CdTrayCheck 2
|
||||
|
||||
/*
|
||||
* Macros for sceCdGetDiskType() //comments translated from japanese;)
|
||||
*/
|
||||
|
||||
// These are already declared with different names in PS2Edefs.h. And aren't used.
|
||||
#define SCECdIllgalMedia 0xff // ILIMEDIA (Illegal Media) A non-PS / non-PS2 Disc.
|
||||
#define SCECdDVDV 0xfe // DVDV (DVD Video) A non-PS / non-PS2 Disc, but a DVD Video Disc
|
||||
#define SCECdCDDA 0xfd // CDDA (CD DA) A non-PS / non-PS2 Disc that include a DA track
|
||||
#define SCECdPS2DVD 0x14 // PS2DVD PS2 consumer DVD.
|
||||
#define SCECdPS2CDDA 0x13 // PS2CDDA PS2 consumer CD that includes a DA track
|
||||
#define SCECdPS2CD 0x12 // PS2CD PS2 consumer CD that does not include a DA track
|
||||
#define SCECdPSCDDA 0x11 // PSCDDA PS CD that includes a DA track
|
||||
#define SCECdPSCD 0x10 // PSCD PS CD that does not include a DA track
|
||||
#define SCECdDETCT 0x01 // DETCT (Detecting) Disc distinction action
|
||||
#define SCECdNODISC 0x00 // NODISC (No disc) No disc entered
|
||||
|
||||
/*
|
||||
* Media mode
|
||||
*/
|
||||
#define SCECdCD 1
|
||||
#define SCECdDVD 2
|
||||
|
||||
typedef struct {
|
||||
u8 stat; // 0: normal. Any other: error
|
||||
u8 second; // second (BCD value)
|
||||
u8 minute; // minute (BCD value)
|
||||
u8 hour; // hour (BCD value)
|
||||
u8 week; // week (BCD value)
|
||||
u8 day; // day (BCD value)
|
||||
u8 month; // month (BCD value)
|
||||
u8 year; // year (BCD value)
|
||||
} CdCLOCK;
|
||||
|
||||
typedef struct {
|
||||
u32 lsn; // Logical sector number of file
|
||||
u32 size; // File size (in bytes)
|
||||
char name[16]; // Filename
|
||||
u8 date[8]; // 1th: Seconds
|
||||
// 2th: Minutes
|
||||
// 3th: Hours
|
||||
// 4th: Date
|
||||
// 5th: Month
|
||||
// 6th 7th: Year (4 digits)
|
||||
} CdlFILE;
|
||||
|
||||
typedef struct {
|
||||
u8 minute; // Minutes
|
||||
u8 second; // Seconds
|
||||
u8 sector; // Sector
|
||||
u8 track; // Track number
|
||||
} CdlLOCCD;
|
||||
|
||||
typedef struct {
|
||||
u8 trycount; // Read try count (No. of error retries + 1) (0 - 255)
|
||||
u8 spindlctrl; // SCECdSpinStm: Recommended stream rotation speed.
|
||||
// SCECdSpinNom: Starts reading data at maximum rotational velocity and if a read error occurs, the rotational velocity is reduced.
|
||||
u8 datapattern; // SCECdSecS2048: Data size 2048 bytes
|
||||
// SCECdSecS2328: 2328 bytes
|
||||
// SCECdSecS2340: 2340 bytes
|
||||
u8 pad; // Padding data produced by alignment.
|
||||
} CdRMode;
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma pack(1)
|
||||
#endif
|
||||
|
||||
struct TocEntry
|
||||
{
|
||||
u32 fileLBA;
|
||||
u32 fileSize;
|
||||
u8 fileProperties;
|
||||
u8 padding1[3];
|
||||
char filename[128+1];
|
||||
u8 date[7];
|
||||
#if defined(_MSC_VER)
|
||||
};
|
||||
#else
|
||||
} __attribute__((packed));
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
int CDVD_findfile(const char* fname, struct TocEntry* tocEntry);
|
||||
int CdRead(u32 lsn, u32 sectors, void *buf, CdRMode *mode);
|
||||
int DvdRead(u32 lsn, u32 sectors, void *buf, CdRMode *mode);
|
||||
|
||||
#endif // _CDVDLIB_H
|
|
@ -141,7 +141,7 @@ static void ReadTrack() {
|
|||
cdr.Prev[2] = itob(cdr.SetSector[2]);
|
||||
|
||||
CDR_LOG("KEY *** %x:%x:%x", cdr.Prev[0], cdr.Prev[1], cdr.Prev[2]);
|
||||
cdr.RErr = CDVDreadTrack(MSFtoLSN(cdr.SetSector), CDVD_MODE_2352);
|
||||
cdr.RErr = DoCDVDreadTrack(MSFtoLSN(cdr.SetSector), CDVD_MODE_2340);
|
||||
}
|
||||
|
||||
// cdr.Stat:
|
||||
|
@ -332,7 +332,7 @@ void cdrInterrupt() {
|
|||
SetResultSize(3);
|
||||
cdr.StatP|= 0x2;
|
||||
cdr.Result[0] = cdr.StatP;
|
||||
if (CDVDgetTN(&cdr.ResultTN) == -1) {
|
||||
if (CDVD.getTN(&cdr.ResultTN) == -1) {
|
||||
cdr.Stat = DiskError;
|
||||
cdr.Result[0]|= 0x01;
|
||||
} else {
|
||||
|
@ -347,7 +347,7 @@ void cdrInterrupt() {
|
|||
cdr.Track = btoi(cdr.Param[0]);
|
||||
SetResultSize(4);
|
||||
cdr.StatP|= 0x2;
|
||||
if (CDVDgetTD(cdr.Track, &trackInfo) == -1) {
|
||||
if (CDVD.getTD(cdr.Track, &trackInfo) == -1) {
|
||||
cdr.Stat = DiskError;
|
||||
cdr.Result[0]|= 0x01;
|
||||
} else {
|
||||
|
@ -496,7 +496,6 @@ void cdrInterrupt() {
|
|||
}
|
||||
|
||||
void cdrReadInterrupt() {
|
||||
u8 *buf;
|
||||
|
||||
if (!cdr.Reading)
|
||||
return;
|
||||
|
@ -514,10 +513,9 @@ void cdrReadInterrupt() {
|
|||
cdr.Result[0] = cdr.StatP;
|
||||
|
||||
Console::Status("Reading From CDR");
|
||||
buf = CDVDgetBuffer();
|
||||
if (buf == NULL) cdr.RErr = -1;
|
||||
|
||||
if (cdr.RErr == -1) {
|
||||
cdr.RErr = DoCDVDgetBuffer(cdr.Transfer);
|
||||
if (cdr.RErr == -1)
|
||||
{
|
||||
CDR_LOG(" err\n");
|
||||
memzero_ptr<2340>(cdr.Transfer);
|
||||
cdr.Stat = DiskError;
|
||||
|
@ -526,7 +524,6 @@ void cdrReadInterrupt() {
|
|||
CDREAD_INT((cdr.Mode & 0x80) ? (cdReadTime / 2) : cdReadTime);
|
||||
return;
|
||||
}
|
||||
memcpy_fast(cdr.Transfer, buf+12, 2340);
|
||||
cdr.Stat = DataReady;
|
||||
|
||||
CDR_LOG(" %x:%x:%x", cdr.Transfer[0], cdr.Transfer[1], cdr.Transfer[2]);
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
/* Pcsx2 - Pc Ps2 Emulator
|
||||
* Copyright (C) 2002-2008 Pcsx2 Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
/*
|
||||
* Original code from libcdvd by Hiryu & Sjeep (C) 2002
|
||||
* Linux kernel headers
|
||||
* Modified by Florin for PCSX2 emu
|
||||
*/
|
||||
|
||||
#ifndef _ISOFSCDVD_H
|
||||
#define _ISOFSCDVD_H
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma pack(1)
|
||||
#endif
|
||||
|
||||
struct TocEntry
|
||||
{
|
||||
u32 fileLBA;
|
||||
u32 fileSize;
|
||||
u8 fileProperties;
|
||||
u8 padding1[3];
|
||||
char filename[128+1];
|
||||
u8 date[7];
|
||||
#if defined(_MSC_VER)
|
||||
};
|
||||
#else
|
||||
} __attribute__((packed));
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
int IsoFS_findFile(const char* fname, struct TocEntry* tocEntry);
|
||||
int IsoFS_readSectors(u32 lsn, u32 sectors, void *buf);
|
||||
|
||||
#endif // _ISOFSCDVD_H
|
|
@ -15,6 +15,7 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* Original code from libcdvd by Hiryu & Sjeep (C) 2002
|
||||
* Modified by Florin for PCSX2 emu
|
||||
|
@ -22,10 +23,8 @@
|
|||
|
||||
#include "PrecompiledHeader.h"
|
||||
|
||||
#include "CDVDiso.h"
|
||||
#include "CDVDisodrv.h"
|
||||
|
||||
CdRMode cdReadMode;
|
||||
#include "IsoFStools.h"
|
||||
#include "IsoFSdrv.h"
|
||||
|
||||
struct fdtable{
|
||||
//int fd;
|
||||
|
@ -46,22 +45,12 @@ static int inited=FALSE;
|
|||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// CDVDFS_init
|
||||
// called by 80000592 sceCdInit()
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
void CDVDFS_init(){
|
||||
void IsoFS_init()
|
||||
{
|
||||
if (inited) return; //might change in the future as a param; forceInit/Reset
|
||||
|
||||
if (inited) return;//might change in the future as a param; forceInit/Reset
|
||||
|
||||
RPC_LOG("[CDVDisodrv:init] CDVD Filesystem v1.00");
|
||||
RPC_LOG("[CDVDisodrv ] \tby A.Lee (aka Hiryu) & Nicholas Van Veen (aka Sjeep)");
|
||||
RPC_LOG("[CDVDisodrv ] Initializing '%s' file driver.", "cdfs");
|
||||
|
||||
//CdInit(0); already called by plugin loading system ;)
|
||||
|
||||
cdReadMode.trycount = 0;
|
||||
cdReadMode.spindlctrl = CdSpinStm;
|
||||
cdReadMode.datapattern = CdSecS2048; //isofs driver only needs
|
||||
//2KB sectors
|
||||
ISOFS_LOG("[IsoFSdrv:init] Initializing '%s' file driver.", "IsoFS");
|
||||
|
||||
memzero_obj( fd_table );
|
||||
memzero_obj( fd_used );
|
||||
|
@ -73,14 +62,13 @@ void CDVDFS_init(){
|
|||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// CDVDFS_open
|
||||
// called by 80000001 fileio_open for devices: "cdrom:", "cdrom0:"
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
int CDVDFS_open(const char *name, int mode){
|
||||
int IsoFS_open(const char *name, int mode){
|
||||
int j;
|
||||
static struct TocEntry tocEntry;
|
||||
|
||||
// check if the file exists
|
||||
if (CDVD_findfile(name, &tocEntry) != TRUE)
|
||||
if (IsoFS_findFile(name, &tocEntry) != TRUE)
|
||||
return -1;
|
||||
|
||||
if(mode != 1) return -2; //SCE_RDONLY
|
||||
|
@ -92,24 +80,23 @@ int CDVDFS_open(const char *name, int mode){
|
|||
fd_used[j] = 1;
|
||||
files_open++;
|
||||
|
||||
RPC_LOG("[CDVDisodrv:open] internal fd=%d", j);
|
||||
ISOFS_LOG("[IsoFSdrv:open] internal fd=%d", j);
|
||||
|
||||
fd_table[j].fileSize = tocEntry.fileSize;
|
||||
fd_table[j].LBA = tocEntry.fileLBA;
|
||||
fd_table[j].filePos = 0;
|
||||
|
||||
RPC_LOG("[CDVDisodrv ] tocEntry.fileSize = %d",tocEntry.fileSize);
|
||||
ISOFS_LOG("[IsoFSdrv:open] tocEntry.fileSize = %d",tocEntry.fileSize);
|
||||
return j;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// CDVDFS_lseek
|
||||
// called by 80000001 fileio_lseek for devices: "cdrom:", "cdrom0:"
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
int CDVDFS_lseek(int fd, int offset, int whence){
|
||||
int IsoFS_lseek(int fd, int offset, int whence){
|
||||
|
||||
if ((fd >= 16) || (fd_used[fd]==0)){
|
||||
RPC_LOG("[CDVDisodrv:lseek] ERROR: File does not appear to be open!");
|
||||
ISOFS_LOG("[IsoFSdrv:lseek] ERROR: File does not appear to be open!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -141,28 +128,27 @@ int CDVDFS_lseek(int fd, int offset, int whence){
|
|||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// CDVDFS_read
|
||||
// called by 80000001 fileio_read for devices: "cdrom:", "cdrom0:", "cdfs:"
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
int CDVDFS_read( int fd, char *buffer, int size ){
|
||||
// int start_sector;
|
||||
int IsoFS_read( int fd, char *buffer, int size )
|
||||
{
|
||||
int off_sector;
|
||||
// int num_sectors;
|
||||
|
||||
//static char local_buffer[2024*2048]; //4MB
|
||||
static char lb[2048]; //2KB
|
||||
|
||||
//Start, Aligned, End
|
||||
int ssector, asector, esector;
|
||||
int ssize=0, asize, esize;
|
||||
|
||||
if ((fd >= 16) || (fd_used[fd]==0)){
|
||||
RPC_LOG("[CDVDisodrv:read] ERROR: File does not appear to be open!");
|
||||
if ((fd >= 16) || (fd_used[fd]==0))
|
||||
{
|
||||
ISOFS_LOG("[IsoFSdrv:read] ERROR: File does not appear to be open!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// A few sanity checks
|
||||
if (fd_table[fd].filePos > fd_table[fd].fileSize){
|
||||
if (fd_table[fd].filePos > fd_table[fd].fileSize)
|
||||
{
|
||||
// We cant start reading from past the beginning of the file
|
||||
return 0; // File exists but we couldnt read anything from it
|
||||
return 0; // File exists but we couldn't read anything from it
|
||||
}
|
||||
|
||||
if ((fd_table[fd].filePos + size) > fd_table[fd].fileSize)
|
||||
|
@ -171,7 +157,8 @@ int CDVDFS_read( int fd, char *buffer, int size ){
|
|||
// Now work out where we want to start reading from
|
||||
asector = ssector = fd_table[fd].LBA + (fd_table[fd].filePos >> 11);
|
||||
off_sector = (fd_table[fd].filePos & 0x7FF);
|
||||
if (off_sector){
|
||||
if (off_sector)
|
||||
{
|
||||
ssize = std::min(2048 - off_sector, size);
|
||||
size -= ssize;
|
||||
asector++;
|
||||
|
@ -181,22 +168,27 @@ int CDVDFS_read( int fd, char *buffer, int size ){
|
|||
esector=asector + (asize >> 11);
|
||||
size += ssize;
|
||||
|
||||
RPC_LOG("[CDVDisodrv:read] read sectors 0x%08X to 0x%08X", ssector, esector-(esize==0));
|
||||
ISOFS_LOG("[IsoFSdrv:read] read sectors 0x%08X to 0x%08X", ssector, esector-(esize==0));
|
||||
|
||||
if (ssize){
|
||||
if (CdRead(ssector, 1, lb, &cdReadMode) != TRUE){
|
||||
RPC_LOG("[CDVDisodrv: ] Couldn't Read from file for some reason");
|
||||
if (ssize)
|
||||
{
|
||||
if (IsoFS_readSectors(ssector, 1, lb) != TRUE)
|
||||
{
|
||||
ISOFS_LOG("[IsoFSdrv:read] Couldn't Read from file for some reason");
|
||||
return 0;
|
||||
}
|
||||
memcpy_fast(buffer, lb + off_sector, ssize);
|
||||
}
|
||||
if (asize) if (CdRead(asector, asize >> 11, buffer+ssize, &cdReadMode) != TRUE){
|
||||
RPC_LOG("[CDVDisodrv: ] Couldn't Read from file for some reason");
|
||||
if (asize) if (IsoFS_readSectors(asector, asize >> 11, buffer+ssize) != TRUE)
|
||||
{
|
||||
ISOFS_LOG("[IsoFSdrv:read] Couldn't Read from file for some reason");
|
||||
return 0;
|
||||
}
|
||||
if (esize){
|
||||
if (CdRead(esector, 1, lb, &cdReadMode) != TRUE){
|
||||
RPC_LOG("[CDVDisodrv: ] Couldn't Read from file for some reason");
|
||||
if (esize)
|
||||
{
|
||||
if (IsoFS_readSectors(esector, 1, lb) != TRUE)
|
||||
{
|
||||
ISOFS_LOG("[IsoFSdrv:read] Couldn't Read from file for some reason");
|
||||
return 0;
|
||||
}
|
||||
memcpy_fast(buffer+ssize+asize, lb, esize);
|
||||
|
@ -207,13 +199,13 @@ int CDVDFS_read( int fd, char *buffer, int size ){
|
|||
off_sector = (fd_table[fd].filePos & 0x7FF);
|
||||
num_sectors = ((off_sector + size) >> 11) + 1;
|
||||
|
||||
RPC_LOG("[CDVDisodrv:read] read sectors 0x%08X to 0x%08X",start_sector,start_sector+num_sectors);
|
||||
RPC_LOG("[IsoFSdrv:read] read sectors 0x%08X to 0x%08X",start_sector,start_sector+num_sectors);
|
||||
|
||||
// Read the data (we only ever get 16KB max request at once)
|
||||
if (CdRead(start_sector, num_sectors, local_buffer, &cdReadMode) != TRUE){
|
||||
|
||||
//RPC_LOG("sector = %d, start sector = %d",sector,start_sector);
|
||||
RPC_LOG("[CDVDisodrv: ] Couldn't Read from file for some reason");
|
||||
RPC_LOG("[IsoFSdrv: ] Couldn't Read from file for some reason");
|
||||
return 0;
|
||||
}
|
||||
//CdSync(0); hm, a wait function maybe...
|
||||
|
@ -225,27 +217,18 @@ int CDVDFS_read( int fd, char *buffer, int size ){
|
|||
return (size);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// CDVDFS_write
|
||||
// called by 80000001 fileio_write for devices: "cdrom:", "cdrom0:"
|
||||
// hehe, this ain't a CD writing option :D
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
int CDVDFS_write( int fd, char * buffer, int size ){
|
||||
if(size == 0) return 0;
|
||||
else return -1;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// CDVDFS_close
|
||||
// called by 80000001 fileio_close for devices: "cdrom:", "cdrom0:"
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
int CDVDFS_close( int fd){
|
||||
int IsoFS_close( int fd)
|
||||
{
|
||||
|
||||
if ((fd >= 16) || (fd_used[fd]==0)){
|
||||
RPC_LOG("[CDVDisodrv:close] ERROR: File does not appear to be open!");
|
||||
if ((fd >= 16) || (fd_used[fd]==0))
|
||||
{
|
||||
ISOFS_LOG("[IsoFSdrv:close] ERROR: File does not appear to be open!");
|
||||
return -1;
|
||||
}
|
||||
RPC_LOG("[CDVDisodrv:close] internal fd %d", fd);
|
||||
ISOFS_LOG("[IsoFSdrv:close] internal fd %d", fd);
|
||||
fd_used[fd] = 0;
|
||||
files_open--;
|
||||
|
|
@ -20,19 +20,16 @@
|
|||
* Modified by Florin for PCSX2 emu
|
||||
*/
|
||||
|
||||
#ifndef __CDVDISODRV_H__
|
||||
#define __CDVDISODRV_H__
|
||||
#ifndef __ISOFSDRV_H__
|
||||
#define __ISOFSDRV_H__
|
||||
|
||||
#include "CDVDlib.h"
|
||||
|
||||
extern CdRMode cdReadMode;
|
||||
#include "IsoFScdvd.h"
|
||||
|
||||
/* Filing-system exported functions */
|
||||
void CDVDFS_init();
|
||||
int CDVDFS_open(const char *name, int mode);
|
||||
int CDVDFS_lseek(int fd, int offset, int whence);
|
||||
int CDVDFS_read( int fd, char * buffer, int size );
|
||||
int CDVDFS_write( int fd, char * buffer, int size );
|
||||
int CDVDFS_close( int fd);
|
||||
void IsoFS_init();
|
||||
int IsoFS_open(const char *name, int mode);
|
||||
int IsoFS_lseek(int fd, int offset, int whence);
|
||||
int IsoFS_read( int fd, char * buffer, int size );
|
||||
int IsoFS_close( int fd);
|
||||
|
||||
#endif//__CDVDISODRV_H__
|
||||
#endif//__ISOFSDRV_H__
|
|
@ -15,17 +15,20 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* Original code from libcdvd by Hiryu & Sjeep (C) 2002
|
||||
* Modified by Florin for PCSX2 emu
|
||||
* Fixed CdRead by linuzappz
|
||||
*/
|
||||
|
||||
#include "PrecompiledHeader.h"
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#include "CDVDiso.h"
|
||||
#include "CDVDisodrv.h"
|
||||
#include "IsoFStools.h"
|
||||
#include "IsoFSdrv.h"
|
||||
#include "CDVDaccess.h"
|
||||
|
||||
struct dir_toc_data
|
||||
{
|
||||
|
@ -168,79 +171,35 @@ int TocEntryCompare(char* filename, char* extensions){
|
|||
#define CD_FRAMES 75 /* frames per second */
|
||||
#define CD_MSF_OFFSET 150 /* MSF numbering offset of first frame */
|
||||
|
||||
int CdRead(u32 lsn, u32 sectors, void *buf, CdRMode *mode){
|
||||
int IsoFS_readSectors(u32 lsn, u32 sectors, void *buf)
|
||||
{
|
||||
u32 i;
|
||||
u8* buff;
|
||||
int rmode;
|
||||
|
||||
switch (mode->datapattern) {
|
||||
case CdSecS2048:
|
||||
rmode = CDVD_MODE_2048; break;
|
||||
case CdSecS2328:
|
||||
rmode = CDVD_MODE_2328; break;
|
||||
case CdSecS2340:
|
||||
rmode = CDVD_MODE_2340; break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i=0; i<sectors; i++){
|
||||
if (CDVDreadTrack(lsn+i, rmode)==-1)
|
||||
return 0;
|
||||
buff = CDVDgetBuffer();
|
||||
if (buff==NULL) return 0;
|
||||
switch (mode->datapattern){
|
||||
case CdSecS2048:
|
||||
memcpy_fast((void*)((uptr)buf+2048*i), buff, 2048);break;//only data
|
||||
case CdSecS2328:
|
||||
memcpy_fast((void*)((uptr)buf+2328*i), buff, 2328);break;//without sync & head & sub
|
||||
case CdSecS2340:
|
||||
memcpy_fast((void*)((uptr)buf+2340*i), buff, 2340);break;//without sync
|
||||
}
|
||||
for (i=0; i<sectors; i++)
|
||||
{
|
||||
if (DoCDVDreadSector((u8*)((uptr)buf+2048*i), lsn+i, CDVD_MODE_2048) == -1) return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int DvdRead(u32 lsn, u32 sectors, void *buf, CdRMode *mode){
|
||||
u32 i;
|
||||
u8* buff;
|
||||
|
||||
for (i=lsn; i<(lsn+sectors); i++){
|
||||
if (CDVDreadTrack(i, CDVD_MODE_2048)==-1)
|
||||
return 0;
|
||||
buff = CDVDgetBuffer();
|
||||
if (buff==NULL) return 0;
|
||||
|
||||
// switch (mode->datapattern){
|
||||
// case CdSecS2064:
|
||||
((u32*)buf)[0] = i + 0x30000;
|
||||
memcpy_fast((u8*)buf+12, buff, 2048);
|
||||
buf = (char*)buf + 2064; break;
|
||||
// default:
|
||||
// return 0;
|
||||
// }
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**************************************************************
|
||||
* The functions below are not exported for normal file-system *
|
||||
* operations, but are used by the file-system operations, and *
|
||||
* may also be exported for use via RPC *
|
||||
**************************************************************/
|
||||
|
||||
int CDVD_GetVolumeDescriptor(void){
|
||||
int IsoFS_getVolumeDescriptor(void)
|
||||
{
|
||||
// Read until we find the last valid Volume Descriptor
|
||||
int volDescSector;
|
||||
|
||||
cdVolDesc localVolDesc;
|
||||
|
||||
DbgCon::WriteLn("CDVD_GetVolumeDescriptor called");
|
||||
DbgCon::WriteLn("IsoFS_GetVolumeDescriptor called");
|
||||
|
||||
for (volDescSector = 16; volDescSector<20; volDescSector++)
|
||||
{
|
||||
CdRead(volDescSector,1,&localVolDesc,&cdReadMode);
|
||||
IsoFS_readSectors(volDescSector,1,&localVolDesc);
|
||||
// CdSync(0x00);
|
||||
|
||||
// If this is still a volume Descriptor
|
||||
|
@ -267,7 +226,7 @@ int CDVD_GetVolumeDescriptor(void){
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
int CDVD_findfile(const char* fname, TocEntry* tocEntry){
|
||||
int IsoFS_findFile(const char* fname, TocEntry* tocEntry){
|
||||
char filename[g_MaxPath+1];
|
||||
char pathname[JolietMaxPath+1];
|
||||
char toc[2048];
|
||||
|
@ -284,24 +243,20 @@ int CDVD_findfile(const char* fname, TocEntry* tocEntry){
|
|||
|
||||
dirTocEntry* tocEntryPointer;
|
||||
|
||||
DbgCon::WriteLn("CDVD_findfile called");
|
||||
|
||||
//make sure we have good cdReadMode
|
||||
cdReadMode.trycount = 0;
|
||||
cdReadMode.spindlctrl = CdSpinStm;
|
||||
cdReadMode.datapattern = CdSecS2048;
|
||||
DbgCon::WriteLn("IsoFS_findfile(\"%s\") called", params fname);
|
||||
|
||||
_splitpath2(fname, pathname, filename);
|
||||
|
||||
// Find the TOC for a specific directory
|
||||
if (CDVD_GetVolumeDescriptor() != TRUE){
|
||||
RPC_LOG("Could not get CD Volume Descriptor");
|
||||
if (IsoFS_getVolumeDescriptor() != TRUE)
|
||||
{
|
||||
ISOFS_LOG("Could not get CD Volume Descriptor");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Read the TOC of the root directory
|
||||
if (CdRead(CDVolDesc.rootToc.tocLBA,1,toc,&cdReadMode) != TRUE){
|
||||
RPC_LOG("Couldn't Read from CD !");
|
||||
if (IsoFS_readSectors(CDVolDesc.rootToc.tocLBA,1,toc) != TRUE){
|
||||
ISOFS_LOG("Couldn't Read from CD !");
|
||||
return -1;
|
||||
}
|
||||
//CdSync(0x00);
|
||||
|
@ -360,7 +315,7 @@ int CDVD_findfile(const char* fname, TocEntry* tocEntry){
|
|||
// then load another sector
|
||||
|
||||
current_sector++;
|
||||
if (CdRead(current_sector,1,toc,&cdReadMode) != TRUE)
|
||||
if (IsoFS_readSectors(current_sector,1,toc) != TRUE)
|
||||
{
|
||||
Console::Error("Couldn't Read from CD !");
|
||||
return -1;
|
||||
|
@ -398,7 +353,7 @@ int CDVD_findfile(const char* fname, TocEntry* tocEntry){
|
|||
// If we havent found the directory name we wanted then fail
|
||||
if (found_dir != TRUE)
|
||||
{
|
||||
Console::Notice( "CDVD_findfile: could not find dir" );
|
||||
Console::Notice( "IsoFS_findfile: could not find dir" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -406,7 +361,7 @@ int CDVD_findfile(const char* fname, TocEntry* tocEntry){
|
|||
dirname = strtok( NULL, "\\/" );
|
||||
|
||||
// Read the TOC of the found subdirectory
|
||||
if (CdRead(localTocEntry.fileLBA,1,toc,&cdReadMode) != TRUE)
|
||||
if (IsoFS_readSectors(localTocEntry.fileLBA,1,toc) != TRUE)
|
||||
{
|
||||
Console::Error("Couldn't Read from CD !");
|
||||
return -1;
|
||||
|
@ -422,7 +377,7 @@ int CDVD_findfile(const char* fname, TocEntry* tocEntry){
|
|||
tocEntryPointer = (dirTocEntry*)((char*)tocEntryPointer + tocEntryPointer->length);
|
||||
}
|
||||
|
||||
RPC_LOG("[RPC:cdvd] findfile: found dir, now looking for file");
|
||||
ISOFS_LOG("[IsoFStools] findfile: found dir, now looking for file");
|
||||
|
||||
tocEntryPointer = (dirTocEntry*)toc;
|
||||
|
||||
|
@ -453,7 +408,7 @@ int CDVD_findfile(const char* fname, TocEntry* tocEntry){
|
|||
strcpy(tocEntry->filename, localTocEntry.filename);
|
||||
memcpy(tocEntry->date, localTocEntry.date, 7);
|
||||
|
||||
DbgCon::WriteLn("CDVD_findfile: found file");
|
||||
DbgCon::WriteLn("IsoFS_findfile: found file");
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -467,7 +422,7 @@ int CDVD_findfile(const char* fname, TocEntry* tocEntry){
|
|||
{
|
||||
dir_lba++;
|
||||
|
||||
if (CdRead(dir_lba,1,toc,&cdReadMode) != TRUE){
|
||||
if (IsoFS_readSectors(dir_lba,1,toc) != TRUE){
|
||||
Console::Error("Couldn't Read from CD !");
|
||||
return -1;
|
||||
}
|
||||
|
@ -477,13 +432,13 @@ int CDVD_findfile(const char* fname, TocEntry* tocEntry){
|
|||
}
|
||||
}
|
||||
|
||||
DbgCon::Notice("CDVD_findfile: could not find file");
|
||||
DbgCon::Notice("IsoFS_findfile: could not find file");
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// This is the RPC-ready function which takes the request to start the tocEntry retrieval
|
||||
int CDVD_GetDir_RPC_request(char* pathname, char* extensions, unsigned int inc_dirs){
|
||||
int IsoFS_initDirectoryList(char* pathname, char* extensions, unsigned int inc_dirs){
|
||||
// int dir_depth = 1;
|
||||
char toc[2048];
|
||||
char* dirname;
|
||||
|
@ -501,16 +456,16 @@ int CDVD_GetDir_RPC_request(char* pathname, char* extensions, unsigned int inc_d
|
|||
getDirTocData.inc_dirs = inc_dirs;
|
||||
|
||||
// Find the TOC for a specific directory
|
||||
if (CDVD_GetVolumeDescriptor() != TRUE){
|
||||
RPC_LOG("[RPC:cdvd] Could not get CD Volume Descriptor");
|
||||
if (IsoFS_getVolumeDescriptor() != TRUE){
|
||||
ISOFS_LOG("[IsoFStools] Could not get CD Volume Descriptor");
|
||||
return -1;
|
||||
}
|
||||
|
||||
RPC_LOG("[RPC:cdvd] Getting Directory Listing for: \"%s\"", pathname);
|
||||
ISOFS_LOG("[IsoFStools] Getting Directory Listing for: \"%s\"", pathname);
|
||||
|
||||
// Read the TOC of the root directory
|
||||
if (CdRead(CDVolDesc.rootToc.tocLBA,1,toc,&cdReadMode) != TRUE){
|
||||
RPC_LOG("[RPC: ] Couldn't Read from CD !");
|
||||
if (IsoFS_readSectors(CDVolDesc.rootToc.tocLBA,1,toc) != TRUE){
|
||||
ISOFS_LOG("[IsoFStools] Couldn't Read from CD !");
|
||||
return -1;
|
||||
}
|
||||
//CdSync(0x00);
|
||||
|
@ -526,12 +481,12 @@ int CDVD_GetDir_RPC_request(char* pathname, char* extensions, unsigned int inc_d
|
|||
|
||||
// use strtok to get the next dir name
|
||||
|
||||
// if there isnt one, then assume we want the LBA
|
||||
// if there isn't one, then assume we want the LBA
|
||||
// for the current one, and exit the while loop
|
||||
|
||||
// if there is another dir name then increment dir_depth
|
||||
// and look through dir table entries until we find the right name
|
||||
// if we dont find the right name
|
||||
// if we don't find the right name
|
||||
// before finding an entry at a higher level (lower num), then return nothing
|
||||
|
||||
localTocEntry.fileLBA = CDVolDesc.rootToc.tocLBA;
|
||||
|
@ -550,8 +505,8 @@ int CDVD_GetDir_RPC_request(char* pathname, char* extensions, unsigned int inc_d
|
|||
// then load another sector
|
||||
|
||||
current_sector++;
|
||||
if (CdRead(current_sector,1,toc,&cdReadMode) != TRUE){
|
||||
RPC_LOG("[RPC: ] Couldn't Read from CD !");
|
||||
if (IsoFS_readSectors(current_sector,1,toc) != TRUE){
|
||||
ISOFS_LOG("[IsoFStools] Couldn't Read from CD !");
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
@ -573,8 +528,8 @@ int CDVD_GetDir_RPC_request(char* pathname, char* extensions, unsigned int inc_d
|
|||
if (strcmp(dirname,localTocEntry.filename) == 0){
|
||||
// if the name matches then we've found the directory
|
||||
found_dir = TRUE;
|
||||
RPC_LOG("[RPC: ] Found directory %s in subdir at sector %d",dirname,current_sector);
|
||||
RPC_LOG("[RPC: ] LBA of found subdirectory = %d",localTocEntry.fileLBA);
|
||||
ISOFS_LOG("[IsoFStools] Found directory %s in subdir at sector %d",dirname,current_sector);
|
||||
ISOFS_LOG("[IsoFStools] LBA of found subdirectory = %d",localTocEntry.fileLBA);
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -592,8 +547,8 @@ int CDVD_GetDir_RPC_request(char* pathname, char* extensions, unsigned int inc_d
|
|||
dirname = strtok( NULL, "\\/" );
|
||||
|
||||
// Read the TOC of the found subdirectory
|
||||
if (CdRead(localTocEntry.fileLBA,1,toc,&cdReadMode) != TRUE){
|
||||
RPC_LOG("[RPC: ] Couldn't Read from CD !");
|
||||
if (IsoFS_readSectors(localTocEntry.fileLBA,1,toc) != TRUE){
|
||||
ISOFS_LOG("[IsoFStools] Couldn't Read from CD !");
|
||||
return -1;
|
||||
}
|
||||
//CdSync(0x00);
|
||||
|
@ -644,8 +599,8 @@ int CDVD_GetDir_RPC_request(char* pathname, char* extensions, unsigned int inc_d
|
|||
// then load another sector
|
||||
getDirTocData.current_sector++;
|
||||
|
||||
if (CdRead(getDirTocData.current_sector,1,toc,&cdReadMode) != TRUE){
|
||||
RPC_LOG("[RPC: ] Couldn't Read from CD !");
|
||||
if (IsoFS_readSectors(getDirTocData.current_sector,1,toc) != TRUE){
|
||||
ISOFS_LOG("[IsoFStools] Couldn't Read from CD !");
|
||||
return -1;
|
||||
}
|
||||
//CdSync(0x00);
|
||||
|
@ -703,14 +658,14 @@ int CDVD_GetDir_RPC_request(char* pathname, char* extensions, unsigned int inc_d
|
|||
|
||||
// This function can be called repeatedly after CDVD_GetDir_RPC_request to get the actual entries
|
||||
// buffer (tocEntry) must be 18KB in size, and this will be filled with a maximum of 128 entries in one go
|
||||
int CDVD_GetDir_RPC_get_entries(TocEntry tocEntry[], int req_entries){
|
||||
int IsoFS_getDirectories(TocEntry tocEntry[], int req_entries){
|
||||
char toc[2048];
|
||||
int toc_entry_num;
|
||||
|
||||
dirTocEntry* tocEntryPointer;
|
||||
|
||||
if (CdRead(getDirTocData.current_sector,1,toc,&cdReadMode) != TRUE){
|
||||
RPC_LOG("[RPC:cdvd] Couldn't Read from CD !");
|
||||
if (IsoFS_readSectors(getDirTocData.current_sector,1,toc) != TRUE){
|
||||
ISOFS_LOG("[IsoFStools] Couldn't Read from CD !");
|
||||
return -1;
|
||||
}
|
||||
//CdSync(0x00);
|
||||
|
@ -730,18 +685,21 @@ int CDVD_GetDir_RPC_get_entries(TocEntry tocEntry[], int req_entries){
|
|||
if (req_entries > 128)
|
||||
req_entries = 128;
|
||||
|
||||
for (toc_entry_num=0; toc_entry_num < req_entries;){
|
||||
if ((tocEntryPointer->length == 0) || (getDirTocData.current_sector_offset >= 2048)){
|
||||
for (toc_entry_num=0; toc_entry_num < req_entries;)
|
||||
{
|
||||
if ((tocEntryPointer->length == 0) || (getDirTocData.current_sector_offset >= 2048))
|
||||
{
|
||||
// decrease the number of dirs remaining
|
||||
getDirTocData.num_sectors--;
|
||||
|
||||
if (getDirTocData.num_sectors > 0){
|
||||
if (getDirTocData.num_sectors > 0)
|
||||
{
|
||||
// If we've run out of entries, but arent on the last sector
|
||||
// then load another sector
|
||||
getDirTocData.current_sector++;
|
||||
|
||||
if (CdRead(getDirTocData.current_sector,1,toc,&cdReadMode) != TRUE){
|
||||
RPC_LOG("[RPC:cdvd] Couldn't Read from CD !");
|
||||
if (IsoFS_readSectors(getDirTocData.current_sector,1,toc) != TRUE){
|
||||
ISOFS_LOG("[IsoFStools] Couldn't Read from CD !");
|
||||
return -1;
|
||||
}
|
||||
//CdSync(0x00);
|
||||
|
@ -751,7 +709,8 @@ int CDVD_GetDir_RPC_get_entries(TocEntry tocEntry[], int req_entries){
|
|||
|
||||
// continue;
|
||||
}
|
||||
else{
|
||||
else
|
||||
{
|
||||
return (toc_entry_num);
|
||||
}
|
||||
}
|
||||
|
@ -792,27 +751,6 @@ int CDVD_GetDir_RPC_get_entries(TocEntry tocEntry[], int req_entries){
|
|||
tocEntryPointer = (dirTocEntry*)(toc + getDirTocData.current_sector_offset);
|
||||
}
|
||||
}
|
||||
/*
|
||||
if (strlen(getDirTocData.extension_list) > 0)
|
||||
{
|
||||
if (TocEntryCompare(tocEntry[toc_entry_num].filename, getDirTocData.extension_list) == TRUE)
|
||||
{
|
||||
|
||||
// increment this here, rather than in the main for loop
|
||||
// since this should count the number of matching entries
|
||||
toc_entry_num++;
|
||||
}
|
||||
|
||||
getDirTocData.current_sector_offset += tocEntryPointer->length;
|
||||
(char*)tocEntryPointer = toc + getDirTocData.current_sector_offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
toc_entry_num++;
|
||||
getDirTocData.current_sector_offset += tocEntryPointer->length;
|
||||
(char*)tocEntryPointer = toc + getDirTocData.current_sector_offset;
|
||||
}
|
||||
*/
|
||||
}
|
||||
return (toc_entry_num);
|
||||
}
|
|
@ -20,14 +20,13 @@
|
|||
* Modified by Florin for PCSX2 emu
|
||||
*/
|
||||
|
||||
#ifndef __CDVDISO_H__
|
||||
#define __CDVDISO_H__
|
||||
#ifndef __ISOFSTOOLS_H__
|
||||
#define __ISOFSTOOLS_H__
|
||||
|
||||
#include "CDVDlib.h"
|
||||
#include "IsoFScdvd.h"
|
||||
|
||||
int CDVD_findfile(const char* fname, TocEntry* tocEntry);
|
||||
int CDVD_GetDir_RPC_request(char* pathname, char* extensions, unsigned int inc_dirs);
|
||||
int CDVD_GetDir_RPC_get_entries(TocEntry tocEntry[], int req_entries);
|
||||
int IsoFS_initDirectoryList(char* pathname, char* extensions, unsigned int inc_dirs);
|
||||
int IsoFS_getDirectories(TocEntry tocEntry[], int req_entries);
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma pack(1)
|
||||
|
@ -146,4 +145,4 @@ struct dirTocEntry
|
|||
#pragma pack()
|
||||
#endif
|
||||
|
||||
#endif//__CDVDISO_H__
|
||||
#endif//__ISOFSTOOLS_H__
|
|
@ -0,0 +1,555 @@
|
|||
/* Pcsx2 - Pc Ps2 Emulator
|
||||
* Copyright (C) 2002-2009 Pcsx2 Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include "PrecompiledHeader.h"
|
||||
#include "IopCommon.h"
|
||||
#include "IsoFStools.h"
|
||||
#include "IsoFSdrv.h"
|
||||
#include "IsoFileFormats.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
|
||||
void *_openfile(const char *filename, int flags)
|
||||
{
|
||||
HANDLE handle;
|
||||
wxString fn( wxString::FromAscii( filename ) );
|
||||
|
||||
// Console::WriteLn("_openfile %s, %d", params filename, flags & O_RDONLY);
|
||||
if (flags & O_WRONLY)
|
||||
{
|
||||
int _flags = CREATE_NEW;
|
||||
if (flags & O_CREAT) _flags = CREATE_ALWAYS;
|
||||
handle = CreateFile(fn.c_str(), GENERIC_WRITE, 0, NULL, _flags, 0, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
handle = CreateFile(fn.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
|
||||
}
|
||||
|
||||
return handle == INVALID_HANDLE_VALUE ? NULL : handle;
|
||||
}
|
||||
|
||||
u64 _tellfile(void *handle)
|
||||
{
|
||||
u64 ofs;
|
||||
PLONG _ofs = (LONG*) & ofs;
|
||||
_ofs[1] = 0;
|
||||
_ofs[0] = SetFilePointer(handle, 0, &_ofs[1], FILE_CURRENT);
|
||||
return ofs;
|
||||
}
|
||||
|
||||
int _seekfile(void *handle, u64 offset, int whence)
|
||||
{
|
||||
u64 ofs = (u64)offset;
|
||||
PLONG _ofs = (LONG*) & ofs;
|
||||
// Console::WriteLn("_seekfile %p, %d_%d", params handle, _ofs[1], _ofs[0]);
|
||||
if (whence == SEEK_SET)
|
||||
{
|
||||
SetFilePointer(handle, _ofs[0], &_ofs[1], FILE_BEGIN);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetFilePointer(handle, _ofs[0], &_ofs[1], FILE_END);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _readfile(void *handle, void *dst, int size)
|
||||
{
|
||||
DWORD ret;
|
||||
|
||||
// Console::WriteLn("_readfile %p %d", params handle, size);
|
||||
ReadFile(handle, dst, size, &ret, NULL);
|
||||
// Console::WriteLn("_readfile ret %d; %d", params ret, GetLastError());
|
||||
return ret;
|
||||
}
|
||||
|
||||
int _writefile(void *handle, void *src, int size)
|
||||
{
|
||||
DWORD ret;
|
||||
|
||||
// Console::WriteLn("_writefile %p, %d", params handle, size);
|
||||
// _seekfile(handle, _tellfile(handle));
|
||||
WriteFile(handle, src, size, &ret, NULL);
|
||||
// Console::WriteLn("_writefile ret %d", params ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void _closefile(void *handle)
|
||||
{
|
||||
CloseHandle(handle);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void *_openfile(const char *filename, int flags)
|
||||
{
|
||||
// Console::WriteLn("_openfile %s %x", params filename, flags);
|
||||
|
||||
if (flags & O_WRONLY)
|
||||
return fopen64(filename, "wb");
|
||||
else
|
||||
return fopen64(filename, "rb");
|
||||
}
|
||||
|
||||
u64 _tellfile(void *handle)
|
||||
{
|
||||
s64 cursize = ftell(handle);
|
||||
|
||||
if (cursize == -1)
|
||||
{
|
||||
// try 64bit
|
||||
cursize = ftello64(handle);
|
||||
if (cursize < -1)
|
||||
{
|
||||
// zero top 32 bits
|
||||
cursize &= 0xffffffff;
|
||||
}
|
||||
}
|
||||
return cursize;
|
||||
}
|
||||
|
||||
int _seekfile(void *handle, u64 offset, int whence)
|
||||
{
|
||||
int seekerr = fseeko64(handle, offset, whence);
|
||||
|
||||
if (seekerr == -1) Console::Error("Failed to seek.");
|
||||
|
||||
return seekerr;
|
||||
}
|
||||
|
||||
int _readfile(void *handle, void *dst, int size)
|
||||
{
|
||||
return fread(dst, 1, size, handle);
|
||||
}
|
||||
|
||||
int _writefile(void *handle, void *src, int size)
|
||||
{
|
||||
return fwrite(src, 1, size, handle);
|
||||
}
|
||||
|
||||
void _closefile(void *handle)
|
||||
{
|
||||
fclose(handle);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int detect(isoFile *iso)
|
||||
{
|
||||
u8 buf[2448];
|
||||
struct cdVolDesc *volDesc;
|
||||
|
||||
if (isoReadBlock(iso, buf + iso->blockofs, 16) == -1) return -1;
|
||||
|
||||
volDesc = (struct cdVolDesc *)(buf + 24);
|
||||
|
||||
if (strncmp((char*)volDesc->volID, "CD001", 5)) return 0;
|
||||
|
||||
if (volDesc->rootToc.tocSize == 2048)
|
||||
iso->type = ISOTYPE_CD;
|
||||
else
|
||||
iso->type = ISOTYPE_DVD;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int _isoReadDtable(isoFile *iso)
|
||||
{
|
||||
int ret;
|
||||
|
||||
_seekfile(iso->handle, 0, SEEK_END);
|
||||
iso->dtablesize = (_tellfile(iso->handle) - 16) / (iso->blocksize + 4);
|
||||
iso->dtable = (u32*)malloc(iso->dtablesize * 4);
|
||||
|
||||
for (int i = 0; i < iso->dtablesize; i++)
|
||||
{
|
||||
_seekfile(iso->handle, 16 + (iso->blocksize + 4) * i, SEEK_SET);
|
||||
ret = _readfile(iso->handle, &iso->dtable[i], 4);
|
||||
if (ret < 4) return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool tryIsoType(isoFile *iso, u32 size, u32 offset, u32 blockofs)
|
||||
{
|
||||
iso->blocksize = size;
|
||||
iso->offset = offset;
|
||||
iso->blockofs = blockofs;
|
||||
if (detect(iso) == 1) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int isoDetect(isoFile *iso) // based on florin's CDVDbin detection code :)
|
||||
{
|
||||
char buf[32];
|
||||
int len;
|
||||
|
||||
iso->type = ISOTYPE_ILLEGAL;
|
||||
|
||||
len = strlen(iso->filename);
|
||||
|
||||
_seekfile(iso->handle, 0, SEEK_SET);
|
||||
_readfile(iso->handle, buf, 4);
|
||||
|
||||
if (strncmp(buf, "BDV2", 4) == 0)
|
||||
{
|
||||
iso->flags = ISOFLAGS_BLOCKDUMP;
|
||||
_readfile(iso->handle, &iso->blocksize, 4);
|
||||
_readfile(iso->handle, &iso->blocks, 4);
|
||||
_readfile(iso->handle, &iso->blockofs, 4);
|
||||
_isoReadDtable(iso);
|
||||
return (detect(iso) == 1) ? 0 : -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
iso->blocks = 16;
|
||||
}
|
||||
|
||||
if (tryIsoType(iso, 2048, 0, 24)) return 0; // ISO 2048
|
||||
if (tryIsoType(iso, 2336, 0, 16)) return 0; // RAW 2336
|
||||
if (tryIsoType(iso, 2352, 0, 0)) return 0; // RAW 2352
|
||||
if (tryIsoType(iso, 2448, 0, 0)) return 0; // RAWQ 2448
|
||||
if (tryIsoType(iso, 2048, 150 * 2048, 24)) return 0; // NERO ISO 2048
|
||||
if (tryIsoType(iso, 2352, 150 * 2048, 0)) return 0; // NERO RAW 2352
|
||||
if (tryIsoType(iso, 2448, 150 * 2048, 0)) return 0; // NERO RAWQ 2448
|
||||
if (tryIsoType(iso, 2048, -8, 24)) return 0; // ISO 2048
|
||||
if (tryIsoType(iso, 2352, -8, 0)) return 0; // RAW 2352
|
||||
if (tryIsoType(iso, 2448, -8, 0)) return 0; // RAWQ 2448
|
||||
|
||||
iso->offset = 0;
|
||||
iso->blocksize = 2352;
|
||||
iso->blockofs = 0;
|
||||
iso->type = ISOTYPE_AUDIO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
isoFile *isoOpen(const char *filename)
|
||||
{
|
||||
isoFile *iso;
|
||||
|
||||
iso = (isoFile*)malloc(sizeof(isoFile));
|
||||
if (iso == NULL) return NULL;
|
||||
|
||||
memset(iso, 0, sizeof(isoFile));
|
||||
strcpy(iso->filename, filename);
|
||||
|
||||
iso->handle = _openfile(iso->filename, O_RDONLY);
|
||||
if (iso->handle == NULL)
|
||||
{
|
||||
Console::Error("error loading %s", params iso->filename);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (isoDetect(iso) == -1) return NULL;
|
||||
|
||||
Console::WriteLn("detected blocksize = %d", params iso->blocksize);
|
||||
|
||||
if ((strlen(iso->filename) > 3) && strncmp(iso->filename + (strlen(iso->filename) - 3), "I00", 3) == 0)
|
||||
{
|
||||
int i;
|
||||
|
||||
_closefile(iso->handle);
|
||||
iso->flags |= ISOFLAGS_MULTI;
|
||||
iso->blocks = 0;
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
iso->filename[strlen(iso->filename) - 1] = '0' + i;
|
||||
iso->multih[i].handle = _openfile(iso->filename, O_RDONLY);
|
||||
|
||||
if (iso->multih[i].handle == NULL)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
iso->multih[i].slsn = iso->blocks;
|
||||
_seekfile(iso->multih[i].handle, 0, SEEK_END);
|
||||
iso->blocks += (u32)((_tellfile(iso->multih[i].handle) - iso->offset) / (iso->blocksize));
|
||||
iso->multih[i].elsn = iso->blocks - 1;
|
||||
}
|
||||
|
||||
if (i == 0)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (iso->flags == 0)
|
||||
{
|
||||
_seekfile(iso->handle, 0, SEEK_END);
|
||||
iso->blocks = (u32)((_tellfile(iso->handle) - iso->offset) / (iso->blocksize));
|
||||
}
|
||||
|
||||
Console::WriteLn("isoOpen: %s ok", params iso->filename);
|
||||
Console::WriteLn("offset = %d", params iso->offset);
|
||||
Console::WriteLn("blockofs = %d", params iso->blockofs);
|
||||
Console::WriteLn("blocksize = %d", params iso->blocksize);
|
||||
Console::WriteLn("blocks = %d", params iso->blocks);
|
||||
Console::WriteLn("type = %d", params iso->type);
|
||||
|
||||
return iso;
|
||||
}
|
||||
|
||||
isoFile *isoCreate(const char *filename, int flags)
|
||||
{
|
||||
isoFile *iso;
|
||||
char Zfile[256];
|
||||
|
||||
iso = (isoFile*)malloc(sizeof(isoFile));
|
||||
if (iso == NULL) return NULL;
|
||||
|
||||
memset(iso, 0, sizeof(isoFile));
|
||||
strcpy(iso->filename, filename);
|
||||
|
||||
iso->flags = flags;
|
||||
iso->offset = 0;
|
||||
iso->blockofs = 24;
|
||||
iso->blocksize = 2048;
|
||||
|
||||
if (iso->flags & (ISOFLAGS_Z | ISOFLAGS_Z2 | ISOFLAGS_BZ2))
|
||||
{
|
||||
sprintf(Zfile, "%s.table", iso->filename);
|
||||
iso->htable = _openfile(Zfile, O_WRONLY);
|
||||
|
||||
if (iso->htable == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
iso->handle = _openfile(iso->filename, O_WRONLY | O_CREAT);
|
||||
|
||||
if (iso->handle == NULL)
|
||||
{
|
||||
Console::Error("Error loading %s", params iso->filename);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Console::WriteLn("isoCreate: %s ok", params iso->filename);
|
||||
Console::WriteLn("offset = %d", params iso->offset);
|
||||
|
||||
return iso;
|
||||
}
|
||||
|
||||
int isoSetFormat(isoFile *iso, int blockofs, int blocksize, int blocks)
|
||||
{
|
||||
iso->blocksize = blocksize;
|
||||
iso->blocks = blocks;
|
||||
iso->blockofs = blockofs;
|
||||
|
||||
Console::WriteLn("blockofs = %d", params iso->blockofs);
|
||||
Console::WriteLn("blocksize = %d", params iso->blocksize);
|
||||
Console::WriteLn("blocks = %d", params iso->blocks);
|
||||
|
||||
if (iso->flags & ISOFLAGS_BLOCKDUMP)
|
||||
{
|
||||
if (_writefile(iso->handle, "BDV2", 4) < 4) return -1;
|
||||
if (_writefile(iso->handle, &blocksize, 4) < 4) return -1;
|
||||
if (_writefile(iso->handle, &blocks, 4) < 4) return -1;
|
||||
if (_writefile(iso->handle, &blockofs, 4) < 4) return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 MSFtoLSN(u8 *Time)
|
||||
{
|
||||
u32 lsn;
|
||||
|
||||
lsn = Time[2];
|
||||
lsn += (Time[1] - 2) * 75;
|
||||
lsn += Time[0] * 75 * 60;
|
||||
return lsn;
|
||||
}
|
||||
|
||||
void LSNtoMSF(u8 *Time, s32 lsn)
|
||||
{
|
||||
u8 m, s, f;
|
||||
|
||||
lsn += 150;
|
||||
m = lsn / 4500; // minuten
|
||||
lsn = lsn - m * 4500; // minuten rest
|
||||
s = lsn / 75; // sekunden
|
||||
f = lsn - (s * 75); // sekunden rest
|
||||
Time[0] = itob(m);
|
||||
Time[1] = itob(s);
|
||||
Time[2] = itob(f);
|
||||
}
|
||||
|
||||
int _isoReadBlock(isoFile *iso, u8 *dst, int lsn)
|
||||
{
|
||||
u64 ofs = (u64)lsn * iso->blocksize + iso->offset;
|
||||
int ret;
|
||||
|
||||
memset(dst, 0, iso->blockofs);
|
||||
_seekfile(iso->handle, ofs, SEEK_SET);
|
||||
|
||||
ret = _readfile(iso->handle, dst, iso->blocksize);
|
||||
|
||||
if (ret < iso->blocksize)
|
||||
{
|
||||
Console::Error("read error %d in _isoReadBlock", params ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _isoReadBlockD(isoFile *iso, u8 *dst, int lsn)
|
||||
{
|
||||
int ret;
|
||||
|
||||
// Console::WriteLn("_isoReadBlockD %d, blocksize=%d, blockofs=%d\n", params lsn, iso->blocksize, iso->blockofs);
|
||||
|
||||
memset(dst, 0, iso->blockofs);
|
||||
for (int i = 0; i < iso->dtablesize;i++)
|
||||
{
|
||||
if (iso->dtable[i] != lsn) continue;
|
||||
|
||||
_seekfile(iso->handle, 16 + i * (iso->blocksize + 4) + 4, SEEK_SET);
|
||||
ret = _readfile(iso->handle, dst, iso->blocksize);
|
||||
|
||||
if (ret < iso->blocksize) return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
Console::WriteLn("Block %d not found in dump", params lsn);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _isoReadBlockM(isoFile *iso, u8 *dst, int lsn)
|
||||
{
|
||||
u64 ofs;
|
||||
int ret, i;
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
if ((lsn >= iso->multih[i].slsn) && (lsn <= iso->multih[i].elsn))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == 8) return -1;
|
||||
|
||||
ofs = (u64)(lsn - iso->multih[i].slsn) * iso->blocksize + iso->offset;
|
||||
|
||||
// Console::WriteLn("_isoReadBlock %d, blocksize=%d, blockofs=%d\n", params lsn, iso->blocksize, iso->blockofs);
|
||||
|
||||
memset(dst, 0, iso->blockofs);
|
||||
_seekfile(iso->multih[i].handle, ofs, SEEK_SET);
|
||||
ret = _readfile(iso->multih[i].handle, dst, iso->blocksize);
|
||||
|
||||
if (ret < iso->blocksize)
|
||||
{
|
||||
Console::WriteLn("read error %d in _isoReadBlockM", params ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int isoReadBlock(isoFile *iso, u8 *dst, int lsn)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (lsn > iso->blocks)
|
||||
{
|
||||
Console::WriteLn("isoReadBlock: %d > %d", params lsn, iso->blocks);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (iso->flags & ISOFLAGS_BLOCKDUMP)
|
||||
ret = _isoReadBlockD(iso, dst, lsn);
|
||||
else if (iso->flags & ISOFLAGS_MULTI)
|
||||
ret = _isoReadBlockM(iso, dst, lsn);
|
||||
else
|
||||
ret = _isoReadBlock(iso, dst, lsn);
|
||||
|
||||
if (ret == -1) return ret;
|
||||
|
||||
if (iso->type == ISOTYPE_CD)
|
||||
{
|
||||
LSNtoMSF(dst + 12, lsn);
|
||||
dst[15] = 2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int _isoWriteBlock(isoFile *iso, u8 *src, int lsn)
|
||||
{
|
||||
int ret;
|
||||
u64 ofs = (u64)lsn * iso->blocksize + iso->offset;
|
||||
|
||||
_seekfile(iso->handle, ofs, SEEK_SET);
|
||||
ret = _writefile(iso->handle, src, iso->blocksize);
|
||||
if (ret < iso->blocksize) return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _isoWriteBlockD(isoFile *iso, u8 *src, int lsn)
|
||||
{
|
||||
int ret;
|
||||
|
||||
// Console::WriteLn("_isoWriteBlock %d (ofs=%d)", params iso->blocksize, ofs);
|
||||
|
||||
ret = _writefile(iso->handle, &lsn, 4);
|
||||
if (ret < 4) return -1;
|
||||
ret = _writefile(iso->handle, src, iso->blocksize);
|
||||
|
||||
// Console::WriteLn("_isoWriteBlock %d", params ret);
|
||||
|
||||
if (ret < iso->blocksize) return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int isoWriteBlock(isoFile *iso, u8 *src, int lsn)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (iso->flags & ISOFLAGS_BLOCKDUMP)
|
||||
ret = _isoWriteBlockD(iso, src, lsn);
|
||||
else
|
||||
ret = _isoWriteBlock(iso, src, lsn);
|
||||
|
||||
if (ret == -1) return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void isoClose(isoFile *iso)
|
||||
{
|
||||
if (iso->handle) _closefile(iso->handle);
|
||||
if (iso->htable) _closefile(iso->htable);
|
||||
if (iso->buffer) free(iso->buffer);
|
||||
|
||||
free(iso);
|
||||
}
|
||||
|
|
@ -0,0 +1,109 @@
|
|||
/* Pcsx2 - Pc Ps2 Emulator
|
||||
* Copyright (C) 2002-2009 Pcsx2 Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef __LIBISO_H__
|
||||
#define __LIBISO_H__
|
||||
|
||||
#ifndef __USE_LARGEFILE64
|
||||
#define __USE_LARGEFILE64
|
||||
#endif
|
||||
|
||||
#ifndef _LARGEFILE64_SOURCE
|
||||
#define _LARGEFILE_SOURCE
|
||||
#endif
|
||||
|
||||
#ifndef _LARGEFILE64_SOURCE
|
||||
#define _LARGEFILE64_SOURCE
|
||||
#endif
|
||||
|
||||
#define __USE_FILE_OFFSET64
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4018)
|
||||
#endif
|
||||
|
||||
#include "CDVD.h"
|
||||
|
||||
enum isoType
|
||||
{
|
||||
ISOTYPE_ILLEGAL = 0,
|
||||
ISOTYPE_CD,
|
||||
ISOTYPE_DVD,
|
||||
ISOTYPE_AUDIO,
|
||||
ISOTYPE_DVDDL
|
||||
};
|
||||
|
||||
enum isoFlags
|
||||
{
|
||||
ISOFLAGS_Z = 0x0001,
|
||||
ISOFLAGS_Z2 = 0x0002,
|
||||
ISOFLAGS_BLOCKDUMP = 0x0004,
|
||||
ISOFLAGS_MULTI = 0x0008,
|
||||
ISOFLAGS_BZ2 = 0x0010
|
||||
};
|
||||
|
||||
#define CD_FRAMESIZE_RAW 2352
|
||||
#define DATA_SIZE (CD_FRAMESIZE_RAW-12)
|
||||
|
||||
//#define itob(i) ((i)/10*16 + (i)%10) /* u_char to BCD */
|
||||
//#define btoi(b) ((b)/16*10 + (b)%16) /* BCD to u_char */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32 slsn;
|
||||
u32 elsn;
|
||||
void *handle;
|
||||
} _multih;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char filename[256];
|
||||
u32 type;
|
||||
u32 flags;
|
||||
u32 offset;
|
||||
u32 blockofs;
|
||||
u32 blocksize;
|
||||
u32 blocks;
|
||||
void *handle;
|
||||
void *htable;
|
||||
char *Ztable;
|
||||
u32 *dtable;
|
||||
int dtablesize;
|
||||
_multih multih[8];
|
||||
int buflsn;
|
||||
u8 *buffer;
|
||||
} isoFile;
|
||||
|
||||
|
||||
isoFile *isoOpen(const char *filename);
|
||||
isoFile *isoCreate(const char *filename, int mode);
|
||||
int isoSetFormat(isoFile *iso, int blockofs, int blocksize, int blocks);
|
||||
int isoDetect(isoFile *iso);
|
||||
int isoReadBlock(isoFile *iso, u8 *dst, int lsn);
|
||||
int isoWriteBlock(isoFile *iso, u8 *src, int lsn);
|
||||
void isoClose(isoFile *iso);
|
||||
|
||||
void *_openfile(const char *filename, int flags);
|
||||
u64 _tellfile(void *handle);
|
||||
int _seekfile(void *handle, u64 offset, int whence);
|
||||
int _readfile(void *handle, void *dst, int size);
|
||||
int _writefile(void *handle, void *src, int size);
|
||||
void _closefile(void *handle);
|
||||
|
||||
#endif /* __LIBISO_H__ */
|
|
@ -1,18 +0,0 @@
|
|||
pcsx2_dir = $(top_srcdir)/..
|
||||
common_dir = $(pcsx2_dir)/common/include
|
||||
third_dir = $(pcsx2_dir)/3rdparty
|
||||
cdvd_dir = $(top_srcdir)/CDVD
|
||||
x86_dir = $(top_srcdir)/x86
|
||||
rdebug_dir = $(top_srcdir)/RDebug
|
||||
debugtools_dir = $(top_srcdir)/DebugTools
|
||||
ipu_dir = $(top_srcdir)/IPU
|
||||
linux_dir = $(top_srcdir)/Linux
|
||||
|
||||
INCLUDES = -I$(top_srcdir) -I$(x86_dir) -I$(common_dir) -I$(third_dir)
|
||||
noinst_LIBRARIES = libps2_cdvd.a
|
||||
|
||||
libps2_cdvd_a_SOURCES = \
|
||||
CDVD.cpp CDVDiso.cpp CDVDisodrv.cpp CdRom.cpp \
|
||||
CDVD.h CDVD_internal.h CDVDiso.h CDVDisodrv.h CDVDlib.h CdRom.h
|
||||
|
||||
#SUBDIRS =
|
|
@ -83,6 +83,7 @@ struct LogSources
|
|||
DMA:1,
|
||||
Bios:1,
|
||||
ELF:1,
|
||||
IsoFS:1, // Iso Filesystem support
|
||||
VU0:1,
|
||||
COP0:1, // TLB logs, PERF logs, Debug register logs
|
||||
VIF:1,
|
||||
|
@ -140,6 +141,7 @@ extern bool SrcLog_PSXCNT( const char* fmt, ... );
|
|||
extern bool SrcLog_MEMCARDS( const char* fmt, ... );
|
||||
extern bool SrcLog_PAD( const char* fmt, ... );
|
||||
extern bool SrcLog_CDR( const char* fmt, ... );
|
||||
extern bool SrcLog_CDVD( const char* fmt, ... );
|
||||
extern bool SrcLog_GPU( const char* fmt, ... );
|
||||
|
||||
#define CPU_LOG (varLog.R5900) && SrcLog_CPU
|
||||
|
@ -158,6 +160,7 @@ extern bool SrcLog_GPU( const char* fmt, ... );
|
|||
#define VUM_LOG (varLog.VUMacro) && SrcLog_VUM
|
||||
#define RPC_LOG (varLog.RPC) && SrcLog_RPC
|
||||
#define EECNT_LOG (varLog.Counters) && SrcLog_EECNT
|
||||
#define ISOFS_LOG (varLog.IsoFS) && SrcLog_RPC
|
||||
|
||||
#define PSXCPU_LOG (varLog.R3000A) && SrcLog_PSXCPU
|
||||
#define PSXMEM_LOG (varLog.IopMemory) && SrcLog_PSXMEM
|
||||
|
@ -171,6 +174,7 @@ extern bool SrcLog_GPU( const char* fmt, ... );
|
|||
#define PAD_LOG (varLog.Pad) && SrcLog_PAD
|
||||
#define CDR_LOG (varLog.CDVD) && SrcLog_CDR
|
||||
#define GPU_LOG (varLog.GPU) && SrcLog_GPU
|
||||
#define CDVD_LOG SrcLog_CDVD
|
||||
|
||||
// fixme - currently we don't log cache
|
||||
#define CACHE_LOG 0&&
|
||||
|
@ -195,7 +199,7 @@ extern bool SrcLog_GPU( const char* fmt, ... );
|
|||
#define SIF_LOG 0&&
|
||||
#define IPU_LOG 0&&
|
||||
#define VUM_LOG 0&&
|
||||
#define RPC_LOG 0&&
|
||||
#define ISOFS_LOG 0&&
|
||||
|
||||
#define PSXCPU_LOG 0&&
|
||||
#define PSXMEM_LOG 0&&
|
||||
|
@ -205,6 +209,7 @@ extern bool SrcLog_GPU( const char* fmt, ... );
|
|||
|
||||
#define PAD_LOG 0&&
|
||||
#define CDR_LOG 0&&
|
||||
#define CDVD_LOG 0&&
|
||||
#define GPU_LOG 0&&
|
||||
#define PSXCNT_LOG 0&&
|
||||
#define EECNT_LOG 0&&
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
#include "PrecompiledHeader.h"
|
||||
|
||||
#include "Common.h"
|
||||
#include "CDVD/CDVDisodrv.h"
|
||||
#include "CDVD/IsoFSdrv.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
@ -307,13 +307,13 @@ struct ElfObject
|
|||
if ((strnicmp( work.data(), "cdrom0:", strlen("cdromN:")) == 0) ||
|
||||
(strnicmp( work.data(), "cdrom1:", strlen("cdromN:")) == 0))
|
||||
{
|
||||
int fi = CDVDFS_open(work.data() + strlen("cdromN:"), 1);//RDONLY
|
||||
|
||||
int fi = IsoFS_open(work.data() + strlen("cdromN:"), 1);//RDONLY
|
||||
|
||||
if (fi < 0) throw Exception::FileNotFound( filename );
|
||||
|
||||
CDVDFS_lseek( fi, 0, SEEK_SET );
|
||||
rsize = CDVDFS_read( fi, (char*)data.GetPtr(), data.GetSizeInBytes() );
|
||||
CDVDFS_close( fi );
|
||||
IsoFS_lseek( fi, 0, SEEK_SET );
|
||||
rsize = IsoFS_read( fi, (char*)data.GetPtr(), data.GetSizeInBytes() );
|
||||
IsoFS_close( fi );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -494,8 +494,8 @@ u32 loadElfCRC( const char* filename )
|
|||
{
|
||||
TocEntry toc;
|
||||
|
||||
CDVDFS_init( );
|
||||
if ( CDVD_findfile( filename + strlen( "cdromN:" ), &toc ) == -1 )
|
||||
IsoFS_init( );
|
||||
if ( IsoFS_findFile( filename + strlen( "cdromN:" ), &toc ) == -1 )
|
||||
return 0;
|
||||
|
||||
DevCon::Status( "loadElfFile: %d bytes", params toc.fileSize );
|
||||
|
@ -537,8 +537,8 @@ int loadElfFile(const wxString& filename)
|
|||
{
|
||||
// Loading from a CD rom or CD image.
|
||||
TocEntry toc;
|
||||
CDVDFS_init( );
|
||||
if ( CDVD_findfile( fnptr + strlen( "cdromN:" ), &toc ) == -1 )
|
||||
IsoFS_init( );
|
||||
if ( IsoFS_findFile( fnptr + strlen( "cdromN:" ), &toc ) == -1 )
|
||||
return -1;
|
||||
elfsize = toc.fileSize;
|
||||
}
|
||||
|
|
11
pcsx2/GS.cpp
11
pcsx2/GS.cpp
|
@ -175,6 +175,7 @@ void gsInit()
|
|||
// Opens the gsRingbuffer thread.
|
||||
s32 gsOpen()
|
||||
{
|
||||
u32 curFrameLimit = Config.Options & PCSX2_FRAMELIMIT_MASK;
|
||||
if( m_gsOpened ) return 0;
|
||||
|
||||
//video
|
||||
|
@ -200,6 +201,16 @@ s32 gsOpen()
|
|||
UpdateVSyncRate()
|
||||
);
|
||||
}*/
|
||||
|
||||
if(GSsetFrameLimit == NULL)
|
||||
{
|
||||
DevCon::Notice("Notice: GS Plugin does not implement GSsetFrameLimit.");
|
||||
}
|
||||
else
|
||||
{
|
||||
GSsetFrameLimit(curFrameLimit != PCSX2_FRAMELIMIT_NORMAL);
|
||||
}
|
||||
|
||||
return !m_gsOpened;
|
||||
}
|
||||
|
||||
|
|
30
pcsx2/Hw.h
30
pcsx2/Hw.h
|
@ -85,17 +85,17 @@ enum HWaddress
|
|||
RCNT3_TARGET = 0x10001820,
|
||||
|
||||
IPU_CMD = 0x10002000,
|
||||
IPU_CTRL = 0x10002010,
|
||||
IPU_CTRL = 0x10002010,
|
||||
IPU_BP = 0x10002020,
|
||||
IPU_TOP = 0x10002030,
|
||||
|
||||
GIF_CTRL = 0x10003000,
|
||||
GIF_CTRL = 0x10003000,
|
||||
GIF_MODE = 0x10003010,
|
||||
GIF_STAT = 0x10003020,
|
||||
GIF_TAG0 = 0x10003040,
|
||||
GIF_TAG1 = 0x10003050,
|
||||
GIF_TAG2 = 0x10003060,
|
||||
GIF_TAG3 = 0x10003070,
|
||||
GIF_STAT = 0x10003020,
|
||||
GIF_TAG0 = 0x10003040,
|
||||
GIF_TAG1 = 0x10003050,
|
||||
GIF_TAG2 = 0x10003060,
|
||||
GIF_TAG3 = 0x10003070,
|
||||
GIF_CNT = 0x10003080,
|
||||
GIF_P3CNT = 0x10003090,
|
||||
GIF_P3TAG = 0x100030A0,
|
||||
|
@ -103,16 +103,16 @@ enum HWaddress
|
|||
// Vif Memory Locations
|
||||
VIF0_STAT = 0x10003800,
|
||||
VIF0_FBRST = 0x10003810,
|
||||
VIF0_ERR = 0x10003820,
|
||||
VIF0_ERR = 0x10003820,
|
||||
VIF0_MARK = 0x10003830,
|
||||
VIF0_CYCLE = 0x10003840,
|
||||
VIF0_MODE = 0x10003850,
|
||||
VIF0_NUM = 0x10003860,
|
||||
VIF0_NUM = 0x10003860,
|
||||
VIF0_MASK = 0x10003870,
|
||||
VIF0_CODE = 0x10003880,
|
||||
VIF0_ITOPS = 0x10003890,
|
||||
VIF0_ITOP = 0x100038d0,
|
||||
VIF0_TOP = 0x100038e0,
|
||||
VIF0_TOP = 0x100038e0,
|
||||
VIF0_R0 = 0x10003900,
|
||||
VIF0_R1 = 0x10003910,
|
||||
VIF0_R2 = 0x10003920,
|
||||
|
@ -124,11 +124,11 @@ enum HWaddress
|
|||
|
||||
VIF1_STAT = 0x10003c00,
|
||||
VIF1_FBRST = 0x10003c10,
|
||||
VIF1_ERR = 0x10003c20,
|
||||
VIF1_ERR = 0x10003c20,
|
||||
VIF1_MARK = 0x10003c30,
|
||||
VIF1_CYCLE = 0x10003c40,
|
||||
VIF1_MODE = 0x10003c50,
|
||||
VIF1_NUM = 0x10003c60,
|
||||
VIF1_NUM = 0x10003c60,
|
||||
VIF1_MASK = 0x10003c70,
|
||||
VIF1_CODE = 0x10003c80,
|
||||
VIF1_ITOPS = 0x10003c90,
|
||||
|
@ -136,7 +136,7 @@ enum HWaddress
|
|||
VIF1_OFST = 0x10003cb0,
|
||||
VIF1_TOPS = 0x10003cc0,
|
||||
VIF1_ITOP = 0x10003cd0,
|
||||
VIF1_TOP = 0x10003ce0,
|
||||
VIF1_TOP = 0x10003ce0,
|
||||
VIF1_R0 = 0x10003d00,
|
||||
VIF1_R1 = 0x10003d10,
|
||||
VIF1_R2 = 0x10003d20,
|
||||
|
@ -148,7 +148,7 @@ enum HWaddress
|
|||
|
||||
VIF0_FIFO = 0x10004000,
|
||||
VIF1_FIFO = 0x10005000,
|
||||
GIF_FIFO = 0x10006000,
|
||||
GIF_FIFO = 0x10006000,
|
||||
|
||||
IPUout_FIFO = 0x10007000,
|
||||
IPUin_FIFO = 0x10007010,
|
||||
|
@ -242,7 +242,7 @@ enum HWaddress
|
|||
SBUS_F260 = 0x1000F260,
|
||||
|
||||
MCH_RICM = 0x1000F430,
|
||||
MCH_DRD = 0x1000F440,
|
||||
MCH_DRD = 0x1000F440,
|
||||
|
||||
DMAC_ENABLER = 0x1000F520,
|
||||
DMAC_ENABLEW = 0x1000F590,
|
||||
|
|
|
@ -1131,6 +1131,7 @@ void __forceinline finishmpeg2sliceIDEC(decoder_t* &decoder)
|
|||
}
|
||||
|
||||
// This fixes Mana Khemia if uncommented, but needs testing.
|
||||
// Breaks Figital Devil Saga.
|
||||
//#define ALWAYS_RESUME_BEFORE_EXITING
|
||||
void mpeg2sliceIDEC(void* pdone)
|
||||
{
|
||||
|
@ -1231,6 +1232,7 @@ void mpeg2sliceIDEC(void* pdone)
|
|||
{
|
||||
g_pIPU0Pointer += read * 16;
|
||||
g_nIPU0Data -= read;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1239,7 +1241,7 @@ void mpeg2sliceIDEC(void* pdone)
|
|||
|
||||
NEEDBITS(decoder->bitstream_buf, decoder->bitstream_bits, decoder->bitstream_ptr);
|
||||
mba_inc = 0;
|
||||
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (decoder->bitstream_buf >= 0x10000000)
|
||||
|
@ -1269,7 +1271,7 @@ void mpeg2sliceIDEC(void* pdone)
|
|||
#ifdef ALWAYS_RESUME_BEFORE_EXITING
|
||||
if (!resumed) so_resume();
|
||||
#endif
|
||||
|
||||
|
||||
finishmpeg2sliceIDEC(decoder);
|
||||
|
||||
*(int*)pdone = 1;
|
||||
|
|
|
@ -25,32 +25,43 @@
|
|||
#ifndef __MPEG_H__
|
||||
#define __MPEG_H__
|
||||
|
||||
/* macroblock modes */
|
||||
#define MACROBLOCK_INTRA 1
|
||||
#define MACROBLOCK_PATTERN 2
|
||||
#define MACROBLOCK_MOTION_BACKWARD 4
|
||||
#define MACROBLOCK_MOTION_FORWARD 8
|
||||
#define MACROBLOCK_QUANT 16
|
||||
#define DCT_TYPE_INTERLACED 32
|
||||
/* motion_type */
|
||||
#define MOTION_TYPE_SHIFT 6
|
||||
#define MOTION_TYPE_MASK (3*64)
|
||||
#define MOTION_TYPE_BASE 64
|
||||
#define MC_FIELD (1*64)
|
||||
#define MC_FRAME (2*64)
|
||||
#define MC_16X8 (2*64)
|
||||
#define MC_DMV (3*64)
|
||||
enum macroblock_modes
|
||||
{
|
||||
MACROBLOCK_INTRA = 1,
|
||||
MACROBLOCK_PATTERN = 2,
|
||||
MACROBLOCK_MOTION_BACKWARD = 4,
|
||||
MACROBLOCK_MOTION_FORWARD = 8,
|
||||
MACROBLOCK_QUANT = 16,
|
||||
DCT_TYPE_INTERLACED = 32
|
||||
};
|
||||
|
||||
enum motion_type
|
||||
{
|
||||
MOTION_TYPE_SHIFT = 6,
|
||||
MOTION_TYPE_MASK = (3*64),
|
||||
MOTION_TYPE_BASE = 64,
|
||||
MC_FIELD = (1*64),
|
||||
MC_FRAME = (2*64),
|
||||
MC_16X8 = (2*64),
|
||||
MC_DMV = (3*64)
|
||||
};
|
||||
|
||||
/* picture structure */
|
||||
#define TOP_FIELD 1
|
||||
#define BOTTOM_FIELD 2
|
||||
#define FRAME_PICTURE 3
|
||||
|
||||
enum picture_structure
|
||||
{
|
||||
TOP_FIELD = 1,
|
||||
BOTTOM_FIELD = 2,
|
||||
FRAME_PICTURE = 3
|
||||
};
|
||||
|
||||
/* picture coding type */
|
||||
#define I_TYPE 1
|
||||
#define P_TYPE 2
|
||||
#define B_TYPE 3
|
||||
#define D_TYPE 4
|
||||
enum picture_coding_type
|
||||
{
|
||||
I_TYPE =1,
|
||||
P_TYPE = 2,
|
||||
B_TYPE = 3,
|
||||
D_TYPE = 4
|
||||
};
|
||||
|
||||
struct macroblock_8{
|
||||
unsigned char Y[16][16]; //0
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -30,7 +30,7 @@
|
|||
#include "IopCommon.h"
|
||||
#include "HostGui.h"
|
||||
|
||||
#include "CDVD/CDVDisodrv.h"
|
||||
#include "CDVD/IsoFSdrv.h"
|
||||
#include "VUmicro.h"
|
||||
#include "VU.h"
|
||||
#include "iCore.h"
|
||||
|
@ -244,17 +244,17 @@ int GetPS2ElfName( wxString& name )
|
|||
char *pos;
|
||||
TocEntry tocEntry;
|
||||
|
||||
CDVDFS_init();
|
||||
IsoFS_init();
|
||||
|
||||
// check if the file exists
|
||||
if (CDVD_findfile("SYSTEM.CNF;1", &tocEntry) != TRUE){
|
||||
if (IsoFS_findFile("SYSTEM.CNF;1", &tocEntry) != TRUE){
|
||||
Console::Error("Boot Error > SYSTEM.CNF not found");
|
||||
return 0;//could not find; not a PS/PS2 cdvd
|
||||
}
|
||||
|
||||
f=CDVDFS_open("SYSTEM.CNF;1", 1);
|
||||
CDVDFS_read(f, buffer, g_MaxPath);
|
||||
CDVDFS_close(f);
|
||||
f=IsoFS_open("SYSTEM.CNF;1", 1);
|
||||
IsoFS_read(f, buffer, g_MaxPath);
|
||||
IsoFS_close(f);
|
||||
|
||||
buffer[tocEntry.fileSize]='\0';
|
||||
|
||||
|
@ -422,6 +422,16 @@ void CycleFrameLimit(int dir)
|
|||
newOptions = (Config.Options & ~PCSX2_FRAMELIMIT_MASK) | newFrameLimit;
|
||||
|
||||
gsResetFrameSkip();
|
||||
|
||||
// Allows sync to vblank only when framelimit is on, if GS can.
|
||||
if(GSsetFrameLimit == NULL)
|
||||
{
|
||||
DevCon::Notice("Notice: GS Plugin does not implement GSsetFrameLimit.");
|
||||
}
|
||||
else
|
||||
{
|
||||
GSsetFrameLimit(newFrameLimit);
|
||||
}
|
||||
|
||||
switch(newFrameLimit) {
|
||||
case PCSX2_FRAMELIMIT_NORMAL:
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "IopCommon.h"
|
||||
#include "GS.h"
|
||||
#include "HostGui.h"
|
||||
#include "CDVD/CDVDisoReader.h"
|
||||
|
||||
_GSinit GSinit;
|
||||
_GSopen GSopen;
|
||||
|
@ -45,6 +46,7 @@ _GSprintf GSprintf;
|
|||
_GSsetBaseMem GSsetBaseMem;
|
||||
_GSsetGameCRC GSsetGameCRC;
|
||||
_GSsetFrameSkip GSsetFrameSkip;
|
||||
_GSsetFrameLimit GSsetFrameLimit;
|
||||
_GSsetupRecording GSsetupRecording;
|
||||
_GSreset GSreset;
|
||||
_GSwriteCSR GSwriteCSR;
|
||||
|
@ -137,25 +139,8 @@ _SPU2test SPU2test;
|
|||
_SPU2about SPU2about;
|
||||
|
||||
// CDVD
|
||||
_CDVDinit CDVDinit;
|
||||
_CDVDopen CDVDopen;
|
||||
_CDVDclose CDVDclose;
|
||||
_CDVDshutdown CDVDshutdown;
|
||||
_CDVDreadTrack CDVDreadTrack;
|
||||
_CDVDgetBuffer CDVDgetBuffer;
|
||||
_CDVDreadSubQ CDVDreadSubQ;
|
||||
_CDVDgetTN CDVDgetTN;
|
||||
_CDVDgetTD CDVDgetTD;
|
||||
_CDVDgetTOC CDVDgetTOC;
|
||||
_CDVDgetDiskType CDVDgetDiskType;
|
||||
_CDVDgetTrayStatus CDVDgetTrayStatus;
|
||||
_CDVDctrlTrayOpen CDVDctrlTrayOpen;
|
||||
_CDVDctrlTrayClose CDVDctrlTrayClose;
|
||||
|
||||
_CDVDconfigure CDVDconfigure;
|
||||
_CDVDtest CDVDtest;
|
||||
_CDVDabout CDVDabout;
|
||||
_CDVDnewDiskCB CDVDnewDiskCB;
|
||||
CDVDplugin CDVD_plugin = {0};
|
||||
CDVDplugin CDVD = {0};
|
||||
|
||||
// DEV9
|
||||
_DEV9init DEV9init;
|
||||
|
@ -247,18 +232,21 @@ void CloseGS()
|
|||
|
||||
#ifdef _not_wxWidgets_Land_
|
||||
|
||||
enum PluginTypes
|
||||
namespace PluginTypes
|
||||
{
|
||||
GS = 0,
|
||||
PAD,
|
||||
PAD1,
|
||||
PAD2,
|
||||
SPU2,
|
||||
CDVD,
|
||||
DEV9,
|
||||
USB,
|
||||
FW
|
||||
};
|
||||
enum PluginTypes
|
||||
{
|
||||
GS = 0,
|
||||
PAD,
|
||||
PAD1,
|
||||
PAD2,
|
||||
SPU2,
|
||||
CDVD,
|
||||
DEV9,
|
||||
USB,
|
||||
FW
|
||||
};
|
||||
}
|
||||
|
||||
int PS2E_LT[9] = {
|
||||
PS2E_LT_GS,
|
||||
|
@ -294,6 +282,10 @@ PS2E_FW_VERSION};
|
|||
#define MapSymbol_Fallback(name,fallback) MapSymbolVar_Fallback(name,name,fallback)
|
||||
#define MapSymbol_Error(name) MapSymbolVar_Error(name,name)
|
||||
|
||||
#define MapSymbol2(base,name) MapSymbolVar(base##_plugin.name,base##name)
|
||||
#define MapSymbol2_Fallback(base,name,fallback) MapSymbolVar_Fallback(base##_plugin.name,base##name,fallback)
|
||||
#define MapSymbol2_Error(base,name) MapSymbolVar_Error(base##_plugin.name,base##name)
|
||||
|
||||
// for pad1/2
|
||||
#define MapSymbolPAD(var,name) MapSymbolVar(var##name,PAD##name)
|
||||
#define MapSymbolPAD_Fallback(var,name) if((MapSymbolVarType(var##name,_PAD##name,PAD##name))==NULL) var##name = var##_##name
|
||||
|
@ -321,7 +313,7 @@ static int _TestPS2Esyms(void* drv, int type, int expected_version, const wxStri
|
|||
return 0;
|
||||
}
|
||||
|
||||
static __forceinline bool TestPS2Esyms(void* &drv, PluginTypes type, const string& filename)
|
||||
static __forceinline bool TestPS2Esyms(void* &drv, PluginTypes::PluginTypes type, const string& filename)
|
||||
{
|
||||
if (_TestPS2Esyms(drv, PS2E_LT[type],PS2E_VERSION[type],filename) < 0) return false;
|
||||
return true;
|
||||
|
@ -353,7 +345,7 @@ int LoadGSplugin(const wxString& filename)
|
|||
GSplugin = SysLoadLibrary(filename.c_str());
|
||||
if (GSplugin == NULL) { Msgbox::Alert ("Could Not Load GS Plugin '%hs': %s", params &filename, SysLibError()); return -1; }
|
||||
drv = GSplugin;
|
||||
if (!TestPS2Esyms(drv, GS, filename)) return -1;
|
||||
if (!TestPS2Esyms(drv, PluginTypes::GS, filename)) return -1;
|
||||
MapSymbol_Error(GSinit);
|
||||
MapSymbol_Error(GSshutdown);
|
||||
MapSymbol_Error(GSopen);
|
||||
|
@ -380,6 +372,7 @@ int LoadGSplugin(const wxString& filename)
|
|||
MapSymbol(GSgetDriverInfo);
|
||||
|
||||
MapSymbol(GSsetFrameSkip);
|
||||
MapSymbol(GSsetFrameLimit);
|
||||
MapSymbol(GSsetupRecording);
|
||||
|
||||
#ifdef _WIN32
|
||||
|
@ -408,7 +401,7 @@ int LoadPAD1plugin(const wxString& filename) {
|
|||
PAD1plugin = SysLoadLibrary(filename.c_str());
|
||||
if (PAD1plugin == NULL) { Msgbox::Alert("Could Not Load PAD1 Plugin '%hs': %s", params &filename, SysLibError()); return -1; }
|
||||
drv = PAD1plugin;
|
||||
if (!TestPS2Esyms(drv, PAD, filename)) return -1;
|
||||
if (!TestPS2Esyms(drv, PluginTypes::PAD, filename)) return -1;
|
||||
MapSymbolPAD_Error(PAD1,init);
|
||||
MapSymbolPAD_Error(PAD1,shutdown);
|
||||
MapSymbolPAD_Error(PAD1,open);
|
||||
|
@ -445,7 +438,7 @@ int LoadPAD2plugin(const wxString& filename) {
|
|||
PAD2plugin = SysLoadLibrary(filename.c_str());
|
||||
if (PAD2plugin == NULL) { Msgbox::Alert("Could Not Load PAD2 Plugin '%hs': %s", params &filename, SysLibError()); return -1; }
|
||||
drv = PAD2plugin;
|
||||
if (!TestPS2Esyms(drv, PAD, filename)) return -1;
|
||||
if (!TestPS2Esyms(drv, PluginTypes::PAD, filename)) return -1;
|
||||
MapSymbolPAD_Error(PAD2,init);
|
||||
MapSymbolPAD_Error(PAD2,shutdown);
|
||||
MapSymbolPAD_Error(PAD2,open);
|
||||
|
@ -480,7 +473,7 @@ int LoadSPU2plugin(const wxString& filename) {
|
|||
SPU2plugin = SysLoadLibrary(filename.c_str());
|
||||
if (SPU2plugin == NULL) { Msgbox::Alert("Could Not Load SPU2 Plugin '%hs': %s", params &filename, SysLibError()); return -1; }
|
||||
drv = SPU2plugin;
|
||||
if (!TestPS2Esyms(drv, SPU2, filename)) return -1;
|
||||
if (!TestPS2Esyms(drv, PluginTypes::SPU2, filename)) return -1;
|
||||
MapSymbol_Error(SPU2init);
|
||||
MapSymbol_Error(SPU2shutdown);
|
||||
MapSymbol_Error(SPU2open);
|
||||
|
@ -516,33 +509,117 @@ void *CDVDplugin;
|
|||
void CALLBACK CDVD_configure() {}
|
||||
void CALLBACK CDVD_about() {}
|
||||
s32 CALLBACK CDVD_test() { return 0; }
|
||||
void CALLBACK CDVD_newDiskCB(void (*callback)()) {}
|
||||
|
||||
extern int lastReadSize;
|
||||
s32 CALLBACK CDVD_getBuffer2(u8* buffer)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
||||
// TEMP: until I fix all the plugins to use this function style
|
||||
u8* pb = CDVD.getBuffer();
|
||||
if(pb!=NULL)
|
||||
{
|
||||
memcpy(buffer,pb,lastReadSize);
|
||||
ret=0;
|
||||
}
|
||||
else ret= -1;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
s32 CALLBACK CDVD_readSector(u8* buffer, u32 lsn, int mode)
|
||||
{
|
||||
if(CDVD.readTrack(lsn,mode)<0)
|
||||
return -1;
|
||||
|
||||
// TEMP: until all the plugins use the new CDVDgetBuffer style
|
||||
switch (mode)
|
||||
{
|
||||
case CDVD_MODE_2352:
|
||||
lastReadSize = 2352;
|
||||
break;
|
||||
case CDVD_MODE_2340:
|
||||
lastReadSize = 2340;
|
||||
break;
|
||||
case CDVD_MODE_2328:
|
||||
lastReadSize = 2328;
|
||||
break;
|
||||
case CDVD_MODE_2048:
|
||||
lastReadSize = 2048;
|
||||
break;
|
||||
}
|
||||
return CDVD.getBuffer2(buffer);
|
||||
}
|
||||
|
||||
s32 CALLBACK CDVD_getDualInfo(s32* dualType, u32* layer1Start)
|
||||
{
|
||||
u8 toc[2064];
|
||||
|
||||
// if error getting toc, settle for single layer disc ;)
|
||||
if(CDVD.getTOC(toc))
|
||||
return 0;
|
||||
if(toc[14] & 0x60)
|
||||
{
|
||||
if(toc[14] & 0x10)
|
||||
{
|
||||
// otp dvd
|
||||
*dualType = 2;
|
||||
*layer1Start = (toc[25]<<16) + (toc[26]<<8) + (toc[27]) - 0x30000 + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// ptp dvd
|
||||
*dualType = 1;
|
||||
*layer1Start = (toc[21]<<16) + (toc[22]<<8) + (toc[23]) - 0x30000 + 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// single layer dvd
|
||||
*dualType = 0;
|
||||
*layer1Start = (toc[21]<<16) + (toc[22]<<8) + (toc[23]) - 0x30000 + 1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int cdvdInitCount;
|
||||
int LoadCDVDplugin(const wxString& filename) {
|
||||
void *drv;
|
||||
|
||||
CDVDplugin = SysLoadLibrary(filename.c_str());
|
||||
if (CDVDplugin == NULL) { Msgbox::Alert("Could Not Load CDVD Plugin '%hs': %s", params &filename, SysLibError()); return -1; }
|
||||
drv = CDVDplugin;
|
||||
if (!TestPS2Esyms(drv, CDVD, filename)) return -1;
|
||||
MapSymbol_Error(CDVDinit);
|
||||
MapSymbol_Error(CDVDshutdown);
|
||||
MapSymbol_Error(CDVDopen);
|
||||
MapSymbol_Error(CDVDclose);
|
||||
MapSymbol_Error(CDVDreadTrack);
|
||||
MapSymbol_Error(CDVDgetBuffer);
|
||||
MapSymbol_Error(CDVDreadSubQ);
|
||||
MapSymbol_Error(CDVDgetTN);
|
||||
MapSymbol_Error(CDVDgetTD);
|
||||
MapSymbol_Error(CDVDgetTOC);
|
||||
MapSymbol_Error(CDVDgetDiskType);
|
||||
MapSymbol_Error(CDVDgetTrayStatus);
|
||||
MapSymbol_Error(CDVDctrlTrayOpen);
|
||||
MapSymbol_Error(CDVDctrlTrayClose);
|
||||
if (!TestPS2Esyms(drv, PluginTypes::CDVD, filename)) return -1;
|
||||
MapSymbol2_Error(CDVD,init);
|
||||
MapSymbol2_Error(CDVD,shutdown);
|
||||
MapSymbol2_Error(CDVD,open);
|
||||
MapSymbol2_Error(CDVD,close);
|
||||
MapSymbol2_Error(CDVD,readTrack);
|
||||
MapSymbol2_Error(CDVD,getBuffer);
|
||||
MapSymbol2_Error(CDVD,readSubQ);
|
||||
MapSymbol2_Error(CDVD,getTN);
|
||||
MapSymbol2_Error(CDVD,getTD);
|
||||
MapSymbol2_Error(CDVD,getTOC);
|
||||
MapSymbol2_Error(CDVD,getDiskType);
|
||||
MapSymbol2_Error(CDVD,getTrayStatus);
|
||||
MapSymbol2_Error(CDVD,ctrlTrayOpen);
|
||||
MapSymbol2_Error(CDVD,ctrlTrayClose);
|
||||
|
||||
MapSymbol_Fallback(CDVDconfigure,CDVD_configure);
|
||||
MapSymbol_Fallback(CDVDabout,CDVD_about);
|
||||
MapSymbol_Fallback(CDVDtest,CDVD_test);
|
||||
MapSymbol(CDVDnewDiskCB);
|
||||
MapSymbol2_Fallback(CDVD,configure,CDVD_configure);
|
||||
MapSymbol2_Fallback(CDVD,about,CDVD_about);
|
||||
MapSymbol2_Fallback(CDVD,test,CDVD_test);
|
||||
MapSymbol2_Fallback(CDVD,newDiskCB,CDVD_newDiskCB);
|
||||
|
||||
MapSymbol2_Fallback(CDVD,readSector,CDVD_readSector);
|
||||
MapSymbol2_Fallback(CDVD,getBuffer2,CDVD_getBuffer2);
|
||||
MapSymbol2_Fallback(CDVD,getDualInfo,CDVD_getDualInfo);
|
||||
|
||||
CDVD.initCount = &cdvdInitCount;
|
||||
cdvdInitCount=0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -560,7 +637,7 @@ int LoadDEV9plugin(const wxString& filename) {
|
|||
DEV9plugin = SysLoadLibrary(filename.c_str());
|
||||
if (DEV9plugin == NULL) { Msgbox::Alert("Could Not Load DEV9 Plugin '%hs': %s", params &filename, SysLibError()); return -1; }
|
||||
drv = DEV9plugin;
|
||||
if (!TestPS2Esyms(drv, DEV9, filename)) return -1;
|
||||
if (!TestPS2Esyms(drv, PluginTypes::DEV9, filename)) return -1;
|
||||
MapSymbol_Error(DEV9init);
|
||||
MapSymbol_Error(DEV9shutdown);
|
||||
MapSymbol_Error(DEV9open);
|
||||
|
@ -597,7 +674,7 @@ int LoadUSBplugin(const wxString& filename) {
|
|||
USBplugin = SysLoadLibrary(filename.c_str());
|
||||
if (USBplugin == NULL) { Msgbox::Alert("Could Not Load USB Plugin '%hs': %s", params &filename, SysLibError()); return -1; }
|
||||
drv = USBplugin;
|
||||
if (!TestPS2Esyms(drv, USB, filename)) return -1;
|
||||
if (!TestPS2Esyms(drv, PluginTypes::USB, filename)) return -1;
|
||||
MapSymbol_Error(USBinit);
|
||||
MapSymbol_Error(USBshutdown);
|
||||
MapSymbol_Error(USBopen);
|
||||
|
@ -634,7 +711,7 @@ int LoadFWplugin(const wxString& filename) {
|
|||
FWplugin = SysLoadLibrary(filename.c_str());
|
||||
if (FWplugin == NULL) { Msgbox::Alert("Could Not Load FW Plugin '%hs': %s", params &filename, SysLibError()); return -1; }
|
||||
drv = FWplugin;
|
||||
if (!TestPS2Esyms(drv, FW, filename)) return -1;
|
||||
if (!TestPS2Esyms(drv, PluginTypes::FW, filename)) return -1;
|
||||
MapSymbol_Error(FWinit);
|
||||
MapSymbol_Error(FWshutdown);
|
||||
MapSymbol_Error(FWopen);
|
||||
|
@ -721,7 +798,9 @@ int InitPlugins()
|
|||
if (ReportError(PAD1init(1), "PAD1init")) return -1;
|
||||
if (ReportError(PAD2init(2), "PAD2init")) return -1;
|
||||
if (ReportError(SPU2init(), "SPU2init")) return -1;
|
||||
if (ReportError(CDVDinit(), "CDVDinit")) return -1;
|
||||
|
||||
if (ReportError(DoCDVDinit(), "CDVDinit")) return -1;
|
||||
|
||||
if (ReportError(DEV9init(), "DEV9init")) return -1;
|
||||
if (ReportError(USBinit(), "USBinit")) return -1;
|
||||
if (ReportError(FWinit(), "FWinit")) return -1;
|
||||
|
@ -744,7 +823,14 @@ void ShutdownPlugins()
|
|||
if (PAD2shutdown != NULL) PAD2shutdown();
|
||||
|
||||
if (SPU2shutdown != NULL) SPU2shutdown();
|
||||
if (CDVDshutdown != NULL) CDVDshutdown();
|
||||
|
||||
//if (CDVDshutdown != NULL) CDVDshutdown();
|
||||
DoCDVDshutdown();
|
||||
|
||||
// safety measures, in case ISO is currently loaded.
|
||||
if(cdvdInitCount>0)
|
||||
CDVD_plugin.shutdown();
|
||||
|
||||
if (DEV9shutdown != NULL) DEV9shutdown();
|
||||
if (USBshutdown != NULL) USBshutdown();
|
||||
if (FWshutdown != NULL) FWshutdown();
|
||||
|
@ -786,9 +872,9 @@ bool OpenCDVD(const char* pTitleFilename)
|
|||
if (!OpenStatus.CDVD && !only_loading_elf)
|
||||
{
|
||||
//First, we need the data.
|
||||
if (CDVDnewDiskCB) CDVDnewDiskCB(cdvdNewDiskCB);
|
||||
CDVD.newDiskCB(cdvdNewDiskCB);
|
||||
|
||||
if (CDVDopen(pTitleFilename) != 0)
|
||||
if (DoCDVDopen(pTitleFilename) != 0)
|
||||
{
|
||||
if (g_Startup.BootMode != BootMode_Elf)
|
||||
{
|
||||
|
@ -915,7 +1001,7 @@ int OpenPlugins(const char* pTitleFilename)
|
|||
(!OpenSPU2()) || (!OpenDEV9()) || (!OpenUSB()) || (!OpenFW()))
|
||||
return -1;
|
||||
|
||||
if (!only_loading_elf) cdvdNewDiskCB();
|
||||
if (!only_loading_elf) cdvdDetectDisk();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -926,6 +1012,12 @@ int OpenPlugins(const char* pTitleFilename)
|
|||
OpenStatus.name = false; \
|
||||
}
|
||||
|
||||
#define CLOSE_PLUGIN2( name ) \
|
||||
if( OpenStatus.name ) { \
|
||||
name.close(); \
|
||||
OpenStatus.name = false; \
|
||||
}
|
||||
|
||||
|
||||
void ClosePlugins( bool closegs )
|
||||
{
|
||||
|
@ -951,7 +1043,12 @@ void ClosePlugins( bool closegs )
|
|||
}
|
||||
}
|
||||
|
||||
CLOSE_PLUGIN( CDVD );
|
||||
if( OpenStatus.CDVD )
|
||||
{
|
||||
DoCDVDclose();
|
||||
OpenStatus.CDVD=false;
|
||||
}
|
||||
|
||||
CLOSE_PLUGIN( DEV9 );
|
||||
CLOSE_PLUGIN( USB );
|
||||
CLOSE_PLUGIN( FW );
|
||||
|
|
|
@ -50,7 +50,7 @@ R5900cpu *Cpu = NULL;
|
|||
u32 bExecBIOS = 0; // set if the BIOS has already been executed
|
||||
|
||||
static bool cpuIsInitialized = false;
|
||||
static uint eeWaitCycles = 1024;
|
||||
static const uint eeWaitCycles = 3072;
|
||||
|
||||
bool eeEventTestIsActive = false;
|
||||
|
||||
|
@ -80,12 +80,6 @@ void cpuReset()
|
|||
g_nextBranchCycle = cpuRegs.cycle + 4;
|
||||
EEsCycle = 0;
|
||||
EEoCycle = cpuRegs.cycle;
|
||||
eeWaitCycles = Config.Hacks.WaitCycleExt ? 3072 : 768;
|
||||
|
||||
// Cyclerate hacks effectively speed up the rate of event tests, so we can safely boost
|
||||
// the WaitCycles value here for x2 and x3 modes:
|
||||
if( Config.Hacks.EECycleRate > 1 )
|
||||
eeWaitCycles += 1024;
|
||||
|
||||
hwReset();
|
||||
vif0Reset();
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
#include "IopCommon.h"
|
||||
#include "SaveState.h"
|
||||
|
||||
#include "CDVD/CDVDisodrv.h"
|
||||
#include "CDVD/IsoFSdrv.h"
|
||||
#include "VUmicro.h"
|
||||
#include "VU.h"
|
||||
#include "iCore.h"
|
||||
|
|
|
@ -182,6 +182,7 @@ IMPLEMENT_SOURCE_LOG( MEMCARDS, 'I', 7 )
|
|||
IMPLEMENT_SOURCE_LOG( PAD, 'I', 7 )
|
||||
IMPLEMENT_SOURCE_LOG( GTE, 'I', 3 )
|
||||
IMPLEMENT_SOURCE_LOG( CDR, 'I', 8 )
|
||||
IMPLEMENT_SOURCE_LOG( CDVD, 'I', 8 )
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -29,6 +29,8 @@
|
|||
|
||||
#include "R5900Exceptions.h"
|
||||
|
||||
#include "CDVD/CDVD.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
// disable all session overrides by default...
|
||||
|
@ -346,6 +348,10 @@ void SysEndExecution()
|
|||
// use_bios - forces the game to boot through the PS2 bios, instead of bypassing it.
|
||||
void SysPrepareExecution( const wxString& elf_file, bool use_bios )
|
||||
{
|
||||
// solve a little crash
|
||||
if(CDVD.init == NULL)
|
||||
CDVD = CDVD_plugin;
|
||||
|
||||
if( !g_EmulationInProgress )
|
||||
{
|
||||
try
|
||||
|
|
|
@ -1776,6 +1776,26 @@
|
|||
RelativePath="..\..\CDVD\CDVD_internal.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\CDVD\CDVDaccess.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\CDVD\CDVDaccess.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\CDVD\CDVDisoReader.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\CDVD\CDVDisoReader.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\CDVD\CDVDlib.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
</Filter>
|
||||
<Filter
|
||||
|
@ -2153,26 +2173,6 @@
|
|||
<Filter
|
||||
Name="ISO"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\..\CDVD\CDVDiso.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\CDVD\CDVDiso.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\CDVD\CDVDisodrv.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\CDVD\CDVDisodrv.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\CDVD\CDVDlib.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\Elfheader.cpp"
|
||||
>
|
||||
|
@ -2181,6 +2181,34 @@
|
|||
RelativePath="..\..\Elfheader.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\CDVD\IsoFileFormats.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\CDVD\IsoFileFormats.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\CDVD\IsoFScdvd.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\CDVD\IsoFSdrv.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\CDVD\IsoFSdrv.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\CDVD\IsoFStools.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\CDVD\IsoFStools.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Include"
|
||||
|
|
|
@ -175,6 +175,8 @@ void IniFile::DoConfig( PcsxConfig& Conf )
|
|||
{
|
||||
SetCurrentSection( "Misc" );
|
||||
|
||||
Entry( "Blockdump", Conf.Blockdump, false );
|
||||
|
||||
Entry( "Patching", Conf.Patch, false );
|
||||
Entry( "GameFixes", Conf.GameFixes);
|
||||
|
||||
|
@ -229,7 +231,7 @@ void IniFile::DoConfig( PcsxConfig& Conf )
|
|||
if (Config.Hacks.EECycleRate > 2)
|
||||
Config.Hacks.EECycleRate = 2;
|
||||
Entry("IOPCycleDouble", Config.Hacks.IOPCycleDouble);
|
||||
Entry("WaitCycleExt", Config.Hacks.WaitCycleExt);
|
||||
//Entry("WaitCycleExt", Config.Hacks.WaitCycleExt);
|
||||
Entry("INTCSTATSlow", Config.Hacks.INTCSTATSlow);
|
||||
Entry("VUCycleSteal", Config.Hacks.VUCycleSteal);
|
||||
Entry("vuFlagHack", Config.Hacks.vuFlagHack);
|
||||
|
|
|
@ -140,7 +140,7 @@ void _eeOnWriteReg(int reg, int signext);
|
|||
void _deleteEEreg(int reg, int flush);
|
||||
|
||||
// allocates memory on the instruction size and returns the pointer
|
||||
u32* recAllocStackMem(int size, int align);
|
||||
u32* recGetImm64(u32 hi, u32 lo);
|
||||
|
||||
void _vuRegsCOP22(VURegs * VU, _VURegsNum *VUregsn);
|
||||
|
||||
|
|
|
@ -74,24 +74,24 @@ u32 g_cpuHasConstReg = 0, g_cpuFlushedConstReg = 0;
|
|||
// Static Private Variables - R5900 Dynarec
|
||||
|
||||
#define X86
|
||||
static const int RECSTACK_SIZE = 0x00020000;
|
||||
static const int RECCONSTBUF_SIZE = 16384 * 2; // 64 bit consts in 32 bit units
|
||||
|
||||
static u8 *recMem = NULL; // the recompiled blocks will be here
|
||||
static u8* recStack = NULL; // stack mem
|
||||
static u32* recConstBuf = NULL; // 64-bit pseudo-immediates
|
||||
static BASEBLOCK *recRAM = NULL; // and the ptr to the blocks here
|
||||
static BASEBLOCK *recROM = NULL; // and here
|
||||
static BASEBLOCK *recROM1 = NULL; // also here
|
||||
static u32 *recRAMCopy = NULL;
|
||||
void JITCompile();
|
||||
static BaseBlocks recBlocks((uptr)JITCompile);
|
||||
static u8* recPtr = NULL, *recStackPtr = NULL;
|
||||
static u8* recPtr = NULL;
|
||||
static u32 *recConstBufPtr = NULL;
|
||||
EEINST* s_pInstCache = NULL;
|
||||
static u32 s_nInstCacheSize = 0;
|
||||
|
||||
static BASEBLOCK* s_pCurBlock = NULL;
|
||||
static BASEBLOCKEX* s_pCurBlockEx = NULL;
|
||||
u32 s_nEndBlock = 0; // what pc the current block ends
|
||||
static u32 s_nHasDelay = 0;
|
||||
static bool s_nBlockFF;
|
||||
|
||||
// save states for branches
|
||||
|
@ -208,13 +208,8 @@ u32* _eeGetConstReg(int reg)
|
|||
return &cpuRegs.GPR.r[ reg ].UL[0];
|
||||
|
||||
// if written in the future, don't flush
|
||||
if( _recIsRegWritten(g_pCurInstInfo+1, (s_nEndBlock-pc)/4, XMMTYPE_GPRREG, reg) ) {
|
||||
u32* ptempmem;
|
||||
ptempmem = recAllocStackMem(8, 4);
|
||||
ptempmem[0] = g_cpuConstRegs[ reg ].UL[0];
|
||||
ptempmem[1] = g_cpuConstRegs[ reg ].UL[1];
|
||||
return ptempmem;
|
||||
}
|
||||
if( _recIsRegWritten(g_pCurInstInfo+1, (s_nEndBlock-pc)/4, XMMTYPE_GPRREG, reg) )
|
||||
return recGetImm64(g_cpuConstRegs[reg].UL[1], g_cpuConstRegs[reg].UL[0]);
|
||||
|
||||
_flushConstReg(reg);
|
||||
return &cpuRegs.GPR.r[ reg ].UL[0];
|
||||
|
@ -340,19 +335,44 @@ int _flushUnusedConstReg()
|
|||
return 0;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// recAllocStackMem -- an optimization trick to write data to a location so that
|
||||
// recompiled code can reference it later on during execution.
|
||||
//
|
||||
// Intended use is for setting up 64/128 bit SSE immediates, primarily.
|
||||
//
|
||||
u32* recAllocStackMem(int size, int align)
|
||||
// Some of the generated MMX code needs 64-bit immediates but x86 doesn't
|
||||
// provide this. One of the reasons we are probably better off not doing
|
||||
// MMX register allocation for the EE.
|
||||
u32* recGetImm64(u32 hi, u32 lo)
|
||||
{
|
||||
jASSUME( align == 4 || align == 8 || align == 16 );
|
||||
u32 *imm64; // returned pointer
|
||||
static u32 *imm64_cache[509];
|
||||
int cacheidx = lo % (sizeof imm64_cache / sizeof *imm64_cache);
|
||||
//static int count; count++;
|
||||
|
||||
recStackPtr = (u8*) ( (((uptr)recStackPtr) + (align-1)) & ~(align-1) );
|
||||
recStackPtr += size;
|
||||
return (u32*)(recStackPtr-size);
|
||||
imm64 = imm64_cache[cacheidx];
|
||||
if (imm64 && imm64[0] == lo && imm64[1] == hi)
|
||||
return imm64;
|
||||
|
||||
if (recConstBufPtr >= recConstBuf + RECCONSTBUF_SIZE) {
|
||||
// TODO: flag an error in recompilation which would reset the recompiler
|
||||
// immediately and recompile the current block again. There is currently
|
||||
// no way to do this, so have a last ditch attempt at making things sane
|
||||
// and return some nonsense if that fails.
|
||||
for (u32 *p = recConstBuf; p < recConstBuf + RECCONSTBUF_SIZE; p += 2)
|
||||
if (p[0] == lo && p[1] == hi) {
|
||||
imm64_cache[cacheidx] = p;
|
||||
return p;
|
||||
}
|
||||
|
||||
return recConstBuf;
|
||||
}
|
||||
|
||||
imm64 = recConstBufPtr;
|
||||
recConstBufPtr += 2;
|
||||
imm64_cache[cacheidx] = imm64;
|
||||
|
||||
imm64[0] = lo;
|
||||
imm64[1] = hi;
|
||||
|
||||
//Console::Notice("Consts allocated: %d of %u", params (recConstBufPtr - recConstBuf) / 2, count);
|
||||
|
||||
return imm64;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -365,7 +385,7 @@ static u8* m_recBlockAlloc = NULL;
|
|||
|
||||
static const uint m_recBlockAllocSize =
|
||||
(((Ps2MemSize::Base + Ps2MemSize::Rom + Ps2MemSize::Rom1) / 4) * sizeof(BASEBLOCK))
|
||||
+ RECSTACK_SIZE + Ps2MemSize::Base;
|
||||
+ RECCONSTBUF_SIZE * sizeof(u32) + Ps2MemSize::Base;
|
||||
|
||||
static void recAlloc()
|
||||
{
|
||||
|
@ -407,7 +427,7 @@ static void recAlloc()
|
|||
recRAM = (BASEBLOCK*)curpos; curpos += (Ps2MemSize::Base / 4) * sizeof(BASEBLOCK);
|
||||
recROM = (BASEBLOCK*)curpos; curpos += (Ps2MemSize::Rom / 4) * sizeof(BASEBLOCK);
|
||||
recROM1 = (BASEBLOCK*)curpos; curpos += (Ps2MemSize::Rom1 / 4) * sizeof(BASEBLOCK);
|
||||
recStack = (u8*)curpos; curpos += RECSTACK_SIZE;
|
||||
recConstBuf = (u32*)curpos; curpos += RECCONSTBUF_SIZE * sizeof(u32);
|
||||
recRAMCopy = (u32*)curpos;
|
||||
|
||||
if( s_pInstCache == NULL )
|
||||
|
@ -436,8 +456,10 @@ void recResetEE( void )
|
|||
|
||||
maxrecmem = 0;
|
||||
|
||||
memset_8<0xcc, REC_CACHEMEM>(recMem); // 0xcc is INT3
|
||||
memzero_ptr<m_recBlockAllocSize>( m_recBlockAlloc );
|
||||
if (IsDevBuild)
|
||||
memset_8<0xcc, REC_CACHEMEM>(recMem); // 0xcc is INT3
|
||||
memzero_ptr<m_recBlockAllocSize - Ps2MemSize::Base>( m_recBlockAlloc ); // Excluding the 32mb ram copy
|
||||
memzero_ptr<RECCONSTBUF_SIZE * sizeof(u32)>(recConstBuf);
|
||||
memzero_obj( manual_page );
|
||||
memzero_obj( manual_counter );
|
||||
ClearRecLUT((BASEBLOCK*)m_recBlockAlloc,
|
||||
|
@ -489,7 +511,7 @@ void recResetEE( void )
|
|||
x86SetPtr(recMem);
|
||||
|
||||
recPtr = recMem;
|
||||
recStackPtr = recStack;
|
||||
recConstBufPtr = recConstBuf;
|
||||
x86FpuState = FPU_STATE;
|
||||
|
||||
branch = 0;
|
||||
|
@ -504,7 +526,7 @@ static void recShutdown( void )
|
|||
SafeSysMunmap( recMem, REC_CACHEMEM );
|
||||
safe_aligned_free( m_recBlockAlloc );
|
||||
recRAM = recROM = recROM1 = NULL;
|
||||
recStack = NULL;
|
||||
recConstBuf = NULL;
|
||||
recRAMCopy = NULL;
|
||||
|
||||
safe_free( s_pInstCache );
|
||||
|
@ -1246,7 +1268,7 @@ void recRecompile( const u32 startpc )
|
|||
if ( ( (uptr)recPtr - (uptr)recMem ) >= REC_CACHEMEM-0x40000 || dumplog == 0xffffffff) {
|
||||
recResetEE();
|
||||
}
|
||||
if ( ( (uptr)recStackPtr - (uptr)recStack ) >= RECSTACK_SIZE-0x100 ) {
|
||||
if ( (recConstBufPtr - recConstBuf) >= RECCONSTBUF_SIZE - 64 ) {
|
||||
DevCon::WriteLn("EE recompiler stack reset");
|
||||
recResetEE();
|
||||
}
|
||||
|
@ -1300,7 +1322,6 @@ void recRecompile( const u32 startpc )
|
|||
// go until the next branch
|
||||
i = startpc;
|
||||
s_nEndBlock = 0xffffffff;
|
||||
s_nHasDelay = 0;
|
||||
|
||||
while(1) {
|
||||
BASEBLOCK* pblock = PC_GETBLOCK(i);
|
||||
|
@ -1331,7 +1352,6 @@ void recRecompile( const u32 startpc )
|
|||
case 0: // special
|
||||
if( _Funct_ == 8 || _Funct_ == 9 ) { // JR, JALR
|
||||
s_nEndBlock = i + 8;
|
||||
s_nHasDelay = 1;
|
||||
goto StartRecomp;
|
||||
}
|
||||
break;
|
||||
|
@ -1340,9 +1360,6 @@ void recRecompile( const u32 startpc )
|
|||
|
||||
if( _Rt_ < 4 || (_Rt_ >= 16 && _Rt_ < 20) ) {
|
||||
// branches
|
||||
if( _Rt_ == 2 || _Rt_ == 3 || _Rt_ == 18 || _Rt_ == 19 ) s_nHasDelay = 1;
|
||||
else s_nHasDelay = 2;
|
||||
|
||||
branchTo = _Imm_ * 4 + i + 4;
|
||||
if( branchTo > startpc && branchTo < i ) s_nEndBlock = branchTo;
|
||||
else s_nEndBlock = i+8;
|
||||
|
@ -1353,17 +1370,12 @@ void recRecompile( const u32 startpc )
|
|||
|
||||
case 2: // J
|
||||
case 3: // JAL
|
||||
s_nHasDelay = 1;
|
||||
s_nEndBlock = i + 8;
|
||||
goto StartRecomp;
|
||||
|
||||
// branches
|
||||
case 4: case 5: case 6: case 7:
|
||||
case 20: case 21: case 22: case 23:
|
||||
|
||||
if( (cpuRegs.code >> 26) >= 20 ) s_nHasDelay = 1;
|
||||
else s_nHasDelay = 2;
|
||||
|
||||
branchTo = _Imm_ * 4 + i + 4;
|
||||
if( branchTo > startpc && branchTo < i ) s_nEndBlock = branchTo;
|
||||
else s_nEndBlock = i+8;
|
||||
|
@ -1385,9 +1397,6 @@ void recRecompile( const u32 startpc )
|
|||
if( _Rs_ == 8 ) {
|
||||
// BC1F, BC1T, BC1FL, BC1TL
|
||||
// BC2F, BC2T, BC2FL, BC2TL
|
||||
if( _Rt_ >= 2 ) s_nHasDelay = 1;
|
||||
else s_nHasDelay = 2;
|
||||
|
||||
branchTo = _Imm_ * 4 + i + 4;
|
||||
if( branchTo > startpc && branchTo < i ) s_nEndBlock = branchTo;
|
||||
else s_nEndBlock = i+8;
|
||||
|
@ -1645,7 +1654,7 @@ StartRecomp:
|
|||
}
|
||||
|
||||
assert( x86Ptr < recMem+REC_CACHEMEM );
|
||||
assert( recStackPtr < recStack+RECSTACK_SIZE );
|
||||
assert( recConstBufPtr < recConstBuf + RECCONSTBUF_SIZE );
|
||||
assert( x86FpuState == 0 );
|
||||
|
||||
assert(x86Ptr - recPtr < 0x10000);
|
||||
|
|
|
@ -1306,10 +1306,6 @@ void recSLTs_consts(int info, int sign)
|
|||
PSRLQItoR(EEREC_D, 63);
|
||||
}
|
||||
else {
|
||||
u32* ptempmem = recAllocStackMem(8,4);
|
||||
ptempmem[0] = g_cpuConstRegs[_Rs_].UL[0]^0x80000000;
|
||||
ptempmem[1] = 0;
|
||||
|
||||
if( EEREC_D != EEREC_T ) {
|
||||
MOVDMtoMMX(EEREC_D, (u32)&s_sltconst);
|
||||
PXORRtoR(EEREC_D, EEREC_T);
|
||||
|
@ -1318,7 +1314,7 @@ void recSLTs_consts(int info, int sign)
|
|||
PXORMtoR(EEREC_D, (u32)&s_sltconst);
|
||||
}
|
||||
|
||||
PCMPGTDMtoR(EEREC_D, (u32)ptempmem);
|
||||
PCMPGTDMtoR(EEREC_D, (uptr)recGetImm64(0, g_cpuConstRegs[_Rs_].UL[0] ^ 0x80000000));
|
||||
|
||||
PUNPCKLDQRtoR(EEREC_D, EEREC_D);
|
||||
PSRLQItoR(EEREC_D, 63);
|
||||
|
@ -1439,11 +1435,7 @@ void recSLTs_constt(int info, int sign)
|
|||
recSLTmemconstt(EEREC_D, EEREC_S, (u32)_eeGetConstReg(_Rt_), 1);
|
||||
}
|
||||
else {
|
||||
u32* ptempmem = recAllocStackMem(8,4);
|
||||
ptempmem[0] = g_cpuConstRegs[_Rt_].UL[0]^0x80000000;
|
||||
ptempmem[1] = 0;
|
||||
|
||||
recSLTmemconstt(EEREC_D, EEREC_S, (u32)ptempmem, 0);
|
||||
recSLTmemconstt(EEREC_D, EEREC_S, (uptr)recGetImm64(0, g_cpuConstRegs[_Rt_].UL[0] ^ 0x80000000), 0);
|
||||
}
|
||||
|
||||
return;
|
||||
|
|
|
@ -63,13 +63,8 @@ void recADDI_(int info)
|
|||
|
||||
if ( info & PROCESS_EE_MMX ) {
|
||||
if ( _Imm_ != 0 ) {
|
||||
|
||||
u32* ptempmem = recAllocStackMem(8, 8);
|
||||
ptempmem[0] = (s32)_Imm_;
|
||||
ptempmem[1] = 0;
|
||||
|
||||
if ( EEREC_T != EEREC_S ) MOVQRtoR(EEREC_T, EEREC_S);
|
||||
PADDDMtoR(EEREC_T, (u32)ptempmem);
|
||||
PADDDMtoR(EEREC_T, (uptr)recGetImm64(0, _Imm_));
|
||||
if ( EEINST_ISLIVE1(_Rt_) ) _signExtendGPRtoMMX(EEREC_T, _Rt_, 0);
|
||||
else EEINST_RESETHASLIVE1(_Rt_);
|
||||
}
|
||||
|
@ -89,12 +84,8 @@ void recADDI_(int info)
|
|||
SetMMXstate();
|
||||
|
||||
if ( _Imm_ != 0 ) {
|
||||
u32* ptempmem = recAllocStackMem(8, 8);
|
||||
ptempmem[0] = (s32)_Imm_;
|
||||
ptempmem[1] = 0;
|
||||
|
||||
MOVDMtoMMX(rtreg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]);
|
||||
PADDDMtoR(rtreg, (u32)ptempmem);
|
||||
PADDDMtoR(rtreg, (uptr)recGetImm64(0, _Imm_));
|
||||
|
||||
if ( EEINST_ISLIVE1(_Rt_) ) _signExtendGPRtoMMX(rtreg, _Rt_, 0);
|
||||
else EEINST_RESETHASLIVE1(_Rt_);
|
||||
|
@ -162,13 +153,8 @@ void recDADDI_(int info)
|
|||
if( info & PROCESS_EE_MMX ) {
|
||||
|
||||
if( _Imm_ != 0 ) {
|
||||
|
||||
// flush
|
||||
u32* ptempmem = recAllocStackMem(8, 8);
|
||||
ptempmem[0] = _Imm_;
|
||||
ptempmem[1] = _Imm_ >= 0 ? 0 : 0xffffffff;
|
||||
if( EEREC_T != EEREC_S ) MOVQRtoR(EEREC_T, EEREC_S);
|
||||
PADDQMtoR(EEREC_T, (u32)ptempmem);
|
||||
PADDQMtoR(EEREC_T, (uptr)recGetImm64(-(_Imm_ < 0), _Imm_));
|
||||
}
|
||||
else {
|
||||
if( EEREC_T != EEREC_S ) MOVQRtoR(EEREC_T, EEREC_S);
|
||||
|
@ -178,15 +164,12 @@ void recDADDI_(int info)
|
|||
|
||||
if( (g_pCurInstInfo->regs[_Rt_]&EEINST_MMX) ) {
|
||||
int rtreg;
|
||||
u32* ptempmem = recAllocStackMem(8, 8);
|
||||
ptempmem[0] = _Imm_;
|
||||
ptempmem[1] = _Imm_ >= 0 ? 0 : 0xffffffff;
|
||||
|
||||
rtreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_WRITE);
|
||||
SetMMXstate();
|
||||
|
||||
MOVQMtoR(rtreg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]);
|
||||
PADDQMtoR(rtreg, (u32)ptempmem);
|
||||
PADDQMtoR(rtreg, (uptr)recGetImm64(-(_Imm_ < 0), _Imm_));
|
||||
}
|
||||
else {
|
||||
if( _Rt_ == _Rs_ ) {
|
||||
|
@ -239,10 +222,7 @@ void recSLTIU_(int info)
|
|||
{
|
||||
if( info & PROCESS_EE_MMX ) {
|
||||
if( EEINST_ISSIGNEXT(_Rs_) ) {
|
||||
u32* ptempmem = recAllocStackMem(8,4);
|
||||
ptempmem[0] = ((s32)(_Imm_))^0x80000000;
|
||||
ptempmem[1] = 0;
|
||||
recSLTmemconstt(EEREC_T, EEREC_S, (u32)ptempmem, 0);
|
||||
recSLTmemconstt(EEREC_T, EEREC_S, (uptr)recGetImm64(0, ((s32)_Imm_)^0x80000000), 0);
|
||||
EEINST_SETSIGNEXT(_Rt_);
|
||||
return;
|
||||
}
|
||||
|
@ -292,10 +272,7 @@ void recSLTI_(int info)
|
|||
if( info & PROCESS_EE_MMX) {
|
||||
|
||||
if( EEINST_ISSIGNEXT(_Rs_) ) {
|
||||
u32* ptempmem = recAllocStackMem(8,4);
|
||||
ptempmem[0] = _Imm_;
|
||||
ptempmem[1] = 0;
|
||||
recSLTmemconstt(EEREC_T, EEREC_S, (u32)ptempmem, 1);
|
||||
recSLTmemconstt(EEREC_T, EEREC_S, (uptr)recGetImm64(0, _Imm_), 1);
|
||||
EEINST_SETSIGNEXT(_Rt_);
|
||||
return;
|
||||
}
|
||||
|
@ -347,12 +324,8 @@ void recLogicalOpI(int info, int op)
|
|||
SetMMXstate();
|
||||
|
||||
if( _ImmU_ != 0 ) {
|
||||
u32* ptempmem = recAllocStackMem(8, 8);
|
||||
ptempmem[0] = _ImmU_;
|
||||
ptempmem[1] = 0;
|
||||
|
||||
if( EEREC_T != EEREC_S ) MOVQRtoR(EEREC_T, EEREC_S);
|
||||
LogicalOpMtoR(EEREC_T, (u32)ptempmem, op);
|
||||
LogicalOpMtoR(EEREC_T, (uptr)recGetImm64(0, _ImmU_), op);
|
||||
}
|
||||
else {
|
||||
if( op == 0 ) PXORRtoR(EEREC_T, EEREC_T);
|
||||
|
@ -367,21 +340,15 @@ void recLogicalOpI(int info, int op)
|
|||
|
||||
if( op == 0 ) {
|
||||
if ( _ImmU_ != 0 ) {
|
||||
u32* ptempmem = recAllocStackMem(8, 8);
|
||||
ptempmem[0] = _ImmU_;
|
||||
ptempmem[1] = 0;
|
||||
MOVDMtoMMX(rtreg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]);
|
||||
PANDMtoR(rtreg, (u32)ptempmem);
|
||||
PANDMtoR(rtreg, (uptr)recGetImm64(0, _ImmU_));
|
||||
}
|
||||
else PXORRtoR(rtreg, rtreg);
|
||||
}
|
||||
else {
|
||||
MOVQMtoR(rtreg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]);
|
||||
if ( _ImmU_ != 0 ) {
|
||||
u32* ptempmem = recAllocStackMem(8, 8);
|
||||
ptempmem[0] = _ImmU_;
|
||||
ptempmem[1] = 0;
|
||||
LogicalOpMtoR(rtreg, (u32)ptempmem, op);
|
||||
LogicalOpMtoR(rtreg, (uptr)recGetImm64(0, _ImmU_), op);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -442,15 +442,12 @@ void recMOVZtemp_consts(int info)
|
|||
CMP8ItoR(EAX, 0xff);
|
||||
j8Ptr[ 0 ] = JNE8( 0 );
|
||||
|
||||
if( g_cpuFlushedConstReg & (1<<_Rs_) ) mem = &cpuRegs.GPR.r[_Rs_].UL[0];
|
||||
else {
|
||||
mem = recAllocStackMem(8,8);
|
||||
if( g_cpuFlushedConstReg & (1<<_Rs_) )
|
||||
mem = &cpuRegs.GPR.r[_Rs_].UL[0];
|
||||
else
|
||||
mem = recGetImm64(g_cpuConstRegs[_Rs_].UL[1], g_cpuConstRegs[_Rs_].UL[0]);
|
||||
|
||||
mem[0] = g_cpuConstRegs[_Rs_].UL[0];
|
||||
mem[1] = g_cpuConstRegs[_Rs_].UL[1];
|
||||
}
|
||||
|
||||
MOVQMtoR(EEREC_D, (u32)mem);
|
||||
MOVQMtoR(EEREC_D, (uptr)mem);
|
||||
x86SetJ8( j8Ptr[ 0 ] );
|
||||
|
||||
_freeMMXreg(t0reg);
|
||||
|
@ -566,15 +563,12 @@ void recMOVNtemp_consts(int info)
|
|||
CMP8ItoR(EAX, 0xff);
|
||||
j8Ptr[ 0 ] = JE8( 0 );
|
||||
|
||||
if( g_cpuFlushedConstReg & (1<<_Rs_) ) mem = &cpuRegs.GPR.r[_Rs_].UL[0];
|
||||
else {
|
||||
mem = recAllocStackMem(8,8);
|
||||
if( g_cpuFlushedConstReg & (1<<_Rs_) )
|
||||
mem = &cpuRegs.GPR.r[_Rs_].UL[0];
|
||||
else
|
||||
mem = recGetImm64(g_cpuConstRegs[_Rs_].UL[1], g_cpuConstRegs[_Rs_].UL[0]);
|
||||
|
||||
mem[0] = g_cpuConstRegs[_Rs_].UL[0];
|
||||
mem[1] = g_cpuConstRegs[_Rs_].UL[1];
|
||||
}
|
||||
|
||||
MOVQMtoR(EEREC_D, (u32)mem);
|
||||
MOVQMtoR(EEREC_D, (uptr)mem);
|
||||
x86SetJ8( j8Ptr[ 0 ] );
|
||||
|
||||
_freeMMXreg(t0reg);
|
||||
|
|
|
@ -266,20 +266,15 @@ void recWritebackConstHILO(u64 res, int writed, int upper)
|
|||
|
||||
if( g_pCurInstInfo->regs[XMMGPR_LO] & testlive ) {
|
||||
if( !upper && (reglo = _allocCheckGPRtoMMX(g_pCurInstInfo, XMMGPR_LO, MODE_WRITE)) >= 0 ) {
|
||||
u32* ptr = recAllocStackMem(8, 8);
|
||||
ptr[0] = res & 0xffffffff;
|
||||
ptr[1] = (res&0x80000000)?0xffffffff:0;
|
||||
MOVQMtoR(reglo, (u32)ptr);
|
||||
MOVQMtoR(reglo, (uptr)recGetImm64(res & 0x80000000 ? -1 : 0, (u32)res));
|
||||
}
|
||||
else {
|
||||
reglo = _allocCheckGPRtoXMM(g_pCurInstInfo, XMMGPR_LO, MODE_WRITE|MODE_READ);
|
||||
|
||||
if( reglo >= 0 ) {
|
||||
u32* ptr = recAllocStackMem(8, 8);
|
||||
ptr[0] = res & 0xffffffff;
|
||||
ptr[1] = (res&0x80000000)?0xffffffff:0;
|
||||
if( upper ) SSE_MOVHPS_M64_to_XMM(reglo, (u32)ptr);
|
||||
else SSE_MOVLPS_M64_to_XMM(reglo, (u32)ptr);
|
||||
u32* ptr = recGetImm64(res & 0x80000000 ? -1 : 0, (u32)res);
|
||||
if( upper ) SSE_MOVHPS_M64_to_XMM(reglo, (uptr)ptr);
|
||||
else SSE_MOVLPS_M64_to_XMM(reglo, (uptr)ptr);
|
||||
}
|
||||
else {
|
||||
MOV32ItoM(loaddr, res & 0xffffffff);
|
||||
|
@ -291,18 +286,13 @@ void recWritebackConstHILO(u64 res, int writed, int upper)
|
|||
if( g_pCurInstInfo->regs[XMMGPR_HI] & testlive ) {
|
||||
|
||||
if( !upper && (reghi = _allocCheckGPRtoMMX(g_pCurInstInfo, XMMGPR_HI, MODE_WRITE)) >= 0 ) {
|
||||
u32* ptr = recAllocStackMem(8, 8);
|
||||
ptr[0] = res >> 32;
|
||||
ptr[1] = (res>>63)?0xffffffff:0;
|
||||
MOVQMtoR(reghi, (u32)ptr);
|
||||
MOVQMtoR(reghi, (uptr)recGetImm64(res >> 63 ? -1 : 0, res >> 32));
|
||||
}
|
||||
else {
|
||||
reghi = _allocCheckGPRtoXMM(g_pCurInstInfo, XMMGPR_HI, MODE_WRITE|MODE_READ);
|
||||
|
||||
if( reghi >= 0 ) {
|
||||
u32* ptr = recAllocStackMem(8, 8);
|
||||
ptr[0] = res >> 32;
|
||||
ptr[1] = (res>>63)?0xffffffff:0;
|
||||
u32* ptr = recGetImm64(res >> 63 ? -1 : 0, res >> 32);
|
||||
if( upper ) SSE_MOVHPS_M64_to_XMM(reghi, (u32)ptr);
|
||||
else SSE_MOVLPS_M64_to_XMM(reghi, (u32)ptr);
|
||||
}
|
||||
|
|
|
@ -50,6 +50,7 @@ microVUt(void) mVUinit(VURegs* vuRegsPtr, int vuIndex) {
|
|||
mVU->prog.max = mMaxProg - 1;
|
||||
mVU->prog.prog = (microProgram*)_aligned_malloc(sizeof(microProgram)*(mVU->prog.max+1), 64);
|
||||
mVU->prog.progList = new int[mMaxProg];
|
||||
mVU->regAlloc = new microRegAlloc(mVU->regs);
|
||||
mVUprint((vuIndex) ? "microVU1: init" : "microVU0: init");
|
||||
|
||||
mVU->cache = SysMmapEx((vuIndex ? 0x5f240000 : 0x5e240000), mVU->cacheSize + 0x1000, 0, (vuIndex ? "Micro VU1" : "Micro VU0"));
|
||||
|
@ -107,12 +108,13 @@ microVUt(void) mVUclose(mV) {
|
|||
if (mVU->prog.prog) {
|
||||
for (int i = 0; i <= mVU->prog.max; i++) {
|
||||
for (u32 j = 0; j < (mVU->progSize / 2); j++) {
|
||||
microBlockManager::Delete(mVU->prog.prog[i].block[j]);
|
||||
safe_delete(mVU->prog.prog[i].block[j]);
|
||||
}
|
||||
}
|
||||
safe_aligned_free(mVU->prog.prog);
|
||||
}
|
||||
safe_delete_array(mVU->prog.progList);
|
||||
safe_delete(mVU->regAlloc);
|
||||
}
|
||||
|
||||
// Clears Block Data in specified range
|
||||
|
@ -139,7 +141,7 @@ microVUf(void) mVUclearProg(int progIndex) {
|
|||
mVUprogI.ranges.total = -1;
|
||||
}
|
||||
for (u32 i = 0; i < (mVU->progSize / 2); i++) {
|
||||
microBlockManager::Delete(mVUprogI.block[i]);
|
||||
safe_delete(mVUprogI.block[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -39,12 +39,6 @@ private:
|
|||
int listI;
|
||||
|
||||
public:
|
||||
// Use instead of normal 'delete'
|
||||
static void Delete(microBlockManager* &dead) {
|
||||
if (!dead) return;
|
||||
dead->~microBlockManager();
|
||||
safe_delete(dead);
|
||||
}
|
||||
microBlockManager() {
|
||||
listI = -1;
|
||||
blockList.block = NULL;
|
||||
|
@ -121,7 +115,7 @@ struct microProgram {
|
|||
|
||||
#define mMaxProg ((mVU->index)?400:8) // The amount of Micro Programs Recs will 'remember' (For n = 1, 2, 4, 8, 16, etc...)
|
||||
struct microProgManager {
|
||||
microIR<mProgSize> allocInfo; // IR information
|
||||
microIR<mProgSize> IRinfo; // IR information
|
||||
microProgram* prog; // Store MicroPrograms in memory
|
||||
int* progList; // List of program indexes ordered by age (ordered from newest to oldest)
|
||||
int max; // Max Number of MicroPrograms minus 1
|
||||
|
@ -150,7 +144,8 @@ struct microVU {
|
|||
u32 progSize; // VU Micro Memory Size (in u32's)
|
||||
u32 cacheSize; // VU Cache Size
|
||||
|
||||
microProgManager prog; // Micro Program Data
|
||||
microProgManager prog; // Micro Program Data
|
||||
microRegAlloc* regAlloc; // Reg Alloc Class
|
||||
|
||||
FILE* logFile; // Log File Pointer
|
||||
VURegs* regs; // VU Regs Struct
|
||||
|
|
|
@ -22,614 +22,6 @@
|
|||
// Micro VU - Pass 2 Functions
|
||||
//------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// FMAC1 - Normal FMAC Opcodes
|
||||
//------------------------------------------------------------------
|
||||
|
||||
#define getReg(reg, _reg_) { \
|
||||
mVUloadReg(reg, (uptr)&mVU->regs->VF[_reg_].UL[0], _X_Y_Z_W); \
|
||||
if (CHECK_VU_EXTRA_OVERFLOW) mVUclamp2(reg, xmmT2, _X_Y_Z_W); \
|
||||
}
|
||||
|
||||
#define getZero(reg) { \
|
||||
if (_W) { mVUloadReg(reg, (uptr)&mVU->regs->VF[0].UL[0], _X_Y_Z_W); } \
|
||||
else { SSE_XORPS_XMM_to_XMM(reg, reg); } \
|
||||
}
|
||||
|
||||
#define getReg6(reg, _reg_) { \
|
||||
if (!_reg_) { getZero(reg); } \
|
||||
else { getReg(reg, _reg_); } \
|
||||
}
|
||||
|
||||
microVUt(void) mVUallocFMAC1a(mV, int& Fd, int& Fs, int& Ft) {
|
||||
Fs = xmmFs;
|
||||
Ft = xmmFt;
|
||||
Fd = xmmFs;
|
||||
getReg6(Fs, _Fs_);
|
||||
if (_Ft_ == _Fs_) { Ft = Fs; }
|
||||
else { getReg6(Ft, _Ft_); }
|
||||
}
|
||||
|
||||
microVUt(void) mVUallocFMAC1b(mV, int& Fd) {
|
||||
if (!_Fd_) return;
|
||||
if (CHECK_VU_OVERFLOW) mVUclamp1(Fd, xmmT1, _X_Y_Z_W);
|
||||
mVUsaveReg(Fd, (uptr)&mVU->regs->VF[_Fd_].UL[0], _X_Y_Z_W, 1);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// FMAC2 - ABS/FTOI/ITOF Opcodes
|
||||
//------------------------------------------------------------------
|
||||
|
||||
microVUt(void) mVUallocFMAC2a(mV, int& Fs, int& Ft) {
|
||||
Fs = xmmFs;
|
||||
Ft = xmmFs;
|
||||
getReg6(Fs, _Fs_);
|
||||
}
|
||||
|
||||
microVUt(void) mVUallocFMAC2b(mV, int& Ft) {
|
||||
if (!_Ft_) return;
|
||||
//if (CHECK_VU_OVERFLOW) mVUclamp1<vuIndex>(Ft, xmmT1, _X_Y_Z_W);
|
||||
mVUsaveReg(Ft, (uptr)&mVU->regs->VF[_Ft_].UL[0], _X_Y_Z_W, 1);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// FMAC3 - BC(xyzw) FMAC Opcodes
|
||||
//------------------------------------------------------------------
|
||||
|
||||
#define getReg3SS(reg, _reg_) { \
|
||||
mVUloadReg(reg, (uptr)&mVU->regs->VF[_reg_].UL[0], (1 << (3 - _bc_))); \
|
||||
if (CHECK_VU_EXTRA_OVERFLOW) mVUclamp2(reg, xmmT2, (1 << (3 - _bc_))); \
|
||||
}
|
||||
|
||||
#define getReg3(reg, _reg_) { \
|
||||
mVUloadReg(reg, (uptr)&mVU->regs->VF[_reg_].UL[0], (1 << (3 - _bc_))); \
|
||||
if (CHECK_VU_EXTRA_OVERFLOW) mVUclamp2(reg, xmmT2, (1 << (3 - _bc_))); \
|
||||
mVUunpack_xyzw(reg, reg, 0); \
|
||||
}
|
||||
|
||||
#define getZero3SS(reg) { \
|
||||
if (_bc_w) { mVUloadReg(reg, (uptr)&mVU->regs->VF[0].UL[0], 1); } \
|
||||
else { SSE_XORPS_XMM_to_XMM(reg, reg); } \
|
||||
}
|
||||
|
||||
#define getZero3(reg) { \
|
||||
if (_bc_w) { \
|
||||
mVUloadReg(reg, (uptr)&mVU->regs->VF[0].UL[0], 1); \
|
||||
mVUunpack_xyzw(reg, reg, 0); \
|
||||
} \
|
||||
else { SSE_XORPS_XMM_to_XMM(reg, reg); } \
|
||||
}
|
||||
|
||||
microVUt(void) mVUallocFMAC3a(mV, int& Fd, int& Fs, int& Ft) {
|
||||
Fs = xmmFs;
|
||||
Ft = xmmFt;
|
||||
Fd = xmmFs;
|
||||
if (_XYZW_SS) {
|
||||
getReg6(Fs, _Fs_);
|
||||
if ( (_Ft_ == _Fs_) && ((_X && _bc_x) || (_Y && _bc_y) || (_Z && _bc_z) || (_W && _bc_w)) ) {
|
||||
Ft = Fs;
|
||||
}
|
||||
else if (!_Ft_) { getZero3SS(Ft); }
|
||||
else { getReg3SS(Ft, _Ft_); }
|
||||
}
|
||||
else {
|
||||
getReg6(Fs, _Fs_);
|
||||
if (!_Ft_) { getZero3(Ft); }
|
||||
else { getReg3(Ft, _Ft_); }
|
||||
}
|
||||
}
|
||||
|
||||
microVUt(void) mVUallocFMAC3b(mV, int& Fd) {
|
||||
mVUallocFMAC1b(mVU, Fd);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// FMAC4 - FMAC Opcodes Storing Result to ACC
|
||||
//------------------------------------------------------------------
|
||||
|
||||
#define getReg4(reg, _reg_) { \
|
||||
mVUloadReg(reg, (uptr)&mVU->regs->VF[_reg_].UL[0], _xyzw_ACC); \
|
||||
if (CHECK_VU_EXTRA_OVERFLOW) mVUclamp2(reg, xmmT2, _xyzw_ACC); \
|
||||
}
|
||||
|
||||
#define getZero4(reg) { \
|
||||
if (_W) { mVUloadReg(reg, (uptr)&mVU->regs->VF[0].UL[0], _xyzw_ACC); } \
|
||||
else { SSE_XORPS_XMM_to_XMM(reg, reg); } \
|
||||
}
|
||||
|
||||
microVUt(void) mVUallocFMAC4a(mV, int& ACC, int& Fs, int& Ft) {
|
||||
ACC = xmmACC;
|
||||
Fs = (_X_Y_Z_W == 15) ? xmmACC : xmmFs;
|
||||
Ft = xmmFt;
|
||||
if (_X_Y_Z_W == 8) {
|
||||
getReg6(Fs, _Fs_);
|
||||
if (_Ft_ == _Fs_) { Ft = Fs; }
|
||||
else { getReg6(Ft, _Ft_); }
|
||||
}
|
||||
else {
|
||||
if (!_Fs_) { getZero4(Fs); }
|
||||
else { getReg4(Fs, _Fs_); }
|
||||
|
||||
if (_Ft_ == _Fs_) { Ft = Fs; }
|
||||
else if (!_Ft_) { getZero4(Ft); }
|
||||
else { getReg4(Ft, _Ft_); }
|
||||
}
|
||||
}
|
||||
|
||||
microVUt(void) mVUallocFMAC4b(mV, int& ACC, int& Fs) {
|
||||
if (CHECK_VU_OVERFLOW) mVUclamp1(Fs, xmmT1, _xyzw_ACC);
|
||||
mVUmergeRegs(ACC, Fs, _X_Y_Z_W);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// FMAC5 - FMAC BC(xyzw) Opcodes Storing Result to ACC
|
||||
//------------------------------------------------------------------
|
||||
|
||||
microVUt(void) mVUallocFMAC5a(mV, int& ACC, int& Fs, int& Ft) {
|
||||
ACC = xmmACC;
|
||||
Fs = (_X_Y_Z_W == 15) ? xmmACC : xmmFs;
|
||||
Ft = xmmFt;
|
||||
if (_X_Y_Z_W == 8) {
|
||||
getReg6(Fs, _Fs_);
|
||||
if ((_Ft_ == _Fs_) && _bc_x) { Ft = Fs; }
|
||||
else if (!_Ft_) { getZero3SS(Ft); }
|
||||
else { getReg3SS(Ft, _Ft_); }
|
||||
}
|
||||
else {
|
||||
if (!_Fs_) { getZero4(Fs); }
|
||||
else { getReg4(Fs, _Fs_); }
|
||||
|
||||
if (!_Ft_) { getZero3(Ft); }
|
||||
else { getReg3(Ft, _Ft_); }
|
||||
}
|
||||
}
|
||||
|
||||
microVUt(void) mVUallocFMAC5b(mV, int& ACC, int& Fs) {
|
||||
mVUallocFMAC4b(mVU, ACC, Fs);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// FMAC6 - Normal FMAC Opcodes (I Reg)
|
||||
//------------------------------------------------------------------
|
||||
|
||||
#define getIreg(reg, modXYZW) { \
|
||||
MOV32MtoR(gprT1, (uptr)&mVU->regs->VI[REG_I].UL); \
|
||||
SSE2_MOVD_R_to_XMM(reg, gprT1); \
|
||||
if (CHECK_VU_EXTRA_OVERFLOW) mVUclamp2(reg, xmmT2, 8); \
|
||||
if (!((_XYZW_SS && modXYZW) || (_X_Y_Z_W == 8))) { mVUunpack_xyzw(reg, reg, 0); } \
|
||||
}
|
||||
|
||||
microVUt(void) mVUallocFMAC6a(mV, int& Fd, int& Fs, int& Ft) {
|
||||
Fs = xmmFs;
|
||||
Ft = xmmFt;
|
||||
Fd = xmmFs;
|
||||
getIreg(Ft, 1);
|
||||
getReg6(Fs, _Fs_);
|
||||
}
|
||||
|
||||
microVUt(void) mVUallocFMAC6b(mV, int& Fd) {
|
||||
mVUallocFMAC1b(mVU, Fd);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// FMAC7 - FMAC Opcodes Storing Result to ACC (I Reg)
|
||||
//------------------------------------------------------------------
|
||||
|
||||
microVUt(void) mVUallocFMAC7a(mV, int& ACC, int& Fs, int& Ft) {
|
||||
ACC = xmmACC;
|
||||
Fs = (_X_Y_Z_W == 15) ? xmmACC : xmmFs;
|
||||
Ft = xmmFt;
|
||||
getIreg(Ft, 0);
|
||||
if (_X_Y_Z_W == 8) { getReg6(Fs, _Fs_); }
|
||||
else if (!_Fs_) { getZero4(Fs); }
|
||||
else { getReg4(Fs, _Fs_); }
|
||||
}
|
||||
|
||||
microVUt(void) mVUallocFMAC7b(mV, int& ACC, int& Fs) {
|
||||
mVUallocFMAC4b(mVU, ACC, Fs);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// FMAC8 - MADD FMAC Opcode Storing Result to Fd
|
||||
//------------------------------------------------------------------
|
||||
|
||||
microVUt(void) mVUallocFMAC8a(mV, int& Fd, int& ACC, int& Fs, int& Ft) {
|
||||
Fs = xmmFs;
|
||||
Ft = xmmFt;
|
||||
Fd = xmmFs;
|
||||
ACC = xmmACC;
|
||||
if (_X_Y_Z_W == 8) {
|
||||
getReg6(Fs, _Fs_);
|
||||
if (_Ft_ == _Fs_) { Ft = Fs; }
|
||||
else { getReg6(Ft, _Ft_); }
|
||||
}
|
||||
else {
|
||||
if (!_Fs_) { getZero4(Fs); }
|
||||
else { getReg4(Fs, _Fs_); }
|
||||
|
||||
if (_Ft_ == _Fs_) { Ft = Fs; }
|
||||
else if (!_Ft_) { getZero4(Ft); }
|
||||
else { getReg4(Ft, _Ft_); }
|
||||
}
|
||||
}
|
||||
|
||||
microVUt(void) mVUallocFMAC8b(mV, int& Fd) {
|
||||
if (!_Fd_) return;
|
||||
if (CHECK_VU_OVERFLOW) mVUclamp1(Fd, xmmT1, _xyzw_ACC);
|
||||
mVUsaveReg(Fd, (uptr)&mVU->regs->VF[_Fd_].UL[0], _X_Y_Z_W, 0);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// FMAC9 - MSUB FMAC Opcode Storing Result to Fd
|
||||
//------------------------------------------------------------------
|
||||
|
||||
microVUt(void) mVUallocFMAC9a(mV, int& Fd, int& ACC, int& Fs, int& Ft) {
|
||||
Fs = xmmFs;
|
||||
Ft = xmmFt;
|
||||
Fd = xmmT1;
|
||||
ACC = xmmT1;
|
||||
if (_X_Y_Z_W == 8) {
|
||||
getReg6(Fs, _Fs_);
|
||||
if (_Ft_ == _Fs_) { Ft = Fs; }
|
||||
else { getReg6(Ft, _Ft_); }
|
||||
}
|
||||
else {
|
||||
if (!_Fs_) { getZero4(Fs); }
|
||||
else { getReg4(Fs, _Fs_); }
|
||||
|
||||
if (_Ft_ == _Fs_) { Ft = Fs; }
|
||||
else if (!_Ft_) { getZero4(Ft); }
|
||||
else { getReg4(Ft, _Ft_); }
|
||||
}
|
||||
SSE_MOVAPS_XMM_to_XMM(ACC, xmmACC);
|
||||
}
|
||||
|
||||
microVUt(void) mVUallocFMAC9b(mV, int& Fd) {
|
||||
if (!_Fd_) return;
|
||||
if (CHECK_VU_OVERFLOW) mVUclamp1(Fd, xmmFt, _xyzw_ACC);
|
||||
mVUsaveReg(Fd, (uptr)&mVU->regs->VF[_Fd_].UL[0], _X_Y_Z_W, 0);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// FMAC10 - MADD FMAC BC(xyzw) Opcode Storing Result to Fd
|
||||
//------------------------------------------------------------------
|
||||
|
||||
microVUt(void) mVUallocFMAC10a(mV, int& Fd, int& ACC, int& Fs, int& Ft) {
|
||||
Fs = xmmFs;
|
||||
Ft = xmmFt;
|
||||
Fd = xmmFs;
|
||||
ACC = xmmACC;
|
||||
if (_X_Y_Z_W == 8) {
|
||||
getReg6(Fs, _Fs_);
|
||||
if ( (_Ft_ == _Fs_) && _bc_x) { Ft = Fs; }
|
||||
else if (!_Ft_) { getZero3SS(Ft); }
|
||||
else { getReg3SS(Ft, _Ft_); }
|
||||
}
|
||||
else {
|
||||
if (!_Fs_) { getZero4(Fs); }
|
||||
else { getReg4(Fs, _Fs_); }
|
||||
|
||||
if (!_Ft_) { getZero3(Ft); }
|
||||
else { getReg3(Ft, _Ft_); }
|
||||
}
|
||||
}
|
||||
|
||||
microVUt(void) mVUallocFMAC10b(mV, int& Fd) {
|
||||
mVUallocFMAC8b(mVU, Fd);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// FMAC11 - MSUB FMAC BC(xyzw) Opcode Storing Result to Fd
|
||||
//------------------------------------------------------------------
|
||||
|
||||
microVUt(void) mVUallocFMAC11a(mV, int& Fd, int& ACC, int& Fs, int& Ft) {
|
||||
Fs = xmmFs;
|
||||
Ft = xmmFt;
|
||||
Fd = xmmT1;
|
||||
ACC = xmmT1;
|
||||
if (_X_Y_Z_W == 8) {
|
||||
getReg6(Fs, _Fs_);
|
||||
if ( (_Ft_ == _Fs_) && _bc_x) { Ft = Fs; }
|
||||
else if (!_Ft_) { getZero3SS(Ft); }
|
||||
else { getReg3SS(Ft, _Ft_); }
|
||||
}
|
||||
else {
|
||||
if (!_Fs_) { getZero4(Fs); }
|
||||
else { getReg4(Fs, _Fs_); }
|
||||
|
||||
if (!_Ft_) { getZero3(Ft); }
|
||||
else { getReg3(Ft, _Ft_); }
|
||||
}
|
||||
SSE_MOVAPS_XMM_to_XMM(ACC, xmmACC);
|
||||
}
|
||||
|
||||
microVUt(void) mVUallocFMAC11b(mV, int& Fd) {
|
||||
mVUallocFMAC9b(mVU, Fd);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// FMAC12 - MADD FMAC Opcode Storing Result to Fd (I Reg)
|
||||
//------------------------------------------------------------------
|
||||
|
||||
microVUt(void) mVUallocFMAC12a(mV, int& Fd, int& ACC, int& Fs, int& Ft) {
|
||||
Fs = xmmFs;
|
||||
Ft = xmmFt;
|
||||
Fd = xmmFs;
|
||||
ACC = xmmACC;
|
||||
getIreg(Ft, 0);
|
||||
if (_X_Y_Z_W == 8) { getReg6(Fs, _Fs_); }
|
||||
else if (!_Fs_) { getZero4(Fs); }
|
||||
else { getReg4(Fs, _Fs_); }
|
||||
}
|
||||
|
||||
microVUt(void) mVUallocFMAC12b(mV, int& Fd) {
|
||||
mVUallocFMAC8b(mVU, Fd);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// FMAC13 - MSUB FMAC Opcode Storing Result to Fd (I Reg)
|
||||
//------------------------------------------------------------------
|
||||
|
||||
microVUt(void) mVUallocFMAC13a(mV, int& Fd, int& ACC, int& Fs, int& Ft) {
|
||||
Fs = xmmFs;
|
||||
Ft = xmmFt;
|
||||
Fd = xmmT1;
|
||||
ACC = xmmT1;
|
||||
getIreg(Ft, 0);
|
||||
if (_X_Y_Z_W == 8) { getReg6(Fs, _Fs_); }
|
||||
else if (!_Fs_) { getZero4(Fs); }
|
||||
else { getReg4(Fs, _Fs_); }
|
||||
SSE_MOVAPS_XMM_to_XMM(ACC, xmmACC);
|
||||
}
|
||||
|
||||
microVUt(void) mVUallocFMAC13b(mV, int& Fd) {
|
||||
mVUallocFMAC9b(mVU, Fd);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// FMAC14 - MADDA/MSUBA FMAC Opcodes
|
||||
//------------------------------------------------------------------
|
||||
|
||||
microVUt(void) mVUallocFMAC14a(mV, int& ACCw, int& ACCr, int& Fs, int& Ft) {
|
||||
Fs = xmmFs;
|
||||
Ft = xmmFt;
|
||||
ACCw = xmmACC;
|
||||
ACCr = ((_X_Y_Z_W == 15) || (_X_Y_Z_W == 8)) ? xmmACC : xmmT1;
|
||||
|
||||
if (_X_Y_Z_W == 8) {
|
||||
getReg6(Fs, _Fs_);
|
||||
if (_Ft_ == _Fs_) { Ft = Fs; }
|
||||
else { getReg6(Ft, _Ft_); }
|
||||
}
|
||||
else {
|
||||
if (!_Fs_) { getZero4(Fs); }
|
||||
else { getReg4(Fs, _Fs_); }
|
||||
|
||||
if (_Ft_ == _Fs_) { Ft = Fs; }
|
||||
else if (!_Ft_) { getZero4(Ft); }
|
||||
else { getReg4(Ft, _Ft_); }
|
||||
}
|
||||
SSE_MOVAPS_XMM_to_XMM(ACCr, xmmACC);
|
||||
}
|
||||
|
||||
microVUt(void) mVUallocFMAC14b(mV, int& ACCw, int& ACCr) {
|
||||
if (CHECK_VU_OVERFLOW) mVUclamp1(ACCr, xmmFt, _xyzw_ACC);
|
||||
mVUmergeRegs(ACCw, ACCr, _X_Y_Z_W);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// FMAC15 - MADDA/MSUBA BC(xyzw) FMAC Opcode
|
||||
//------------------------------------------------------------------
|
||||
|
||||
microVUt(void) mVUallocFMAC15a(mV, int& ACCw, int& ACCr, int& Fs, int& Ft) {
|
||||
Fs = xmmFs;
|
||||
Ft = xmmFt;
|
||||
ACCw = xmmACC;
|
||||
ACCr = ((_X_Y_Z_W == 15) || (_X_Y_Z_W == 8)) ? xmmACC : xmmT1;
|
||||
|
||||
if (_X_Y_Z_W == 8) {
|
||||
getReg6(Fs, _Fs_);
|
||||
if ((_Ft_ == _Fs_) && _bc_x) { Ft = Fs; }
|
||||
else if (!_Ft_) { getZero3SS(Ft); }
|
||||
else { getReg3SS(Ft, _Ft_); }
|
||||
}
|
||||
else {
|
||||
if (!_Fs_) { getZero4(Fs); }
|
||||
else { getReg4(Fs, _Fs_); }
|
||||
|
||||
if (!_Ft_) { getZero3(Ft); }
|
||||
else { getReg3(Ft, _Ft_); }
|
||||
}
|
||||
SSE_MOVAPS_XMM_to_XMM(ACCr, xmmACC);
|
||||
}
|
||||
|
||||
microVUt(void) mVUallocFMAC15b(mV, int& ACCw, int& ACCr) {
|
||||
mVUallocFMAC14b(mVU, ACCw, ACCr);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// FMAC16 - MADDA/MSUBA FMAC Opcode (I Reg)
|
||||
//------------------------------------------------------------------
|
||||
|
||||
microVUt(void) mVUallocFMAC16a(mV, int& ACCw, int& ACCr, int& Fs, int& Ft) {
|
||||
Fs = xmmFs;
|
||||
Ft = xmmFt;
|
||||
ACCw = xmmACC;
|
||||
ACCr = ((_X_Y_Z_W == 15) || (_X_Y_Z_W == 8)) ? xmmACC : xmmT1;
|
||||
getIreg(Ft, 0);
|
||||
if (_X_Y_Z_W == 8) { getReg6(Fs, _Fs_); }
|
||||
else if (!_Fs_) { getZero4(Fs); }
|
||||
else { getReg4(Fs, _Fs_); }
|
||||
SSE_MOVAPS_XMM_to_XMM(ACCr, xmmACC);
|
||||
}
|
||||
|
||||
microVUt(void) mVUallocFMAC16b(mV, int& ACCw, int& ACCr) {
|
||||
mVUallocFMAC14b(mVU, ACCw, ACCr);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// FMAC17 - CLIP FMAC Opcode
|
||||
//------------------------------------------------------------------
|
||||
|
||||
#define getReg9(reg, _reg_) { \
|
||||
mVUloadReg(reg, (uptr)&mVU->regs->VF[_reg_].UL[0], 1); \
|
||||
if (CHECK_VU_EXTRA_OVERFLOW) mVUclamp2(reg, xmmT2, 1); \
|
||||
mVUunpack_xyzw(reg, reg, 0); \
|
||||
}
|
||||
|
||||
microVUt(void) mVUallocFMAC17a(mV, int& Fs, int& Ft) {
|
||||
Fs = xmmFs;
|
||||
Ft = xmmFt;
|
||||
getReg6(Fs, _Fs_);
|
||||
getReg9(Ft, _Ft_);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// FMAC18 - OPMULA FMAC Opcode
|
||||
//------------------------------------------------------------------
|
||||
|
||||
microVUt(void) mVUallocFMAC18a(mV, int& ACC, int& Fs, int& Ft) {
|
||||
Fs = xmmFs;
|
||||
Ft = xmmFt;
|
||||
ACC = xmmACC;
|
||||
|
||||
if (!_Fs_) { getZero4(Fs); }
|
||||
else { getReg4(Fs, _Fs_); }
|
||||
|
||||
if (!_Ft_) { getZero4(Ft); }
|
||||
else { getReg4(Ft, _Ft_); }
|
||||
|
||||
SSE2_PSHUFD_XMM_to_XMM(Fs, Fs, 0xC9); // WXZY
|
||||
SSE2_PSHUFD_XMM_to_XMM(Ft, Ft, 0xD2); // WYXZ
|
||||
}
|
||||
|
||||
microVUt(void) mVUallocFMAC18b(mV, int& ACC, int& Fs) {
|
||||
mVUallocFMAC4b(mVU, ACC, Fs);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// FMAC19 - OPMSUB FMAC Opcode
|
||||
//------------------------------------------------------------------
|
||||
|
||||
microVUt(void) mVUallocFMAC19a(mV, int& Fd, int& ACC, int& Fs, int& Ft) {
|
||||
Fs = xmmFs;
|
||||
Ft = xmmFt;
|
||||
Fd = xmmT1;
|
||||
ACC = xmmT1;
|
||||
|
||||
if (!_Fs_) { getZero4(Fs); }
|
||||
else { getReg4(Fs, _Fs_); }
|
||||
|
||||
if (!_Ft_) { getZero4(Ft); }
|
||||
else { getReg4(Ft, _Ft_); }
|
||||
|
||||
SSE2_PSHUFD_XMM_to_XMM(Fs, Fs, 0xC9); // WXZY
|
||||
SSE2_PSHUFD_XMM_to_XMM(Ft, Ft, 0xD2); // WYXZ
|
||||
SSE_MOVAPS_XMM_to_XMM(ACC, xmmACC);
|
||||
}
|
||||
|
||||
microVUt(void) mVUallocFMAC19b(mV, int& Fd) {
|
||||
mVUallocFMAC9b(mVU, Fd);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// FMAC22 - Normal FMAC Opcodes (Q Reg)
|
||||
//------------------------------------------------------------------
|
||||
|
||||
#define getQreg(reg) { \
|
||||
mVUunpack_xyzw(reg, xmmPQ, mVUinfo.readQ); \
|
||||
/*if (CHECK_VU_EXTRA_OVERFLOW) mVUclamp2<vuIndex>(reg, xmmT1, 15);*/ \
|
||||
}
|
||||
|
||||
microVUt(void) mVUallocFMAC22a(mV, int& Fd, int& Fs, int& Ft) {
|
||||
Fs = xmmFs;
|
||||
Ft = xmmFt;
|
||||
Fd = xmmFs;
|
||||
getQreg(Ft);
|
||||
getReg6(Fs, _Fs_);
|
||||
}
|
||||
|
||||
microVUt(void) mVUallocFMAC22b(mV, int& Fd) {
|
||||
mVUallocFMAC1b(mVU, Fd);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// FMAC23 - FMAC Opcodes Storing Result to ACC (Q Reg)
|
||||
//------------------------------------------------------------------
|
||||
|
||||
microVUt(void) mVUallocFMAC23a(mV, int& ACC, int& Fs, int& Ft) {
|
||||
ACC = xmmACC;
|
||||
Fs = (_X_Y_Z_W == 15) ? xmmACC : xmmFs;
|
||||
Ft = xmmFt;
|
||||
getQreg(Ft);
|
||||
if (_X_Y_Z_W == 8) { getReg6(Fs, _Fs_); }
|
||||
else if (!_Fs_) { getZero4(Fs); }
|
||||
else { getReg4(Fs, _Fs_); }
|
||||
}
|
||||
|
||||
microVUt(void) mVUallocFMAC23b(mV, int& ACC, int& Fs) {
|
||||
mVUallocFMAC4b(mVU, ACC, Fs);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// FMAC24 - MADD FMAC Opcode Storing Result to Fd (Q Reg)
|
||||
//------------------------------------------------------------------
|
||||
|
||||
microVUt(void) mVUallocFMAC24a(mV, int& Fd, int& ACC, int& Fs, int& Ft) {
|
||||
Fs = xmmFs;
|
||||
Ft = xmmFt;
|
||||
Fd = xmmFs;
|
||||
ACC = xmmACC;
|
||||
getQreg(Ft);
|
||||
if (_X_Y_Z_W == 8) { getReg6(Fs, _Fs_); }
|
||||
else if (!_Fs_) { getZero4(Fs); }
|
||||
else { getReg4(Fs, _Fs_); }
|
||||
}
|
||||
|
||||
microVUt(void) mVUallocFMAC24b(mV, int& Fd) {
|
||||
mVUallocFMAC8b(mVU, Fd);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// FMAC25 - MSUB FMAC Opcode Storing Result to Fd (Q Reg)
|
||||
//------------------------------------------------------------------
|
||||
|
||||
microVUt(void) mVUallocFMAC25a(mV, int& Fd, int& ACC, int& Fs, int& Ft) {
|
||||
Fs = xmmFs;
|
||||
Ft = xmmFt;
|
||||
Fd = xmmT1;
|
||||
ACC = xmmT1;
|
||||
getQreg(Ft);
|
||||
if (_X_Y_Z_W == 8) { getReg6(Fs, _Fs_); }
|
||||
else if (!_Fs_) { getZero4(Fs); }
|
||||
else { getReg4(Fs, _Fs_); }
|
||||
SSE_MOVAPS_XMM_to_XMM(ACC, xmmACC);
|
||||
}
|
||||
|
||||
microVUt(void) mVUallocFMAC25b(mV, int& Fd) {
|
||||
mVUallocFMAC9b(mVU, Fd);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// FMAC26 - MADDA/MSUBA FMAC Opcode (Q Reg)
|
||||
//------------------------------------------------------------------
|
||||
|
||||
microVUt(void) mVUallocFMAC26a(mV, int& ACCw, int& ACCr, int& Fs, int& Ft) {
|
||||
Fs = xmmFs;
|
||||
Ft = xmmFt;
|
||||
ACCw = xmmACC;
|
||||
ACCr = ((_X_Y_Z_W == 15) || (_X_Y_Z_W == 8)) ? xmmACC : xmmT1;
|
||||
getQreg(Ft);
|
||||
if (_X_Y_Z_W == 8) { getReg6(Fs, _Fs_); }
|
||||
else if (!_Fs_) { getZero4(Fs); }
|
||||
else { getReg4(Fs, _Fs_); }
|
||||
SSE_MOVAPS_XMM_to_XMM(ACCr, xmmACC);
|
||||
}
|
||||
|
||||
microVUt(void) mVUallocFMAC26b(mV, int& ACCw, int& ACCr) {
|
||||
mVUallocFMAC14b(mVU, ACCw, ACCr);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Flag Allocators
|
||||
//------------------------------------------------------------------
|
||||
|
@ -707,9 +99,8 @@ microVUt(void) mVUallocCFLAGb(mV, int reg, int fInstance) {
|
|||
//------------------------------------------------------------------
|
||||
|
||||
microVUt(void) mVUallocVIa(mV, int GPRreg, int _reg_) {
|
||||
if (!_reg_) { XOR32RtoR(GPRreg, GPRreg); }
|
||||
else if (isMMX(_reg_)) { MOVD32MMXtoR(GPRreg, mmVI(_reg_)); }
|
||||
else { MOVZX32Rm16toR(GPRreg, gprR, (_reg_ - 9) * 16); }
|
||||
if (!_reg_) { XOR32RtoR(GPRreg, GPRreg); }
|
||||
else { MOVZX32Rm16toR(GPRreg, gprR, (_reg_ - 9) * 16); }
|
||||
}
|
||||
|
||||
microVUt(void) mVUallocVIb(mV, int GPRreg, int _reg_) {
|
||||
|
@ -718,15 +109,26 @@ microVUt(void) mVUallocVIb(mV, int GPRreg, int _reg_) {
|
|||
MOV32RtoM((uptr)&mVU->VIbackup, gprR);
|
||||
MOV32ItoR(gprR, Roffset);
|
||||
}
|
||||
if (_reg_ == 0) { return; }
|
||||
else if (isMMX(_reg_)) { MOVD32RtoMMX(mmVI(_reg_), GPRreg); }
|
||||
else if (_reg_ < 16) { MOV16RtoRm(gprR, GPRreg, (_reg_ - 9) * 16); }
|
||||
if (_reg_ == 0) { return; }
|
||||
else if (_reg_ < 16) { MOV16RtoRm(gprR, GPRreg, (_reg_ - 9) * 16); }
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// P Reg Allocator
|
||||
// I/Q/P Reg Allocators
|
||||
//------------------------------------------------------------------
|
||||
|
||||
#define getIreg(reg, modXYZW) { \
|
||||
MOV32MtoR(gprT1, (uptr)&mVU->regs->VI[REG_I].UL); \
|
||||
SSE2_MOVD_R_to_XMM(reg, gprT1); \
|
||||
if (CHECK_VU_EXTRA_OVERFLOW) mVUclamp2(reg, xmmT2, 8); \
|
||||
if (!((_XYZW_SS && modXYZW) || (_X_Y_Z_W == 8))) { mVUunpack_xyzw(reg, reg, 0); } \
|
||||
}
|
||||
|
||||
#define getQreg(reg) { \
|
||||
mVUunpack_xyzw(reg, xmmPQ, mVUinfo.readQ); \
|
||||
/*if (CHECK_VU_EXTRA_OVERFLOW) mVUclamp2<vuIndex>(reg, xmmT1, 15);*/ \
|
||||
}
|
||||
|
||||
#define getPreg(reg) { \
|
||||
mVUunpack_xyzw(reg, xmmPQ, (2 + mVUinfo.readP)); \
|
||||
/*if (CHECK_VU_EXTRA_OVERFLOW) mVUclamp2(reg, xmmT1, 15);*/ \
|
||||
|
@ -736,6 +138,21 @@ microVUt(void) mVUallocVIb(mV, int GPRreg, int _reg_) {
|
|||
// Lower Instruction Allocator Helpers
|
||||
//------------------------------------------------------------------
|
||||
|
||||
#define getReg(reg, _reg_) { \
|
||||
mVUloadReg(reg, (uptr)&mVU->regs->VF[_reg_].UL[0], _X_Y_Z_W); \
|
||||
if (CHECK_VU_EXTRA_OVERFLOW) mVUclamp2(reg, xmmT2, _X_Y_Z_W); \
|
||||
}
|
||||
|
||||
#define getZero(reg) { \
|
||||
if (_W) { mVUloadReg(reg, (uptr)&mVU->regs->VF[0].UL[0], _X_Y_Z_W); } \
|
||||
else { SSE_XORPS_XMM_to_XMM(reg, reg); } \
|
||||
}
|
||||
|
||||
#define getReg6(reg, _reg_) { \
|
||||
if (!_reg_) { getZero(reg); } \
|
||||
else { getReg(reg, _reg_); } \
|
||||
}
|
||||
|
||||
#define getReg5(reg, _reg_, _fxf_) { \
|
||||
if (!_reg_) { \
|
||||
if (_fxf_ < 3) { SSE_XORPS_XMM_to_XMM(reg, reg); } \
|
||||
|
|
|
@ -174,6 +174,9 @@ microVUt(void) mVUsetupBranch(mV, int* xStatus, int* xMac, int* xClip, int xCycl
|
|||
|
||||
// Shuffle P/Q regs since every block starts at instance #0
|
||||
if (mVU->p || mVU->q) { SSE2_PSHUFD_XMM_to_XMM(xmmPQ, xmmPQ, shufflePQ); }
|
||||
|
||||
// Flush Allocated Regs
|
||||
mVU->regAlloc->flushAll();
|
||||
}
|
||||
|
||||
microVUt(void) mVUincCycles(mV, int x) {
|
||||
|
@ -367,6 +370,9 @@ microVUr(void*) mVUcompile(microVU* mVU, u32 startPC, uptr pState) {
|
|||
|
||||
// Setup Program Bounds/Range
|
||||
mVUsetupRange(mVU, startPC, 1);
|
||||
|
||||
// Reset regAlloc
|
||||
mVU->regAlloc->reset();
|
||||
|
||||
// First Pass
|
||||
iPC = startPC / 4;
|
||||
|
@ -512,8 +518,8 @@ microVUr(void*) mVUcompile(microVU* mVU, u32 startPC, uptr pState) {
|
|||
// Check if branch-block has already been compiled
|
||||
blockCreate(branchAddr/8);
|
||||
pBlock = mVUblocks[branchAddr/8]->search((microRegInfo*)&mVUregs);
|
||||
if (pBlock) { xJMP( pBlock->x86ptrStart ); }
|
||||
else { mVUblockFetch(mVU, branchAddr, (uptr)&mVUregs); }
|
||||
if (pBlock) { xJMP( pBlock->x86ptrStart ); }
|
||||
else { mVUblockFetch(mVU, branchAddr, (uptr)&mVUregs); }
|
||||
}
|
||||
else {
|
||||
uptr jumpAddr;
|
||||
|
|
|
@ -68,17 +68,11 @@ void mVUdispatcherA(mV) {
|
|||
SSE_SHUFPS_XMM_to_XMM (xmmT1, xmmT1, 0);
|
||||
SSE_MOVAPS_XMM_to_M128((uptr)mVU->clipFlag, xmmT1);
|
||||
|
||||
SSE_MOVAPS_M128_to_XMM(xmmACC, (uptr)&mVU->regs->ACC.UL[0]);
|
||||
SSE_MOVAPS_M128_to_XMM(xmmMax, (uptr)mVU_maxvals);
|
||||
SSE_MOVAPS_M128_to_XMM(xmmMin, (uptr)mVU_minvals);
|
||||
//SSE_MOVAPS_M128_to_XMM(xmmACC, (uptr)&mVU->regs->ACC.UL[0]);
|
||||
SSE_MOVAPS_M128_to_XMM(xmmT1, (uptr)&mVU->regs->VI[REG_P].UL);
|
||||
SSE_MOVAPS_M128_to_XMM(xmmPQ, (uptr)&mVU->regs->VI[REG_Q].UL);
|
||||
SSE_SHUFPS_XMM_to_XMM(xmmPQ, xmmT1, 0); // wzyx = PPQQ
|
||||
|
||||
for (int i = 1; i < 16; i++) {
|
||||
if (isMMX(i)) { MOVQMtoR(mmVI(i), (uptr)&mVU->regs->VI[i].UL); }
|
||||
}
|
||||
|
||||
// Jump to Recompiled Code Block
|
||||
JMPR(EAX);
|
||||
}
|
||||
|
@ -91,11 +85,7 @@ void mVUdispatcherB(mV) {
|
|||
SSE_LDMXCSR((uptr)&g_sseMXCSR);
|
||||
|
||||
// Save Regs (Other Regs Saved in mVUcompile)
|
||||
SSE_MOVAPS_XMM_to_M128((uptr)&mVU->regs->ACC.UL[0], xmmACC);
|
||||
|
||||
for (int i = 1; i < 16; i++) {
|
||||
if (isMMX(i)) { MOVDMMXtoM((uptr)&mVU->regs->VI[i].UL, mmVI(i)); }
|
||||
}
|
||||
//SSE_MOVAPS_XMM_to_M128((uptr)&mVU->regs->ACC.UL[0], xmmACC);
|
||||
|
||||
// __fastcall = The first two DWORD or smaller arguments are passed in ECX and EDX registers; all other arguments are passed right to left.
|
||||
if (!isVU1) { CALLFunc((uptr)mVUcleanUpVU0); }
|
||||
|
@ -107,7 +97,6 @@ void mVUdispatcherB(mV) {
|
|||
POP32R(EBP);
|
||||
POP32R(EBX);
|
||||
|
||||
if (isMMX(1)) EMMS();
|
||||
RET();
|
||||
|
||||
mVUcacheCheck(x86Ptr, mVU->cache, 0x1000);
|
||||
|
|
|
@ -156,3 +156,167 @@ struct microIR {
|
|||
u32 startPC; // Start PC for Cur Block
|
||||
u32 sFlagHack; // Optimize out all Status flag updates if microProgram doesn't use Status flags
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Reg Alloc
|
||||
//------------------------------------------------------------------
|
||||
|
||||
void mVUmergeRegs(int dest, int src, int xyzw, bool modXYZW);
|
||||
void mVUsaveReg(int reg, uptr offset, int xyzw, bool modXYZW);
|
||||
void mVUloadReg(int reg, uptr offset, int xyzw);
|
||||
|
||||
struct microXMM {
|
||||
int reg; // VF Reg Number Stored (-1 = Temp; 0 = vf0 and will not be written back; 32 = ACC)
|
||||
int xyzw; // xyzw to write back (0 = Don't write back anything AND cached vfReg has all vectors valid)
|
||||
int count; // Count of when last used
|
||||
bool isNeeded; // Is needed for current instruction
|
||||
};
|
||||
|
||||
#define xmmTotal 7 // Don't allocate PQ?
|
||||
class microRegAlloc {
|
||||
private:
|
||||
microXMM xmmReg[xmmTotal];
|
||||
VURegs* vuRegs;
|
||||
int counter;
|
||||
int findFreeRegRec(int startIdx) {
|
||||
for (int i = startIdx; i < xmmTotal; i++) {
|
||||
if (!xmmReg[i].isNeeded) {
|
||||
if ((i+1) >= xmmTotal) return i;
|
||||
int x = findFreeRegRec(i+1);
|
||||
if (x == -1) return i;
|
||||
return ((xmmReg[i].count < xmmReg[x].count) ? i : x);
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
int findFreeReg() {
|
||||
for (int i = 0; i < xmmTotal; i++) {
|
||||
if (!xmmReg[i].isNeeded && (xmmReg[i].reg < 0)) {
|
||||
return i; // Reg is not needed and was a temp reg
|
||||
}
|
||||
}
|
||||
int x = findFreeRegRec(0);
|
||||
if (x < 0) { DevCon::Error("microVU Allocation Error!"); return 0; }
|
||||
return x;
|
||||
}
|
||||
|
||||
public:
|
||||
microRegAlloc(VURegs* vuRegsPtr) {
|
||||
vuRegs = vuRegsPtr;
|
||||
reset();
|
||||
}
|
||||
void reset() {
|
||||
for (int i = 0; i < xmmTotal; i++) {
|
||||
clearReg(i);
|
||||
}
|
||||
counter = 0;
|
||||
}
|
||||
void flushAll() {
|
||||
for (int i = 0; i < xmmTotal; i++) {
|
||||
writeBackReg(i);
|
||||
}
|
||||
}
|
||||
void clearReg(int reg) {
|
||||
xmmReg[reg].reg = -1;
|
||||
xmmReg[reg].count = 0;
|
||||
xmmReg[reg].xyzw = 0;
|
||||
xmmReg[reg].isNeeded = 0;
|
||||
}
|
||||
void writeBackReg(int reg) {
|
||||
if ((xmmReg[reg].reg > 0) && xmmReg[reg].xyzw) { // Reg was modified and not Temp or vf0
|
||||
if (xmmReg[reg].reg == 32) mVUsaveReg(reg, (uptr)&vuRegs->ACC.UL[0], xmmReg[reg].xyzw, 1);
|
||||
else mVUsaveReg(reg, (uptr)&vuRegs->VF[xmmReg[reg].reg].UL[0], xmmReg[reg].xyzw, 1);
|
||||
for (int i = 0; i < xmmTotal; i++) {
|
||||
if (i == reg) continue;
|
||||
if (xmmReg[i].reg == xmmReg[reg].reg) {
|
||||
clearReg(i); // Invalidate any Cached Regs of same vf Reg
|
||||
}
|
||||
}
|
||||
if (xmmReg[reg].xyzw == 0xf) { // Make Cached Reg if All Vectors were Modified
|
||||
xmmReg[reg].count = counter;
|
||||
xmmReg[reg].xyzw = 0;
|
||||
xmmReg[reg].isNeeded = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
clearReg(reg); // Clear Reg
|
||||
}
|
||||
void clearNeeded(int reg) {
|
||||
xmmReg[reg].isNeeded = 0;
|
||||
if (xmmReg[reg].xyzw) { // Reg was modified
|
||||
if (xmmReg[reg].reg > 0) {
|
||||
int mergeRegs = 0;
|
||||
if (xmmReg[reg].xyzw < 0xf) { mergeRegs = 1; } // Try to merge partial writes
|
||||
for (int i = 0; i < xmmTotal; i++) { // Invalidate any other read-only regs of same vfReg
|
||||
if (i == reg) continue;
|
||||
if (xmmReg[i].reg == xmmReg[reg].reg) {
|
||||
if (xmmReg[i].xyzw && xmmReg[i].xyzw < 0xf) DevCon::Error("microVU Error: clearNeeded() [%d]", params xmmReg[i].reg);
|
||||
if (mergeRegs == 1) {
|
||||
mVUmergeRegs(i, reg, xmmReg[reg].xyzw, 1);
|
||||
xmmReg[i].xyzw = 0xf;
|
||||
xmmReg[i].count = counter;
|
||||
mergeRegs = 2;
|
||||
}
|
||||
else clearReg(i);
|
||||
}
|
||||
}
|
||||
if (mergeRegs == 2) clearReg(reg); // Clear Current Reg if Merged
|
||||
else if (mergeRegs) writeBackReg(reg); // Write Back Partial Writes if couldn't merge
|
||||
}
|
||||
else clearReg(reg); // If Reg was temp or vf0, then invalidate itself
|
||||
}
|
||||
}
|
||||
int allocReg(int vfLoadReg = -1, int vfWriteReg = -1, int xyzw = 0, bool cloneWrite = 1) {
|
||||
counter++;
|
||||
if (vfLoadReg >= 0) { // Search For Cached Regs
|
||||
for (int i = 0; i < xmmTotal; i++) {
|
||||
if ((xmmReg[i].reg == vfLoadReg) && (!xmmReg[i].xyzw // Reg Was Not Modified
|
||||
|| (/*!xmmReg[i].isNeeded &&*/ xmmReg[i].reg && (xmmReg[i].xyzw==0xf)))) { // Reg Had All Vectors Modified and != VF0
|
||||
int z = i;
|
||||
if (vfWriteReg >= 0) { // Reg will be modified
|
||||
if (cloneWrite) { // Clone Reg so as not to use the same Cached Reg
|
||||
z = findFreeReg();
|
||||
writeBackReg(z);
|
||||
if (z!=i && xyzw==8) SSE_MOVAPS_XMM_to_XMM (z, i);
|
||||
else if (xyzw == 4) SSE2_PSHUFD_XMM_to_XMM(z, i, 1);
|
||||
else if (xyzw == 2) SSE2_PSHUFD_XMM_to_XMM(z, i, 2);
|
||||
else if (xyzw == 1) SSE2_PSHUFD_XMM_to_XMM(z, i, 3);
|
||||
else if (z != i) SSE_MOVAPS_XMM_to_XMM (z, i);
|
||||
xmmReg[i].count = counter; // Reg i was used, so update counter
|
||||
}
|
||||
else { // Don't clone reg, but shuffle to adjust for SS ops
|
||||
if ((vfLoadReg != vfWriteReg) || (xyzw != 0xf)) { writeBackReg(z); }
|
||||
else if (xyzw == 4) SSE2_PSHUFD_XMM_to_XMM(z, i, 1);
|
||||
else if (xyzw == 2) SSE2_PSHUFD_XMM_to_XMM(z, i, 2);
|
||||
else if (xyzw == 1) SSE2_PSHUFD_XMM_to_XMM(z, i, 3);
|
||||
}
|
||||
xmmReg[z].reg = vfWriteReg;
|
||||
xmmReg[z].xyzw = xyzw;
|
||||
}
|
||||
xmmReg[z].count = counter;
|
||||
xmmReg[z].isNeeded = 1;
|
||||
return z;
|
||||
}
|
||||
}
|
||||
}
|
||||
int x = findFreeReg();
|
||||
writeBackReg(x);
|
||||
|
||||
if (vfWriteReg >= 0) { // Reg Will Be Modified (allow partial reg loading)
|
||||
if ((vfLoadReg == 0) && !(xyzw & 1)) { SSE2_PXOR_XMM_to_XMM(x, x); }
|
||||
else if (vfLoadReg == 32) mVUloadReg(x, (uptr)&vuRegs->ACC.UL[0], xyzw);
|
||||
else if (vfLoadReg >= 0) mVUloadReg(x, (uptr)&vuRegs->VF[vfLoadReg].UL[0], xyzw);
|
||||
xmmReg[x].reg = vfWriteReg;
|
||||
xmmReg[x].xyzw = xyzw;
|
||||
}
|
||||
else { // Reg Will Not Be Modified (always load full reg for caching)
|
||||
if (vfLoadReg == 32) SSE_MOVAPS_M128_to_XMM(x, (uptr)&vuRegs->ACC.UL[0]);
|
||||
else if (vfLoadReg >= 0) SSE_MOVAPS_M128_to_XMM(x, (uptr)&vuRegs->VF[vfLoadReg].UL[0]);
|
||||
xmmReg[x].reg = vfLoadReg;
|
||||
xmmReg[x].xyzw = 0;
|
||||
}
|
||||
xmmReg[x].count = counter;
|
||||
xmmReg[x].isNeeded = 1;
|
||||
return x;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -60,9 +60,9 @@ mVUop(mVU_DIV) {
|
|||
MOV32ItoM((uptr)&mVU->divFlag, divD); // Zero divide (only when not 0/0)
|
||||
x86SetJ8(bjmp);
|
||||
|
||||
SSE_XORPS_XMM_to_XMM(xmmFs, xmmFt);
|
||||
SSE_XORPS_XMM_to_XMM (xmmFs, xmmFt);
|
||||
SSE_ANDPS_M128_to_XMM(xmmFs, (uptr)mVU_signbit);
|
||||
SSE_ORPS_XMM_to_XMM(xmmFs, xmmMax); // If division by zero, then xmmFs = +/- fmax
|
||||
SSE_ORPS_M128_to_XMM (xmmFs, (uptr)mVU_maxvals); // If division by zero, then xmmFs = +/- fmax
|
||||
|
||||
djmp = JMP8(0);
|
||||
x86SetJ8(cjmp);
|
||||
|
@ -87,7 +87,7 @@ mVUop(mVU_SQRT) {
|
|||
MOV32ItoM((uptr)&mVU->divFlag, 0); // Clear I/D flags
|
||||
testNeg(xmmFt, gprT1, ajmp); // Check for negative sqrt
|
||||
|
||||
if (CHECK_VU_OVERFLOW) SSE_MINSS_XMM_to_XMM(xmmFt, xmmMax); // Clamp infinities (only need to do positive clamp since xmmFt is positive)
|
||||
if (CHECK_VU_OVERFLOW) SSE_MINSS_M32_to_XMM(xmmFt, (uptr)mVU_maxvals); // Clamp infinities (only need to do positive clamp since xmmFt is positive)
|
||||
SSE_SQRTSS_XMM_to_XMM(xmmFt, xmmFt);
|
||||
if (mVUinfo.writeQ) SSE2_PSHUFD_XMM_to_XMM(xmmPQ, xmmPQ, 0xe1);
|
||||
SSE_MOVSS_XMM_to_XMM(xmmPQ, xmmFt);
|
||||
|
@ -119,7 +119,7 @@ mVUop(mVU_RSQRT) {
|
|||
x86SetJ8(cjmp);
|
||||
|
||||
SSE_ANDPS_M128_to_XMM(xmmFs, (uptr)mVU_signbit);
|
||||
SSE_ORPS_XMM_to_XMM(xmmFs, xmmMax); // xmmFs = +/-Max
|
||||
SSE_ORPS_M128_to_XMM (xmmFs, (uptr)mVU_maxvals); // xmmFs = +/-Max
|
||||
|
||||
djmp = JMP8(0);
|
||||
x86SetJ8(ajmp);
|
||||
|
@ -666,11 +666,10 @@ mVUop(mVU_ISUB) {
|
|||
SUB16RtoR(gprT1, gprT2);
|
||||
mVUallocVIb(mVU, gprT1, _Id_);
|
||||
}
|
||||
else if (!isMMX(_Id_)) {
|
||||
else {
|
||||
XOR32RtoR(gprT1, gprT1);
|
||||
mVUallocVIb(mVU, gprT1, _Id_);
|
||||
}
|
||||
else { PXORRtoR(mmVI(_Id_), mmVI(_Id_)); }
|
||||
}
|
||||
pass3 { mVUlog("ISUB vi%02d, vi%02d, vi%02d", _Fd_, _Fs_, _Ft_); }
|
||||
}
|
||||
|
|
|
@ -118,21 +118,12 @@ declareAllVariables
|
|||
#define xmmT1 0 // Temp Reg
|
||||
#define xmmFs 1 // Holds the Value of Fs (writes back result Fd)
|
||||
#define xmmFt 2 // Holds the Value of Ft
|
||||
#define xmmACC 3 // Holds ACC
|
||||
#define xmmMax 4 // Holds mVU_maxvals
|
||||
#define xmmMin 5 // Holds mVU_minvals
|
||||
#define xmmT2 6 // Temp Reg?
|
||||
#define xmmT2 3 // Temp Reg?
|
||||
#define xmmT3 4 // Temp Reg?
|
||||
#define xmmT4 5 // Temp Reg?
|
||||
#define xmmACC 6 // Holds ACC
|
||||
#define xmmPQ 7 // Holds the Value and Backup Values of P and Q regs
|
||||
|
||||
#define mmxVI1 0 // Holds VI 1
|
||||
#define mmxVI2 1 // Holds VI 2
|
||||
#define mmxVI3 2 // Holds VI 3
|
||||
#define mmxVI4 3 // Holds VI 4
|
||||
#define mmxVI5 4 // Holds VI 5
|
||||
#define mmxVI6 5 // Holds VI 6
|
||||
#define mmxVI7 6 // Holds VI 7
|
||||
#define mmxVI8 7 // Holds VI 8
|
||||
|
||||
#define gprT1 0 // Temp Reg
|
||||
#define gprT2 1 // Temp Reg
|
||||
#define gprR 2 // VI Reg Offset
|
||||
|
@ -150,7 +141,7 @@ declareAllVariables
|
|||
|
||||
// Recursive Inline
|
||||
#ifndef __LINUX__
|
||||
#define __recInline __forceinline
|
||||
#define __recInline __releaseinline
|
||||
#else
|
||||
#define __recInline inline
|
||||
#endif
|
||||
|
@ -169,6 +160,12 @@ declareAllVariables
|
|||
#define pass3 if (recPass == 2)
|
||||
#define pass4 if (recPass == 3)
|
||||
|
||||
// Upper Opcode Cases
|
||||
#define opCase1 if (opCase == 1) // Normal Opcodes
|
||||
#define opCase2 if (opCase == 2) // BC Opcodes
|
||||
#define opCase3 if (opCase == 3) // I Opcodes
|
||||
#define opCase4 if (opCase == 4) // Q Opcodes
|
||||
|
||||
// Define mVUquickSearch
|
||||
#ifndef __LINUX__
|
||||
PCSX2_ALIGNED16_EXTERN( u8 mVUsearchXMM[0x1000] );
|
||||
|
@ -187,25 +184,25 @@ typedef u32 (__fastcall *mVUCall)(void*, void*);
|
|||
#define mVUprogI mVU->prog.prog[progIndex]
|
||||
#define mVUcurProg mVU->prog.prog[mVU->prog.cur]
|
||||
#define mVUblocks mVU->prog.prog[mVU->prog.cur].block
|
||||
#define mVUallocInfo mVU->prog.allocInfo
|
||||
#define mVUbranch mVUallocInfo.branch
|
||||
#define mVUcycles mVUallocInfo.cycles
|
||||
#define mVUcount mVUallocInfo.count
|
||||
#define mVUpBlock mVUallocInfo.pBlock
|
||||
#define mVUblock mVUallocInfo.block
|
||||
#define mVUregs mVUallocInfo.block.pState
|
||||
#define mVUregsTemp mVUallocInfo.regsTemp
|
||||
#define iPC mVUallocInfo.curPC
|
||||
#define mVUsFlagHack mVUallocInfo.sFlagHack
|
||||
#define mVUinfo mVUallocInfo.info[iPC / 2]
|
||||
#define mVUconstReg mVUallocInfo.constReg
|
||||
#define mVUir mVU->prog.IRinfo
|
||||
#define mVUbranch mVU->prog.IRinfo.branch
|
||||
#define mVUcycles mVU->prog.IRinfo.cycles
|
||||
#define mVUcount mVU->prog.IRinfo.count
|
||||
#define mVUpBlock mVU->prog.IRinfo.pBlock
|
||||
#define mVUblock mVU->prog.IRinfo.block
|
||||
#define mVUregs mVU->prog.IRinfo.block.pState
|
||||
#define mVUregsTemp mVU->prog.IRinfo.regsTemp
|
||||
#define iPC mVU->prog.IRinfo.curPC
|
||||
#define mVUsFlagHack mVU->prog.IRinfo.sFlagHack
|
||||
#define mVUconstReg mVU->prog.IRinfo.constReg
|
||||
#define mVUstartPC mVU->prog.IRinfo.startPC
|
||||
#define mVUinfo mVU->prog.IRinfo.info[iPC / 2]
|
||||
#define mVUstall mVUinfo.stall
|
||||
#define mVUup mVUinfo.uOp
|
||||
#define mVUlow mVUinfo.lOp
|
||||
#define sFLAG mVUinfo.sFlag
|
||||
#define mFLAG mVUinfo.mFlag
|
||||
#define cFLAG mVUinfo.cFlag
|
||||
#define mVUstartPC mVUallocInfo.startPC
|
||||
#define mVUflagInfo mVUregs.needExactMatch
|
||||
#define mVUrange mVUcurProg.ranges.range[mVUcurProg.ranges.total]
|
||||
#define xPC ((iPC / 2) * 8)
|
||||
|
@ -220,6 +217,7 @@ typedef u32 (__fastcall *mVUCall)(void*, void*);
|
|||
#define Rmem (uptr)&mVU->regs->VI[REG_R].UL
|
||||
#define Roffset (uptr)&mVU->regs->VI[9].UL
|
||||
#define aWrap(x, m) ((x > m) ? 0 : x)
|
||||
#define shuffleSS(x) ((x==1)?(0x27):((x==2)?(0xc6):((x==4)?(0xe1):(0xe4))))
|
||||
|
||||
// Flag Info
|
||||
#define __Status (mVUflagInfo & (0xf<<0))
|
||||
|
@ -241,10 +239,6 @@ typedef u32 (__fastcall *mVUCall)(void*, void*);
|
|||
#define mVUlogQ() { mVUlog(", Q"); }
|
||||
#define mVUlogCLIP() { mVUlog("w.xyz vf%02d, vf%02dw", _Fs_, _Ft_); }
|
||||
|
||||
// Store VI regs in mmx regs?
|
||||
#define isMMX(_VIreg_) 0 //(_VIreg_ >= 1 && _VIreg_ <=8)
|
||||
#define mmVI(_VIreg_) (_VIreg_ - 1)
|
||||
|
||||
// Debug Stuff...
|
||||
#ifdef mVUdebug
|
||||
#define mVUprint Console::Status
|
||||
|
|
|
@ -26,12 +26,12 @@
|
|||
void mVUclamp1(int reg, int regT1, int xyzw) {
|
||||
switch (xyzw) {
|
||||
case 1: case 2: case 4: case 8:
|
||||
SSE_MINSS_XMM_to_XMM(reg, xmmMax);
|
||||
SSE_MAXSS_XMM_to_XMM(reg, xmmMin);
|
||||
SSE_MINSS_M32_to_XMM(reg, (uptr)mVU_maxvals);
|
||||
SSE_MAXSS_M32_to_XMM(reg, (uptr)mVU_minvals);
|
||||
break;
|
||||
default:
|
||||
SSE_MINPS_XMM_to_XMM(reg, xmmMax);
|
||||
SSE_MAXPS_XMM_to_XMM(reg, xmmMin);
|
||||
SSE_MINPS_M128_to_XMM(reg, (uptr)mVU_maxvals);
|
||||
SSE_MAXPS_M128_to_XMM(reg, (uptr)mVU_minvals);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -43,15 +43,15 @@ void mVUclamp2(int reg, int regT1, int xyzw) {
|
|||
case 1: case 2: case 4: case 8:
|
||||
SSE_MOVSS_XMM_to_XMM(regT1, reg);
|
||||
SSE_ANDPS_M128_to_XMM(regT1, (uptr)mVU_signbit);
|
||||
SSE_MINSS_XMM_to_XMM(reg, xmmMax);
|
||||
SSE_MAXSS_XMM_to_XMM(reg, xmmMin);
|
||||
SSE_MINSS_M32_to_XMM(reg, (uptr)mVU_maxvals);
|
||||
SSE_MAXSS_M32_to_XMM(reg, (uptr)mVU_minvals);
|
||||
SSE_ORPS_XMM_to_XMM(reg, regT1);
|
||||
break;
|
||||
default:
|
||||
SSE_MOVAPS_XMM_to_XMM(regT1, reg);
|
||||
SSE_ANDPS_M128_to_XMM(regT1, (uptr)mVU_signbit);
|
||||
SSE_MINPS_XMM_to_XMM(reg, xmmMax);
|
||||
SSE_MAXPS_XMM_to_XMM(reg, xmmMin);
|
||||
SSE_MINPS_M128_to_XMM(reg, (uptr)mVU_maxvals);
|
||||
SSE_MAXPS_M128_to_XMM(reg, (uptr)mVU_minvals);
|
||||
SSE_ORPS_XMM_to_XMM(reg, regT1);
|
||||
break;
|
||||
}
|
||||
|
@ -104,10 +104,16 @@ void mVUsaveReg(int reg, uptr offset, int xyzw, bool modXYZW) {
|
|||
return;*/
|
||||
|
||||
switch ( xyzw ) {
|
||||
case 5: SSE2_PSHUFD_XMM_to_XMM(reg, reg, 0xe1); //WZXY
|
||||
SSE_MOVSS_XMM_to_M32(offset+4, reg);
|
||||
SSE2_PSHUFD_XMM_to_XMM(reg, reg, 0xff); //WWWW
|
||||
SSE_MOVSS_XMM_to_M32(offset+12, reg);
|
||||
case 5: if (cpucaps.hasStreamingSIMD4Extensions) {
|
||||
SSE4_EXTRACTPS_XMM_to_M32(offset+4, reg, 1);
|
||||
SSE4_EXTRACTPS_XMM_to_M32(offset+12, reg, 3);
|
||||
}
|
||||
else {
|
||||
SSE2_PSHUFD_XMM_to_XMM(reg, reg, 0xe1); //WZXY
|
||||
SSE_MOVSS_XMM_to_M32(offset+4, reg);
|
||||
SSE2_PSHUFD_XMM_to_XMM(reg, reg, 0xff); //WWWW
|
||||
SSE_MOVSS_XMM_to_M32(offset+12, reg);
|
||||
}
|
||||
break; // YW
|
||||
case 6: SSE2_PSHUFD_XMM_to_XMM(reg, reg, 0xc9);
|
||||
SSE_MOVLPS_XMM_to_M64(offset+4, reg);
|
||||
|
@ -203,25 +209,33 @@ void mVUsaveReg2(int reg, int gprReg, u32 offset, int xyzw) {
|
|||
}
|
||||
}
|
||||
|
||||
// Modifies the Source Reg!
|
||||
void mVUmergeRegs(int dest, int src, int xyzw) {
|
||||
// Modifies the Source Reg! (ToDo: Optimize modXYZW = 1 cases)
|
||||
void mVUmergeRegs(int dest, int src, int xyzw, bool modXYZW = 0) {
|
||||
xyzw &= 0xf;
|
||||
if ( (dest != src) && (xyzw != 0) ) {
|
||||
if ( cpucaps.hasStreamingSIMD4Extensions && (xyzw != 0x8) && (xyzw != 0xf) ) {
|
||||
if (cpucaps.hasStreamingSIMD4Extensions && (xyzw != 0x8) && (xyzw != 0xf)) {
|
||||
if (modXYZW) {
|
||||
if (xyzw == 1) { SSE4_INSERTPS_XMM_to_XMM(dest, src, _MM_MK_INSERTPS_NDX(0, 3, 0)); return; }
|
||||
else if (xyzw == 2) { SSE4_INSERTPS_XMM_to_XMM(dest, src, _MM_MK_INSERTPS_NDX(0, 2, 0)); return; }
|
||||
else if (xyzw == 4) { SSE4_INSERTPS_XMM_to_XMM(dest, src, _MM_MK_INSERTPS_NDX(0, 1, 0)); return; }
|
||||
}
|
||||
xyzw = ((xyzw & 1) << 3) | ((xyzw & 2) << 1) | ((xyzw & 4) >> 1) | ((xyzw & 8) >> 3);
|
||||
SSE4_BLENDPS_XMM_to_XMM(dest, src, xyzw);
|
||||
}
|
||||
else {
|
||||
switch (xyzw) {
|
||||
case 1: SSE_MOVHLPS_XMM_to_XMM(src, dest);
|
||||
SSE_SHUFPS_XMM_to_XMM(dest, src, 0xc4);
|
||||
case 1: if (modXYZW) mVUunpack_xyzw(src, src, 0);
|
||||
SSE_MOVHLPS_XMM_to_XMM(src, dest); // src = Sw Sz Dw Dz
|
||||
SSE_SHUFPS_XMM_to_XMM(dest, src, 0xc4); // 11 00 01 00
|
||||
break;
|
||||
case 2: SSE_MOVHLPS_XMM_to_XMM(src, dest);
|
||||
case 2: if (modXYZW) mVUunpack_xyzw(src, src, 0);
|
||||
SSE_MOVHLPS_XMM_to_XMM(src, dest);
|
||||
SSE_SHUFPS_XMM_to_XMM(dest, src, 0x64);
|
||||
break;
|
||||
case 3: SSE_SHUFPS_XMM_to_XMM(dest, src, 0xe4);
|
||||
break;
|
||||
case 4: SSE_MOVSS_XMM_to_XMM(src, dest);
|
||||
case 4: if (modXYZW) mVUunpack_xyzw(src, src, 0);
|
||||
SSE_MOVSS_XMM_to_XMM(src, dest);
|
||||
SSE2_MOVSD_XMM_to_XMM(dest, src);
|
||||
break;
|
||||
case 5: SSE_SHUFPS_XMM_to_XMM(dest, src, 0xd8);
|
||||
|
@ -285,17 +299,14 @@ microVUt(void) mVUaddrFix(mV, int gprReg) {
|
|||
}
|
||||
|
||||
// Backup Volatile Regs (EAX, ECX, EDX, MM0~7, XMM0~7, are all volatile according to 32bit Win/Linux ABI)
|
||||
microVUt(void) mVUbackupRegs(mV) {
|
||||
SSE_MOVAPS_XMM_to_M128((uptr)&mVU->regs->ACC.UL[0], xmmACC);
|
||||
microVUt(void) mVUbackupRegs(microVU* mVU) {
|
||||
mVU->regAlloc->flushAll();
|
||||
SSE_MOVAPS_XMM_to_M128((uptr)&mVU->xmmPQb[0], xmmPQ);
|
||||
}
|
||||
|
||||
// Restore Volatile Regs
|
||||
microVUt(void) mVUrestoreRegs(mV) {
|
||||
SSE_MOVAPS_M128_to_XMM(xmmACC, (uptr)&mVU->regs->ACC.UL[0]);
|
||||
microVUt(void) mVUrestoreRegs(microVU* mVU) {
|
||||
SSE_MOVAPS_M128_to_XMM(xmmPQ, (uptr)&mVU->xmmPQb[0]);
|
||||
SSE_MOVAPS_M128_to_XMM(xmmMax, (uptr)mVU_maxvals);
|
||||
SSE_MOVAPS_M128_to_XMM(xmmMin, (uptr)mVU_minvals);
|
||||
MOV32ItoR(gprR, Roffset); // Restore gprR
|
||||
}
|
||||
|
||||
|
@ -335,8 +346,8 @@ void MIN_MAX_(x86SSERegType to, x86SSERegType from, bool min) {
|
|||
// Warning: Modifies from and to's upper 3 vectors
|
||||
void MIN_MAX_SS(x86SSERegType to, x86SSERegType from, bool min) {
|
||||
SSE_SHUFPS_XMM_to_XMM (to, from, 0);
|
||||
SSE2_PAND_M128_to_XMM (to, (uptr)MIN_MAX_MASK1);
|
||||
SSE2_POR_M128_to_XMM (to, (uptr)MIN_MAX_MASK2);
|
||||
SSE2_PAND_M128_to_XMM (to, (uptr)MIN_MAX_MASK1);
|
||||
SSE2_POR_M128_to_XMM (to, (uptr)MIN_MAX_MASK2);
|
||||
SSE2_PSHUFD_XMM_to_XMM(from, to, 0xee);
|
||||
if (min) SSE2_MINPD_XMM_to_XMM(to, from);
|
||||
else SSE2_MAXPD_XMM_to_XMM(to, from);
|
||||
|
|
|
@ -238,7 +238,7 @@ mVUop(mVULowerOP_T3_11) { doTableStuff(mVULowerOP_T3_11_OPCODE, ((mVUgetCode >>
|
|||
mVUop(mVUopU) { doTableStuff(mVU_UPPER_OPCODE, (mVUgetCode & 0x3f)); } // Gets Upper Opcode
|
||||
mVUop(mVUopL) { doTableStuff(mVULOWER_OPCODE, (mVUgetCode >> 25)); } // Gets Lower Opcode
|
||||
mVUop(mVUunknown) {
|
||||
pass2 { Console::Error("microVU%d: Unknown Micro VU opcode called (%08x)\n", params getIndex, mVUgetCode); }
|
||||
pass2 { Console::Error("microVU%d: Unknown Micro VU opcode called (%x) [%04x]\n", params getIndex, mVUgetCode, xPC); }
|
||||
pass3 { mVUlog("Unknown", mVUgetCode); }
|
||||
}
|
||||
|
||||
|
|
|
@ -27,30 +27,31 @@
|
|||
#define SHIFT_XYZW(gprReg) { if (_XYZW_SS && modXYZW && !_W) { SHL32ItoR(gprReg, ADD_XYZW); } }
|
||||
|
||||
// Note: If modXYZW is true, then it adjusts XYZW for Single Scalar operations
|
||||
microVUt(void) mVUupdateFlags(mV, int reg, int regT1, int regT2, int xyzw, bool modXYZW) {
|
||||
int sReg, mReg = gprT1;
|
||||
microVUt(void) mVUupdateFlags(mV, int reg, int regT1, bool modXYZW = 1) {
|
||||
int sReg, mReg = gprT1, xyzw = _X_Y_Z_W;
|
||||
static const u16 flipMask[16] = {0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15};
|
||||
|
||||
//SysPrintf("Status = %d; Mac = %d\n", sFLAG.doFlag, mFLAG.doFlag);
|
||||
if (mVUsFlagHack) { sFLAG.doFlag = 0; }
|
||||
if (!sFLAG.doFlag && !mFLAG.doFlag) { return; }
|
||||
if (!mFLAG.doFlag || (_XYZW_SS && modXYZW)) { regT1 = reg; }
|
||||
else { SSE2_PSHUFD_XMM_to_XMM(regT1, reg, 0x1B); } // Flip wzyx to xyzw
|
||||
if (!sFLAG.doFlag && !mFLAG.doFlag) { return; }
|
||||
if (!(!mFLAG.doFlag || (_XYZW_SS && modXYZW))) {
|
||||
SSE2_PSHUFD_XMM_to_XMM(reg, reg, 0x1B); // Flip wzyx to xyzw
|
||||
}
|
||||
if (sFLAG.doFlag) {
|
||||
getFlagReg(sReg, sFLAG.write); // Set sReg to valid GPR by Cur Flag Instance
|
||||
mVUallocSFLAGa(sReg, sFLAG.lastWrite); // Get Prev Status Flag
|
||||
if (sFLAG.doNonSticky) AND32ItoR(sReg, 0xfffc00ff); // Clear O,U,S,Z flags
|
||||
}
|
||||
if (regT1 < 0) { regT1 = mVU->regAlloc->allocReg(); }
|
||||
|
||||
//-------------------------Check for Signed flags------------------------------
|
||||
|
||||
// The following code makes sure the Signed Bit isn't set with Negative Zero
|
||||
SSE_XORPS_XMM_to_XMM(regT2, regT2); // Clear regT2
|
||||
SSE_CMPEQPS_XMM_to_XMM(regT2, regT1); // Set all F's if each vector is zero
|
||||
SSE_MOVMSKPS_XMM_to_R32(gprT2, regT2); // Used for Zero Flag Calculation
|
||||
SSE_ANDNPS_XMM_to_XMM(regT2, regT1);
|
||||
|
||||
SSE_MOVMSKPS_XMM_to_R32(mReg, regT2); // Move the sign bits of the t1reg
|
||||
SSE_XORPS_XMM_to_XMM (regT1, regT1); // Clear regT2
|
||||
SSE_CMPEQPS_XMM_to_XMM (regT1, reg); // Set all F's if each vector is zero
|
||||
SSE_MOVMSKPS_XMM_to_R32(gprT2, regT1); // Used for Zero Flag Calculation
|
||||
SSE_ANDNPS_XMM_to_XMM (regT1, reg); // Used for Sign Flag Calculation
|
||||
SSE_MOVMSKPS_XMM_to_R32(mReg, regT1); // Move the Sign Bits of the t1reg
|
||||
|
||||
AND32ItoR(mReg, AND_XYZW); // Grab "Is Signed" bits from the previous calculation
|
||||
SHL32ItoR(mReg, 4 + ADD_XYZW);
|
||||
|
@ -63,6 +64,9 @@ microVUt(void) mVUupdateFlags(mV, int reg, int regT1, int regT2, int xyzw, bool
|
|||
|
||||
//-------------------------Write back flags------------------------------
|
||||
|
||||
if (!(!mFLAG.doFlag || (_XYZW_SS && modXYZW))) {
|
||||
SSE2_PSHUFD_XMM_to_XMM(reg, reg, 0x1B); // Flip wzyx to xyzw
|
||||
}
|
||||
if (mFLAG.doFlag) mVUallocMFLAGb(mVU, mReg, mFLAG.write); // Set Mac Flag
|
||||
if (sFLAG.doFlag) {
|
||||
OR32RtoR (sReg, mReg);
|
||||
|
@ -74,530 +78,332 @@ microVUt(void) mVUupdateFlags(mV, int reg, int regT1, int regT2, int xyzw, bool
|
|||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Helper Macros
|
||||
// Helper Macros and Functions
|
||||
//------------------------------------------------------------------
|
||||
|
||||
// FMAC1 - Normal FMAC Opcodes
|
||||
#define mVU_FMAC1(operation, OPname) { \
|
||||
pass1 { mVUanalyzeFMAC1(mVU, _Fd_, _Fs_, _Ft_); } \
|
||||
pass2 { \
|
||||
int Fd, Fs, Ft; \
|
||||
mVUallocFMAC1a(mVU, Fd, Fs, Ft); \
|
||||
if (_XYZW_SS) SSE_##operation##SS_XMM_to_XMM(Fs, Ft); \
|
||||
else SSE_##operation##PS_XMM_to_XMM(Fs, Ft); \
|
||||
mVUupdateFlags(mVU, Fd, xmmT1, xmmT2, _X_Y_Z_W, 1); \
|
||||
mVUallocFMAC1b(mVU, Fd); \
|
||||
} \
|
||||
pass3 { mVUlog(OPname); mVUlogFd(); mVUlogFt(); } \
|
||||
}
|
||||
// FMAC3 - BC(xyzw) FMAC Opcodes
|
||||
#define mVU_FMAC3(operation, OPname) { \
|
||||
pass1 { mVUanalyzeFMAC3(mVU, _Fd_, _Fs_, _Ft_); } \
|
||||
pass2 { \
|
||||
int Fd, Fs, Ft; \
|
||||
mVUallocFMAC3a(mVU, Fd, Fs, Ft); \
|
||||
if (_XYZW_SS) SSE_##operation##SS_XMM_to_XMM(Fs, Ft); \
|
||||
else SSE_##operation##PS_XMM_to_XMM(Fs, Ft); \
|
||||
mVUupdateFlags(mVU, Fd, xmmT1, xmmT2, _X_Y_Z_W, 1); \
|
||||
mVUallocFMAC3b(mVU, Fd); \
|
||||
} \
|
||||
pass3 { mVUlog(OPname); mVUlogFd(); mVUlogBC(); } \
|
||||
}
|
||||
// FMAC4 - FMAC Opcodes Storing Result to ACC
|
||||
#define mVU_FMAC4(operation, OPname) { \
|
||||
pass1 { mVUanalyzeFMAC1(mVU, 0, _Fs_, _Ft_); } \
|
||||
pass2 { \
|
||||
int ACC, Fs, Ft; \
|
||||
mVUallocFMAC4a(mVU, ACC, Fs, Ft); \
|
||||
if (_X_Y_Z_W == 8) SSE_##operation##SS_XMM_to_XMM(Fs, Ft); \
|
||||
else SSE_##operation##PS_XMM_to_XMM(Fs, Ft); \
|
||||
mVUupdateFlags(mVU, Fs, xmmT1, xmmT2, _X_Y_Z_W, 0); \
|
||||
mVUallocFMAC4b(mVU, ACC, Fs); \
|
||||
} \
|
||||
pass3 { mVUlog(OPname); mVUlogACC(); mVUlogFt(); } \
|
||||
}
|
||||
// FMAC5 - FMAC BC(xyzw) Opcodes Storing Result to ACC
|
||||
#define mVU_FMAC5(operation, OPname) { \
|
||||
pass1 { mVUanalyzeFMAC3(mVU, 0, _Fs_, _Ft_); } \
|
||||
pass2 { \
|
||||
int ACC, Fs, Ft; \
|
||||
mVUallocFMAC5a(mVU, ACC, Fs, Ft); \
|
||||
if (_X_Y_Z_W == 8) SSE_##operation##SS_XMM_to_XMM(Fs, Ft); \
|
||||
else SSE_##operation##PS_XMM_to_XMM(Fs, Ft); \
|
||||
mVUupdateFlags(mVU, Fs, xmmT1, xmmT2, _X_Y_Z_W, 0); \
|
||||
mVUallocFMAC5b(mVU, ACC, Fs); \
|
||||
} \
|
||||
pass3 { mVUlog(OPname); mVUlogACC(); mVUlogBC(); } \
|
||||
}
|
||||
// FMAC6 - Normal FMAC Opcodes (I Reg)
|
||||
#define mVU_FMAC6(operation, OPname) { \
|
||||
pass1 { mVUanalyzeFMAC1(mVU, _Fd_, _Fs_, 0); } \
|
||||
pass2 { \
|
||||
int Fd, Fs, Ft; \
|
||||
mVUallocFMAC6a(mVU, Fd, Fs, Ft); \
|
||||
if (_XYZW_SS) SSE_##operation##SS_XMM_to_XMM(Fs, Ft); \
|
||||
else SSE_##operation##PS_XMM_to_XMM(Fs, Ft); \
|
||||
mVUupdateFlags(mVU, Fd, xmmT1, xmmT2, _X_Y_Z_W, 1); \
|
||||
mVUallocFMAC6b(mVU, Fd); \
|
||||
} \
|
||||
pass3 { mVUlog(OPname); mVUlogFd(); mVUlogI(); } \
|
||||
}
|
||||
// FMAC7 - FMAC Opcodes Storing Result to ACC (I Reg)
|
||||
#define mVU_FMAC7(operation, OPname) { \
|
||||
pass1 { mVUanalyzeFMAC1(mVU, 0, _Fs_, 0); } \
|
||||
pass2 { \
|
||||
int ACC, Fs, Ft; \
|
||||
mVUallocFMAC7a(mVU, ACC, Fs, Ft); \
|
||||
if (_X_Y_Z_W == 8) SSE_##operation##SS_XMM_to_XMM(Fs, Ft); \
|
||||
else SSE_##operation##PS_XMM_to_XMM(Fs, Ft); \
|
||||
mVUupdateFlags(mVU, Fs, xmmT1, xmmT2, _X_Y_Z_W, 0); \
|
||||
mVUallocFMAC7b(mVU, ACC, Fs); \
|
||||
} \
|
||||
pass3 { mVUlog(OPname); mVUlogACC(); mVUlogI(); } \
|
||||
}
|
||||
// FMAC8 - MADD FMAC Opcode Storing Result to Fd
|
||||
#define mVU_FMAC8(operation, OPname) { \
|
||||
pass1 { mVUanalyzeFMAC1(mVU, _Fd_, _Fs_, _Ft_); } \
|
||||
pass2 { \
|
||||
int Fd, ACC, Fs, Ft; \
|
||||
mVUallocFMAC8a(mVU, Fd, ACC, Fs, Ft); \
|
||||
if (_X_Y_Z_W == 8) { \
|
||||
SSE_MULSS_XMM_to_XMM(Fs, Ft); \
|
||||
SSE_##operation##SS_XMM_to_XMM(Fs, ACC); \
|
||||
} \
|
||||
else { \
|
||||
SSE_MULPS_XMM_to_XMM(Fs, Ft); \
|
||||
SSE_##operation##PS_XMM_to_XMM(Fs, ACC); \
|
||||
} \
|
||||
mVUupdateFlags(mVU, Fd, xmmT1, xmmT2, _X_Y_Z_W, 0); \
|
||||
mVUallocFMAC8b(mVU, Fd); \
|
||||
} \
|
||||
pass3 { mVUlog(OPname); mVUlogFd(); mVUlogFt(); } \
|
||||
}
|
||||
// FMAC9 - MSUB FMAC Opcode Storing Result to Fd
|
||||
#define mVU_FMAC9(operation, OPname) { \
|
||||
pass1 { mVUanalyzeFMAC1(mVU, _Fd_, _Fs_, _Ft_); } \
|
||||
pass2 { \
|
||||
int Fd, ACC, Fs, Ft; \
|
||||
mVUallocFMAC9a(mVU, Fd, ACC, Fs, Ft); \
|
||||
if (_X_Y_Z_W == 8) { \
|
||||
SSE_MULSS_XMM_to_XMM(Fs, Ft); \
|
||||
SSE_##operation##SS_XMM_to_XMM(ACC, Fs); \
|
||||
} \
|
||||
else { \
|
||||
SSE_MULPS_XMM_to_XMM(Fs, Ft); \
|
||||
SSE_##operation##PS_XMM_to_XMM(ACC, Fs); \
|
||||
} \
|
||||
mVUupdateFlags(mVU, Fd, Fs, xmmT2, _X_Y_Z_W, 0); \
|
||||
mVUallocFMAC9b(mVU, Fd); \
|
||||
} \
|
||||
pass3 { mVUlog(OPname); mVUlogFd(); mVUlogFt(); } \
|
||||
}
|
||||
// FMAC10 - MADD FMAC BC(xyzw) Opcode Storing Result to Fd
|
||||
#define mVU_FMAC10(operation, OPname) { \
|
||||
pass1 { mVUanalyzeFMAC3(mVU, _Fd_, _Fs_, _Ft_); } \
|
||||
pass2 { \
|
||||
int Fd, ACC, Fs, Ft; \
|
||||
mVUallocFMAC10a(mVU, Fd, ACC, Fs, Ft); \
|
||||
if (_X_Y_Z_W == 8) { \
|
||||
SSE_MULSS_XMM_to_XMM(Fs, Ft); \
|
||||
SSE_##operation##SS_XMM_to_XMM(Fs, ACC); \
|
||||
} \
|
||||
else { \
|
||||
SSE_MULPS_XMM_to_XMM(Fs, Ft); \
|
||||
SSE_##operation##PS_XMM_to_XMM(Fs, ACC); \
|
||||
} \
|
||||
mVUupdateFlags(mVU, Fd, xmmT1, xmmT2, _X_Y_Z_W, 0); \
|
||||
mVUallocFMAC10b(mVU, Fd); \
|
||||
} \
|
||||
pass3 { mVUlog(OPname); mVUlogFd(); mVUlogBC(); } \
|
||||
}
|
||||
// FMAC11 - MSUB FMAC BC(xyzw) Opcode Storing Result to Fd
|
||||
#define mVU_FMAC11(operation, OPname) { \
|
||||
pass1 { mVUanalyzeFMAC3(mVU, _Fd_, _Fs_, _Ft_); } \
|
||||
pass2 { \
|
||||
int Fd, ACC, Fs, Ft; \
|
||||
mVUallocFMAC11a(mVU, Fd, ACC, Fs, Ft); \
|
||||
if (_X_Y_Z_W == 8) { \
|
||||
SSE_MULSS_XMM_to_XMM(Fs, Ft); \
|
||||
SSE_##operation##SS_XMM_to_XMM(ACC, Fs); \
|
||||
} \
|
||||
else { \
|
||||
SSE_MULPS_XMM_to_XMM(Fs, Ft); \
|
||||
SSE_##operation##PS_XMM_to_XMM(ACC, Fs); \
|
||||
} \
|
||||
mVUupdateFlags(mVU, Fd, Fs, xmmT2, _X_Y_Z_W, 0); \
|
||||
mVUallocFMAC11b(mVU, Fd); \
|
||||
} \
|
||||
pass3 { mVUlog(OPname); mVUlogFd(); mVUlogBC(); } \
|
||||
}
|
||||
// FMAC12 - MADD FMAC Opcode Storing Result to Fd (I Reg)
|
||||
#define mVU_FMAC12(operation, OPname) { \
|
||||
pass1 { mVUanalyzeFMAC1(mVU, _Fd_, _Fs_, 0); } \
|
||||
pass2 { \
|
||||
int Fd, ACC, Fs, Ft; \
|
||||
mVUallocFMAC12a(mVU, Fd, ACC, Fs, Ft); \
|
||||
if (_X_Y_Z_W == 8) { \
|
||||
SSE_MULSS_XMM_to_XMM(Fs, Ft); \
|
||||
SSE_##operation##SS_XMM_to_XMM(Fs, ACC); \
|
||||
} \
|
||||
else { \
|
||||
SSE_MULPS_XMM_to_XMM(Fs, Ft); \
|
||||
SSE_##operation##PS_XMM_to_XMM(Fs, ACC); \
|
||||
} \
|
||||
mVUupdateFlags(mVU, Fd, xmmT1, xmmT2, _X_Y_Z_W, 0); \
|
||||
mVUallocFMAC12b(mVU, Fd); \
|
||||
} \
|
||||
pass3 { mVUlog(OPname); mVUlogFd(); mVUlogI(); } \
|
||||
}
|
||||
// FMAC13 - MSUB FMAC Opcode Storing Result to Fd (I Reg)
|
||||
#define mVU_FMAC13(operation, OPname) { \
|
||||
pass1 { mVUanalyzeFMAC1(mVU, _Fd_, _Fs_, 0); } \
|
||||
pass2 { \
|
||||
int Fd, ACC, Fs, Ft; \
|
||||
mVUallocFMAC13a(mVU, Fd, ACC, Fs, Ft); \
|
||||
if (_X_Y_Z_W == 8) { \
|
||||
SSE_MULSS_XMM_to_XMM(Fs, Ft); \
|
||||
SSE_##operation##SS_XMM_to_XMM(ACC, Fs); \
|
||||
} \
|
||||
else { \
|
||||
SSE_MULPS_XMM_to_XMM(Fs, Ft); \
|
||||
SSE_##operation##PS_XMM_to_XMM(ACC, Fs); \
|
||||
} \
|
||||
mVUupdateFlags(mVU, Fd, Fs, xmmT2, _X_Y_Z_W, 0); \
|
||||
mVUallocFMAC13b(mVU, Fd); \
|
||||
} \
|
||||
pass3 { mVUlog(OPname); mVUlogFd(); mVUlogI(); } \
|
||||
}
|
||||
// FMAC14 - MADDA/MSUBA FMAC Opcode
|
||||
#define mVU_FMAC14(operation, OPname) { \
|
||||
pass1 { mVUanalyzeFMAC1(mVU, 0, _Fs_, _Ft_); } \
|
||||
pass2 { \
|
||||
int ACCw, ACCr, Fs, Ft; \
|
||||
mVUallocFMAC14a(mVU, ACCw, ACCr, Fs, Ft); \
|
||||
if (_X_Y_Z_W == 8) { \
|
||||
SSE_MULSS_XMM_to_XMM(Fs, Ft); \
|
||||
SSE_##operation##SS_XMM_to_XMM(ACCr, Fs); \
|
||||
} \
|
||||
else { \
|
||||
SSE_MULPS_XMM_to_XMM(Fs, Ft); \
|
||||
SSE_##operation##PS_XMM_to_XMM(ACCr, Fs); \
|
||||
} \
|
||||
mVUupdateFlags(mVU, ACCr, Fs, xmmT2, _X_Y_Z_W, 0); \
|
||||
mVUallocFMAC14b(mVU, ACCw, ACCr); \
|
||||
} \
|
||||
pass3 { mVUlog(OPname); mVUlogACC(); mVUlogFt(); } \
|
||||
}
|
||||
// FMAC15 - MADDA/MSUBA BC(xyzw) FMAC Opcode
|
||||
#define mVU_FMAC15(operation, OPname) { \
|
||||
pass1 { mVUanalyzeFMAC3(mVU, 0, _Fs_, _Ft_); } \
|
||||
pass2 { \
|
||||
int ACCw, ACCr, Fs, Ft; \
|
||||
mVUallocFMAC15a(mVU, ACCw, ACCr, Fs, Ft); \
|
||||
if (_X_Y_Z_W == 8) { \
|
||||
SSE_MULSS_XMM_to_XMM(Fs, Ft); \
|
||||
SSE_##operation##SS_XMM_to_XMM(ACCr, Fs); \
|
||||
} \
|
||||
else { \
|
||||
SSE_MULPS_XMM_to_XMM(Fs, Ft); \
|
||||
SSE_##operation##PS_XMM_to_XMM(ACCr, Fs); \
|
||||
} \
|
||||
mVUupdateFlags(mVU, ACCr, Fs, xmmT2, _X_Y_Z_W, 0); \
|
||||
mVUallocFMAC15b(mVU, ACCw, ACCr); \
|
||||
} \
|
||||
pass3 { mVUlog(OPname); mVUlogACC(); mVUlogBC(); } \
|
||||
}
|
||||
// FMAC16 - MADDA/MSUBA FMAC Opcode (I Reg)
|
||||
#define mVU_FMAC16(operation, OPname) { \
|
||||
pass1 { mVUanalyzeFMAC1(mVU, 0, _Fs_, 0); } \
|
||||
pass2 { \
|
||||
int ACCw, ACCr, Fs, Ft; \
|
||||
mVUallocFMAC16a(mVU, ACCw, ACCr, Fs, Ft); \
|
||||
if (_X_Y_Z_W == 8) { \
|
||||
SSE_MULSS_XMM_to_XMM(Fs, Ft); \
|
||||
SSE_##operation##SS_XMM_to_XMM(ACCr, Fs); \
|
||||
} \
|
||||
else { \
|
||||
SSE_MULPS_XMM_to_XMM(Fs, Ft); \
|
||||
SSE_##operation##PS_XMM_to_XMM(ACCr, Fs); \
|
||||
} \
|
||||
mVUupdateFlags(mVU, ACCr, Fs, xmmT2, _X_Y_Z_W, 0); \
|
||||
mVUallocFMAC16b(mVU, ACCw, ACCr); \
|
||||
} \
|
||||
pass3 { mVUlog(OPname); mVUlogACC(); mVUlogI(); } \
|
||||
}
|
||||
// FMAC18 - OPMULA FMAC Opcode
|
||||
#define mVU_FMAC18(operation, OPname) { \
|
||||
pass1 { mVUanalyzeFMAC1(mVU, 0, _Fs_, _Ft_); } \
|
||||
pass2 { \
|
||||
int ACC, Fs, Ft; \
|
||||
mVUallocFMAC18a(mVU, ACC, Fs, Ft); \
|
||||
SSE_##operation##PS_XMM_to_XMM(Fs, Ft); \
|
||||
mVUupdateFlags(mVU, Fs, xmmT1, xmmT2, _X_Y_Z_W, 0); \
|
||||
mVUallocFMAC18b(mVU, ACC, Fs); \
|
||||
} \
|
||||
pass3 { mVUlog(OPname); mVUlogACC(); mVUlogFt(); } \
|
||||
}
|
||||
// FMAC19 - OPMSUB FMAC Opcode
|
||||
#define mVU_FMAC19(operation, OPname) { \
|
||||
pass1 { mVUanalyzeFMAC1(mVU, _Fd_, _Fs_, _Ft_); } \
|
||||
pass2 { \
|
||||
int Fd, ACC, Fs, Ft; \
|
||||
mVUallocFMAC19a(mVU, Fd, ACC, Fs, Ft); \
|
||||
SSE_MULPS_XMM_to_XMM(Fs, Ft); \
|
||||
SSE_##operation##PS_XMM_to_XMM(ACC, Fs); \
|
||||
mVUupdateFlags(mVU, Fd, Fs, xmmT2, _X_Y_Z_W, 0); \
|
||||
mVUallocFMAC19b(mVU, Fd); \
|
||||
} \
|
||||
pass3 { mVUlog(OPname); mVUlogFd(); mVUlogFt(); } \
|
||||
}
|
||||
// FMAC22 - Normal FMAC Opcodes (Q Reg)
|
||||
#define mVU_FMAC22(operation, OPname) { \
|
||||
pass1 { mVUanalyzeFMAC1(mVU, _Fd_, _Fs_, 0); } \
|
||||
pass2 { \
|
||||
int Fd, Fs, Ft; \
|
||||
mVUallocFMAC22a(mVU, Fd, Fs, Ft); \
|
||||
if (_XYZW_SS) SSE_##operation##SS_XMM_to_XMM(Fs, Ft); \
|
||||
else SSE_##operation##PS_XMM_to_XMM(Fs, Ft); \
|
||||
mVUupdateFlags(mVU, Fd, xmmT1, xmmT2, _X_Y_Z_W, 1); \
|
||||
mVUallocFMAC22b(mVU, Fd); \
|
||||
} \
|
||||
pass3 { mVUlog(OPname); mVUlogFd(); mVUlogQ(); } \
|
||||
}
|
||||
// FMAC23 - FMAC Opcodes Storing Result to ACC (Q Reg)
|
||||
#define mVU_FMAC23(operation, OPname) { \
|
||||
pass1 { mVUanalyzeFMAC1(mVU, 0, _Fs_, 0); } \
|
||||
pass2 { \
|
||||
int ACC, Fs, Ft; \
|
||||
mVUallocFMAC23a(mVU, ACC, Fs, Ft); \
|
||||
if (_X_Y_Z_W == 8) SSE_##operation##SS_XMM_to_XMM(Fs, Ft); \
|
||||
else SSE_##operation##PS_XMM_to_XMM(Fs, Ft); \
|
||||
mVUupdateFlags(mVU, Fs, xmmT1, xmmT2, _X_Y_Z_W, 0); \
|
||||
mVUallocFMAC23b(mVU, ACC, Fs); \
|
||||
} \
|
||||
pass3 { mVUlog(OPname); mVUlogACC(); mVUlogQ();} \
|
||||
}
|
||||
// FMAC24 - MADD FMAC Opcode Storing Result to Fd (Q Reg)
|
||||
#define mVU_FMAC24(operation, OPname) { \
|
||||
pass1 { mVUanalyzeFMAC1(mVU, _Fd_, _Fs_, 0); } \
|
||||
pass2 { \
|
||||
int Fd, ACC, Fs, Ft; \
|
||||
mVUallocFMAC24a(mVU, Fd, ACC, Fs, Ft); \
|
||||
if (_X_Y_Z_W == 8) { \
|
||||
SSE_MULSS_XMM_to_XMM(Fs, Ft); \
|
||||
SSE_##operation##SS_XMM_to_XMM(Fs, ACC); \
|
||||
} \
|
||||
else { \
|
||||
SSE_MULPS_XMM_to_XMM(Fs, Ft); \
|
||||
SSE_##operation##PS_XMM_to_XMM(Fs, ACC); \
|
||||
} \
|
||||
mVUupdateFlags(mVU, Fd, xmmT1, xmmT2, _X_Y_Z_W, 0); \
|
||||
mVUallocFMAC24b(mVU, Fd); \
|
||||
} \
|
||||
pass3 { mVUlog(OPname); mVUlogFd(); mVUlogQ(); } \
|
||||
}
|
||||
// FMAC25 - MSUB FMAC Opcode Storing Result to Fd (Q Reg)
|
||||
#define mVU_FMAC25(operation, OPname) { \
|
||||
pass1 { mVUanalyzeFMAC1(mVU, _Fd_, _Fs_, 0); } \
|
||||
pass2 { \
|
||||
int Fd, ACC, Fs, Ft; \
|
||||
mVUallocFMAC25a(mVU, Fd, ACC, Fs, Ft); \
|
||||
if (_X_Y_Z_W == 8) { \
|
||||
SSE_MULSS_XMM_to_XMM(Fs, Ft); \
|
||||
SSE_##operation##SS_XMM_to_XMM(ACC, Fs); \
|
||||
} \
|
||||
else { \
|
||||
SSE_MULPS_XMM_to_XMM(Fs, Ft); \
|
||||
SSE_##operation##PS_XMM_to_XMM(ACC, Fs); \
|
||||
} \
|
||||
mVUupdateFlags(mVU, Fd, Fs, xmmT2, _X_Y_Z_W, 0); \
|
||||
mVUallocFMAC25b(mVU, Fd); \
|
||||
} \
|
||||
pass3 { mVUlog(OPname); mVUlogFd(); mVUlogQ(); } \
|
||||
}
|
||||
// FMAC26 - MADDA/MSUBA FMAC Opcode (Q Reg)
|
||||
#define mVU_FMAC26(operation, OPname) { \
|
||||
pass1 { mVUanalyzeFMAC1(mVU, 0, _Fs_, 0); } \
|
||||
pass2 { \
|
||||
int ACCw, ACCr, Fs, Ft; \
|
||||
mVUallocFMAC26a(mVU, ACCw, ACCr, Fs, Ft); \
|
||||
if (_X_Y_Z_W == 8) { \
|
||||
SSE_MULSS_XMM_to_XMM(Fs, Ft); \
|
||||
SSE_##operation##SS_XMM_to_XMM(ACCr, Fs); \
|
||||
} \
|
||||
else { \
|
||||
SSE_MULPS_XMM_to_XMM(Fs, Ft); \
|
||||
SSE_##operation##PS_XMM_to_XMM(ACCr, Fs); \
|
||||
} \
|
||||
mVUupdateFlags(mVU, ACCr, Fs, xmmT2, _X_Y_Z_W, 0); \
|
||||
mVUallocFMAC26b(mVU, ACCw, ACCr); \
|
||||
} \
|
||||
pass3 { mVUlog(OPname); mVUlogACC(); mVUlogQ(); } \
|
||||
static void (*SSE_PS[]) (x86SSERegType, x86SSERegType) = {
|
||||
SSE_ADDPS_XMM_to_XMM, // 0
|
||||
SSE_SUBPS_XMM_to_XMM, // 1
|
||||
SSE_MULPS_XMM_to_XMM, // 2
|
||||
SSE_MAXPS_XMM_to_XMM, // 3
|
||||
SSE_MINPS_XMM_to_XMM // 4
|
||||
};
|
||||
|
||||
static void (*SSE_SS[]) (x86SSERegType, x86SSERegType) = {
|
||||
SSE_ADDSS_XMM_to_XMM, // 0
|
||||
SSE_SUBSS_XMM_to_XMM, // 1
|
||||
SSE_MULSS_XMM_to_XMM, // 2
|
||||
SSE_MAXSS_XMM_to_XMM, // 3
|
||||
SSE_MINSS_XMM_to_XMM // 4
|
||||
};
|
||||
|
||||
// Prints Opcode to MicroProgram Logs
|
||||
void mVU_printOP(microVU* mVU, int opCase, char* opName, bool isACC) {
|
||||
mVUlog(opName);
|
||||
opCase1 { if (isACC) { mVUlogACC(); } else { mVUlogFd(); } mVUlogFt(); }
|
||||
opCase2 { if (isACC) { mVUlogACC(); } else { mVUlogFd(); } mVUlogBC(); }
|
||||
opCase3 { if (isACC) { mVUlogACC(); } else { mVUlogFd(); } mVUlogI(); }
|
||||
opCase4 { if (isACC) { mVUlogACC(); } else { mVUlogFd(); } mVUlogQ(); }
|
||||
}
|
||||
|
||||
// FMAC27~29 - MAX/MINI FMAC Opcodes
|
||||
#define mVU_FMAC27(operation, OPname) { mVU_FMAC1 (operation, OPname); pass1 { sFLAG.doFlag = 0; } }
|
||||
#define mVU_FMAC28(operation, OPname) { mVU_FMAC6 (operation, OPname); pass1 { sFLAG.doFlag = 0; } }
|
||||
#define mVU_FMAC29(operation, OPname) { mVU_FMAC3 (operation, OPname); pass1 { sFLAG.doFlag = 0; } }
|
||||
// Sets Up Pass1 Info for Normal, BC, I, and Q Cases
|
||||
void setupPass1(microVU* mVU, int opCase, bool isACC, bool noFlagUpdate) {
|
||||
opCase1 { mVUanalyzeFMAC1(mVU, ((isACC) ? 0 : _Fd_), _Fs_, _Ft_); }
|
||||
opCase2 { mVUanalyzeFMAC3(mVU, ((isACC) ? 0 : _Fd_), _Fs_, _Ft_); }
|
||||
opCase3 { mVUanalyzeFMAC1(mVU, ((isACC) ? 0 : _Fd_), _Fs_, 0); }
|
||||
opCase4 { mVUanalyzeFMAC1(mVU, ((isACC) ? 0 : _Fd_), _Fs_, 0); }
|
||||
if (noFlagUpdate) { sFLAG.doFlag = 0; }
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Micro VU Micromode Upper instructions
|
||||
//------------------------------------------------------------------
|
||||
// Sets Up Ft Reg for Normal, BC, I, and Q Cases
|
||||
void setupFtReg(microVU* mVU, int& Ft, int opCase) {
|
||||
opCase1 { Ft = mVU->regAlloc->allocReg(_Ft_); }
|
||||
opCase2 {
|
||||
if (!_XYZW_SS) {
|
||||
Ft = mVU->regAlloc->allocReg(_Ft_, 0, 0xf);
|
||||
mVUunpack_xyzw(Ft, Ft, _bc_);
|
||||
}
|
||||
else Ft = mVU->regAlloc->allocReg(_Ft_);
|
||||
}
|
||||
opCase3 { Ft = mVU->regAlloc->allocReg(); getIreg(Ft, 1); }
|
||||
opCase4 { Ft = mVU->regAlloc->allocReg(); getQreg(Ft); }
|
||||
}
|
||||
|
||||
// Normal FMAC Opcodes
|
||||
void mVU_FMACa(microVU* mVU, int recPass, int opCase, int opType, bool isACC, char* opName) {
|
||||
pass1 { setupPass1(mVU, opCase, isACC, ((opType == 3) || (opType == 4))); }
|
||||
pass2 {
|
||||
int Fs, Ft, ACC;
|
||||
mVU->regAlloc->reset(); // Reset for Testing
|
||||
setupFtReg(mVU, Ft, opCase);
|
||||
|
||||
if (isACC) {
|
||||
ACC = mVU->regAlloc->allocReg((_X_Y_Z_W == 0xf) ? -1 : 32, 32, 0xf, 0);
|
||||
Fs = mVU->regAlloc->allocReg(_Fs_, 0, _X_Y_Z_W);
|
||||
if (_XYZW_SS && _X_Y_Z_W != 8) SSE2_PSHUFD_XMM_to_XMM(ACC, ACC, shuffleSS(_X_Y_Z_W));
|
||||
}
|
||||
else { Fs = mVU->regAlloc->allocReg(_Fs_, _Fd_, _X_Y_Z_W); }
|
||||
|
||||
opCase1 { if (_XYZW_SS && _X_Y_Z_W != 8) { SSE2_PSHUFD_XMM_to_XMM(Ft, Ft, shuffleSS(_X_Y_Z_W)); } }
|
||||
opCase2 { if (_XYZW_SS && (!_bc_x)) { SSE2_PSHUFD_XMM_to_XMM(Ft, Ft, shuffleSS((1 << (3 - _bc_)))); } }
|
||||
|
||||
if (_XYZW_SS) SSE_SS[opType](Fs, Ft);
|
||||
else SSE_PS[opType](Fs, Ft);
|
||||
|
||||
opCase1 { if (_XYZW_SS && _X_Y_Z_W != 8) { SSE2_PSHUFD_XMM_to_XMM(Ft, Ft, shuffleSS(_X_Y_Z_W)); } }
|
||||
opCase2 { if (_XYZW_SS && (!_bc_x)) { SSE2_PSHUFD_XMM_to_XMM(Ft, Ft, shuffleSS((1 << (3 - _bc_)))); } }
|
||||
|
||||
if (isACC) {
|
||||
if (_XYZW_SS) SSE_MOVSS_XMM_to_XMM(ACC, Fs);
|
||||
else mVUmergeRegs(ACC, Fs, _X_Y_Z_W);
|
||||
mVUupdateFlags(mVU, ACC, Fs);
|
||||
if (_XYZW_SS && _X_Y_Z_W != 8) SSE2_PSHUFD_XMM_to_XMM(ACC, ACC, shuffleSS(_X_Y_Z_W));
|
||||
mVU->regAlloc->clearNeeded(ACC);
|
||||
}
|
||||
else mVUupdateFlags(mVU, Fs, (((opCase==2)&&(!_XYZW_SS)) ? Ft : -1));
|
||||
|
||||
//if (isACC) SSE_MOVAPS_XMM_to_XMM(xmmACC, ACC); // For Testing
|
||||
mVU->regAlloc->clearNeeded(Fs); // Always Clear Written Reg First
|
||||
mVU->regAlloc->clearNeeded(Ft);
|
||||
mVU->regAlloc->flushAll(); // Flush All for Testing
|
||||
}
|
||||
pass3 { mVU_printOP(mVU, opCase, opName, isACC); }
|
||||
}
|
||||
|
||||
// MADDA/MSUBA Opcodes
|
||||
void mVU_FMACb(microVU* mVU, int recPass, int opCase, int opType, char* opName) {
|
||||
pass1 { setupPass1(mVU, opCase, 1, 0); }
|
||||
pass2 {
|
||||
int Fs, Ft, ACC;
|
||||
mVU->regAlloc->reset(); // Reset for Testing
|
||||
setupFtReg(mVU, Ft, opCase);
|
||||
|
||||
ACC = mVU->regAlloc->allocReg(32, 32, 0xf, 0);
|
||||
Fs = mVU->regAlloc->allocReg(_Fs_, 0, _X_Y_Z_W);
|
||||
|
||||
if (_XYZW_SS && _X_Y_Z_W != 8) { SSE2_PSHUFD_XMM_to_XMM(ACC, ACC, shuffleSS(_X_Y_Z_W)); }
|
||||
opCase1 { if (_XYZW_SS && _X_Y_Z_W != 8) { SSE2_PSHUFD_XMM_to_XMM(Ft, Ft, shuffleSS(_X_Y_Z_W)); } }
|
||||
opCase2 { if (_XYZW_SS && (!_bc_x)) { SSE2_PSHUFD_XMM_to_XMM(Ft, Ft, shuffleSS((1 << (3 - _bc_)))); } }
|
||||
|
||||
if (_XYZW_SS) SSE_SS[2](Fs, Ft);
|
||||
else SSE_PS[2](Fs, Ft);
|
||||
|
||||
opCase1 { if (_XYZW_SS && _X_Y_Z_W != 8) { SSE2_PSHUFD_XMM_to_XMM(Ft, Ft, shuffleSS(_X_Y_Z_W)); } }
|
||||
opCase2 { if (_XYZW_SS && (!_bc_x)) { SSE2_PSHUFD_XMM_to_XMM(Ft, Ft, shuffleSS((1 << (3 - _bc_)))); } }
|
||||
|
||||
if (_XYZW_SS || _X_Y_Z_W == 0xf) {
|
||||
if (_XYZW_SS) SSE_SS[opType](ACC, Fs);
|
||||
else SSE_PS[opType](ACC, Fs);
|
||||
mVUupdateFlags(mVU, ACC, Fs);
|
||||
if (_XYZW_SS && _X_Y_Z_W != 8) SSE2_PSHUFD_XMM_to_XMM(ACC, ACC, shuffleSS(_X_Y_Z_W));
|
||||
}
|
||||
else {
|
||||
int tempACC = mVU->regAlloc->allocReg();
|
||||
SSE_MOVAPS_XMM_to_XMM(tempACC, ACC);
|
||||
SSE_PS[opType](tempACC, Fs);
|
||||
mVUmergeRegs(ACC, tempACC, _X_Y_Z_W);
|
||||
mVU->regAlloc->clearNeeded(tempACC);
|
||||
}
|
||||
|
||||
//SSE_MOVAPS_XMM_to_XMM(xmmACC, ACC); // For Testing
|
||||
mVU->regAlloc->clearNeeded(ACC);
|
||||
mVU->regAlloc->clearNeeded(Fs);
|
||||
mVU->regAlloc->clearNeeded(Ft);
|
||||
mVU->regAlloc->flushAll(); // Flush All for Testing
|
||||
}
|
||||
pass3 { mVU_printOP(mVU, opCase, opName, 1); }
|
||||
}
|
||||
|
||||
// MADD Opcodes
|
||||
void mVU_FMACc(microVU* mVU, int recPass, int opCase, char* opName) {
|
||||
pass1 { setupPass1(mVU, opCase, 0, 0); }
|
||||
pass2 {
|
||||
int Fs, Ft, ACC;
|
||||
mVU->regAlloc->reset(); // Reset for Testing
|
||||
setupFtReg(mVU, Ft, opCase);
|
||||
|
||||
ACC = mVU->regAlloc->allocReg(32);
|
||||
Fs = mVU->regAlloc->allocReg(_Fs_, _Fd_, _X_Y_Z_W);
|
||||
|
||||
if (_XYZW_SS && _X_Y_Z_W != 8) { SSE2_PSHUFD_XMM_to_XMM(ACC, ACC, shuffleSS(_X_Y_Z_W)); }
|
||||
opCase1 { if (_XYZW_SS && _X_Y_Z_W != 8) { SSE2_PSHUFD_XMM_to_XMM(Ft, Ft, shuffleSS(_X_Y_Z_W)); } }
|
||||
opCase2 { if (_XYZW_SS && (!_bc_x)) { SSE2_PSHUFD_XMM_to_XMM(Ft, Ft, shuffleSS((1 << (3 - _bc_)))); } }
|
||||
|
||||
if (_XYZW_SS) { SSE_SS[2](Fs, Ft); SSE_SS[0](Fs, ACC); }
|
||||
else { SSE_PS[2](Fs, Ft); SSE_PS[0](Fs, ACC); }
|
||||
|
||||
mVUupdateFlags(mVU, Fs, -1);
|
||||
|
||||
if (_XYZW_SS && _X_Y_Z_W != 8) { SSE2_PSHUFD_XMM_to_XMM(ACC, ACC, shuffleSS(_X_Y_Z_W)); }
|
||||
opCase1 { if (_XYZW_SS && _X_Y_Z_W != 8) { SSE2_PSHUFD_XMM_to_XMM(Ft, Ft, shuffleSS(_X_Y_Z_W)); } }
|
||||
opCase2 { if (_XYZW_SS && (!_bc_x)) { SSE2_PSHUFD_XMM_to_XMM(Ft, Ft, shuffleSS((1 << (3 - _bc_)))); } }
|
||||
|
||||
mVU->regAlloc->clearNeeded(ACC);
|
||||
mVU->regAlloc->clearNeeded(Fs); // Always Clear Written Reg First
|
||||
mVU->regAlloc->clearNeeded(Ft);
|
||||
mVU->regAlloc->flushAll(); // Flush All for Testing
|
||||
}
|
||||
pass3 { mVU_printOP(mVU, opCase, opName, 0); }
|
||||
}
|
||||
|
||||
// MSUB Opcodes
|
||||
void mVU_FMACd(microVU* mVU, int recPass, int opCase, char* opName) {
|
||||
pass1 { setupPass1(mVU, opCase, 0, 0); }
|
||||
pass2 {
|
||||
int Fs, Ft, Fd;
|
||||
mVU->regAlloc->reset(); // Reset for Testing
|
||||
setupFtReg(mVU, Ft, opCase);
|
||||
|
||||
Fs = mVU->regAlloc->allocReg(_Fs_, 0, _X_Y_Z_W);
|
||||
Fd = mVU->regAlloc->allocReg(32, _Fd_, _X_Y_Z_W);
|
||||
|
||||
opCase1 { if (_XYZW_SS && _X_Y_Z_W != 8) { SSE2_PSHUFD_XMM_to_XMM(Ft, Ft, shuffleSS(_X_Y_Z_W)); } }
|
||||
opCase2 { if (_XYZW_SS && (!_bc_x)) { SSE2_PSHUFD_XMM_to_XMM(Ft, Ft, shuffleSS((1 << (3 - _bc_)))); } }
|
||||
|
||||
if (_XYZW_SS) { SSE_SS[2](Fs, Ft); SSE_SS[1](Fd, Fs); }
|
||||
else { SSE_PS[2](Fs, Ft); SSE_PS[1](Fd, Fs); }
|
||||
|
||||
mVUupdateFlags(mVU, Fd, Fs);
|
||||
|
||||
opCase1 { if (_XYZW_SS && _X_Y_Z_W != 8) { SSE2_PSHUFD_XMM_to_XMM(Ft, Ft, shuffleSS(_X_Y_Z_W)); } }
|
||||
opCase2 { if (_XYZW_SS && (!_bc_x)) { SSE2_PSHUFD_XMM_to_XMM(Ft, Ft, shuffleSS((1 << (3 - _bc_)))); } }
|
||||
|
||||
mVU->regAlloc->clearNeeded(Fd); // Always Clear Written Reg First
|
||||
mVU->regAlloc->clearNeeded(Ft);
|
||||
mVU->regAlloc->clearNeeded(Fs);
|
||||
mVU->regAlloc->flushAll(); // Flush All for Testing
|
||||
}
|
||||
pass3 { mVU_printOP(mVU, opCase, opName, 0); }
|
||||
}
|
||||
|
||||
// ABS Opcode
|
||||
mVUop(mVU_ABS) {
|
||||
pass1 { mVUanalyzeFMAC2(mVU, _Fs_, _Ft_); }
|
||||
pass2 {
|
||||
int Fs, Ft;
|
||||
mVUallocFMAC2a(mVU, Fs, Ft);
|
||||
if (!_Ft_) return;
|
||||
mVU->regAlloc->reset(); // Reset for Testing
|
||||
int Fs = mVU->regAlloc->allocReg(_Fs_, _Ft_, _X_Y_Z_W, ((_Fs_ == _Ft_) && (_X_Y_Z_W == 0xf)));
|
||||
SSE_ANDPS_M128_to_XMM(Fs, (uptr)mVU_absclip);
|
||||
mVUallocFMAC2b(mVU, Ft);
|
||||
mVU->regAlloc->clearNeeded(Fs);
|
||||
mVU->regAlloc->flushAll(); // Flush All for Testing
|
||||
}
|
||||
pass3 { mVUlog("ABS"); mVUlogFtFs(); }
|
||||
}
|
||||
mVUop(mVU_ADD) { mVU_FMAC1 (ADD, "ADD"); }
|
||||
mVUop(mVU_ADDi) { mVU_FMAC6 (ADD2, "ADDi"); }
|
||||
mVUop(mVU_ADDq) { mVU_FMAC22(ADD, "ADDq"); }
|
||||
mVUop(mVU_ADDx) { mVU_FMAC3 (ADD, "ADDx"); }
|
||||
mVUop(mVU_ADDy) { mVU_FMAC3 (ADD, "ADDy"); }
|
||||
mVUop(mVU_ADDz) { mVU_FMAC3 (ADD, "ADDz"); }
|
||||
mVUop(mVU_ADDw) { mVU_FMAC3 (ADD, "ADDw"); }
|
||||
mVUop(mVU_ADDA) { mVU_FMAC4 (ADD, "ADDA"); }
|
||||
mVUop(mVU_ADDAi) { mVU_FMAC7 (ADD, "ADDAi"); }
|
||||
mVUop(mVU_ADDAq) { mVU_FMAC23(ADD, "ADDAq"); }
|
||||
mVUop(mVU_ADDAx) { mVU_FMAC5 (ADD, "ADDAx"); }
|
||||
mVUop(mVU_ADDAy) { mVU_FMAC5 (ADD, "ADDAy"); }
|
||||
mVUop(mVU_ADDAz) { mVU_FMAC5 (ADD, "ADDAz"); }
|
||||
mVUop(mVU_ADDAw) { mVU_FMAC5 (ADD, "ADDAw"); }
|
||||
mVUop(mVU_SUB) { mVU_FMAC1 (SUB, "SUB"); }
|
||||
mVUop(mVU_SUBi) { mVU_FMAC6 (SUB, "SUBi"); }
|
||||
mVUop(mVU_SUBq) { mVU_FMAC22(SUB, "SUBq"); }
|
||||
mVUop(mVU_SUBx) { mVU_FMAC3 (SUB, "SUBx"); }
|
||||
mVUop(mVU_SUBy) { mVU_FMAC3 (SUB, "SUBy"); }
|
||||
mVUop(mVU_SUBz) { mVU_FMAC3 (SUB, "SUBz"); }
|
||||
mVUop(mVU_SUBw) { mVU_FMAC3 (SUB, "SUBw"); }
|
||||
mVUop(mVU_SUBA) { mVU_FMAC4 (SUB, "SUBA"); }
|
||||
mVUop(mVU_SUBAi) { mVU_FMAC7 (SUB, "SUBAi"); }
|
||||
mVUop(mVU_SUBAq) { mVU_FMAC23(SUB, "SUBAq"); }
|
||||
mVUop(mVU_SUBAx) { mVU_FMAC5 (SUB, "SUBAx"); }
|
||||
mVUop(mVU_SUBAy) { mVU_FMAC5 (SUB, "SUBAy"); }
|
||||
mVUop(mVU_SUBAz) { mVU_FMAC5 (SUB, "SUBAz"); }
|
||||
mVUop(mVU_SUBAw) { mVU_FMAC5 (SUB, "SUBAw"); }
|
||||
mVUop(mVU_MUL) { mVU_FMAC1 (MUL, "MUL"); }
|
||||
mVUop(mVU_MULi) { mVU_FMAC6 (MUL, "MULi"); }
|
||||
mVUop(mVU_MULq) { mVU_FMAC22(MUL, "MULq"); }
|
||||
mVUop(mVU_MULx) { mVU_FMAC3 (MUL, "MULx"); }
|
||||
mVUop(mVU_MULy) { mVU_FMAC3 (MUL, "MULy"); }
|
||||
mVUop(mVU_MULz) { mVU_FMAC3 (MUL, "MULz"); }
|
||||
mVUop(mVU_MULw) { mVU_FMAC3 (MUL, "MULw"); }
|
||||
mVUop(mVU_MULA) { mVU_FMAC4 (MUL, "MULA"); }
|
||||
mVUop(mVU_MULAi) { mVU_FMAC7 (MUL, "MULAi"); }
|
||||
mVUop(mVU_MULAq) { mVU_FMAC23(MUL, "MULAq"); }
|
||||
mVUop(mVU_MULAx) { mVU_FMAC5 (MUL, "MULAx"); }
|
||||
mVUop(mVU_MULAy) { mVU_FMAC5 (MUL, "MULAy"); }
|
||||
mVUop(mVU_MULAz) { mVU_FMAC5 (MUL, "MULAz"); }
|
||||
mVUop(mVU_MULAw) { mVU_FMAC5 (MUL, "MULAw"); }
|
||||
mVUop(mVU_MADD) { mVU_FMAC8 (ADD, "MADD"); }
|
||||
mVUop(mVU_MADDi) { mVU_FMAC12(ADD, "MADDi"); }
|
||||
mVUop(mVU_MADDq) { mVU_FMAC24(ADD, "MADDq"); }
|
||||
mVUop(mVU_MADDx) { mVU_FMAC10(ADD, "MADDx"); }
|
||||
mVUop(mVU_MADDy) { mVU_FMAC10(ADD, "MADDy"); }
|
||||
mVUop(mVU_MADDz) { mVU_FMAC10(ADD, "MADDz"); }
|
||||
mVUop(mVU_MADDw) { mVU_FMAC10(ADD, "MADDw"); }
|
||||
mVUop(mVU_MADDA) { mVU_FMAC14(ADD, "MADDA"); }
|
||||
mVUop(mVU_MADDAi) { mVU_FMAC16(ADD, "MADDAi"); }
|
||||
mVUop(mVU_MADDAq) { mVU_FMAC26(ADD, "MADDAq"); }
|
||||
mVUop(mVU_MADDAx) { mVU_FMAC15(ADD, "MADDAx"); }
|
||||
mVUop(mVU_MADDAy) { mVU_FMAC15(ADD, "MADDAy"); }
|
||||
mVUop(mVU_MADDAz) { mVU_FMAC15(ADD, "MADDAz"); }
|
||||
mVUop(mVU_MADDAw) { mVU_FMAC15(ADD, "MADDAw"); }
|
||||
mVUop(mVU_MSUB) { mVU_FMAC9 (SUB, "MSUB"); }
|
||||
mVUop(mVU_MSUBi) { mVU_FMAC13(SUB, "MSUBi"); }
|
||||
mVUop(mVU_MSUBq) { mVU_FMAC25(SUB, "MSUBq"); }
|
||||
mVUop(mVU_MSUBx) { mVU_FMAC11(SUB, "MSUBx"); }
|
||||
mVUop(mVU_MSUBy) { mVU_FMAC11(SUB, "MSUBy"); }
|
||||
mVUop(mVU_MSUBz) { mVU_FMAC11(SUB, "MSUBz"); }
|
||||
mVUop(mVU_MSUBw) { mVU_FMAC11(SUB, "MSUBw"); }
|
||||
mVUop(mVU_MSUBA) { mVU_FMAC14(SUB, "MSUBA"); }
|
||||
mVUop(mVU_MSUBAi) { mVU_FMAC16(SUB, "MSUBAi"); }
|
||||
mVUop(mVU_MSUBAq) { mVU_FMAC26(SUB, "MSUBAq"); }
|
||||
mVUop(mVU_MSUBAx) { mVU_FMAC15(SUB, "MSUBAx"); }
|
||||
mVUop(mVU_MSUBAy) { mVU_FMAC15(SUB, "MSUBAy"); }
|
||||
mVUop(mVU_MSUBAz) { mVU_FMAC15(SUB, "MSUBAz"); }
|
||||
mVUop(mVU_MSUBAw) { mVU_FMAC15(SUB, "MSUBAw"); }
|
||||
mVUop(mVU_MAX) { mVU_FMAC27(MAX2, "MAX"); }
|
||||
mVUop(mVU_MAXi) { mVU_FMAC28(MAX2, "MAXi"); }
|
||||
mVUop(mVU_MAXx) { mVU_FMAC29(MAX2, "MAXx"); }
|
||||
mVUop(mVU_MAXy) { mVU_FMAC29(MAX2, "MAXy"); }
|
||||
mVUop(mVU_MAXz) { mVU_FMAC29(MAX2, "MAXz"); }
|
||||
mVUop(mVU_MAXw) { mVU_FMAC29(MAX2, "MAXw"); }
|
||||
mVUop(mVU_MINI) { mVU_FMAC27(MIN2, "MINI"); }
|
||||
mVUop(mVU_MINIi) { mVU_FMAC28(MIN2, "MINIi"); }
|
||||
mVUop(mVU_MINIx) { mVU_FMAC29(MIN2, "MINIx"); }
|
||||
mVUop(mVU_MINIy) { mVU_FMAC29(MIN2, "MINIy"); }
|
||||
mVUop(mVU_MINIz) { mVU_FMAC29(MIN2, "MINIz"); }
|
||||
mVUop(mVU_MINIw) { mVU_FMAC29(MIN2, "MINIw"); }
|
||||
mVUop(mVU_OPMULA) { mVU_FMAC18(MUL, "OPMULA"); }
|
||||
mVUop(mVU_OPMSUB) { mVU_FMAC19(SUB, "OPMSUB"); }
|
||||
mVUop(mVU_NOP) { pass3 { mVUlog("NOP"); } }
|
||||
void mVU_FTOIx(mP, uptr addr) {
|
||||
|
||||
// OPMULA Opcode
|
||||
mVUop(mVU_OPMULA) {
|
||||
pass1 { mVUanalyzeFMAC1(mVU, 0, _Fs_, _Ft_); }
|
||||
pass2 {
|
||||
mVU->regAlloc->reset(); // Reset for Testing
|
||||
int Fs = mVU->regAlloc->allocReg(_Fs_, 32, _X_Y_Z_W);
|
||||
int Ft = mVU->regAlloc->allocReg(_Ft_, 0, _X_Y_Z_W);
|
||||
|
||||
SSE2_PSHUFD_XMM_to_XMM(Fs, Fs, 0xC9); // WXZY
|
||||
SSE2_PSHUFD_XMM_to_XMM(Ft, Ft, 0xD2); // WYXZ
|
||||
SSE_MULPS_XMM_to_XMM(Fs, Ft);
|
||||
mVUupdateFlags(mVU, Fs, Ft);
|
||||
|
||||
mVU->regAlloc->clearNeeded(Fs);
|
||||
mVU->regAlloc->clearNeeded(Ft);
|
||||
mVU->regAlloc->flushAll(); // Flush All for Testing
|
||||
}
|
||||
pass3 { mVUlog("OPMULA"); mVUlogACC(); mVUlogFt(); }
|
||||
}
|
||||
|
||||
// OPMSUB Opcode
|
||||
mVUop(mVU_OPMSUB) {
|
||||
pass1 { mVUanalyzeFMAC1(mVU, _Fd_, _Fs_, _Ft_); }
|
||||
pass2 {
|
||||
mVU->regAlloc->reset(); // Reset for Testing
|
||||
int Ft = mVU->regAlloc->allocReg(_Ft_);
|
||||
int Fs = mVU->regAlloc->allocReg(_Fs_, 0, _X_Y_Z_W);
|
||||
int ACC = mVU->regAlloc->allocReg(32, _Fd_, _X_Y_Z_W);
|
||||
|
||||
SSE2_PSHUFD_XMM_to_XMM(Fs, Fs, 0xC9); // WXZY
|
||||
SSE2_PSHUFD_XMM_to_XMM(Ft, Ft, 0xD2); // WYXZ
|
||||
SSE_MULPS_XMM_to_XMM(Fs, Ft);
|
||||
SSE_SUBPS_XMM_to_XMM(ACC, Fs);
|
||||
mVUupdateFlags(mVU, ACC, Fs);
|
||||
|
||||
mVU->regAlloc->clearNeeded(32);
|
||||
mVU->regAlloc->clearNeeded(Fs);
|
||||
mVU->regAlloc->clearNeeded(Ft);
|
||||
mVU->regAlloc->flushAll(); // Flush All for Testing
|
||||
|
||||
}
|
||||
pass3 { mVUlog("OPMSUB"); mVUlogFd(); mVUlogFt(); }
|
||||
}
|
||||
|
||||
// FTOI0/FTIO4/FTIO12/FTIO15 Opcodes
|
||||
void mVU_FTOIx(mP, uptr addr, char* opName) {
|
||||
pass1 { mVUanalyzeFMAC2(mVU, _Fs_, _Ft_); }
|
||||
pass2 {
|
||||
int Fs, Ft;
|
||||
mVUallocFMAC2a(mVU, Fs, Ft);
|
||||
if (!_Ft_) return;
|
||||
mVU->regAlloc->reset(); // Reset for Testing
|
||||
int Fs = mVU->regAlloc->allocReg(_Fs_, _Ft_, _X_Y_Z_W, ((_Fs_ == _Ft_) && (_X_Y_Z_W == 0xf)));
|
||||
int t1 = mVU->regAlloc->allocReg();
|
||||
int t2 = mVU->regAlloc->allocReg();
|
||||
|
||||
// Note: For help understanding this algorithm see recVUMI_FTOI_Saturate()
|
||||
SSE_MOVAPS_XMM_to_XMM(xmmT1, Fs);
|
||||
SSE_MOVAPS_XMM_to_XMM(t1, Fs);
|
||||
if (addr) { SSE_MULPS_M128_to_XMM(Fs, addr); }
|
||||
SSE2_CVTTPS2DQ_XMM_to_XMM(Fs, Fs);
|
||||
SSE2_PXOR_M128_to_XMM(xmmT1, (uptr)mVU_signbit);
|
||||
SSE2_PSRAD_I8_to_XMM(xmmT1, 31);
|
||||
SSE_MOVAPS_XMM_to_XMM(xmmFt, Fs);
|
||||
SSE2_PCMPEQD_M128_to_XMM(xmmFt, (uptr)mVU_signbit);
|
||||
SSE_ANDPS_XMM_to_XMM(xmmT1, xmmFt);
|
||||
SSE2_PADDD_XMM_to_XMM(Fs, xmmT1);
|
||||
SSE2_PXOR_M128_to_XMM(t1, (uptr)mVU_signbit);
|
||||
SSE2_PSRAD_I8_to_XMM (t1, 31);
|
||||
SSE_MOVAPS_XMM_to_XMM(t2, Fs);
|
||||
SSE2_PCMPEQD_M128_to_XMM(t2, (uptr)mVU_signbit);
|
||||
SSE_ANDPS_XMM_to_XMM (t1, t2);
|
||||
SSE2_PADDD_XMM_to_XMM(Fs, t1);
|
||||
|
||||
mVUallocFMAC2b(mVU, Ft);
|
||||
mVU->regAlloc->clearNeeded(Fs);
|
||||
mVU->regAlloc->clearNeeded(t1);
|
||||
mVU->regAlloc->clearNeeded(t2);
|
||||
mVU->regAlloc->flushAll(); // Flush All for Testing
|
||||
}
|
||||
pass3 { mVUlog(opName); mVUlogFtFs(); }
|
||||
}
|
||||
mVUop(mVU_FTOI0) { mVU_FTOIx(mX, (uptr)0); pass3 { mVUlog("FTOI0"); mVUlogFtFs(); } }
|
||||
mVUop(mVU_FTOI4) { mVU_FTOIx(mX, (uptr)mVU_FTOI_4); pass3 { mVUlog("FTOI4"); mVUlogFtFs(); } }
|
||||
mVUop(mVU_FTOI12) { mVU_FTOIx(mX, (uptr)mVU_FTOI_12); pass3 { mVUlog("FTOI12"); mVUlogFtFs(); } }
|
||||
mVUop(mVU_FTOI15) { mVU_FTOIx(mX, (uptr)mVU_FTOI_15); pass3 { mVUlog("FTOI15"); mVUlogFtFs(); } }
|
||||
void mVU_ITOFx(mP, uptr addr) {
|
||||
|
||||
// ITOF0/ITOF4/ITOF12/ITOF15 Opcodes
|
||||
void mVU_ITOFx(mP, uptr addr, char* opName) {
|
||||
pass1 { mVUanalyzeFMAC2(mVU, _Fs_, _Ft_); }
|
||||
pass2 {
|
||||
int Fs, Ft;
|
||||
mVUallocFMAC2a(mVU, Fs, Ft);
|
||||
|
||||
SSE2_CVTDQ2PS_XMM_to_XMM(Ft, Fs);
|
||||
if (addr) { SSE_MULPS_M128_to_XMM(Ft, addr); }
|
||||
//mVUclamp2(Ft, xmmT1, 15); // Clamp (not sure if this is needed)
|
||||
if (!_Ft_) return;
|
||||
mVU->regAlloc->reset(); // Reset for Testing
|
||||
int Fs = mVU->regAlloc->allocReg(_Fs_, _Ft_, _X_Y_Z_W, ((_Fs_ == _Ft_) && (_X_Y_Z_W == 0xf)));
|
||||
|
||||
mVUallocFMAC2b(mVU, Ft);
|
||||
SSE2_CVTDQ2PS_XMM_to_XMM(Fs, Fs);
|
||||
if (addr) { SSE_MULPS_M128_to_XMM(Fs, addr); }
|
||||
//mVUclamp2(Fs, xmmT1, 15); // Clamp (not sure if this is needed)
|
||||
|
||||
mVU->regAlloc->clearNeeded(Fs);
|
||||
mVU->regAlloc->flushAll(); // Flush All for Testing
|
||||
}
|
||||
pass3 { mVUlog(opName); mVUlogFtFs(); }
|
||||
}
|
||||
mVUop(mVU_ITOF0) { mVU_ITOFx(mX, (uptr)0); pass3 { mVUlog("ITOF0"); mVUlogFtFs(); } }
|
||||
mVUop(mVU_ITOF4) { mVU_ITOFx(mX, (uptr)mVU_ITOF_4); pass3 { mVUlog("ITOF4"); mVUlogFtFs(); } }
|
||||
mVUop(mVU_ITOF12) { mVU_ITOFx(mX, (uptr)mVU_ITOF_12); pass3 { mVUlog("ITOF12"); mVUlogFtFs(); } }
|
||||
mVUop(mVU_ITOF15) { mVU_ITOFx(mX, (uptr)mVU_ITOF_15); pass3 { mVUlog("ITOF15"); mVUlogFtFs(); } }
|
||||
|
||||
// Clip Opcode
|
||||
mVUop(mVU_CLIP) {
|
||||
pass1 { mVUanalyzeFMAC4(mVU, _Fs_, _Ft_); }
|
||||
pass2 {
|
||||
int Fs, Ft;
|
||||
mVUallocFMAC17a(mVU, Fs, Ft);
|
||||
mVU->regAlloc->reset(); // Reset for Testing
|
||||
int Fs = mVU->regAlloc->allocReg(_Fs_);
|
||||
int Ft = mVU->regAlloc->allocReg(_Ft_, 0, 1);
|
||||
int t1 = mVU->regAlloc->allocReg();
|
||||
|
||||
mVUunpack_xyzw(Ft, Ft, 0);
|
||||
mVUallocCFLAGa(mVU, gprT1, cFLAG.lastWrite);
|
||||
SHL32ItoR(gprT1, 6);
|
||||
|
||||
SSE_ANDPS_M128_to_XMM(Ft, (uptr)mVU_absclip);
|
||||
SSE_MOVAPS_XMM_to_XMM(xmmT1, Ft);
|
||||
SSE_ORPS_M128_to_XMM(xmmT1, (uptr)mVU_signbit);
|
||||
SSE_MOVAPS_XMM_to_XMM(t1, Ft);
|
||||
SSE_ORPS_M128_to_XMM(t1, (uptr)mVU_signbit);
|
||||
|
||||
SSE_CMPNLEPS_XMM_to_XMM(xmmT1, Fs); //-w, -z, -y, -x
|
||||
SSE_CMPLTPS_XMM_to_XMM(Ft, Fs); //+w, +z, +y, +x
|
||||
SSE_CMPNLEPS_XMM_to_XMM(t1, Fs); // -w, -z, -y, -x
|
||||
SSE_CMPLTPS_XMM_to_XMM(Ft, Fs); // +w, +z, +y, +x
|
||||
|
||||
SSE_MOVAPS_XMM_to_XMM(Fs, Ft); //Fs = +w, +z, +y, +x
|
||||
SSE_UNPCKLPS_XMM_to_XMM(Ft, xmmT1); //Ft = -y,+y,-x,+x
|
||||
SSE_UNPCKHPS_XMM_to_XMM(Fs, xmmT1); //Fs = -w,+w,-z,+z
|
||||
SSE_MOVAPS_XMM_to_XMM(Fs, Ft); // Fs = +w, +z, +y, +x
|
||||
SSE_UNPCKLPS_XMM_to_XMM(Ft, t1); // Ft = -y,+y,-x,+x
|
||||
SSE_UNPCKHPS_XMM_to_XMM(Fs, t1); // Fs = -w,+w,-z,+z
|
||||
|
||||
SSE_MOVMSKPS_XMM_to_R32(gprT2, Fs); // -w,+w,-z,+z
|
||||
AND32ItoR(gprT2, 0x3);
|
||||
|
@ -610,7 +416,106 @@ mVUop(mVU_CLIP) {
|
|||
AND32ItoR(gprT1, 0xffffff);
|
||||
|
||||
mVUallocCFLAGb(mVU, gprT1, cFLAG.write);
|
||||
mVU->regAlloc->clearNeeded(Fs);
|
||||
mVU->regAlloc->clearNeeded(Ft);
|
||||
mVU->regAlloc->clearNeeded(t1);
|
||||
mVU->regAlloc->flushAll(); // Flush All for Testing
|
||||
}
|
||||
pass3 { mVUlog("CLIP"); mVUlogCLIP(); }
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Micro VU Micromode Upper instructions
|
||||
//------------------------------------------------------------------
|
||||
|
||||
mVUop(mVU_ADD) { mVU_FMACa(mVU, recPass, 1, 0, 0, "ADD"); }
|
||||
mVUop(mVU_ADDi) { mVU_FMACa(mVU, recPass, 3, 0, 0, "ADDi"); }
|
||||
mVUop(mVU_ADDq) { mVU_FMACa(mVU, recPass, 4, 0, 0, "ADDq"); }
|
||||
mVUop(mVU_ADDx) { mVU_FMACa(mVU, recPass, 2, 0, 0, "ADDx"); }
|
||||
mVUop(mVU_ADDy) { mVU_FMACa(mVU, recPass, 2, 0, 0, "ADDy"); }
|
||||
mVUop(mVU_ADDz) { mVU_FMACa(mVU, recPass, 2, 0, 0, "ADDz"); }
|
||||
mVUop(mVU_ADDw) { mVU_FMACa(mVU, recPass, 2, 0, 0, "ADDw"); }
|
||||
mVUop(mVU_ADDA) { mVU_FMACa(mVU, recPass, 1, 0, 1, "ADDA"); }
|
||||
mVUop(mVU_ADDAi) { mVU_FMACa(mVU, recPass, 3, 0, 1, "ADDAi"); }
|
||||
mVUop(mVU_ADDAq) { mVU_FMACa(mVU, recPass, 4, 0, 1, "ADDAq"); }
|
||||
mVUop(mVU_ADDAx) { mVU_FMACa(mVU, recPass, 2, 0, 1, "ADDAx"); }
|
||||
mVUop(mVU_ADDAy) { mVU_FMACa(mVU, recPass, 2, 0, 1, "ADDAy"); }
|
||||
mVUop(mVU_ADDAz) { mVU_FMACa(mVU, recPass, 2, 0, 1, "ADDAz"); }
|
||||
mVUop(mVU_ADDAw) { mVU_FMACa(mVU, recPass, 2, 0, 1, "ADDAw"); }
|
||||
mVUop(mVU_SUB) { mVU_FMACa(mVU, recPass, 1, 1, 0, "SUB"); }
|
||||
mVUop(mVU_SUBi) { mVU_FMACa(mVU, recPass, 3, 1, 0, "SUBi"); }
|
||||
mVUop(mVU_SUBq) { mVU_FMACa(mVU, recPass, 4, 1, 0, "SUBq"); }
|
||||
mVUop(mVU_SUBx) { mVU_FMACa(mVU, recPass, 2, 1, 0, "SUBx"); }
|
||||
mVUop(mVU_SUBy) { mVU_FMACa(mVU, recPass, 2, 1, 0, "SUBy"); }
|
||||
mVUop(mVU_SUBz) { mVU_FMACa(mVU, recPass, 2, 1, 0, "SUBz"); }
|
||||
mVUop(mVU_SUBw) { mVU_FMACa(mVU, recPass, 2, 1, 0, "SUBw"); }
|
||||
mVUop(mVU_SUBA) { mVU_FMACa(mVU, recPass, 1, 1, 1, "SUBA"); }
|
||||
mVUop(mVU_SUBAi) { mVU_FMACa(mVU, recPass, 3, 1, 1, "SUBAi"); }
|
||||
mVUop(mVU_SUBAq) { mVU_FMACa(mVU, recPass, 4, 1, 1, "SUBAq"); }
|
||||
mVUop(mVU_SUBAx) { mVU_FMACa(mVU, recPass, 2, 1, 1, "SUBAx"); }
|
||||
mVUop(mVU_SUBAy) { mVU_FMACa(mVU, recPass, 2, 1, 1, "SUBAy"); }
|
||||
mVUop(mVU_SUBAz) { mVU_FMACa(mVU, recPass, 2, 1, 1, "SUBAz"); }
|
||||
mVUop(mVU_SUBAw) { mVU_FMACa(mVU, recPass, 2, 1, 1, "SUBAw"); }
|
||||
mVUop(mVU_MUL) { mVU_FMACa(mVU, recPass, 1, 2, 0, "MUL"); }
|
||||
mVUop(mVU_MULi) { mVU_FMACa(mVU, recPass, 3, 2, 0, "MULi"); }
|
||||
mVUop(mVU_MULq) { mVU_FMACa(mVU, recPass, 4, 2, 0, "MULq"); }
|
||||
mVUop(mVU_MULx) { mVU_FMACa(mVU, recPass, 2, 2, 0, "MULx"); }
|
||||
mVUop(mVU_MULy) { mVU_FMACa(mVU, recPass, 2, 2, 0, "MULy"); }
|
||||
mVUop(mVU_MULz) { mVU_FMACa(mVU, recPass, 2, 2, 0, "MULz"); }
|
||||
mVUop(mVU_MULw) { mVU_FMACa(mVU, recPass, 2, 2, 0, "MULw"); }
|
||||
mVUop(mVU_MULA) { mVU_FMACa(mVU, recPass, 1, 2, 1, "MULA"); }
|
||||
mVUop(mVU_MULAi) { mVU_FMACa(mVU, recPass, 3, 2, 1, "MULAi"); }
|
||||
mVUop(mVU_MULAq) { mVU_FMACa(mVU, recPass, 4, 2, 1, "MULAq"); }
|
||||
mVUop(mVU_MULAx) { mVU_FMACa(mVU, recPass, 2, 2, 1, "MULAx"); }
|
||||
mVUop(mVU_MULAy) { mVU_FMACa(mVU, recPass, 2, 2, 1, "MULAy"); }
|
||||
mVUop(mVU_MULAz) { mVU_FMACa(mVU, recPass, 2, 2, 1, "MULAz"); }
|
||||
mVUop(mVU_MULAw) { mVU_FMACa(mVU, recPass, 2, 2, 1, "MULAw"); }
|
||||
mVUop(mVU_MADD) { mVU_FMACc(mVU, recPass, 1, "MADD"); }
|
||||
mVUop(mVU_MADDi) { mVU_FMACc(mVU, recPass, 3, "MADDi"); }
|
||||
mVUop(mVU_MADDq) { mVU_FMACc(mVU, recPass, 4, "MADDq"); }
|
||||
mVUop(mVU_MADDx) { mVU_FMACc(mVU, recPass, 2, "MADDx"); }
|
||||
mVUop(mVU_MADDy) { mVU_FMACc(mVU, recPass, 2, "MADDy"); }
|
||||
mVUop(mVU_MADDz) { mVU_FMACc(mVU, recPass, 2, "MADDz"); }
|
||||
mVUop(mVU_MADDw) { mVU_FMACc(mVU, recPass, 2, "MADDw"); }
|
||||
mVUop(mVU_MADDA) { mVU_FMACb(mVU, recPass, 1, 0, "MADDA"); }
|
||||
mVUop(mVU_MADDAi) { mVU_FMACb(mVU, recPass, 3, 0, "MADDAi"); }
|
||||
mVUop(mVU_MADDAq) { mVU_FMACb(mVU, recPass, 4, 0, "MADDAq"); }
|
||||
mVUop(mVU_MADDAx) { mVU_FMACb(mVU, recPass, 2, 0, "MADDAx"); }
|
||||
mVUop(mVU_MADDAy) { mVU_FMACb(mVU, recPass, 2, 0, "MADDAy"); }
|
||||
mVUop(mVU_MADDAz) { mVU_FMACb(mVU, recPass, 2, 0, "MADDAz"); }
|
||||
mVUop(mVU_MADDAw) { mVU_FMACb(mVU, recPass, 2, 0, "MADDAw"); }
|
||||
mVUop(mVU_MSUB) { mVU_FMACd(mVU, recPass, 1, "MSUB"); }
|
||||
mVUop(mVU_MSUBi) { mVU_FMACd(mVU, recPass, 3, "MSUBi"); }
|
||||
mVUop(mVU_MSUBq) { mVU_FMACd(mVU, recPass, 4, "MSUBq"); }
|
||||
mVUop(mVU_MSUBx) { mVU_FMACd(mVU, recPass, 2, "MSUBx"); }
|
||||
mVUop(mVU_MSUBy) { mVU_FMACd(mVU, recPass, 2, "MSUBy"); }
|
||||
mVUop(mVU_MSUBz) { mVU_FMACd(mVU, recPass, 2, "MSUBz"); }
|
||||
mVUop(mVU_MSUBw) { mVU_FMACd(mVU, recPass, 2, "MSUBw"); }
|
||||
mVUop(mVU_MSUBA) { mVU_FMACb(mVU, recPass, 1, 1, "MSUBA"); }
|
||||
mVUop(mVU_MSUBAi) { mVU_FMACb(mVU, recPass, 3, 1, "MSUBAi"); }
|
||||
mVUop(mVU_MSUBAq) { mVU_FMACb(mVU, recPass, 4, 1, "MSUBAq"); }
|
||||
mVUop(mVU_MSUBAx) { mVU_FMACb(mVU, recPass, 2, 1, "MSUBAx"); }
|
||||
mVUop(mVU_MSUBAy) { mVU_FMACb(mVU, recPass, 2, 1, "MSUBAy"); }
|
||||
mVUop(mVU_MSUBAz) { mVU_FMACb(mVU, recPass, 2, 1, "MSUBAz"); }
|
||||
mVUop(mVU_MSUBAw) { mVU_FMACb(mVU, recPass, 2, 1, "MSUBAw"); }
|
||||
mVUop(mVU_MAX) { mVU_FMACa(mVU, recPass, 1, 3, 0, "MAX"); }
|
||||
mVUop(mVU_MAXi) { mVU_FMACa(mVU, recPass, 3, 3, 0, "MAXi"); }
|
||||
mVUop(mVU_MAXx) { mVU_FMACa(mVU, recPass, 2, 3, 0, "MAXx"); }
|
||||
mVUop(mVU_MAXy) { mVU_FMACa(mVU, recPass, 2, 3, 0, "MAXy"); }
|
||||
mVUop(mVU_MAXz) { mVU_FMACa(mVU, recPass, 2, 3, 0, "MAXz"); }
|
||||
mVUop(mVU_MAXw) { mVU_FMACa(mVU, recPass, 2, 3, 0, "MAXw"); }
|
||||
mVUop(mVU_MINI) { mVU_FMACa(mVU, recPass, 1, 4, 0, "MINI"); }
|
||||
mVUop(mVU_MINIi) { mVU_FMACa(mVU, recPass, 3, 4, 0, "MINIi"); }
|
||||
mVUop(mVU_MINIx) { mVU_FMACa(mVU, recPass, 2, 4, 0, "MINIx"); }
|
||||
mVUop(mVU_MINIy) { mVU_FMACa(mVU, recPass, 2, 4, 0, "MINIy"); }
|
||||
mVUop(mVU_MINIz) { mVU_FMACa(mVU, recPass, 2, 4, 0, "MINIz"); }
|
||||
mVUop(mVU_MINIw) { mVU_FMACa(mVU, recPass, 2, 4, 0, "MINIw"); }
|
||||
mVUop(mVU_FTOI0) { mVU_FTOIx(mX, (uptr)0, "FTOI0"); }
|
||||
mVUop(mVU_FTOI4) { mVU_FTOIx(mX, (uptr)mVU_FTOI_4, "FTOI4"); }
|
||||
mVUop(mVU_FTOI12) { mVU_FTOIx(mX, (uptr)mVU_FTOI_12, "FTOI12"); }
|
||||
mVUop(mVU_FTOI15) { mVU_FTOIx(mX, (uptr)mVU_FTOI_15, "FTOI15"); }
|
||||
mVUop(mVU_ITOF0) { mVU_ITOFx(mX, (uptr)0, "ITOF0"); }
|
||||
mVUop(mVU_ITOF4) { mVU_ITOFx(mX, (uptr)mVU_ITOF_4, "ITOF4"); }
|
||||
mVUop(mVU_ITOF12) { mVU_ITOFx(mX, (uptr)mVU_ITOF_12, "ITOF12"); }
|
||||
mVUop(mVU_ITOF15) { mVU_ITOFx(mX, (uptr)mVU_ITOF_15, "ITOF15"); }
|
||||
mVUop(mVU_NOP) { pass3 { mVUlog("NOP"); } }
|
||||
|
|
|
@ -162,7 +162,7 @@ void GPURenderer::VSync()
|
|||
|
||||
GetClientRect(m_hWnd, r);
|
||||
|
||||
m_dev->Present(r.fit(m_aspectratio), 0);
|
||||
m_dev->Present(r.fit(m_aspectratio), 0, true);
|
||||
}
|
||||
|
||||
bool GPURenderer::MakeSnapshot(const string& path)
|
||||
|
|
|
@ -81,7 +81,7 @@ void GPUSettingsDlg::OnInit()
|
|||
memset(&mode, 0, sizeof(mode));
|
||||
m_modes.push_back(mode);
|
||||
|
||||
ComboBoxAppend(IDC_RESOLUTION, "Windowed", (LPARAM)&m_modes.back(), true);
|
||||
ComboBoxAppend(IDC_RESOLUTION, "Please select...", (LPARAM)&m_modes.back(), true);
|
||||
|
||||
if(CComPtr<IDirect3D9> d3d = Direct3DCreate9(D3D_SDK_VERSION))
|
||||
{
|
||||
|
@ -124,6 +124,8 @@ void GPUSettingsDlg::OnInit()
|
|||
ComboBoxInit(IDC_ASPECTRATIO, g_aspectratio, countof(g_aspectratio), theApp.GetConfig("AspectRatio", 1));
|
||||
ComboBoxInit(IDC_SCALE, g_scale, countof(g_scale), theApp.GetConfig("scale_x", 0) | (theApp.GetConfig("scale_y", 0) << 2));
|
||||
|
||||
CheckDlgButton(m_hWnd, IDC_WINDOWED, theApp.GetConfig("windowed", 1));
|
||||
|
||||
SendMessage(GetDlgItem(m_hWnd, IDC_SWTHREADS), UDM_SETRANGE, 0, MAKELPARAM(16, 1));
|
||||
SendMessage(GetDlgItem(m_hWnd, IDC_SWTHREADS), UDM_SETPOS, 0, MAKELPARAM(theApp.GetConfig("swthreads", 1), 0));
|
||||
|
||||
|
@ -176,6 +178,7 @@ bool GPUSettingsDlg::OnCommand(HWND hWnd, UINT id, UINT code)
|
|||
}
|
||||
|
||||
theApp.SetConfig("swthreads", (int)SendMessage(GetDlgItem(m_hWnd, IDC_SWTHREADS), UDM_GETPOS, 0, 0));
|
||||
theApp.SetConfig("windowed", (int)IsDlgButtonChecked(m_hWnd, IDC_WINDOWED));
|
||||
}
|
||||
|
||||
return __super::OnCommand(hWnd, id, code);
|
||||
|
|
|
@ -139,7 +139,10 @@ static INT32 GSopen(void* dsp, char* title, int mt, int renderer)
|
|||
case 13: s_gs = new GSRendererNull(s_basemem, !!mt, s_irq, new GSDeviceNull()); break;
|
||||
}
|
||||
|
||||
if(!s_gs->Create(title))
|
||||
int w = theApp.GetConfig("ModeWidth", 0);
|
||||
int h = theApp.GetConfig("ModeHeight", 0);
|
||||
|
||||
if(!s_gs->Create(title, w, h))
|
||||
{
|
||||
GSclose();
|
||||
|
||||
|
@ -291,7 +294,7 @@ EXPORT_C GSsetGameCRC(uint32 crc, int options)
|
|||
s_gs->SetGameCRC(crc, options);
|
||||
}
|
||||
|
||||
EXPORT_C GSgetLastTag(uint32* tag)
|
||||
EXPORT_C GSgetLastTag(uint32* tag)
|
||||
{
|
||||
s_gs->GetLastTag(tag);
|
||||
}
|
||||
|
@ -301,6 +304,11 @@ EXPORT_C GSsetFrameSkip(int frameskip)
|
|||
s_gs->SetFrameSkip(frameskip);
|
||||
}
|
||||
|
||||
EXPORT_C GSsetFrameLimit(int limit)
|
||||
{
|
||||
s_gs->SetFrameLimit(limit != 0);
|
||||
}
|
||||
|
||||
#ifdef _WINDOWS
|
||||
|
||||
EXPORT_C GSReplay(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
|
||||
|
@ -527,11 +535,13 @@ EXPORT_C GSBenchmark(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow
|
|||
|
||||
fprintf(file, "%6d %6d | ", (int)((float)trlen * n / (end - start) / 1000), (int)((float)(w * h) * n / (end - start) / 1000));
|
||||
|
||||
const GSOffset* o = mem.GetOffset(TEX0.TBP0, TEX0.TBW, TEX0.PSM);
|
||||
|
||||
start = clock();
|
||||
|
||||
for(int j = 0; j < n; j++)
|
||||
{
|
||||
(mem.*rtx)(r, ptr, w * 4, TEX0, TEXA);
|
||||
(mem.*rtx)(o, r, ptr, w * 4, TEXA);
|
||||
}
|
||||
|
||||
end = clock();
|
||||
|
@ -544,7 +554,7 @@ EXPORT_C GSBenchmark(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow
|
|||
|
||||
for(int j = 0; j < n; j++)
|
||||
{
|
||||
(mem.*rtxP)(r, ptr, w, TEX0, TEXA);
|
||||
(mem.*rtxP)(o, r, ptr, w, TEXA);
|
||||
}
|
||||
|
||||
end = clock();
|
||||
|
|
|
@ -815,42 +815,11 @@ REG64_(GIFReg, TEX1)
|
|||
uint32 _PAD2:9;
|
||||
uint32 L:2;
|
||||
uint32 _PAD3:11;
|
||||
uint32 K:12;
|
||||
int32 K:12; // 1:7:4
|
||||
uint32 _PAD4:20;
|
||||
REG_END2
|
||||
|
||||
bool IsMinLinear() const {return (MMIN == 1) || (MMIN & 4);}
|
||||
bool IsMagLinear() const {return MMAG;}
|
||||
|
||||
bool IsLinear() const
|
||||
{
|
||||
bool mmin = IsMinLinear();
|
||||
bool mmag = IsMagLinear();
|
||||
|
||||
return !LCM ? mmag || mmin : K <= 0 ? mmag : mmin;
|
||||
}
|
||||
|
||||
bool IsLinear(float qmin, float qmax) const
|
||||
{
|
||||
bool mmin = IsMinLinear();
|
||||
bool mmag = IsMagLinear();
|
||||
|
||||
if(mmag == mmin) return mmag;
|
||||
|
||||
float LODmin = K;
|
||||
float LODmax = K;
|
||||
|
||||
if(!LCM)
|
||||
{
|
||||
float f = (float)(1 << L) / log(2.0f);
|
||||
|
||||
LODmin += log(1.0f / abs(qmax)) * f;
|
||||
LODmax += log(1.0f / abs(qmin)) * f;
|
||||
}
|
||||
|
||||
return LODmax <= 0 ? mmag : LODmin > 0 ? mmin : mmag || mmin;
|
||||
}
|
||||
|
||||
REG_END2
|
||||
|
||||
REG64_(GIFReg, TEX2)
|
||||
|
|
|
@ -168,16 +168,16 @@ void GSClut::WriteCLUT16S_I4_CSM1(const GIFRegTEX0& TEX0, const GIFRegTEXCLUT& T
|
|||
|
||||
template<int n> void GSClut::WriteCLUT32_CSM2(const GIFRegTEX0& TEX0, const GIFRegTEXCLUT& TEXCLUT)
|
||||
{
|
||||
GSLocalMemory::PixelOffset* po = m_mem->GetPixelOffset(TEX0.CBP, TEXCLUT.CBW, PSM_PSMCT32);
|
||||
GSOffset* o = m_mem->GetOffset(TEX0.CBP, TEXCLUT.CBW, PSM_PSMCT32);
|
||||
|
||||
uint32* RESTRICT s = &m_mem->m_vm32[po->row[TEXCLUT.COV]];
|
||||
int* RESTRICT o = &po->col[0][TEXCLUT.COU << 4];
|
||||
uint32* RESTRICT s = &m_mem->m_vm32[o->pixel.row[TEXCLUT.COV]];
|
||||
int* RESTRICT col = &o->pixel.col[0][TEXCLUT.COU << 4];
|
||||
|
||||
uint16* RESTRICT clut = m_clut + (TEX0.CSA << 4);
|
||||
|
||||
for(int i = 0; i < n; i++)
|
||||
{
|
||||
uint32 c = s[o[i]];
|
||||
uint32 c = s[col[i]];
|
||||
|
||||
clut[i] = (uint16)(c & 0xffff);
|
||||
clut[i + 256] = (uint16)(c >> 16);
|
||||
|
@ -186,31 +186,31 @@ template<int n> void GSClut::WriteCLUT32_CSM2(const GIFRegTEX0& TEX0, const GIFR
|
|||
|
||||
template<int n> void GSClut::WriteCLUT16_CSM2(const GIFRegTEX0& TEX0, const GIFRegTEXCLUT& TEXCLUT)
|
||||
{
|
||||
GSLocalMemory::PixelOffset* po = m_mem->GetPixelOffset(TEX0.CBP, TEXCLUT.CBW, PSM_PSMCT16);
|
||||
GSOffset* o = m_mem->GetOffset(TEX0.CBP, TEXCLUT.CBW, PSM_PSMCT16);
|
||||
|
||||
uint16* RESTRICT s = &m_mem->m_vm16[po->row[TEXCLUT.COV]];
|
||||
int* RESTRICT o = &po->col[0][TEXCLUT.COU << 4];
|
||||
uint16* RESTRICT s = &m_mem->m_vm16[o->pixel.row[TEXCLUT.COV]];
|
||||
int* RESTRICT col = &o->pixel.col[0][TEXCLUT.COU << 4];
|
||||
|
||||
uint16* RESTRICT clut = m_clut + (TEX0.CSA << 4);
|
||||
|
||||
for(int i = 0; i < n; i++)
|
||||
{
|
||||
clut[i] = s[o[i]];
|
||||
clut[i] = s[col[i]];
|
||||
}
|
||||
}
|
||||
|
||||
template<int n> void GSClut::WriteCLUT16S_CSM2(const GIFRegTEX0& TEX0, const GIFRegTEXCLUT& TEXCLUT)
|
||||
{
|
||||
GSLocalMemory::PixelOffset* po = m_mem->GetPixelOffset(TEX0.CBP, TEXCLUT.CBW, PSM_PSMCT16S);
|
||||
GSOffset* o = m_mem->GetOffset(TEX0.CBP, TEXCLUT.CBW, PSM_PSMCT16S);
|
||||
|
||||
uint16* RESTRICT s = &m_mem->m_vm16[po->row[TEXCLUT.COV]];
|
||||
int* RESTRICT o = &po->col[0][TEXCLUT.COU << 4];
|
||||
uint16* RESTRICT s = &m_mem->m_vm16[o->pixel.row[TEXCLUT.COV]];
|
||||
int* RESTRICT col = &o->pixel.col[0][TEXCLUT.COU << 4];
|
||||
|
||||
uint16* RESTRICT clut = m_clut + (TEX0.CSA << 4);
|
||||
|
||||
for(int i = 0; i < n; i++)
|
||||
{
|
||||
clut[i] = s[o[i]];
|
||||
clut[i] = s[col[i]];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -314,43 +314,56 @@ void GSClut::GetAlphaMinMax32(int& amin, int& amax)
|
|||
{
|
||||
m_read.adirty = false;
|
||||
|
||||
// uint32 bpp = GSLocalMemory::m_psm[m_read.TEX0.PSM].trbpp;
|
||||
uint32 cbpp = GSLocalMemory::m_psm[m_read.TEX0.CPSM].trbpp;
|
||||
uint32 pal = GSLocalMemory::m_psm[m_read.TEX0.PSM].pal;
|
||||
|
||||
if(cbpp == 24 && m_read.TEXA.AEM == 0)
|
||||
if(GSLocalMemory::m_psm[m_read.TEX0.CPSM].trbpp == 24 && m_read.TEXA.AEM == 0)
|
||||
{
|
||||
m_read.amin = m_read.TEXA.TA0;
|
||||
m_read.amax = m_read.TEXA.TA0;
|
||||
}
|
||||
else
|
||||
{
|
||||
int amin = 255;
|
||||
int amax = 0;
|
||||
|
||||
const GSVector4i* p = (const GSVector4i*)m_buff32;
|
||||
|
||||
for(int i = 0, j = pal >> 4; i < j; i++)
|
||||
GSVector4i amin, amax;
|
||||
|
||||
if(GSLocalMemory::m_psm[m_read.TEX0.PSM].pal == 256)
|
||||
{
|
||||
GSVector4i v0 = (p[i * 4 + 0] >> 24).ps32(p[i * 4 + 1] >> 24);
|
||||
GSVector4i v1 = (p[i * 4 + 2] >> 24).ps32(p[i * 4 + 3] >> 24);
|
||||
amin = GSVector4i::xffffffff();
|
||||
amax = GSVector4i::zero();
|
||||
|
||||
GSVector4i v2 = v0.min_i16(v1);
|
||||
GSVector4i v3 = v0.max_i16(v1);
|
||||
for(int i = 0; i < 16; i++)
|
||||
{
|
||||
GSVector4i v0 = (p[i * 4 + 0] >> 24).ps32(p[i * 4 + 1] >> 24);
|
||||
GSVector4i v1 = (p[i * 4 + 2] >> 24).ps32(p[i * 4 + 3] >> 24);
|
||||
GSVector4i v2 = v0.pu16(v1);
|
||||
|
||||
v2 = v2.min_i16(v2.zwxy());
|
||||
v3 = v3.max_i16(v3.zwxy());
|
||||
v2 = v2.min_i16(v2.zwxyl());
|
||||
v3 = v3.max_i16(v3.zwxyl());
|
||||
v2 = v2.min_i16(v2.yxwzl());
|
||||
v3 = v3.max_i16(v3.yxwzl());
|
||||
amin = amin.min_u8(v2);
|
||||
amax = amax.max_u8(v2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT(GSLocalMemory::m_psm[m_read.TEX0.PSM].pal == 16);
|
||||
|
||||
amin = min(amin, v2.extract16<0>());
|
||||
amax = max(amax, v3.extract16<0>());
|
||||
GSVector4i v0 = (p[0] >> 24).ps32(p[1] >> 24);
|
||||
GSVector4i v1 = (p[2] >> 24).ps32(p[3] >> 24);
|
||||
GSVector4i v2 = v0.pu16(v1);
|
||||
|
||||
amin = v2;
|
||||
amax = v2;
|
||||
}
|
||||
|
||||
m_read.amin = amin;
|
||||
m_read.amax = amax;
|
||||
amin = amin.min_u8(amin.zwxy());
|
||||
amax = amax.max_u8(amax.zwxy());
|
||||
amin = amin.min_u8(amin.zwxyl());
|
||||
amax = amax.max_u8(amax.zwxyl());
|
||||
amin = amin.min_u8(amin.yxwzl());
|
||||
amax = amax.max_u8(amax.yxwzl());
|
||||
|
||||
GSVector4i v0 = amin.upl8(amax).u8to16();
|
||||
GSVector4i v1 = v0.yxwz();
|
||||
|
||||
m_read.amin = v0.min_i16(v1).extract16<0>();
|
||||
m_read.amax = v0.max_i16(v1).extract16<1>();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -381,14 +394,13 @@ __forceinline void GSClut::WriteCLUT_T32_I4_CSM1(const uint32* RESTRICT src, uin
|
|||
GSVector4i v2 = s[2];
|
||||
GSVector4i v3 = s[3];
|
||||
|
||||
GSVector4i::sw64(v0, v1, v2, v3);
|
||||
GSVector4i::sw16(v0, v1, v2, v3);
|
||||
GSVector4i::sw32(v0, v1, v2, v3);
|
||||
GSVector4i::sw16(v0, v2, v1, v3);
|
||||
GSVector4i::sw16(v0, v1, v2, v3);
|
||||
|
||||
d[0] = v0;
|
||||
d[1] = v1;
|
||||
d[32] = v2;
|
||||
d[1] = v2;
|
||||
d[32] = v1;
|
||||
d[33] = v3;
|
||||
}
|
||||
|
||||
|
|
|
@ -88,7 +88,8 @@ CRC::Game CRC::m_games[] =
|
|||
{0xC19A374E, SoTC, US, 0},
|
||||
{0x7D8F539A, SoTC, EU, 0},
|
||||
{0x3122B508, OnePieceGrandAdventure, US, 0},
|
||||
{0x8DF14A24, OnePieceGrandAdventure, Unknown, 0},
|
||||
{0x8DF14A24, OnePieceGrandAdventure, EU, 0},
|
||||
{0xB049DD5E, OnePieceGrandBattle, US, 0},
|
||||
{0x5D02CC5B, OnePieceGrandBattle, Unknown, 0},
|
||||
{0x6F8545DB, ICO, US, 0},
|
||||
{0xB01A4C95, ICO, JP, 0},
|
||||
|
@ -147,6 +148,7 @@ CRC::Game CRC::m_games[] =
|
|||
{0x04CCB600, ValkyrieProfile2, EU, 0},
|
||||
{0x47B9B2FD, RadiataStories, US, 0},
|
||||
{0xE8FCF8EC, SMTNocturne, US, ZWriteMustNotClear}, // saves/reloads z buffer around shadow drawing
|
||||
{0x0B8AB37B, RozenMaidenGebetGarden, JP, 0},
|
||||
};
|
||||
|
||||
hash_map<uint32, CRC::Game*> CRC::m_map;
|
||||
|
|
|
@ -76,6 +76,7 @@ public:
|
|||
ValkyrieProfile2,
|
||||
RadiataStories,
|
||||
SMTNocturne,
|
||||
RozenMaidenGebetGarden,
|
||||
TitleCount,
|
||||
};
|
||||
|
||||
|
@ -91,7 +92,8 @@ public:
|
|||
DE,
|
||||
IT,
|
||||
ES,
|
||||
ASIA
|
||||
ASIA,
|
||||
RegionCount,
|
||||
};
|
||||
|
||||
enum Flags
|
||||
|
@ -102,8 +104,8 @@ public:
|
|||
|
||||
struct Game
|
||||
{
|
||||
uint32 crc;
|
||||
Title title;
|
||||
uint32 crc;
|
||||
Title title;
|
||||
Region region;
|
||||
uint32 flags;
|
||||
};
|
||||
|
|
|
@ -75,14 +75,14 @@ bool GSDevice::Reset(int w, int h, int mode)
|
|||
return true;
|
||||
}
|
||||
|
||||
void GSDevice::Present(const GSVector4i& r, int shader)
|
||||
void GSDevice::Present(const GSVector4i& r, int shader, bool limit)
|
||||
{
|
||||
GSVector4i cr = m_wnd->GetClientRect();
|
||||
|
||||
int w = std::max(cr.width(), 1);
|
||||
int h = std::max(cr.height(), 1);
|
||||
|
||||
if(!m_backbuffer || m_backbuffer->GetWidth() != w || m_backbuffer->GetHeight() != h)
|
||||
if(!m_backbuffer || m_backbuffer->m_size.x != w || m_backbuffer->m_size.y != h)
|
||||
{
|
||||
if(!Reset(w, h, DontCare))
|
||||
{
|
||||
|
@ -99,7 +99,7 @@ void GSDevice::Present(const GSVector4i& r, int shader)
|
|||
StretchRect(m_current, m_backbuffer, GSVector4(r), s_shader[shader]);
|
||||
}
|
||||
|
||||
Flip();
|
||||
Flip(limit);
|
||||
}
|
||||
|
||||
GSTexture* GSDevice::Fetch(int type, int w, int h, int format)
|
||||
|
@ -240,7 +240,7 @@ bool GSDevice::ResizeTexture(GSTexture** t, int w, int h)
|
|||
|
||||
GSTexture* t2 = *t;
|
||||
|
||||
if(t2 == NULL || t2->GetWidth() != w || t2->GetHeight() != h)
|
||||
if(t2 == NULL || t2->m_size.x != w || t2->m_size.y != h)
|
||||
{
|
||||
delete t2;
|
||||
|
||||
|
@ -251,3 +251,46 @@ bool GSDevice::ResizeTexture(GSTexture** t, int w, int h)
|
|||
|
||||
return t2 != NULL;
|
||||
}
|
||||
|
||||
bool GSDevice::SetFeatureLevel(D3D_FEATURE_LEVEL level, bool compat_mode)
|
||||
{
|
||||
m_shader.level = level;
|
||||
|
||||
switch(level)
|
||||
{
|
||||
case D3D_FEATURE_LEVEL_9_1:
|
||||
case D3D_FEATURE_LEVEL_9_2:
|
||||
m_shader.model = "0x200";
|
||||
m_shader.vs = compat_mode ? "vs_4_0_level_9_1" : "vs_2_0";
|
||||
m_shader.ps = compat_mode ? "ps_4_0_level_9_1" : "ps_2_0";
|
||||
break;
|
||||
case D3D_FEATURE_LEVEL_9_3:
|
||||
m_shader.model = "0x300";
|
||||
m_shader.vs = compat_mode ? "vs_4_0_level_9_3" : "vs_3_0";
|
||||
m_shader.ps = compat_mode ? "ps_4_0_level_9_3" : "ps_3_0";
|
||||
break;
|
||||
case D3D_FEATURE_LEVEL_10_0:
|
||||
m_shader.model = "0x400";
|
||||
m_shader.vs = "vs_4_0";
|
||||
m_shader.gs = "gs_4_0";
|
||||
m_shader.ps = "ps_4_0";
|
||||
break;
|
||||
case D3D_FEATURE_LEVEL_10_1:
|
||||
m_shader.model = "0x401";
|
||||
m_shader.vs = "vs_4_1";
|
||||
m_shader.gs = "gs_4_1";
|
||||
m_shader.ps = "ps_4_1";
|
||||
break;
|
||||
case D3D_FEATURE_LEVEL_11_0:
|
||||
m_shader.model = "0x500";
|
||||
m_shader.vs = "vs_5_0";
|
||||
m_shader.gs = "gs_5_0";
|
||||
m_shader.ps = "ps_5_0";
|
||||
break;
|
||||
default:
|
||||
ASSERT(0);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -62,6 +62,7 @@ protected:
|
|||
GSTexture* m_blend;
|
||||
GSTexture* m_1x1;
|
||||
GSTexture* m_current;
|
||||
struct {D3D_FEATURE_LEVEL level; string model, vs, gs, ps;} m_shader;
|
||||
|
||||
virtual GSTexture* Create(int type, int w, int h, int format) = 0;
|
||||
|
||||
|
@ -79,8 +80,8 @@ public:
|
|||
virtual bool Create(GSWnd* wnd, bool vsync);
|
||||
virtual bool Reset(int w, int h, int mode);
|
||||
virtual bool IsLost(bool update = false) {return false;}
|
||||
virtual void Present(const GSVector4i& r, int shader);
|
||||
virtual void Flip() {}
|
||||
virtual void Present(const GSVector4i& r, int shader, bool limit);
|
||||
virtual void Flip(bool limit) {}
|
||||
|
||||
virtual void BeginScene() {}
|
||||
virtual void DrawPrimitive() {};
|
||||
|
@ -103,6 +104,9 @@ public:
|
|||
virtual void StretchRect(GSTexture* st, GSTexture* dt, const GSVector4& dr, int shader = 0, bool linear = true);
|
||||
virtual void StretchRect(GSTexture* st, const GSVector4& sr, GSTexture* dt, const GSVector4& dr, int shader = 0, bool linear = true) {}
|
||||
|
||||
virtual void PSSetShaderResources(GSTexture* sr0, GSTexture* sr1) {}
|
||||
virtual void OMSetRenderTargets(GSTexture* rt, GSTexture* ds, const GSVector4i* scissor = NULL) {}
|
||||
|
||||
GSTexture* GetCurrent();
|
||||
|
||||
void Merge(GSTexture* st[2], GSVector4* sr, GSVector4* dr, const GSVector2i& fs, bool slbg, bool mmod, const GSVector4& c);
|
||||
|
@ -112,7 +116,7 @@ public:
|
|||
|
||||
bool IsRBSwapped() {return m_rbswapped;}
|
||||
|
||||
template<class T> void PrepareShaderMacro(vector<T>& dst, const T* src, const char* model)
|
||||
template<class T> void PrepareShaderMacro(vector<T>& dst, const T* src)
|
||||
{
|
||||
dst.clear();
|
||||
|
||||
|
@ -124,7 +128,7 @@ public:
|
|||
T m;
|
||||
|
||||
m.Name = "SHADER_MODEL";
|
||||
m.Definition = model;
|
||||
m.Definition = m_shader.model.c_str();
|
||||
|
||||
dst.push_back(m);
|
||||
|
||||
|
@ -133,4 +137,6 @@ public:
|
|||
|
||||
dst.push_back(m);
|
||||
}
|
||||
|
||||
bool SetFeatureLevel(D3D_FEATURE_LEVEL level, bool compat_mode); // TODO: GSDeviceDX
|
||||
};
|
||||
|
|
|
@ -87,12 +87,33 @@ bool GSDevice10::Create(GSWnd* wnd, bool vsync)
|
|||
scd.Windowed = TRUE;
|
||||
|
||||
uint32 flags = 0;
|
||||
|
||||
flags = D3D10_CREATE_DEVICE_SINGLETHREADED; //disables thread safety, should be fine (speedup)
|
||||
#ifdef DEBUG
|
||||
flags |= D3D10_CREATE_DEVICE_DEBUG;
|
||||
#endif
|
||||
|
||||
hr = D3D10CreateDeviceAndSwapChain(NULL, D3D10_DRIVER_TYPE_HARDWARE, NULL, flags, D3D10_SDK_VERSION, &scd, &m_swapchain, &m_dev);
|
||||
D3D10_FEATURE_LEVEL1 levels[] =
|
||||
{
|
||||
D3D10_FEATURE_LEVEL_10_1,
|
||||
D3D10_FEATURE_LEVEL_10_0
|
||||
};
|
||||
|
||||
for(int i = 0; i < countof(levels); i++)
|
||||
{
|
||||
hr = D3D10CreateDeviceAndSwapChain1(NULL, D3D10_DRIVER_TYPE_HARDWARE, NULL, flags, levels[i], D3D10_1_SDK_VERSION, &scd, &m_swapchain, &m_dev);
|
||||
|
||||
if(SUCCEEDED(hr))
|
||||
{
|
||||
if(!SetFeatureLevel((D3D_FEATURE_LEVEL)levels[i], true))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// hr = D3D10CreateDeviceAndSwapChain(NULL, D3D10_DRIVER_TYPE_HARDWARE, NULL, flags, D3D10_SDK_VERSION, &scd, &m_swapchain, &m_dev);
|
||||
|
||||
if(FAILED(hr)) return false;
|
||||
|
||||
|
@ -219,21 +240,24 @@ bool GSDevice10::Reset(int w, int h, int mode)
|
|||
if(!__super::Reset(w, h, mode))
|
||||
return false;
|
||||
|
||||
DXGI_SWAP_CHAIN_DESC scd;
|
||||
memset(&scd, 0, sizeof(scd));
|
||||
m_swapchain->GetDesc(&scd);
|
||||
m_swapchain->ResizeBuffers(scd.BufferCount, w, h, scd.BufferDesc.Format, 0);
|
||||
|
||||
CComPtr<ID3D10Texture2D> backbuffer;
|
||||
m_swapchain->GetBuffer(0, __uuidof(ID3D10Texture2D), (void**)&backbuffer);
|
||||
m_backbuffer = new GSTexture10(backbuffer);
|
||||
if(m_swapchain)
|
||||
{
|
||||
DXGI_SWAP_CHAIN_DESC scd;
|
||||
memset(&scd, 0, sizeof(scd));
|
||||
m_swapchain->GetDesc(&scd);
|
||||
m_swapchain->ResizeBuffers(scd.BufferCount, w, h, scd.BufferDesc.Format, 0);
|
||||
|
||||
CComPtr<ID3D10Texture2D> backbuffer;
|
||||
m_swapchain->GetBuffer(0, __uuidof(ID3D10Texture2D), (void**)&backbuffer);
|
||||
m_backbuffer = new GSTexture10(backbuffer);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GSDevice10::Flip()
|
||||
void GSDevice10::Flip(bool limit)
|
||||
{
|
||||
m_swapchain->Present(m_vsync ? 1 : 0, 0);
|
||||
m_swapchain->Present(m_vsync && limit ? 1 : 0, 0);
|
||||
}
|
||||
|
||||
void GSDevice10::BeginScene()
|
||||
|
@ -454,10 +478,6 @@ void GSDevice10::StretchRect(GSTexture* st, const GSVector4& sr, GSTexture* dt,
|
|||
PSSetSamplerState(linear ? m_convert.ln : m_convert.pt, NULL);
|
||||
PSSetShaderResources(st, NULL);
|
||||
|
||||
// rs
|
||||
|
||||
RSSet(ds.x, ds.y);
|
||||
|
||||
//
|
||||
|
||||
DrawPrimitive();
|
||||
|
@ -560,12 +580,12 @@ void GSDevice10::IASetVertexBuffer(ID3D10Buffer* vb, size_t stride)
|
|||
{
|
||||
if(m_vb != vb || m_vb_stride != stride)
|
||||
{
|
||||
m_vb = vb;
|
||||
m_vb_stride = stride;
|
||||
|
||||
uint32 offset = 0;
|
||||
|
||||
m_dev->IASetVertexBuffers(0, 1, &vb, &stride, &offset);
|
||||
|
||||
m_vb = vb;
|
||||
m_vb_stride = stride;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -573,9 +593,9 @@ void GSDevice10::IASetInputLayout(ID3D10InputLayout* layout)
|
|||
{
|
||||
if(m_layout != layout)
|
||||
{
|
||||
m_dev->IASetInputLayout(layout);
|
||||
|
||||
m_layout = layout;
|
||||
|
||||
m_dev->IASetInputLayout(layout);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -583,9 +603,9 @@ void GSDevice10::IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY topology)
|
|||
{
|
||||
if(m_topology != topology)
|
||||
{
|
||||
m_dev->IASetPrimitiveTopology(topology);
|
||||
|
||||
m_topology = topology;
|
||||
|
||||
m_dev->IASetPrimitiveTopology(topology);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -593,16 +613,16 @@ void GSDevice10::VSSetShader(ID3D10VertexShader* vs, ID3D10Buffer* vs_cb)
|
|||
{
|
||||
if(m_vs != vs)
|
||||
{
|
||||
m_dev->VSSetShader(vs);
|
||||
|
||||
m_vs = vs;
|
||||
|
||||
m_dev->VSSetShader(vs);
|
||||
}
|
||||
|
||||
if(m_vs_cb != vs_cb)
|
||||
{
|
||||
m_dev->VSSetConstantBuffers(0, 1, &vs_cb);
|
||||
|
||||
m_vs_cb = vs_cb;
|
||||
|
||||
m_dev->VSSetConstantBuffers(0, 1, &vs_cb);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -610,9 +630,9 @@ void GSDevice10::GSSetShader(ID3D10GeometryShader* gs)
|
|||
{
|
||||
if(m_gs != gs)
|
||||
{
|
||||
m_dev->GSSetShader(gs);
|
||||
|
||||
m_gs = gs;
|
||||
|
||||
m_dev->GSSetShader(gs);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -626,12 +646,12 @@ void GSDevice10::PSSetShaderResources(GSTexture* sr0, GSTexture* sr1)
|
|||
|
||||
if(m_ps_srv[0] != srv0 || m_ps_srv[1] != srv1)
|
||||
{
|
||||
m_ps_srv[0] = srv0;
|
||||
m_ps_srv[1] = srv1;
|
||||
|
||||
ID3D10ShaderResourceView* srvs[] = {srv0, srv1};
|
||||
|
||||
m_dev->PSSetShaderResources(0, 2, srvs);
|
||||
|
||||
m_ps_srv[0] = srv0;
|
||||
m_ps_srv[1] = srv1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -639,16 +659,16 @@ void GSDevice10::PSSetShader(ID3D10PixelShader* ps, ID3D10Buffer* ps_cb)
|
|||
{
|
||||
if(m_ps != ps)
|
||||
{
|
||||
m_dev->PSSetShader(ps);
|
||||
|
||||
m_ps = ps;
|
||||
|
||||
m_dev->PSSetShader(ps);
|
||||
}
|
||||
|
||||
if(m_ps_cb != ps_cb)
|
||||
{
|
||||
m_dev->PSSetConstantBuffers(0, 1, &ps_cb);
|
||||
|
||||
m_ps_cb = ps_cb;
|
||||
|
||||
m_dev->PSSetConstantBuffers(0, 1, &ps_cb);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -656,42 +676,12 @@ void GSDevice10::PSSetSamplerState(ID3D10SamplerState* ss0, ID3D10SamplerState*
|
|||
{
|
||||
if(m_ps_ss[0] != ss0 || m_ps_ss[1] != ss1)
|
||||
{
|
||||
m_ps_ss[0] = ss0;
|
||||
m_ps_ss[1] = ss1;
|
||||
|
||||
ID3D10SamplerState* sss[] = {ss0, ss1};
|
||||
|
||||
m_dev->PSSetSamplers(0, 2, sss);
|
||||
|
||||
m_ps_ss[0] = ss0;
|
||||
m_ps_ss[1] = ss1;
|
||||
}
|
||||
}
|
||||
|
||||
void GSDevice10::RSSet(int width, int height, const GSVector4i* scissor)
|
||||
{
|
||||
if(m_viewport.x != width || m_viewport.y != height)
|
||||
{
|
||||
D3D10_VIEWPORT vp;
|
||||
|
||||
memset(&vp, 0, sizeof(vp));
|
||||
|
||||
vp.TopLeftX = 0;
|
||||
vp.TopLeftY = 0;
|
||||
vp.Width = width;
|
||||
vp.Height = height;
|
||||
vp.MinDepth = 0.0f;
|
||||
vp.MaxDepth = 1.0f;
|
||||
|
||||
m_dev->RSSetViewports(1, &vp);
|
||||
|
||||
m_viewport = GSVector2i(width, height);
|
||||
}
|
||||
|
||||
GSVector4i r = scissor ? *scissor : GSVector4i(0, 0, width, height);
|
||||
|
||||
if(!m_scissor.eq(r))
|
||||
{
|
||||
m_dev->RSSetScissorRects(1, r);
|
||||
|
||||
m_scissor = r;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -699,10 +689,10 @@ void GSDevice10::OMSetDepthStencilState(ID3D10DepthStencilState* dss, uint8 sref
|
|||
{
|
||||
if(m_dss != dss || m_sref != sref)
|
||||
{
|
||||
m_dev->OMSetDepthStencilState(dss, sref);
|
||||
|
||||
m_dss = dss;
|
||||
m_sref = sref;
|
||||
|
||||
m_dev->OMSetDepthStencilState(dss, sref);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -710,16 +700,16 @@ void GSDevice10::OMSetBlendState(ID3D10BlendState* bs, float bf)
|
|||
{
|
||||
if(m_bs != bs || m_bf != bf)
|
||||
{
|
||||
m_bs = bs;
|
||||
m_bf = bf;
|
||||
|
||||
float BlendFactor[] = {bf, bf, bf, 0};
|
||||
|
||||
m_dev->OMSetBlendState(bs, BlendFactor, 0xffffffff);
|
||||
|
||||
m_bs = bs;
|
||||
m_bf = bf;
|
||||
}
|
||||
}
|
||||
|
||||
void GSDevice10::OMSetRenderTargets(GSTexture* rt, GSTexture* ds)
|
||||
void GSDevice10::OMSetRenderTargets(GSTexture* rt, GSTexture* ds, const GSVector4i* scissor)
|
||||
{
|
||||
ID3D10RenderTargetView* rtv = NULL;
|
||||
ID3D10DepthStencilView* dsv = NULL;
|
||||
|
@ -729,10 +719,37 @@ void GSDevice10::OMSetRenderTargets(GSTexture* rt, GSTexture* ds)
|
|||
|
||||
if(m_rtv != rtv || m_dsv != dsv)
|
||||
{
|
||||
m_dev->OMSetRenderTargets(1, &rtv, dsv);
|
||||
|
||||
m_rtv = rtv;
|
||||
m_dsv = dsv;
|
||||
|
||||
m_dev->OMSetRenderTargets(1, &rtv, dsv);
|
||||
}
|
||||
|
||||
if(m_viewport != rt->m_size)
|
||||
{
|
||||
m_viewport = rt->m_size;
|
||||
|
||||
D3D10_VIEWPORT vp;
|
||||
|
||||
memset(&vp, 0, sizeof(vp));
|
||||
|
||||
vp.TopLeftX = 0;
|
||||
vp.TopLeftY = 0;
|
||||
vp.Width = rt->m_size.x;
|
||||
vp.Height = rt->m_size.y;
|
||||
vp.MinDepth = 0.0f;
|
||||
vp.MaxDepth = 1.0f;
|
||||
|
||||
m_dev->RSSetViewports(1, &vp);
|
||||
}
|
||||
|
||||
GSVector4i r = scissor ? *scissor : GSVector4i(rt->m_size).zwxy();
|
||||
|
||||
if(!m_scissor.eq(r))
|
||||
{
|
||||
m_scissor = r;
|
||||
|
||||
m_dev->RSSetScissorRects(1, r);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -742,11 +759,11 @@ HRESULT GSDevice10::CompileShader(uint32 id, const string& entry, D3D10_SHADER_M
|
|||
|
||||
vector<D3D10_SHADER_MACRO> m;
|
||||
|
||||
PrepareShaderMacro(m, macro, "0x400");
|
||||
PrepareShaderMacro(m, macro);
|
||||
|
||||
CComPtr<ID3D10Blob> shader, error;
|
||||
|
||||
hr = D3DX10CompileFromResource(theApp.GetModuleHandle(), MAKEINTRESOURCE(id), NULL, &m[0], NULL, entry.c_str(), "vs_4_0", 0, 0, NULL, &shader, &error, NULL);
|
||||
hr = D3DX10CompileFromResource(theApp.GetModuleHandle(), MAKEINTRESOURCE(id), NULL, &m[0], NULL, entry.c_str(), m_shader.vs.c_str(), 0, 0, NULL, &shader, &error, NULL);
|
||||
|
||||
if(error)
|
||||
{
|
||||
|
@ -781,11 +798,11 @@ HRESULT GSDevice10::CompileShader(uint32 id, const string& entry, D3D10_SHADER_M
|
|||
|
||||
vector<D3D10_SHADER_MACRO> m;
|
||||
|
||||
PrepareShaderMacro(m, macro, "0x400");
|
||||
PrepareShaderMacro(m, macro);
|
||||
|
||||
CComPtr<ID3D10Blob> shader, error;
|
||||
|
||||
hr = D3DX10CompileFromResource(theApp.GetModuleHandle(), MAKEINTRESOURCE(id), NULL, &m[0], NULL, entry.c_str(), "gs_4_0", 0, 0, NULL, &shader, &error, NULL);
|
||||
hr = D3DX10CompileFromResource(theApp.GetModuleHandle(), MAKEINTRESOURCE(id), NULL, &m[0], NULL, entry.c_str(), m_shader.gs.c_str(), 0, 0, NULL, &shader, &error, NULL);
|
||||
|
||||
if(error)
|
||||
{
|
||||
|
@ -813,11 +830,11 @@ HRESULT GSDevice10::CompileShader(uint32 id, const string& entry, D3D10_SHADER_M
|
|||
|
||||
vector<D3D10_SHADER_MACRO> m;
|
||||
|
||||
PrepareShaderMacro(m, macro, "0x400");
|
||||
PrepareShaderMacro(m, macro);
|
||||
|
||||
CComPtr<ID3D10Blob> shader, error;
|
||||
|
||||
hr = D3DX10CompileFromResource(theApp.GetModuleHandle(), MAKEINTRESOURCE(id), NULL, &m[0], NULL, entry.c_str(), "ps_4_0", 0, 0, NULL, &shader, &error, NULL);
|
||||
hr = D3DX10CompileFromResource(theApp.GetModuleHandle(), MAKEINTRESOURCE(id), NULL, &m[0], NULL, entry.c_str(), m_shader.ps.c_str(), 0, 0, NULL, &shader, &error, NULL);
|
||||
|
||||
if(error)
|
||||
{
|
||||
|
|
|
@ -55,7 +55,7 @@ class GSDevice10 : public GSDevice
|
|||
|
||||
//
|
||||
|
||||
CComPtr<ID3D10Device> m_dev;
|
||||
CComPtr<ID3D10Device1> m_dev;
|
||||
CComPtr<IDXGISwapChain> m_swapchain;
|
||||
|
||||
struct
|
||||
|
@ -97,7 +97,7 @@ public:
|
|||
|
||||
bool Create(GSWnd* wnd, bool vsync);
|
||||
bool Reset(int w, int h, int mode);
|
||||
void Flip();
|
||||
void Flip(bool limit);
|
||||
|
||||
void BeginScene();
|
||||
void DrawPrimitive();
|
||||
|
@ -130,10 +130,9 @@ public:
|
|||
void PSSetShaderResources(GSTexture* sr0, GSTexture* sr1);
|
||||
void PSSetShader(ID3D10PixelShader* ps, ID3D10Buffer* ps_cb);
|
||||
void PSSetSamplerState(ID3D10SamplerState* ss0, ID3D10SamplerState* ss1);
|
||||
void RSSet(int width, int height, const GSVector4i* scissor = NULL);
|
||||
void OMSetDepthStencilState(ID3D10DepthStencilState* dss, uint8 sref);
|
||||
void OMSetBlendState(ID3D10BlendState* bs, float bf);
|
||||
void OMSetRenderTargets(GSTexture* rt, GSTexture* ds);
|
||||
void OMSetRenderTargets(GSTexture* rt, GSTexture* ds, const GSVector4i* scissor = NULL);
|
||||
|
||||
ID3D10Device* operator->() {return m_dev;}
|
||||
operator ID3D10Device*() {return m_dev;}
|
||||
|
|
|
@ -87,53 +87,34 @@ bool GSDevice11::Create(GSWnd* wnd, bool vsync)
|
|||
scd.Windowed = TRUE;
|
||||
|
||||
uint32 flags = 0;
|
||||
|
||||
flags = D3D11_CREATE_DEVICE_SINGLETHREADED; //disables thread safety, should be fine (speedup)
|
||||
#ifdef DEBUG
|
||||
flags |= D3D11_CREATE_DEVICE_DEBUG;
|
||||
#endif
|
||||
|
||||
hr = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, flags, NULL, 0, D3D11_SDK_VERSION, &scd, &m_swapchain, &m_dev, &m_level, &m_ctx);
|
||||
// hr = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_REFERENCE, NULL, flags, NULL, 0, D3D11_SDK_VERSION, &scd, &m_swapchain, &m_dev, &m_level, &m_ctx);
|
||||
D3D_FEATURE_LEVEL levels[] =
|
||||
{
|
||||
D3D_FEATURE_LEVEL_11_0,
|
||||
D3D_FEATURE_LEVEL_10_1,
|
||||
D3D_FEATURE_LEVEL_10_0,
|
||||
};
|
||||
|
||||
D3D_FEATURE_LEVEL level;
|
||||
|
||||
hr = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, flags, levels, countof(levels), D3D11_SDK_VERSION, &scd, &m_swapchain, &m_dev, &level, &m_ctx);
|
||||
// hr = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_REFERENCE, NULL, flags, NULL, 0, D3D11_SDK_VERSION, &scd, &m_swapchain, &m_dev, &level, &m_ctx);
|
||||
|
||||
if(FAILED(hr)) return false;
|
||||
|
||||
if(!SetFeatureLevel(level, true))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
D3D11_FEATURE_DATA_D3D10_X_HARDWARE_OPTIONS options;
|
||||
|
||||
hr = m_dev->CheckFeatureSupport(D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS, &options, sizeof(D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS));
|
||||
|
||||
switch(m_level)
|
||||
{
|
||||
case D3D_FEATURE_LEVEL_9_1:
|
||||
case D3D_FEATURE_LEVEL_9_2:
|
||||
m_shader.model = "0x200";
|
||||
m_shader.vs = "vs_4_0_level_9_1";
|
||||
m_shader.ps = "ps_4_0_level_9_1";
|
||||
break;
|
||||
case D3D_FEATURE_LEVEL_9_3:
|
||||
m_shader.model = "0x300";
|
||||
m_shader.vs = "vs_4_0_level_9_3";
|
||||
m_shader.ps = "ps_4_0_level_9_3";
|
||||
break;
|
||||
case D3D_FEATURE_LEVEL_10_0:
|
||||
case D3D_FEATURE_LEVEL_10_1:
|
||||
m_shader.model = "0x400";
|
||||
m_shader.vs = "vs_4_0";
|
||||
m_shader.gs = "gs_4_0";
|
||||
m_shader.ps = "ps_4_0";
|
||||
break;
|
||||
case D3D_FEATURE_LEVEL_11_0:
|
||||
m_shader.model = "0x500";
|
||||
m_shader.vs = "vs_5_0";
|
||||
m_shader.gs = "gs_5_0";
|
||||
m_shader.ps = "ps_5_0";
|
||||
break;
|
||||
}
|
||||
|
||||
if(m_level < D3D_FEATURE_LEVEL_10_0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// convert
|
||||
|
||||
D3D11_INPUT_ELEMENT_DESC il_convert[] =
|
||||
|
@ -256,21 +237,24 @@ bool GSDevice11::Reset(int w, int h, int mode)
|
|||
if(!__super::Reset(w, h, mode))
|
||||
return false;
|
||||
|
||||
DXGI_SWAP_CHAIN_DESC scd;
|
||||
memset(&scd, 0, sizeof(scd));
|
||||
m_swapchain->GetDesc(&scd);
|
||||
m_swapchain->ResizeBuffers(scd.BufferCount, w, h, scd.BufferDesc.Format, 0);
|
||||
|
||||
CComPtr<ID3D11Texture2D> backbuffer;
|
||||
m_swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)&backbuffer);
|
||||
m_backbuffer = new GSTexture11(backbuffer);
|
||||
if(m_swapchain)
|
||||
{
|
||||
DXGI_SWAP_CHAIN_DESC scd;
|
||||
memset(&scd, 0, sizeof(scd));
|
||||
m_swapchain->GetDesc(&scd);
|
||||
m_swapchain->ResizeBuffers(scd.BufferCount, w, h, scd.BufferDesc.Format, 0);
|
||||
|
||||
CComPtr<ID3D11Texture2D> backbuffer;
|
||||
m_swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)&backbuffer);
|
||||
m_backbuffer = new GSTexture11(backbuffer);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GSDevice11::Flip()
|
||||
void GSDevice11::Flip(bool limit)
|
||||
{
|
||||
m_swapchain->Present(m_vsync ? 1 : 0, 0);
|
||||
m_swapchain->Present(m_vsync && limit ? 1 : 0, 0);
|
||||
}
|
||||
|
||||
void GSDevice11::BeginScene()
|
||||
|
@ -491,10 +475,6 @@ void GSDevice11::StretchRect(GSTexture* st, const GSVector4& sr, GSTexture* dt,
|
|||
PSSetSamplerState(linear ? m_convert.ln : m_convert.pt, NULL);
|
||||
PSSetShaderResources(st, NULL);
|
||||
|
||||
// rs
|
||||
|
||||
RSSet(ds.x, ds.y);
|
||||
|
||||
//
|
||||
|
||||
DrawPrimitive();
|
||||
|
@ -597,12 +577,12 @@ void GSDevice11::IASetVertexBuffer(ID3D11Buffer* vb, size_t stride)
|
|||
{
|
||||
if(m_vb != vb || m_vb_stride != stride)
|
||||
{
|
||||
m_vb = vb;
|
||||
m_vb_stride = stride;
|
||||
|
||||
uint32 offset = 0;
|
||||
|
||||
m_ctx->IASetVertexBuffers(0, 1, &vb, &stride, &offset);
|
||||
|
||||
m_vb = vb;
|
||||
m_vb_stride = stride;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -610,9 +590,9 @@ void GSDevice11::IASetInputLayout(ID3D11InputLayout* layout)
|
|||
{
|
||||
if(m_layout != layout)
|
||||
{
|
||||
m_ctx->IASetInputLayout(layout);
|
||||
|
||||
m_layout = layout;
|
||||
|
||||
m_ctx->IASetInputLayout(layout);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -620,9 +600,9 @@ void GSDevice11::IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY topology)
|
|||
{
|
||||
if(m_topology != topology)
|
||||
{
|
||||
m_ctx->IASetPrimitiveTopology(topology);
|
||||
|
||||
m_topology = topology;
|
||||
|
||||
m_ctx->IASetPrimitiveTopology(topology);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -630,16 +610,16 @@ void GSDevice11::VSSetShader(ID3D11VertexShader* vs, ID3D11Buffer* vs_cb)
|
|||
{
|
||||
if(m_vs != vs)
|
||||
{
|
||||
m_ctx->VSSetShader(vs, NULL, 0);
|
||||
|
||||
m_vs = vs;
|
||||
|
||||
m_ctx->VSSetShader(vs, NULL, 0);
|
||||
}
|
||||
|
||||
if(m_vs_cb != vs_cb)
|
||||
{
|
||||
m_ctx->VSSetConstantBuffers(0, 1, &vs_cb);
|
||||
|
||||
m_vs_cb = vs_cb;
|
||||
|
||||
m_ctx->VSSetConstantBuffers(0, 1, &vs_cb);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -663,12 +643,12 @@ void GSDevice11::PSSetShaderResources(GSTexture* sr0, GSTexture* sr1)
|
|||
|
||||
if(m_ps_srv[0] != srv0 || m_ps_srv[1] != srv1)
|
||||
{
|
||||
m_ps_srv[0] = srv0;
|
||||
m_ps_srv[1] = srv1;
|
||||
|
||||
ID3D11ShaderResourceView* srvs[] = {srv0, srv1};
|
||||
|
||||
m_ctx->PSSetShaderResources(0, 2, srvs);
|
||||
|
||||
m_ps_srv[0] = srv0;
|
||||
m_ps_srv[1] = srv1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -676,16 +656,16 @@ void GSDevice11::PSSetShader(ID3D11PixelShader* ps, ID3D11Buffer* ps_cb)
|
|||
{
|
||||
if(m_ps != ps)
|
||||
{
|
||||
m_ctx->PSSetShader(ps, NULL, 0);
|
||||
|
||||
m_ps = ps;
|
||||
|
||||
m_ctx->PSSetShader(ps, NULL, 0);
|
||||
}
|
||||
|
||||
if(m_ps_cb != ps_cb)
|
||||
{
|
||||
m_ctx->PSSetConstantBuffers(0, 1, &ps_cb);
|
||||
|
||||
m_ps_cb = ps_cb;
|
||||
|
||||
m_ctx->PSSetConstantBuffers(0, 1, &ps_cb);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -693,42 +673,12 @@ void GSDevice11::PSSetSamplerState(ID3D11SamplerState* ss0, ID3D11SamplerState*
|
|||
{
|
||||
if(m_ps_ss[0] != ss0 || m_ps_ss[1] != ss1)
|
||||
{
|
||||
m_ps_ss[0] = ss0;
|
||||
m_ps_ss[1] = ss1;
|
||||
|
||||
ID3D11SamplerState* sss[] = {ss0, ss1};
|
||||
|
||||
m_ctx->PSSetSamplers(0, 2, sss);
|
||||
|
||||
m_ps_ss[0] = ss0;
|
||||
m_ps_ss[1] = ss1;
|
||||
}
|
||||
}
|
||||
|
||||
void GSDevice11::RSSet(int width, int height, const GSVector4i* scissor)
|
||||
{
|
||||
if(m_viewport.x != width || m_viewport.y != height)
|
||||
{
|
||||
D3D11_VIEWPORT vp;
|
||||
|
||||
memset(&vp, 0, sizeof(vp));
|
||||
|
||||
vp.TopLeftX = 0;
|
||||
vp.TopLeftY = 0;
|
||||
vp.Width = width;
|
||||
vp.Height = height;
|
||||
vp.MinDepth = 0.0f;
|
||||
vp.MaxDepth = 1.0f;
|
||||
|
||||
m_ctx->RSSetViewports(1, &vp);
|
||||
|
||||
m_viewport = GSVector2i(width, height);
|
||||
}
|
||||
|
||||
GSVector4i r = scissor ? *scissor : GSVector4i(0, 0, width, height);
|
||||
|
||||
if(!m_scissor.eq(r))
|
||||
{
|
||||
m_ctx->RSSetScissorRects(1, r);
|
||||
|
||||
m_scissor = r;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -756,7 +706,7 @@ void GSDevice11::OMSetBlendState(ID3D11BlendState* bs, float bf)
|
|||
}
|
||||
}
|
||||
|
||||
void GSDevice11::OMSetRenderTargets(GSTexture* rt, GSTexture* ds)
|
||||
void GSDevice11::OMSetRenderTargets(GSTexture* rt, GSTexture* ds, const GSVector4i* scissor)
|
||||
{
|
||||
ID3D11RenderTargetView* rtv = NULL;
|
||||
ID3D11DepthStencilView* dsv = NULL;
|
||||
|
@ -766,10 +716,37 @@ void GSDevice11::OMSetRenderTargets(GSTexture* rt, GSTexture* ds)
|
|||
|
||||
if(m_rtv != rtv || m_dsv != dsv)
|
||||
{
|
||||
m_ctx->OMSetRenderTargets(1, &rtv, dsv);
|
||||
|
||||
m_rtv = rtv;
|
||||
m_dsv = dsv;
|
||||
|
||||
m_ctx->OMSetRenderTargets(1, &rtv, dsv);
|
||||
}
|
||||
|
||||
if(m_viewport != rt->m_size)
|
||||
{
|
||||
m_viewport = rt->m_size;
|
||||
|
||||
D3D11_VIEWPORT vp;
|
||||
|
||||
memset(&vp, 0, sizeof(vp));
|
||||
|
||||
vp.TopLeftX = 0;
|
||||
vp.TopLeftY = 0;
|
||||
vp.Width = rt->m_size.x;
|
||||
vp.Height = rt->m_size.y;
|
||||
vp.MinDepth = 0.0f;
|
||||
vp.MaxDepth = 1.0f;
|
||||
|
||||
m_ctx->RSSetViewports(1, &vp);
|
||||
}
|
||||
|
||||
GSVector4i r = scissor ? *scissor : GSVector4i(rt->m_size).zwxy();
|
||||
|
||||
if(!m_scissor.eq(r))
|
||||
{
|
||||
m_scissor = r;
|
||||
|
||||
m_ctx->RSSetScissorRects(1, r);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -779,7 +756,7 @@ HRESULT GSDevice11::CompileShader(uint32 id, const string& entry, D3D11_SHADER_M
|
|||
|
||||
vector<D3D11_SHADER_MACRO> m;
|
||||
|
||||
PrepareShaderMacro(m, macro, m_shader.model.c_str());
|
||||
PrepareShaderMacro(m, macro);
|
||||
|
||||
CComPtr<ID3D11Blob> shader, error;
|
||||
|
||||
|
@ -818,7 +795,7 @@ HRESULT GSDevice11::CompileShader(uint32 id, const string& entry, D3D11_SHADER_M
|
|||
|
||||
vector<D3D11_SHADER_MACRO> m;
|
||||
|
||||
PrepareShaderMacro(m, macro, m_shader.model.c_str());
|
||||
PrepareShaderMacro(m, macro);
|
||||
|
||||
CComPtr<ID3D11Blob> shader, error;
|
||||
|
||||
|
@ -850,7 +827,7 @@ HRESULT GSDevice11::CompileShader(uint32 id, const string& entry, D3D11_SHADER_M
|
|||
|
||||
vector<D3D11_SHADER_MACRO> m;
|
||||
|
||||
PrepareShaderMacro(m, macro, m_shader.model.c_str());
|
||||
PrepareShaderMacro(m, macro);
|
||||
|
||||
CComPtr<ID3D10Blob> shader, error;
|
||||
|
||||
|
|
|
@ -55,11 +55,9 @@ class GSDevice11 : public GSDevice
|
|||
|
||||
//
|
||||
|
||||
D3D_FEATURE_LEVEL m_level;
|
||||
CComPtr<ID3D11Device> m_dev;
|
||||
CComPtr<ID3D11DeviceContext> m_ctx;
|
||||
CComPtr<IDXGISwapChain> m_swapchain;
|
||||
struct {string model, vs, gs, ps;} m_shader;
|
||||
|
||||
struct
|
||||
{
|
||||
|
@ -100,7 +98,7 @@ public:
|
|||
|
||||
bool Create(GSWnd* wnd, bool vsync);
|
||||
bool Reset(int w, int h, int mode);
|
||||
void Flip();
|
||||
void Flip(bool limit);
|
||||
|
||||
void BeginScene();
|
||||
void DrawPrimitive();
|
||||
|
@ -133,10 +131,9 @@ public:
|
|||
void PSSetShaderResources(GSTexture* sr0, GSTexture* sr1);
|
||||
void PSSetShader(ID3D11PixelShader* ps, ID3D11Buffer* ps_cb);
|
||||
void PSSetSamplerState(ID3D11SamplerState* ss0, ID3D11SamplerState* ss1);
|
||||
void RSSet(int width, int height, const GSVector4i* scissor = NULL);
|
||||
void OMSetDepthStencilState(ID3D11DepthStencilState* dss, uint8 sref);
|
||||
void OMSetBlendState(ID3D11BlendState* bs, float bf);
|
||||
void OMSetRenderTargets(GSTexture* rt, GSTexture* ds);
|
||||
void OMSetRenderTargets(GSTexture* rt, GSTexture* ds, const GSVector4i* scissor = NULL);
|
||||
|
||||
ID3D11Device* operator->() {return m_dev;}
|
||||
operator ID3D11Device*() {return m_dev;}
|
||||
|
|
|
@ -136,7 +136,7 @@ bool GSDevice7::Reset(int w, int h, int mode)
|
|||
return true;
|
||||
}
|
||||
|
||||
void GSDevice7::Present(const GSVector4i& r, int shader)
|
||||
void GSDevice7::Present(const GSVector4i& r, int shader, bool limit)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
|
@ -145,7 +145,7 @@ void GSDevice7::Present(const GSVector4i& r, int shader)
|
|||
int w = std::max(cr.width(), 1);
|
||||
int h = std::max(cr.height(), 1);
|
||||
|
||||
if(!m_backbuffer || m_backbuffer->GetWidth() != w || m_backbuffer->GetHeight() != h)
|
||||
if(!m_backbuffer || m_backbuffer->m_size.x != w || m_backbuffer->m_size.y != h)
|
||||
{
|
||||
if(!Reset(w, h, DontCare))
|
||||
{
|
||||
|
@ -177,7 +177,7 @@ void GSDevice7::Present(const GSVector4i& r, int shader)
|
|||
|
||||
MapWindowPoints((HWND)m_wnd->GetHandle(), HWND_DESKTOP, (POINT*)&r2, 2);
|
||||
|
||||
if(m_vsync)
|
||||
if(m_vsync && limit)
|
||||
{
|
||||
hr = m_dd->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN, NULL);
|
||||
}
|
||||
|
|
|
@ -43,5 +43,5 @@ public:
|
|||
bool Create(GSWnd* wnd, bool vsync);
|
||||
bool Reset(int w, int h, int mode);
|
||||
bool IsLost(bool update) {return m_lost;}
|
||||
void Present(const GSVector4i& r, int shader);
|
||||
void Present(const GSVector4i& r, int shader, bool limit);
|
||||
};
|
||||
|
|
|
@ -108,13 +108,26 @@ bool GSDevice9::Create(GSWnd* wnd, bool vsync)
|
|||
|
||||
m_d3d->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &m_d3dcaps);
|
||||
|
||||
if(!Reset(1, 1, theApp.GetConfig("ModeWidth", 0) > 0 ? Fullscreen : Windowed)) return false;
|
||||
//
|
||||
|
||||
m_dev->Clear(0, NULL, D3DCLEAR_TARGET, 0, 1.0f, 0);
|
||||
if(m_d3dcaps.VertexShaderVersion < (m_d3dcaps.PixelShaderVersion & ~0x10000))
|
||||
{
|
||||
ASSERT(0);
|
||||
|
||||
// shaders
|
||||
return false;
|
||||
}
|
||||
|
||||
if(m_d3dcaps.PixelShaderVersion < D3DPS_VERSION(2, 0))
|
||||
m_d3dcaps.VertexShaderVersion = m_d3dcaps.PixelShaderVersion & ~0x10000;
|
||||
|
||||
if(m_d3dcaps.PixelShaderVersion >= D3DPS_VERSION(3, 0))
|
||||
{
|
||||
SetFeatureLevel(D3D_FEATURE_LEVEL_9_3, false);
|
||||
}
|
||||
else if(m_d3dcaps.PixelShaderVersion >= D3DPS_VERSION(2, 0))
|
||||
{
|
||||
SetFeatureLevel(D3D_FEATURE_LEVEL_9_2, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
string s = format(
|
||||
"Supported pixel shader version is too low!\n\nSupported: %d.%d\nNeeded: 2.0 or higher",
|
||||
|
@ -125,6 +138,15 @@ bool GSDevice9::Create(GSWnd* wnd, bool vsync)
|
|||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
if(!Reset(1, 1, theApp.GetConfig("windowed", 1) ? Windowed : Fullscreen))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_dev->Clear(0, NULL, D3DCLEAR_TARGET, 0, 1.0f, 0);
|
||||
|
||||
// convert
|
||||
|
||||
static const D3DVERTEXELEMENT9 il_convert[] =
|
||||
|
@ -282,7 +304,8 @@ bool GSDevice9::Reset(int w, int h, int mode)
|
|||
|
||||
if(!m_dev)
|
||||
{
|
||||
uint32 flags = D3DCREATE_MULTITHREADED | (m_d3dcaps.VertexProcessingCaps ? D3DCREATE_HARDWARE_VERTEXPROCESSING : D3DCREATE_SOFTWARE_VERTEXPROCESSING);
|
||||
//D3DCREATE_MULTITHREADED flag shouldn't be needed
|
||||
uint32 flags = m_d3dcaps.VertexProcessingCaps ? D3DCREATE_HARDWARE_VERTEXPROCESSING : D3DCREATE_SOFTWARE_VERTEXPROCESSING;
|
||||
|
||||
hr = m_d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, (HWND)m_wnd->GetHandle(), flags, &m_pp, &m_dev);
|
||||
|
||||
|
@ -348,7 +371,7 @@ bool GSDevice9::IsLost(bool update)
|
|||
return m_lost;
|
||||
}
|
||||
|
||||
void GSDevice9::Flip()
|
||||
void GSDevice9::Flip(bool limit)
|
||||
{
|
||||
m_dev->EndScene();
|
||||
|
||||
|
@ -427,7 +450,7 @@ void GSDevice9::ClearRenderTarget(GSTexture* rt, uint32 c)
|
|||
|
||||
void GSDevice9::ClearDepth(GSTexture* t, float c)
|
||||
{
|
||||
GSTexture* rt = CreateRenderTarget(t->GetWidth(), t->GetHeight());
|
||||
GSTexture* rt = CreateRenderTarget(t->m_size.x, t->m_size.y);
|
||||
|
||||
CComPtr<IDirect3DSurface9> rtsurface;
|
||||
CComPtr<IDirect3DSurface9> dssurface;
|
||||
|
@ -448,7 +471,7 @@ void GSDevice9::ClearDepth(GSTexture* t, float c)
|
|||
|
||||
void GSDevice9::ClearStencil(GSTexture* t, uint8 c)
|
||||
{
|
||||
GSTexture* rt = CreateRenderTarget(t->GetWidth(), t->GetHeight());
|
||||
GSTexture* rt = CreateRenderTarget(t->m_size.x, t->m_size.y);
|
||||
|
||||
CComPtr<IDirect3DSurface9> rtsurface;
|
||||
CComPtr<IDirect3DSurface9> dssurface;
|
||||
|
@ -635,10 +658,6 @@ void GSDevice9::StretchRect(GSTexture* st, const GSVector4& sr, GSTexture* dt, c
|
|||
PSSetSamplerState(linear ? &m_convert.ln : &m_convert.pt);
|
||||
PSSetShaderResources(st, NULL);
|
||||
|
||||
// rs
|
||||
|
||||
RSSet(ds.x, ds.y);
|
||||
|
||||
//
|
||||
|
||||
DrawPrimitive();
|
||||
|
@ -732,10 +751,10 @@ void GSDevice9::IASetVertexBuffer(IDirect3DVertexBuffer9* vb, size_t stride)
|
|||
{
|
||||
if(m_vb != vb || m_vb_stride != stride)
|
||||
{
|
||||
m_dev->SetStreamSource(0, vb, 0, stride);
|
||||
|
||||
m_vb = vb;
|
||||
m_vb_stride = stride;
|
||||
|
||||
m_dev->SetStreamSource(0, vb, 0, stride);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -743,9 +762,9 @@ void GSDevice9::IASetInputLayout(IDirect3DVertexDeclaration9* layout)
|
|||
{
|
||||
if(m_layout != layout)
|
||||
{
|
||||
m_dev->SetVertexDeclaration(layout);
|
||||
|
||||
m_layout = layout;
|
||||
|
||||
m_dev->SetVertexDeclaration(layout);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -758,9 +777,9 @@ void GSDevice9::VSSetShader(IDirect3DVertexShader9* vs, const float* vs_cb, int
|
|||
{
|
||||
if(m_vs != vs)
|
||||
{
|
||||
m_dev->SetVertexShader(vs);
|
||||
|
||||
m_vs = vs;
|
||||
|
||||
m_dev->SetVertexShader(vs);
|
||||
}
|
||||
|
||||
if(vs_cb && vs_cb_len > 0)
|
||||
|
@ -776,11 +795,11 @@ void GSDevice9::VSSetShader(IDirect3DVertexShader9* vs, const float* vs_cb, int
|
|||
m_vs_cb = (float*)_aligned_malloc(size, 16);
|
||||
}
|
||||
|
||||
m_vs_cb_len = vs_cb_len;
|
||||
|
||||
memcpy(m_vs_cb, vs_cb, size);
|
||||
|
||||
m_dev->SetVertexShaderConstantF(0, vs_cb, vs_cb_len);
|
||||
|
||||
m_vs_cb_len = vs_cb_len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -795,16 +814,16 @@ void GSDevice9::PSSetShaderResources(GSTexture* sr0, GSTexture* sr1)
|
|||
|
||||
if(m_ps_srvs[0] != srv0)
|
||||
{
|
||||
m_dev->SetTexture(0, srv0);
|
||||
|
||||
m_ps_srvs[0] = srv0;
|
||||
|
||||
m_dev->SetTexture(0, srv0);
|
||||
}
|
||||
|
||||
if(m_ps_srvs[1] != srv1)
|
||||
{
|
||||
m_dev->SetTexture(1, srv1);
|
||||
|
||||
m_ps_srvs[1] = srv1;
|
||||
|
||||
m_dev->SetTexture(1, srv1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -812,9 +831,9 @@ void GSDevice9::PSSetShader(IDirect3DPixelShader9* ps, const float* ps_cb, int p
|
|||
{
|
||||
if(m_ps != ps)
|
||||
{
|
||||
m_dev->SetPixelShader(ps);
|
||||
|
||||
m_ps = ps;
|
||||
|
||||
m_dev->SetPixelShader(ps);
|
||||
}
|
||||
|
||||
if(ps_cb && ps_cb_len > 0)
|
||||
|
@ -830,11 +849,11 @@ void GSDevice9::PSSetShader(IDirect3DPixelShader9* ps, const float* ps_cb, int p
|
|||
m_ps_cb = (float*)_aligned_malloc(size, 16);
|
||||
}
|
||||
|
||||
m_ps_cb_len = ps_cb_len;
|
||||
|
||||
memcpy(m_ps_cb, ps_cb, size);
|
||||
|
||||
m_dev->SetPixelShaderConstantF(0, ps_cb, ps_cb_len);
|
||||
|
||||
m_ps_cb_len = ps_cb_len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -843,6 +862,7 @@ void GSDevice9::PSSetSamplerState(Direct3DSamplerState9* ss)
|
|||
{
|
||||
if(ss && m_ps_ss != ss)
|
||||
{
|
||||
m_ps_ss = ss;
|
||||
|
||||
m_dev->SetSamplerState(0, D3DSAMP_ADDRESSU, ss->AddressU);
|
||||
m_dev->SetSamplerState(0, D3DSAMP_ADDRESSV, ss->AddressV);
|
||||
|
@ -860,20 +880,6 @@ void GSDevice9::PSSetSamplerState(Direct3DSamplerState9* ss)
|
|||
m_dev->SetSamplerState(2, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
|
||||
m_dev->SetSamplerState(3, D3DSAMP_MINFILTER, D3DTEXF_POINT);
|
||||
m_dev->SetSamplerState(3, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
|
||||
|
||||
m_ps_ss = ss;
|
||||
}
|
||||
}
|
||||
|
||||
void GSDevice9::RSSet(int width, int height, const GSVector4i* scissor)
|
||||
{
|
||||
GSVector4i r = scissor ? *scissor : GSVector4i(0, 0, width, height);
|
||||
|
||||
if(!m_scissor.eq(r))
|
||||
{
|
||||
m_dev->SetScissorRect(r);
|
||||
|
||||
m_scissor = r;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -881,6 +887,8 @@ void GSDevice9::OMSetDepthStencilState(Direct3DDepthStencilState9* dss)
|
|||
{
|
||||
if(m_dss != dss)
|
||||
{
|
||||
m_dss = dss;
|
||||
|
||||
m_dev->SetRenderState(D3DRS_ZENABLE, dss->DepthEnable);
|
||||
m_dev->SetRenderState(D3DRS_ZWRITEENABLE, dss->DepthWriteMask);
|
||||
|
||||
|
@ -901,8 +909,6 @@ void GSDevice9::OMSetDepthStencilState(Direct3DDepthStencilState9* dss)
|
|||
m_dev->SetRenderState(D3DRS_STENCILZFAIL, dss->StencilDepthFailOp);
|
||||
m_dev->SetRenderState(D3DRS_STENCILREF, dss->StencilRef);
|
||||
}
|
||||
|
||||
m_dss = dss;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -910,6 +916,9 @@ void GSDevice9::OMSetBlendState(Direct3DBlendState9* bs, uint32 bf)
|
|||
{
|
||||
if(m_bs != bs || m_bf != bf)
|
||||
{
|
||||
m_bs = bs;
|
||||
m_bf = bf;
|
||||
|
||||
m_dev->SetRenderState(D3DRS_ALPHABLENDENABLE, bs->BlendEnable);
|
||||
|
||||
if(bs->BlendEnable)
|
||||
|
@ -925,13 +934,10 @@ void GSDevice9::OMSetBlendState(Direct3DBlendState9* bs, uint32 bf)
|
|||
}
|
||||
|
||||
m_dev->SetRenderState(D3DRS_COLORWRITEENABLE, bs->RenderTargetWriteMask);
|
||||
|
||||
m_bs = bs;
|
||||
m_bf = bf;
|
||||
}
|
||||
}
|
||||
|
||||
void GSDevice9::OMSetRenderTargets(GSTexture* rt, GSTexture* ds)
|
||||
void GSDevice9::OMSetRenderTargets(GSTexture* rt, GSTexture* ds, const GSVector4i* scissor)
|
||||
{
|
||||
IDirect3DSurface9* rtv = NULL;
|
||||
IDirect3DSurface9* dsv = NULL;
|
||||
|
@ -941,16 +947,25 @@ void GSDevice9::OMSetRenderTargets(GSTexture* rt, GSTexture* ds)
|
|||
|
||||
if(m_rtv != rtv)
|
||||
{
|
||||
m_dev->SetRenderTarget(0, rtv);
|
||||
|
||||
m_rtv = rtv;
|
||||
|
||||
m_dev->SetRenderTarget(0, rtv);
|
||||
}
|
||||
|
||||
if(m_dsv != dsv)
|
||||
{
|
||||
m_dev->SetDepthStencilSurface(dsv);
|
||||
|
||||
m_dsv = dsv;
|
||||
|
||||
m_dev->SetDepthStencilSurface(dsv);
|
||||
}
|
||||
|
||||
GSVector4i r = scissor ? *scissor : GSVector4i(rt->m_size).zwxy();
|
||||
|
||||
if(!m_scissor.eq(r))
|
||||
{
|
||||
m_scissor = r;
|
||||
|
||||
m_dev->SetScissorRect(r);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -979,27 +994,9 @@ static HRESULT LoadShader(uint32 id, LPCSTR& data, uint32& size)
|
|||
|
||||
HRESULT GSDevice9::CompileShader(uint32 id, const string& entry, const D3DXMACRO* macro, IDirect3DVertexShader9** vs, const D3DVERTEXELEMENT9* layout, int count, IDirect3DVertexDeclaration9** il)
|
||||
{
|
||||
const char* target;
|
||||
const char* model;
|
||||
|
||||
if(m_d3dcaps.VertexShaderVersion >= D3DVS_VERSION(3, 0))
|
||||
{
|
||||
target = "vs_3_0";
|
||||
model = "0x300";
|
||||
}
|
||||
else if(m_d3dcaps.VertexShaderVersion >= D3DVS_VERSION(2, 0))
|
||||
{
|
||||
target = "vs_2_0";
|
||||
model = "0x200";
|
||||
}
|
||||
else
|
||||
{
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
vector<D3DXMACRO> m;
|
||||
|
||||
PrepareShaderMacro(m, macro, model);
|
||||
PrepareShaderMacro(m, macro);
|
||||
|
||||
HRESULT hr;
|
||||
|
||||
|
@ -1014,7 +1011,7 @@ HRESULT GSDevice9::CompileShader(uint32 id, const string& entry, const D3DXMACRO
|
|||
|
||||
if(FAILED(hr)) return E_FAIL;
|
||||
|
||||
hr = D3DXCompileShader(data, size, &m[0], NULL, entry.c_str(), target, 0, &shader, &error, NULL);
|
||||
hr = D3DXCompileShader(data, size, &m[0], NULL, entry.c_str(), m_shader.vs.c_str(), 0, &shader, &error, NULL);
|
||||
|
||||
if(SUCCEEDED(hr))
|
||||
{
|
||||
|
@ -1044,29 +1041,16 @@ HRESULT GSDevice9::CompileShader(uint32 id, const string& entry, const D3DXMACRO
|
|||
|
||||
HRESULT GSDevice9::CompileShader(uint32 id, const string& entry, const D3DXMACRO* macro, IDirect3DPixelShader9** ps)
|
||||
{
|
||||
const char* target = NULL;
|
||||
const char* model;
|
||||
uint32 flags = 0;
|
||||
|
||||
if(m_d3dcaps.PixelShaderVersion >= D3DPS_VERSION(3, 0))
|
||||
if(m_shader.level >= D3D_FEATURE_LEVEL_9_3)
|
||||
{
|
||||
target = "ps_3_0";
|
||||
model = "0x300";
|
||||
flags |= D3DXSHADER_AVOID_FLOW_CONTROL;
|
||||
}
|
||||
else if(m_d3dcaps.PixelShaderVersion >= D3DPS_VERSION(2, 0))
|
||||
{
|
||||
target = "ps_2_0";
|
||||
model = "0x200";
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
vector<D3DXMACRO> m;
|
||||
|
||||
PrepareShaderMacro(m, macro, model);
|
||||
PrepareShaderMacro(m, macro);
|
||||
|
||||
HRESULT hr;
|
||||
|
||||
|
@ -1081,7 +1065,7 @@ HRESULT GSDevice9::CompileShader(uint32 id, const string& entry, const D3DXMACRO
|
|||
|
||||
if(FAILED(hr)) return E_FAIL;
|
||||
|
||||
hr = D3DXCompileShader(data, size, &m[0], NULL, entry.c_str(), target, 0, &shader, &error, NULL);
|
||||
hr = D3DXCompileShader(data, size, &m[0], NULL, entry.c_str(), m_shader.ps.c_str(), 0, &shader, &error, NULL);
|
||||
|
||||
if(SUCCEEDED(hr))
|
||||
{
|
||||
|
|
|
@ -135,7 +135,7 @@ public:
|
|||
bool Create(GSWnd* wnd, bool vsync);
|
||||
bool Reset(int w, int h, int mode);
|
||||
bool IsLost(bool update);
|
||||
void Flip();
|
||||
void Flip(bool limit);
|
||||
|
||||
void BeginScene();
|
||||
void DrawPrimitive();
|
||||
|
@ -167,10 +167,9 @@ public:
|
|||
void PSSetShaderResources(GSTexture* sr0, GSTexture* sr1);
|
||||
void PSSetShader(IDirect3DPixelShader9* ps, const float* ps_cb, int ps_cb_len);
|
||||
void PSSetSamplerState(Direct3DSamplerState9* ss);
|
||||
void RSSet(int width, int height, const GSVector4i* scissor = NULL);
|
||||
void OMSetDepthStencilState(Direct3DDepthStencilState9* dss);
|
||||
void OMSetBlendState(Direct3DBlendState9* bs, uint32 bf);
|
||||
void OMSetRenderTargets(GSTexture* rt, GSTexture* ds);
|
||||
void OMSetRenderTargets(GSTexture* rt, GSTexture* ds, const GSVector4i* scissor = NULL);
|
||||
|
||||
IDirect3DDevice9* operator->() {return m_dev;}
|
||||
operator IDirect3DDevice9*() {return m_dev;}
|
||||
|
|
|
@ -185,16 +185,16 @@ bool GSDeviceOGL::Reset(int w, int h, int mode)
|
|||
return true;
|
||||
}
|
||||
|
||||
void GSDeviceOGL::Present(const GSVector4i& r, int shader)
|
||||
void GSDeviceOGL::Present(const GSVector4i& r, int shader, bool limit)
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0); CheckError();
|
||||
|
||||
// TODO: m_current => backbuffer
|
||||
|
||||
Flip();
|
||||
Flip(limit);
|
||||
}
|
||||
|
||||
void GSDeviceOGL::Flip()
|
||||
void GSDeviceOGL::Flip(bool limit)
|
||||
{
|
||||
#ifdef _WINDOWS
|
||||
|
||||
|
@ -406,10 +406,17 @@ void GSDeviceOGL::IASetPrimitiveTopology(int topology)
|
|||
m_topology = topology;
|
||||
}
|
||||
|
||||
void GSDeviceOGL::PSSetShaderResources(GSTexture* sr0, GSTexture* sr1)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
void GSDeviceOGL::PSSetSamplerState(SamplerStateOGL* ss)
|
||||
{
|
||||
if(ss && m_ps_ss != ss)
|
||||
{
|
||||
m_ps_ss = ss;
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, ss->wrap.s);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, ss->wrap.t);
|
||||
|
@ -433,27 +440,6 @@ void GSDeviceOGL::PSSetSamplerState(SamplerStateOGL* ss)
|
|||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_POINT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_POINT);
|
||||
|
||||
m_ps_ss = ss;
|
||||
}
|
||||
}
|
||||
|
||||
void GSDeviceOGL::RSSet(int width, int height, const GSVector4i* scissor)
|
||||
{
|
||||
if(m_viewport.x != width || m_viewport.y != height)
|
||||
{
|
||||
glViewport(0, 0, width, height); CheckError();
|
||||
|
||||
m_viewport = GSVector2i(width, height);
|
||||
}
|
||||
|
||||
GSVector4i r = scissor ? *scissor : GSVector4i(0, 0, width, height);
|
||||
|
||||
if(!m_scissor.eq(r))
|
||||
{
|
||||
glScissor(r.left, r.top, r.width(), r.height()); CheckError();
|
||||
|
||||
m_scissor = r;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -461,6 +447,8 @@ void GSDeviceOGL::OMSetDepthStencilState(DepthStencilStateOGL* dss)
|
|||
{
|
||||
if(m_dss != dss)
|
||||
{
|
||||
m_dss = dss;
|
||||
|
||||
if(dss->depth.enable)
|
||||
{
|
||||
glEnable(GL_DEPTH_TEST); CheckError();
|
||||
|
@ -483,8 +471,6 @@ void GSDeviceOGL::OMSetDepthStencilState(DepthStencilStateOGL* dss)
|
|||
{
|
||||
glDisable(GL_STENCIL_TEST); CheckError();
|
||||
}
|
||||
|
||||
m_dss = dss;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -492,6 +478,9 @@ void GSDeviceOGL::OMSetBlendState(BlendStateOGL* bs, float bf)
|
|||
{
|
||||
if(m_bs != bs || m_bf != bf)
|
||||
{
|
||||
m_bs = bs;
|
||||
m_bf = bf;
|
||||
|
||||
if(bs->enable)
|
||||
{
|
||||
glEnable(GL_BLEND); CheckError();
|
||||
|
@ -505,13 +494,10 @@ void GSDeviceOGL::OMSetBlendState(BlendStateOGL* bs, float bf)
|
|||
}
|
||||
|
||||
glColorMask(bs->mask.r, bs->mask.g, bs->mask.b, bs->mask.a); CheckError();
|
||||
|
||||
m_bs = bs;
|
||||
m_bf = bf;
|
||||
}
|
||||
}
|
||||
|
||||
void GSDeviceOGL::OMSetRenderTargets(GSTexture* rt, GSTexture* ds)
|
||||
void GSDeviceOGL::OMSetRenderTargets(GSTexture* rt, GSTexture* ds, const GSVector4i* scissor)
|
||||
{
|
||||
GLuint rti = 0;
|
||||
GLuint dsi = 0;
|
||||
|
@ -521,15 +507,31 @@ void GSDeviceOGL::OMSetRenderTargets(GSTexture* rt, GSTexture* ds)
|
|||
|
||||
if(m_rt != rti)
|
||||
{
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rti); CheckError();
|
||||
|
||||
m_rt = rti;
|
||||
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rti); CheckError();
|
||||
}
|
||||
|
||||
if(m_ds != dsi)
|
||||
{
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT, dsi); CheckError();
|
||||
|
||||
m_ds = dsi;
|
||||
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT, dsi); CheckError();
|
||||
}
|
||||
|
||||
if(m_viewport != rt->m_size)
|
||||
{
|
||||
m_viewport = rt->m_size;
|
||||
|
||||
glViewport(0, 0, rt->m_size.x, rt->m_size.y); CheckError();
|
||||
}
|
||||
|
||||
GSVector4i r = scissor ? *scissor : GSVector4i(rt->m_size).zwxy();
|
||||
|
||||
if(!m_scissor.eq(r))
|
||||
{
|
||||
m_scissor = r;
|
||||
|
||||
glScissor(r.left, r.top, r.width(), r.height()); CheckError();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -111,8 +111,8 @@ public:
|
|||
|
||||
bool Create(GSWnd* wnd, bool vsync);
|
||||
bool Reset(int w, int h, int mode);
|
||||
void Present(const GSVector4i& r, int shader);
|
||||
void Flip();
|
||||
void Present(const GSVector4i& r, int shader, bool limit);
|
||||
void Flip(bool limit);
|
||||
|
||||
void BeginScene();
|
||||
void DrawPrimitive();
|
||||
|
@ -138,11 +138,11 @@ public:
|
|||
void IASetInputLayout(); // TODO
|
||||
void IASetPrimitiveTopology(int topology);
|
||||
|
||||
void PSSetShaderResources(GSTexture* sr0, GSTexture* sr1);
|
||||
void PSSetSamplerState(SamplerStateOGL* ss);
|
||||
void RSSet(int width, int height, const GSVector4i* scissor);
|
||||
void OMSetDepthStencilState(DepthStencilStateOGL* dss);
|
||||
void OMSetBlendState(BlendStateOGL* bs, float bf);
|
||||
void OMSetRenderTargets(GSTexture* rt, GSTexture* ds);
|
||||
void OMSetRenderTargets(GSTexture* rt, GSTexture* ds, const GSVector4i* scissor = NULL);
|
||||
|
||||
static void CheckError()
|
||||
{
|
||||
|
|
|
@ -46,10 +46,10 @@ void GSDrawScanline::BeginDraw(const GSRasterizerData* data, Functions* f)
|
|||
m_sel = p->sel;
|
||||
|
||||
m_env.vm = p->vm;
|
||||
m_env.fbr = p->fbo->row;
|
||||
m_env.zbr = p->zbo->row;
|
||||
m_env.fbc = p->fbo->col[0];
|
||||
m_env.zbc = p->zbo->col[0];
|
||||
m_env.fbr = p->fbo->pixel.row;
|
||||
m_env.zbr = p->zbo->pixel.row;
|
||||
m_env.fbc = p->fbo->pixel.col[0];
|
||||
m_env.zbc = p->zbo->pixel.col[0];
|
||||
m_env.fzbr = p->fzbo->row;
|
||||
m_env.fzbc = p->fzbo->col;
|
||||
m_env.fm = GSVector4i(p->fm);
|
||||
|
|
|
@ -51,8 +51,18 @@ public:
|
|||
GSVector4 ex;
|
||||
} scissor;
|
||||
|
||||
struct
|
||||
{
|
||||
GSOffset* fb;
|
||||
GSOffset* zb;
|
||||
GSOffset* tex;
|
||||
GSPixelOffset4* fzb;
|
||||
} offset;
|
||||
|
||||
GSDrawingContext()
|
||||
{
|
||||
memset(&offset, 0, sizeof(offset));
|
||||
|
||||
Reset();
|
||||
}
|
||||
|
||||
|
|
|
@ -30,18 +30,17 @@
|
|||
#define ASSERT_BLOCK(r, w, h) \
|
||||
ASSERT((r).width() >= w && (r).height() >= h && !((r).left & (w - 1)) && !((r).top & (h - 1)) && !((r).right & (w - 1)) && !((r).bottom & (h - 1))); \
|
||||
|
||||
#define FOREACH_BLOCK_START(r, w, h, bpp, psm) \
|
||||
#define FOREACH_BLOCK_START(r, w, h, bpp) \
|
||||
ASSERT_BLOCK(r, w, h); \
|
||||
const GSLocalMemory::BlockOffset* RESTRICT _bo = GetBlockOffset(TEX0.TBP0, TEX0.TBW, psm); \
|
||||
GSVector4i _r = r >> 3; \
|
||||
uint8* _dst = dst - _r.left * bpp; \
|
||||
int _offset = dstpitch * h; \
|
||||
for(int y = _r.top; y < _r.bottom; y += h >> 3, _dst += _offset) \
|
||||
{ \
|
||||
uint32 _base = _bo->row[y]; \
|
||||
uint32 _base = o->block.row[y]; \
|
||||
for(int x = _r.left; x < _r.right; x += w >> 3) \
|
||||
{ \
|
||||
const uint8* src = BlockPtr(_base + _bo->col[x]); \
|
||||
const uint8* src = BlockPtr(_base + o->block.col[x]); \
|
||||
uint8* dst = &_dst[x * bpp]; \
|
||||
|
||||
#define FOREACH_BLOCK_END }}
|
||||
|
@ -66,14 +65,14 @@ int GSLocalMemory::rowOffset16SZ[2048];
|
|||
int GSLocalMemory::rowOffset8[2][2048];
|
||||
int GSLocalMemory::rowOffset4[2][2048];
|
||||
|
||||
int GSLocalMemory::blockOffset32[256];
|
||||
int GSLocalMemory::blockOffset32Z[256];
|
||||
int GSLocalMemory::blockOffset16[256];
|
||||
int GSLocalMemory::blockOffset16S[256];
|
||||
int GSLocalMemory::blockOffset16Z[256];
|
||||
int GSLocalMemory::blockOffset16SZ[256];
|
||||
int GSLocalMemory::blockOffset8[256];
|
||||
int GSLocalMemory::blockOffset4[256];
|
||||
short GSLocalMemory::blockOffset32[256];
|
||||
short GSLocalMemory::blockOffset32Z[256];
|
||||
short GSLocalMemory::blockOffset16[256];
|
||||
short GSLocalMemory::blockOffset16S[256];
|
||||
short GSLocalMemory::blockOffset16Z[256];
|
||||
short GSLocalMemory::blockOffset16SZ[256];
|
||||
short GSLocalMemory::blockOffset8[256];
|
||||
short GSLocalMemory::blockOffset4[256];
|
||||
|
||||
//
|
||||
|
||||
|
@ -159,42 +158,42 @@ GSLocalMemory::GSLocalMemory()
|
|||
|
||||
for(int x = 0; x < countof(blockOffset32); x++)
|
||||
{
|
||||
blockOffset32[x] = (int)BlockNumber32(x << 3, 0, 0, 32) - (int)BlockNumber32(0, 0, 0, 32);
|
||||
blockOffset32[x] = (short)((int)BlockNumber32(x << 3, 0, 0, 32) - (int)BlockNumber32(0, 0, 0, 32));
|
||||
}
|
||||
|
||||
for(int x = 0; x < countof(blockOffset32Z); x++)
|
||||
{
|
||||
blockOffset32Z[x] = (int)BlockNumber32Z(x << 3, 0, 0, 32) - (int)BlockNumber32Z(0, 0, 0, 32);
|
||||
blockOffset32Z[x] = (short)((int)BlockNumber32Z(x << 3, 0, 0, 32) - (int)BlockNumber32Z(0, 0, 0, 32));
|
||||
}
|
||||
|
||||
for(int x = 0; x < countof(blockOffset16); x++)
|
||||
{
|
||||
blockOffset16[x] = (int)BlockNumber16(x << 3, 0, 0, 32) - (int)BlockNumber16(0, 0, 0, 32);
|
||||
blockOffset16[x] = (short)((int)BlockNumber16(x << 3, 0, 0, 32) - (int)BlockNumber16(0, 0, 0, 32));
|
||||
}
|
||||
|
||||
for(int x = 0; x < countof(blockOffset16S); x++)
|
||||
{
|
||||
blockOffset16S[x] = (int)BlockNumber16S(x << 3, 0, 0, 32) - (int)BlockNumber16S(0, 0, 0, 32);
|
||||
blockOffset16S[x] = (short)((int)BlockNumber16S(x << 3, 0, 0, 32) - (int)BlockNumber16S(0, 0, 0, 32));
|
||||
}
|
||||
|
||||
for(int x = 0; x < countof(blockOffset16Z); x++)
|
||||
{
|
||||
blockOffset16Z[x] = (int)BlockNumber16Z(x << 3, 0, 0, 32) - (int)BlockNumber16Z(0, 0, 0, 32);
|
||||
blockOffset16Z[x] = (short)((int)BlockNumber16Z(x << 3, 0, 0, 32) - (int)BlockNumber16Z(0, 0, 0, 32));
|
||||
}
|
||||
|
||||
for(int x = 0; x < countof(blockOffset16SZ); x++)
|
||||
{
|
||||
blockOffset16SZ[x] = (int)BlockNumber16SZ(x << 3, 0, 0, 32) - (int)BlockNumber16SZ(0, 0, 0, 32);
|
||||
blockOffset16SZ[x] = (short)((int)BlockNumber16SZ(x << 3, 0, 0, 32) - (int)BlockNumber16SZ(0, 0, 0, 32));
|
||||
}
|
||||
|
||||
for(int x = 0; x < countof(blockOffset8); x++)
|
||||
{
|
||||
blockOffset8[x] = (int)BlockNumber8(x << 3, 0, 0, 32) - (int)BlockNumber8(0, 0, 0, 32);
|
||||
blockOffset8[x] = (short)((int)BlockNumber8(x << 3, 0, 0, 32) - (int)BlockNumber8(0, 0, 0, 32));
|
||||
}
|
||||
|
||||
for(int x = 0; x < countof(blockOffset4); x++)
|
||||
{
|
||||
blockOffset4[x] = (int)BlockNumber4(x << 3, 0, 0, 32) - (int)BlockNumber4(0, 0, 0, 32);
|
||||
blockOffset4[x] = (short)((int)BlockNumber4(x << 3, 0, 0, 32) - (int)BlockNumber4(0, 0, 0, 32));
|
||||
}
|
||||
|
||||
for(int i = 0; i < countof(m_psm); i++)
|
||||
|
@ -206,13 +205,11 @@ GSLocalMemory::GSLocalMemory()
|
|||
m_psm[i].wp = &GSLocalMemory::WritePixel32;
|
||||
m_psm[i].wpa = &GSLocalMemory::WritePixel32;
|
||||
m_psm[i].rt = &GSLocalMemory::ReadTexel32;
|
||||
m_psm[i].rtNP = &GSLocalMemory::ReadTexel32;
|
||||
m_psm[i].rta = &GSLocalMemory::ReadTexel32;
|
||||
m_psm[i].wfa = &GSLocalMemory::WritePixel32;
|
||||
m_psm[i].wi = &GSLocalMemory::WriteImage<PSM_PSMCT32, 8, 8, 32>;
|
||||
m_psm[i].ri = &GSLocalMemory::ReadImageX; // TODO
|
||||
m_psm[i].rtx = &GSLocalMemory::ReadTexture32;
|
||||
m_psm[i].rtxNP = &GSLocalMemory::ReadTexture32;
|
||||
m_psm[i].rtxP = &GSLocalMemory::ReadTexture32;
|
||||
m_psm[i].rtxb = &GSLocalMemory::ReadTextureBlock32;
|
||||
m_psm[i].rtxbP = &GSLocalMemory::ReadTextureBlock32;
|
||||
|
@ -328,18 +325,6 @@ GSLocalMemory::GSLocalMemory()
|
|||
m_psm[PSM_PSMZ16].wfa = &GSLocalMemory::WriteFrame16;
|
||||
m_psm[PSM_PSMZ16S].wfa = &GSLocalMemory::WriteFrame16;
|
||||
|
||||
m_psm[PSM_PSMCT16].rtNP = &GSLocalMemory::ReadTexel16NP;
|
||||
m_psm[PSM_PSMCT16S].rtNP = &GSLocalMemory::ReadTexel16SNP;
|
||||
m_psm[PSM_PSMT8].rtNP = &GSLocalMemory::ReadTexel8;
|
||||
m_psm[PSM_PSMT4].rtNP = &GSLocalMemory::ReadTexel4;
|
||||
m_psm[PSM_PSMT8H].rtNP = &GSLocalMemory::ReadTexel8H;
|
||||
m_psm[PSM_PSMT4HL].rtNP = &GSLocalMemory::ReadTexel4HL;
|
||||
m_psm[PSM_PSMT4HH].rtNP = &GSLocalMemory::ReadTexel4HH;
|
||||
m_psm[PSM_PSMZ32].rtNP = &GSLocalMemory::ReadTexel32Z;
|
||||
m_psm[PSM_PSMZ24].rtNP = &GSLocalMemory::ReadTexel24Z;
|
||||
m_psm[PSM_PSMZ16].rtNP = &GSLocalMemory::ReadTexel16ZNP;
|
||||
m_psm[PSM_PSMZ16S].rtNP = &GSLocalMemory::ReadTexel16SZNP;
|
||||
|
||||
m_psm[PSM_PSMCT24].wi = &GSLocalMemory::WriteImage24; // TODO
|
||||
m_psm[PSM_PSMCT16].wi = &GSLocalMemory::WriteImage<PSM_PSMCT16, 16, 8, 16>;
|
||||
m_psm[PSM_PSMCT16S].wi = &GSLocalMemory::WriteImage<PSM_PSMCT16S, 16, 8, 16>;
|
||||
|
@ -366,18 +351,6 @@ GSLocalMemory::GSLocalMemory()
|
|||
m_psm[PSM_PSMZ16].rtx = &GSLocalMemory::ReadTexture16Z;
|
||||
m_psm[PSM_PSMZ16S].rtx = &GSLocalMemory::ReadTexture16SZ;
|
||||
|
||||
m_psm[PSM_PSMCT16].rtxNP = &GSLocalMemory::ReadTexture16NP;
|
||||
m_psm[PSM_PSMCT16S].rtxNP = &GSLocalMemory::ReadTexture16SNP;
|
||||
m_psm[PSM_PSMT8].rtxNP = &GSLocalMemory::ReadTexture8NP;
|
||||
m_psm[PSM_PSMT4].rtxNP = &GSLocalMemory::ReadTexture4NP;
|
||||
m_psm[PSM_PSMT8H].rtxNP = &GSLocalMemory::ReadTexture8HNP;
|
||||
m_psm[PSM_PSMT4HL].rtxNP = &GSLocalMemory::ReadTexture4HLNP;
|
||||
m_psm[PSM_PSMT4HH].rtxNP = &GSLocalMemory::ReadTexture4HHNP;
|
||||
m_psm[PSM_PSMZ32].rtxNP = &GSLocalMemory::ReadTexture32Z;
|
||||
m_psm[PSM_PSMZ24].rtxNP = &GSLocalMemory::ReadTexture24Z;
|
||||
m_psm[PSM_PSMZ16].rtxNP = &GSLocalMemory::ReadTexture16ZNP;
|
||||
m_psm[PSM_PSMZ16S].rtxNP = &GSLocalMemory::ReadTexture16SZNP;
|
||||
|
||||
m_psm[PSM_PSMCT24].rtxP = &GSLocalMemory::ReadTexture24;
|
||||
m_psm[PSM_PSMCT16].rtxP = &GSLocalMemory::ReadTexture16;
|
||||
m_psm[PSM_PSMCT16S].rtxP = &GSLocalMemory::ReadTexture16S;
|
||||
|
@ -417,9 +390,6 @@ GSLocalMemory::GSLocalMemory()
|
|||
m_psm[PSM_PSMZ16].rtxbP = &GSLocalMemory::ReadTextureBlock16Z;
|
||||
m_psm[PSM_PSMZ16S].rtxbP = &GSLocalMemory::ReadTextureBlock16SZ;
|
||||
|
||||
m_psm[PSM_PSMT8].pal = m_psm[PSM_PSMT8H].pal = 256;
|
||||
m_psm[PSM_PSMT4].pal = m_psm[PSM_PSMT4HL].pal = m_psm[PSM_PSMT4HH].pal = 16;
|
||||
|
||||
m_psm[PSM_PSMCT16].bpp = m_psm[PSM_PSMCT16S].bpp = 16;
|
||||
m_psm[PSM_PSMT8].bpp = 8;
|
||||
m_psm[PSM_PSMT4].bpp = 4;
|
||||
|
@ -432,6 +402,15 @@ GSLocalMemory::GSLocalMemory()
|
|||
m_psm[PSM_PSMZ24].trbpp = 24;
|
||||
m_psm[PSM_PSMZ16].trbpp = m_psm[PSM_PSMZ16S].trbpp = 16;
|
||||
|
||||
m_psm[PSM_PSMT8].pal = m_psm[PSM_PSMT8H].pal = 256;
|
||||
m_psm[PSM_PSMT4].pal = m_psm[PSM_PSMT4HL].pal = m_psm[PSM_PSMT4HH].pal = 16;
|
||||
|
||||
for(int i = 0; i < countof(m_psm); i++) m_psm[i].fmt = 3;
|
||||
m_psm[PSM_PSMCT32].fmt = m_psm[PSM_PSMZ32].fmt = 0;
|
||||
m_psm[PSM_PSMCT24].fmt = m_psm[PSM_PSMZ24].fmt = 1;
|
||||
m_psm[PSM_PSMCT16].fmt = m_psm[PSM_PSMZ16].fmt = 2;
|
||||
m_psm[PSM_PSMCT16S].fmt = m_psm[PSM_PSMZ16S].fmt = 2;
|
||||
|
||||
m_psm[PSM_PSMCT16].bs = m_psm[PSM_PSMCT16S].bs = GSVector2i(16, 8);
|
||||
m_psm[PSM_PSMT8].bs = GSVector2i(16, 16);
|
||||
m_psm[PSM_PSMT4].bs = GSVector2i(32, 16);
|
||||
|
@ -465,23 +444,22 @@ GSLocalMemory::~GSLocalMemory()
|
|||
{
|
||||
VirtualFree(m_vm8, 0, MEM_RELEASE);
|
||||
|
||||
for_each(m_bomap.begin(), m_bomap.end(), aligned_free_second());
|
||||
for_each(m_pomap.begin(), m_pomap.end(), aligned_free_second());
|
||||
for_each(m_omap.begin(), m_omap.end(), aligned_free_second());
|
||||
for_each(m_po4map.begin(), m_po4map.end(), aligned_free_second());
|
||||
}
|
||||
|
||||
GSLocalMemory::BlockOffset* GSLocalMemory::GetBlockOffset(uint32 bp, uint32 bw, uint32 psm)
|
||||
GSOffset* GSLocalMemory::GetOffset(uint32 bp, uint32 bw, uint32 psm)
|
||||
{
|
||||
uint32 hash = bp | (bw << 14) | (psm << 20);
|
||||
|
||||
hash_map<uint32, BlockOffset*>::iterator i = m_bomap.find(hash);
|
||||
hash_map<uint32, GSOffset*>::iterator i = m_omap.find(hash);
|
||||
|
||||
if(i != m_bomap.end())
|
||||
if(i != m_omap.end())
|
||||
{
|
||||
return i->second;
|
||||
}
|
||||
|
||||
BlockOffset* o = (BlockOffset*)_aligned_malloc(sizeof(BlockOffset), 16);
|
||||
GSOffset* o = (GSOffset*)_aligned_malloc(sizeof(GSOffset), 16);
|
||||
|
||||
o->hash = hash;
|
||||
|
||||
|
@ -489,49 +467,29 @@ GSLocalMemory::BlockOffset* GSLocalMemory::GetBlockOffset(uint32 bp, uint32 bw,
|
|||
|
||||
for(int i = 0; i < 256; i++)
|
||||
{
|
||||
o->row[i] = (int)bn(0, i << 3, bp, bw);
|
||||
o->block.row[i] = (short)bn(0, i << 3, bp, bw);
|
||||
}
|
||||
|
||||
o->col = m_psm[psm].blockOffset;
|
||||
|
||||
m_bomap[hash] = o;
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
GSLocalMemory::PixelOffset* GSLocalMemory::GetPixelOffset(uint32 bp, uint32 bw, uint32 psm)
|
||||
{
|
||||
uint32 hash = bp | (bw << 14) | (psm << 20);
|
||||
|
||||
hash_map<uint32, PixelOffset*>::iterator i = m_pomap.find(hash);
|
||||
|
||||
if(i != m_pomap.end())
|
||||
{
|
||||
return i->second;
|
||||
}
|
||||
|
||||
PixelOffset* o = (PixelOffset*)_aligned_malloc(sizeof(PixelOffset), 16);
|
||||
|
||||
o->hash = hash;
|
||||
o->block.col = m_psm[psm].blockOffset;
|
||||
|
||||
pixelAddress pa = m_psm[psm].pa;
|
||||
|
||||
for(int i = 0; i < 2048; i++)
|
||||
{
|
||||
o->row[i] = (int)pa(0, i, bp, bw);
|
||||
o->pixel.row[i] = (int)pa(0, i, bp, bw);
|
||||
}
|
||||
|
||||
for(int i = 0; i < 8; i++)
|
||||
{
|
||||
o->col[i] = m_psm[psm].rowOffset[i];
|
||||
o->pixel.col[i] = m_psm[psm].rowOffset[i];
|
||||
}
|
||||
|
||||
m_pomap[hash] = o;
|
||||
m_omap[hash] = o;
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
GSLocalMemory::PixelOffset4* GSLocalMemory::GetPixelOffset4(const GIFRegFRAME& FRAME, const GIFRegZBUF& ZBUF)
|
||||
GSPixelOffset4* GSLocalMemory::GetPixelOffset4(const GIFRegFRAME& FRAME, const GIFRegZBUF& ZBUF)
|
||||
{
|
||||
uint32 fbp = FRAME.Block();
|
||||
uint32 zbp = ZBUF.Block();
|
||||
|
@ -548,14 +506,14 @@ GSLocalMemory::PixelOffset4* GSLocalMemory::GetPixelOffset4(const GIFRegFRAME& F
|
|||
|
||||
uint32 hash = (FRAME.FBP << 0) | (ZBUF.ZBP << 9) | (bw << 18) | (fpsm_hash << 24) | (zpsm_hash << 28);
|
||||
|
||||
hash_map<uint32, PixelOffset4*>::iterator i = m_po4map.find(hash);
|
||||
hash_map<uint32, GSPixelOffset4*>::iterator i = m_po4map.find(hash);
|
||||
|
||||
if(i != m_po4map.end())
|
||||
{
|
||||
return i->second;
|
||||
}
|
||||
|
||||
PixelOffset4* o = (PixelOffset4*)_aligned_malloc(sizeof(PixelOffset4), 16);
|
||||
GSPixelOffset4* o = (GSPixelOffset4*)_aligned_malloc(sizeof(GSPixelOffset4), 16);
|
||||
|
||||
o->hash = hash;
|
||||
|
||||
|
@ -1449,20 +1407,20 @@ void GSLocalMemory::ReadImageX(int& tx, int& ty, uint8* dst, int len, GIFRegBITB
|
|||
|
||||
///////////////////
|
||||
|
||||
void GSLocalMemory::ReadTexture32(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
|
||||
void GSLocalMemory::ReadTexture32(const GSOffset* RESTRICT o, const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEXA& TEXA)
|
||||
{
|
||||
FOREACH_BLOCK_START(r, 8, 8, 32, PSM_PSMCT32)
|
||||
FOREACH_BLOCK_START(r, 8, 8, 32)
|
||||
{
|
||||
ReadBlock32<true>(src, dst, dstpitch);
|
||||
}
|
||||
FOREACH_BLOCK_END
|
||||
}
|
||||
|
||||
void GSLocalMemory::ReadTexture24(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
|
||||
void GSLocalMemory::ReadTexture24(const GSOffset* RESTRICT o, const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEXA& TEXA)
|
||||
{
|
||||
if(TEXA.AEM)
|
||||
{
|
||||
FOREACH_BLOCK_START(r, 8, 8, 32, PSM_PSMCT24)
|
||||
FOREACH_BLOCK_START(r, 8, 8, 32)
|
||||
{
|
||||
ReadAndExpandBlock24<true>(src, dst, dstpitch, TEXA);
|
||||
}
|
||||
|
@ -1470,7 +1428,7 @@ void GSLocalMemory::ReadTexture24(const GSVector4i& r, uint8* dst, int dstpitch,
|
|||
}
|
||||
else
|
||||
{
|
||||
FOREACH_BLOCK_START(r, 8, 8, 32, PSM_PSMCT24)
|
||||
FOREACH_BLOCK_START(r, 8, 8, 32)
|
||||
{
|
||||
ReadAndExpandBlock24<false>(src, dst, dstpitch, TEXA);
|
||||
}
|
||||
|
@ -1478,11 +1436,11 @@ void GSLocalMemory::ReadTexture24(const GSVector4i& r, uint8* dst, int dstpitch,
|
|||
}
|
||||
}
|
||||
|
||||
void GSLocalMemory::ReadTexture16(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
|
||||
void GSLocalMemory::ReadTexture16(const GSOffset* RESTRICT o, const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEXA& TEXA)
|
||||
{
|
||||
__declspec(align(16)) uint16 block[16 * 8];
|
||||
|
||||
FOREACH_BLOCK_START(r, 16, 8, 32, PSM_PSMCT16)
|
||||
FOREACH_BLOCK_START(r, 16, 8, 32)
|
||||
{
|
||||
ReadBlock16<true>(src, (uint8*)block, sizeof(block) / 8);
|
||||
|
||||
|
@ -1491,11 +1449,11 @@ void GSLocalMemory::ReadTexture16(const GSVector4i& r, uint8* dst, int dstpitch,
|
|||
FOREACH_BLOCK_END
|
||||
}
|
||||
|
||||
void GSLocalMemory::ReadTexture16S(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
|
||||
void GSLocalMemory::ReadTexture16S(const GSOffset* RESTRICT o, const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEXA& TEXA)
|
||||
{
|
||||
__declspec(align(16)) uint16 block[16 * 8];
|
||||
|
||||
FOREACH_BLOCK_START(r, 16, 8, 32, PSM_PSMCT16S)
|
||||
FOREACH_BLOCK_START(r, 16, 8, 32)
|
||||
{
|
||||
ReadBlock16<true>(src, (uint8*)block, sizeof(block) / 8);
|
||||
|
||||
|
@ -1504,75 +1462,75 @@ void GSLocalMemory::ReadTexture16S(const GSVector4i& r, uint8* dst, int dstpitch
|
|||
FOREACH_BLOCK_END
|
||||
}
|
||||
|
||||
void GSLocalMemory::ReadTexture8(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
|
||||
void GSLocalMemory::ReadTexture8(const GSOffset* RESTRICT o, const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEXA& TEXA)
|
||||
{
|
||||
const uint32* pal = m_clut;
|
||||
|
||||
FOREACH_BLOCK_START(r, 16, 16, 32, PSM_PSMT8)
|
||||
FOREACH_BLOCK_START(r, 16, 16, 32)
|
||||
{
|
||||
ReadAndExpandBlock8_32(src, dst, dstpitch, pal);
|
||||
}
|
||||
FOREACH_BLOCK_END
|
||||
}
|
||||
|
||||
void GSLocalMemory::ReadTexture4(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
|
||||
void GSLocalMemory::ReadTexture4(const GSOffset* RESTRICT o, const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEXA& TEXA)
|
||||
{
|
||||
const uint64* pal = m_clut;
|
||||
|
||||
FOREACH_BLOCK_START(r, 32, 16, 32, PSM_PSMT4)
|
||||
FOREACH_BLOCK_START(r, 32, 16, 32)
|
||||
{
|
||||
ReadAndExpandBlock4_32(src, dst, dstpitch, pal);
|
||||
}
|
||||
FOREACH_BLOCK_END
|
||||
}
|
||||
|
||||
void GSLocalMemory::ReadTexture8H(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
|
||||
void GSLocalMemory::ReadTexture8H(const GSOffset* RESTRICT o, const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEXA& TEXA)
|
||||
{
|
||||
const uint32* pal = m_clut;
|
||||
|
||||
FOREACH_BLOCK_START(r, 8, 8, 32, PSM_PSMT8H)
|
||||
FOREACH_BLOCK_START(r, 8, 8, 32)
|
||||
{
|
||||
ReadAndExpandBlock8H_32(src, dst, dstpitch, pal);
|
||||
}
|
||||
FOREACH_BLOCK_END
|
||||
}
|
||||
|
||||
void GSLocalMemory::ReadTexture4HL(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
|
||||
void GSLocalMemory::ReadTexture4HL(const GSOffset* RESTRICT o, const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEXA& TEXA)
|
||||
{
|
||||
const uint32* pal = m_clut;
|
||||
|
||||
FOREACH_BLOCK_START(r, 8, 8, 32, PSM_PSMT4HL)
|
||||
FOREACH_BLOCK_START(r, 8, 8, 32)
|
||||
{
|
||||
ReadAndExpandBlock4HL_32(src, dst, dstpitch, pal);
|
||||
}
|
||||
FOREACH_BLOCK_END
|
||||
}
|
||||
|
||||
void GSLocalMemory::ReadTexture4HH(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
|
||||
void GSLocalMemory::ReadTexture4HH(const GSOffset* RESTRICT o, const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEXA& TEXA)
|
||||
{
|
||||
const uint32* pal = m_clut;
|
||||
|
||||
FOREACH_BLOCK_START(r, 8, 8, 32, PSM_PSMT4HH)
|
||||
FOREACH_BLOCK_START(r, 8, 8, 32)
|
||||
{
|
||||
ReadAndExpandBlock4HH_32(src, dst, dstpitch, pal);
|
||||
}
|
||||
FOREACH_BLOCK_END
|
||||
}
|
||||
|
||||
void GSLocalMemory::ReadTexture32Z(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
|
||||
void GSLocalMemory::ReadTexture32Z(const GSOffset* RESTRICT o, const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEXA& TEXA)
|
||||
{
|
||||
FOREACH_BLOCK_START(r, 8, 8, 32, PSM_PSMZ32)
|
||||
FOREACH_BLOCK_START(r, 8, 8, 32)
|
||||
{
|
||||
ReadBlock32<true>(src, dst, dstpitch);
|
||||
}
|
||||
FOREACH_BLOCK_END
|
||||
}
|
||||
|
||||
void GSLocalMemory::ReadTexture24Z(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
|
||||
void GSLocalMemory::ReadTexture24Z(const GSOffset* RESTRICT o, const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEXA& TEXA)
|
||||
{
|
||||
if(TEXA.AEM)
|
||||
{
|
||||
FOREACH_BLOCK_START(r, 8, 8, 32, PSM_PSMZ24)
|
||||
FOREACH_BLOCK_START(r, 8, 8, 32)
|
||||
{
|
||||
ReadAndExpandBlock24<true>(src, dst, dstpitch, TEXA);
|
||||
}
|
||||
|
@ -1580,7 +1538,7 @@ void GSLocalMemory::ReadTexture24Z(const GSVector4i& r, uint8* dst, int dstpitch
|
|||
}
|
||||
else
|
||||
{
|
||||
FOREACH_BLOCK_START(r, 8, 8, 32, PSM_PSMZ24)
|
||||
FOREACH_BLOCK_START(r, 8, 8, 32)
|
||||
{
|
||||
ReadAndExpandBlock24<false>(src, dst, dstpitch, TEXA);
|
||||
}
|
||||
|
@ -1588,11 +1546,11 @@ void GSLocalMemory::ReadTexture24Z(const GSVector4i& r, uint8* dst, int dstpitch
|
|||
}
|
||||
}
|
||||
|
||||
void GSLocalMemory::ReadTexture16Z(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
|
||||
void GSLocalMemory::ReadTexture16Z(const GSOffset* RESTRICT o, const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEXA& TEXA)
|
||||
{
|
||||
__declspec(align(16)) uint16 block[16 * 8];
|
||||
|
||||
FOREACH_BLOCK_START(r, 16, 8, 32, PSM_PSMZ16)
|
||||
FOREACH_BLOCK_START(r, 16, 8, 32)
|
||||
{
|
||||
ReadBlock16<true>(src, (uint8*)block, sizeof(block) / 8);
|
||||
|
||||
|
@ -1601,11 +1559,11 @@ void GSLocalMemory::ReadTexture16Z(const GSVector4i& r, uint8* dst, int dstpitch
|
|||
FOREACH_BLOCK_END
|
||||
}
|
||||
|
||||
void GSLocalMemory::ReadTexture16SZ(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
|
||||
void GSLocalMemory::ReadTexture16SZ(const GSOffset* RESTRICT o, const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEXA& TEXA)
|
||||
{
|
||||
__declspec(align(16)) uint16 block[16 * 8];
|
||||
|
||||
FOREACH_BLOCK_START(r, 16, 8, 32, PSM_PSMZ16S)
|
||||
FOREACH_BLOCK_START(r, 16, 8, 32)
|
||||
{
|
||||
ReadBlock16<true>(src, (uint8*)block, sizeof(block) / 8);
|
||||
|
||||
|
@ -1731,286 +1689,125 @@ void GSLocalMemory::ReadTextureBlock16SZ(uint32 bp, uint8* dst, int dstpitch, co
|
|||
|
||||
///////////////////
|
||||
|
||||
void GSLocalMemory::ReadTexture(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
|
||||
void GSLocalMemory::ReadTexture(const GSOffset* RESTRICT o, const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEXA& TEXA)
|
||||
{
|
||||
readTexture rtx = m_psm[TEX0.PSM].rtx;
|
||||
readTexel rt = m_psm[TEX0.PSM].rt;
|
||||
GSVector2i bs = m_psm[TEX0.PSM].bs;
|
||||
const psm_t& psm = m_psm[o->psm];
|
||||
|
||||
if(r.width() < bs.x || r.height() < bs.y
|
||||
|| (r.left & (bs.x - 1)) || (r.top & (bs.y - 1))
|
||||
|| (r.right & (bs.x - 1)) || (r.bottom & (bs.y - 1)))
|
||||
{
|
||||
ReadTexture<uint32>(r, dst, dstpitch, TEX0, TEXA, rt, rtx);
|
||||
}
|
||||
else
|
||||
{
|
||||
(this->*rtx)(r, dst, dstpitch, TEX0, TEXA);
|
||||
}
|
||||
}
|
||||
///////////////////
|
||||
readTexel rt = psm.rt;
|
||||
readTexture rtx = psm.rtx;
|
||||
|
||||
void GSLocalMemory::ReadTexture16NP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
|
||||
{
|
||||
FOREACH_BLOCK_START(r, 16, 8, 16, PSM_PSMCT16)
|
||||
if(r.width() < psm.bs.x || r.height() < psm.bs.y
|
||||
|| (r.left & (psm.bs.x - 1)) || (r.top & (psm.bs.y - 1))
|
||||
|| (r.right & (psm.bs.x - 1)) || (r.bottom & (psm.bs.y - 1)))
|
||||
{
|
||||
ReadBlock16<true>(src, dst, dstpitch);
|
||||
}
|
||||
FOREACH_BLOCK_END
|
||||
}
|
||||
GIFRegTEX0 TEX0;
|
||||
|
||||
void GSLocalMemory::ReadTexture16SNP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
|
||||
{
|
||||
FOREACH_BLOCK_START(r, 16, 8, 16, PSM_PSMCT16S)
|
||||
{
|
||||
ReadBlock16<true>(src, dst, dstpitch);
|
||||
}
|
||||
FOREACH_BLOCK_END
|
||||
}
|
||||
TEX0.TBP0 = o->bp;
|
||||
TEX0.TBW = o->bw;
|
||||
TEX0.PSM = o->psm;
|
||||
|
||||
void GSLocalMemory::ReadTexture8NP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
|
||||
{
|
||||
const uint32* pal = m_clut;
|
||||
GSVector4i cr = r.ralign<GSVector4i::Inside>(psm.bs);
|
||||
|
||||
if(TEX0.CPSM == PSM_PSMCT32 || TEX0.CPSM == PSM_PSMCT24)
|
||||
{
|
||||
FOREACH_BLOCK_START(r, 16, 16, 32, PSM_PSMT8)
|
||||
bool aligned = ((DWORD_PTR)(dst + (cr.left - r.left) * sizeof(uint32)) & 0xf) == 0;
|
||||
|
||||
if(cr.rempty() || !aligned)
|
||||
{
|
||||
ReadAndExpandBlock8_32(src, dst, dstpitch, pal);
|
||||
// TODO: expand r to block size, read into temp buffer
|
||||
|
||||
if(!aligned) printf("unaligned memory pointer passed to ReadTexture\n");
|
||||
|
||||
for(int y = r.top; y < r.bottom; y++, dst += dstpitch)
|
||||
{
|
||||
for(int x = r.left, i = 0; x < r.right; x++, i++)
|
||||
{
|
||||
((uint32*)dst)[i] = (this->*rt)(x, y, TEX0, TEXA);
|
||||
}
|
||||
}
|
||||
}
|
||||
FOREACH_BLOCK_END
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT(TEX0.CPSM == PSM_PSMCT16 || TEX0.CPSM == PSM_PSMCT16S);
|
||||
|
||||
__declspec(align(16)) uint8 block[16 * 16];
|
||||
|
||||
FOREACH_BLOCK_START(r, 16, 16, 16, PSM_PSMT8)
|
||||
else
|
||||
{
|
||||
ReadBlock8<true>(src, (uint8*)block, sizeof(block) / 16);
|
||||
for(int y = r.top; y < cr.top; y++, dst += dstpitch)
|
||||
{
|
||||
for(int x = r.left, i = 0; x < r.right; x++, i++)
|
||||
{
|
||||
((uint32*)dst)[i] = (this->*rt)(x, y, TEX0, TEXA);
|
||||
}
|
||||
}
|
||||
|
||||
ExpandBlock8_16(block, dst, dstpitch, pal);
|
||||
}
|
||||
FOREACH_BLOCK_END
|
||||
}
|
||||
}
|
||||
for(int y = cr.bottom; y < r.bottom; y++, dst += dstpitch)
|
||||
{
|
||||
for(int x = r.left, i = 0; x < r.right; x++, i++)
|
||||
{
|
||||
((uint32*)dst)[i] = (this->*rt)(x, y, TEX0, TEXA);
|
||||
}
|
||||
}
|
||||
|
||||
void GSLocalMemory::ReadTexture4NP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
|
||||
{
|
||||
const uint64* pal = m_clut;
|
||||
for(int y = cr.top; y < cr.bottom; y++, dst += dstpitch)
|
||||
{
|
||||
for(int x = r.left, i = 0; x < cr.left; x++, i++)
|
||||
{
|
||||
((uint32*)dst)[i] = (this->*rt)(x, y, TEX0, TEXA);
|
||||
}
|
||||
|
||||
if(TEX0.CPSM == PSM_PSMCT32 || TEX0.CPSM == PSM_PSMCT24)
|
||||
{
|
||||
FOREACH_BLOCK_START(r, 32, 16, 32, PSM_PSMT4)
|
||||
{
|
||||
ReadAndExpandBlock4_32(src, dst, dstpitch, pal);
|
||||
}
|
||||
FOREACH_BLOCK_END
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT(TEX0.CPSM == PSM_PSMCT16 || TEX0.CPSM == PSM_PSMCT16S);
|
||||
for(int x = cr.right, i = x - r.left; x < r.right; x++, i++)
|
||||
{
|
||||
((uint32*)dst)[i] = (this->*rt)(x, y, TEX0, TEXA);
|
||||
}
|
||||
}
|
||||
|
||||
__declspec(align(16)) uint8 block[(32 / 2) * 16];
|
||||
|
||||
FOREACH_BLOCK_START(r, 32, 16, 16, PSM_PSMT4)
|
||||
{
|
||||
ReadBlock4<true>(src, (uint8*)block, sizeof(block) / 16);
|
||||
|
||||
ExpandBlock4_16(block, dst, dstpitch, pal);
|
||||
}
|
||||
FOREACH_BLOCK_END
|
||||
}
|
||||
}
|
||||
|
||||
void GSLocalMemory::ReadTexture8HNP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
|
||||
{
|
||||
const uint32* pal = m_clut;
|
||||
|
||||
if(TEX0.CPSM == PSM_PSMCT32 || TEX0.CPSM == PSM_PSMCT24)
|
||||
{
|
||||
FOREACH_BLOCK_START(r, 8, 8, 32, PSM_PSMT8H)
|
||||
{
|
||||
ReadAndExpandBlock8H_32(src, dst, dstpitch, pal);
|
||||
}
|
||||
FOREACH_BLOCK_END
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT(TEX0.CPSM == PSM_PSMCT16 || TEX0.CPSM == PSM_PSMCT16S);
|
||||
|
||||
__declspec(align(16)) uint32 block[8 * 8];
|
||||
|
||||
FOREACH_BLOCK_START(r, 8, 8, 16, PSM_PSMT8H)
|
||||
{
|
||||
ReadBlock32<true>(src, (uint8*)block, sizeof(block) / 8);
|
||||
|
||||
ExpandBlock8H_16(block, dst, dstpitch, pal);
|
||||
}
|
||||
FOREACH_BLOCK_END
|
||||
}
|
||||
}
|
||||
|
||||
void GSLocalMemory::ReadTexture4HLNP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
|
||||
{
|
||||
const uint32* pal = m_clut;
|
||||
|
||||
if(TEX0.CPSM == PSM_PSMCT32 || TEX0.CPSM == PSM_PSMCT24)
|
||||
{
|
||||
FOREACH_BLOCK_START(r, 8, 8, 32, PSM_PSMT4HL)
|
||||
{
|
||||
ReadAndExpandBlock4HL_32(src, dst, dstpitch, pal);
|
||||
}
|
||||
FOREACH_BLOCK_END
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT(TEX0.CPSM == PSM_PSMCT16 || TEX0.CPSM == PSM_PSMCT16S);
|
||||
|
||||
__declspec(align(16)) uint32 block[8 * 8];
|
||||
|
||||
FOREACH_BLOCK_START(r, 8, 8, 16, PSM_PSMT4HL)
|
||||
{
|
||||
ReadBlock32<true>(src, (uint8*)block, sizeof(block) / 8);
|
||||
|
||||
ExpandBlock4HL_16(block, dst, dstpitch, pal);
|
||||
}
|
||||
FOREACH_BLOCK_END
|
||||
}
|
||||
}
|
||||
|
||||
void GSLocalMemory::ReadTexture4HHNP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
|
||||
{
|
||||
const uint32* pal = m_clut;
|
||||
|
||||
if(TEX0.CPSM == PSM_PSMCT32 || TEX0.CPSM == PSM_PSMCT24)
|
||||
{
|
||||
FOREACH_BLOCK_START(r, 8, 8, 32, PSM_PSMT4HH)
|
||||
{
|
||||
ReadAndExpandBlock4HH_32(src, dst, dstpitch, pal);
|
||||
}
|
||||
FOREACH_BLOCK_END
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT(TEX0.CPSM == PSM_PSMCT16 || TEX0.CPSM == PSM_PSMCT16S);
|
||||
|
||||
__declspec(align(16)) uint32 block[8 * 8];
|
||||
|
||||
FOREACH_BLOCK_START(r, 8, 8, 16, PSM_PSMT4HH)
|
||||
{
|
||||
ReadBlock32<true>(src, (uint8*)block, sizeof(block) / 8);
|
||||
|
||||
ExpandBlock4HH_16(block, dst, dstpitch, pal);
|
||||
}
|
||||
FOREACH_BLOCK_END
|
||||
}
|
||||
}
|
||||
|
||||
void GSLocalMemory::ReadTexture16ZNP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
|
||||
{
|
||||
FOREACH_BLOCK_START(r, 16, 8, 16, PSM_PSMZ16)
|
||||
{
|
||||
ReadBlock16<true>(src, dst, dstpitch);
|
||||
}
|
||||
FOREACH_BLOCK_END
|
||||
}
|
||||
|
||||
void GSLocalMemory::ReadTexture16SZNP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
|
||||
{
|
||||
FOREACH_BLOCK_START(r, 16, 8, 16, PSM_PSMZ16S)
|
||||
{
|
||||
ReadBlock16<true>(src, dst, dstpitch);
|
||||
}
|
||||
FOREACH_BLOCK_END
|
||||
}
|
||||
|
||||
///////////////////
|
||||
|
||||
void GSLocalMemory::ReadTextureNP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
|
||||
{
|
||||
readTexture rtx = m_psm[TEX0.PSM].rtxNP;
|
||||
readTexel rt = m_psm[TEX0.PSM].rtNP;
|
||||
GSVector2i bs = m_psm[TEX0.PSM].bs;
|
||||
|
||||
if(r.width() < bs.x || r.height() < bs.y
|
||||
|| (r.left & (bs.x - 1)) || (r.top & (bs.y - 1))
|
||||
|| (r.right & (bs.x - 1)) || (r.bottom & (bs.y - 1)))
|
||||
{
|
||||
uint32 psm = TEX0.PSM;
|
||||
|
||||
switch(psm)
|
||||
{
|
||||
case PSM_PSMT8:
|
||||
case PSM_PSMT8H:
|
||||
case PSM_PSMT4:
|
||||
case PSM_PSMT4HL:
|
||||
case PSM_PSMT4HH:
|
||||
psm = TEX0.CPSM;
|
||||
break;
|
||||
}
|
||||
|
||||
switch(psm)
|
||||
{
|
||||
default:
|
||||
case PSM_PSMCT32:
|
||||
case PSM_PSMCT24:
|
||||
ReadTexture<uint32>(r, dst, dstpitch, TEX0, TEXA, rt, rtx);
|
||||
break;
|
||||
case PSM_PSMCT16:
|
||||
case PSM_PSMCT16S:
|
||||
ReadTexture<uint16>(r, dst, dstpitch, TEX0, TEXA, rt, rtx);
|
||||
break;
|
||||
if(!cr.rempty())
|
||||
{
|
||||
(this->*rtx)(o, cr, dst + (cr.left - r.left) * sizeof(32), dstpitch, TEXA);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
(this->*rtx)(r, dst, dstpitch, TEX0, TEXA);
|
||||
(this->*rtx)(o, r, dst, dstpitch, TEXA);
|
||||
}
|
||||
}
|
||||
|
||||
// 32/8
|
||||
|
||||
void GSLocalMemory::ReadTexture8P(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
|
||||
void GSLocalMemory::ReadTexture8P(const GSOffset* RESTRICT o, const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEXA& TEXA)
|
||||
{
|
||||
FOREACH_BLOCK_START(r, 16, 16, 8, PSM_PSMT8)
|
||||
FOREACH_BLOCK_START(r, 16, 16, 8)
|
||||
{
|
||||
ReadBlock8<true>(src, dst, dstpitch);
|
||||
}
|
||||
FOREACH_BLOCK_END
|
||||
}
|
||||
|
||||
void GSLocalMemory::ReadTexture4P(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
|
||||
void GSLocalMemory::ReadTexture4P(const GSOffset* RESTRICT o, const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEXA& TEXA)
|
||||
{
|
||||
FOREACH_BLOCK_START(r, 32, 16, 8, PSM_PSMT4)
|
||||
FOREACH_BLOCK_START(r, 32, 16, 8)
|
||||
{
|
||||
ReadBlock4P(src, dst, dstpitch);
|
||||
}
|
||||
FOREACH_BLOCK_END
|
||||
}
|
||||
|
||||
void GSLocalMemory::ReadTexture8HP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
|
||||
void GSLocalMemory::ReadTexture8HP(const GSOffset* RESTRICT o, const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEXA& TEXA)
|
||||
{
|
||||
FOREACH_BLOCK_START(r, 8, 8, 8, PSM_PSMT8H)
|
||||
FOREACH_BLOCK_START(r, 8, 8, 8)
|
||||
{
|
||||
ReadBlock8HP(src, dst, dstpitch);
|
||||
}
|
||||
FOREACH_BLOCK_END
|
||||
}
|
||||
|
||||
void GSLocalMemory::ReadTexture4HLP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
|
||||
void GSLocalMemory::ReadTexture4HLP(const GSOffset* RESTRICT o, const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEXA& TEXA)
|
||||
{
|
||||
FOREACH_BLOCK_START(r, 8, 8, 8, PSM_PSMT4HL)
|
||||
FOREACH_BLOCK_START(r, 8, 8, 8)
|
||||
{
|
||||
ReadBlock4HLP(src, dst, dstpitch);
|
||||
}
|
||||
FOREACH_BLOCK_END
|
||||
}
|
||||
|
||||
void GSLocalMemory::ReadTexture4HHP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
|
||||
void GSLocalMemory::ReadTexture4HHP(const GSOffset* RESTRICT o, const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEXA& TEXA)
|
||||
{
|
||||
FOREACH_BLOCK_START(r, 8, 8, 8, PSM_PSMT4HH)
|
||||
FOREACH_BLOCK_START(r, 8, 8, 8)
|
||||
{
|
||||
ReadBlock4HHP(src, dst, dstpitch);
|
||||
}
|
||||
|
@ -2054,47 +1851,6 @@ void GSLocalMemory::ReadTextureBlock4HHP(uint32 bp, uint8* dst, int dstpitch, co
|
|||
|
||||
//
|
||||
|
||||
template<typename T>
|
||||
void GSLocalMemory::ReadTexture(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, readTexel rt, readTexture rtx)
|
||||
{
|
||||
GSVector4i cr = r.ralign<GSVector4i::Inside>(m_psm[TEX0.PSM].bs);
|
||||
|
||||
bool aligned = ((DWORD_PTR)(dst + (cr.left - r.left) * sizeof(T)) & 0xf) == 0;
|
||||
|
||||
if(cr.rempty() || !aligned)
|
||||
{
|
||||
// TODO: expand r to block size, read into temp buffer, copy to r (like above)
|
||||
|
||||
if(!aligned)
|
||||
printf("unaligned memory pointer passed to ReadTexture\n");
|
||||
|
||||
for(int y = r.top; y < r.bottom; y++, dst += dstpitch)
|
||||
for(int x = r.left, i = 0; x < r.right; x++, i++)
|
||||
((T*)dst)[i] = (T)(this->*rt)(x, y, TEX0, TEXA);
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int y = r.top; y < cr.top; y++, dst += dstpitch)
|
||||
for(int x = r.left, i = 0; x < r.right; x++, i++)
|
||||
((T*)dst)[i] = (T)(this->*rt)(x, y, TEX0, TEXA);
|
||||
|
||||
if(!cr.rempty())
|
||||
(this->*rtx)(cr, dst + (cr.left - r.left) * sizeof(T), dstpitch, TEX0, TEXA);
|
||||
|
||||
for(int y = cr.top; y < cr.bottom; y++, dst += dstpitch)
|
||||
{
|
||||
for(int x = r.left, i = 0; x < cr.left; x++, i++)
|
||||
((T*)dst)[i] = (T)(this->*rt)(x, y, TEX0, TEXA);
|
||||
for(int x = cr.right, i = x - r.left; x < r.right; x++, i++)
|
||||
((T*)dst)[i] = (T)(this->*rt)(x, y, TEX0, TEXA);
|
||||
}
|
||||
|
||||
for(int y = cr.bottom; y < r.bottom; y++, dst += dstpitch)
|
||||
for(int x = r.left, i = 0; x < r.right; x++, i++)
|
||||
((T*)dst)[i] = (T)(this->*rt)(x, y, TEX0, TEXA);
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT GSLocalMemory::SaveBMP(const string& fn, uint32 bp, uint32 bw, uint32 psm, int w, int h)
|
||||
{
|
||||
int pitch = w * 4;
|
||||
|
|
|
@ -29,6 +29,32 @@
|
|||
#include "GSBlock.h"
|
||||
#include "GSClut.h"
|
||||
|
||||
struct GSOffset
|
||||
{
|
||||
struct
|
||||
{
|
||||
short row[256]; // yn (n = 0 8 16 ...)
|
||||
short* col; // blockOffset*
|
||||
} block;
|
||||
|
||||
struct
|
||||
{
|
||||
int row[2048]; // yn (n = 0 1 2 ...)
|
||||
int* col[8]; // rowOffset*
|
||||
} pixel;
|
||||
|
||||
union {uint32 hash; struct {uint32 bp:14, bw:6, psm:6;};};
|
||||
};
|
||||
|
||||
struct GSPixelOffset4
|
||||
{
|
||||
// 16 bit offsets (m_vm16[...])
|
||||
|
||||
GSVector2i row[2048]; // f yn | z yn (n = 0 1 2 ...)
|
||||
GSVector2i col[512]; // f xn | z xn (n = 0 4 8 ...)
|
||||
uint32 hash;
|
||||
};
|
||||
|
||||
class GSLocalMemory : public GSBlock
|
||||
{
|
||||
public:
|
||||
|
@ -43,7 +69,7 @@ public:
|
|||
typedef uint32 (GSLocalMemory::*readTexelAddr)(uint32 addr, const GIFRegTEXA& TEXA) const;
|
||||
typedef void (GSLocalMemory::*writeImage)(int& tx, int& ty, uint8* src, int len, GIFRegBITBLTBUF& BITBLTBUF, GIFRegTRXPOS& TRXPOS, GIFRegTRXREG& TRXREG);
|
||||
typedef void (GSLocalMemory::*readImage)(int& tx, int& ty, uint8* dst, int len, GIFRegBITBLTBUF& BITBLTBUF, GIFRegTRXPOS& TRXPOS, GIFRegTRXREG& TRXREG) const;
|
||||
typedef void (GSLocalMemory::*readTexture)(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA);
|
||||
typedef void (GSLocalMemory::*readTexture)(const GSOffset* RESTRICT o, const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEXA& TEXA);
|
||||
typedef void (GSLocalMemory::*readTextureBlock)(uint32 bp, uint8* dst, int dstpitch, const GIFRegTEXA& TEXA) const;
|
||||
|
||||
typedef union
|
||||
|
@ -55,18 +81,17 @@ public:
|
|||
readPixelAddr rpa;
|
||||
writePixel wp;
|
||||
writePixelAddr wpa;
|
||||
readTexel rt, rtNP;
|
||||
readTexel rt;
|
||||
readTexelAddr rta;
|
||||
writeFrameAddr wfa;
|
||||
writeImage wi;
|
||||
readImage ri;
|
||||
readTexture rtx, rtxNP, rtxP;
|
||||
readTexture rtx, rtxP;
|
||||
readTextureBlock rtxb, rtxbP;
|
||||
short bpp, trbpp;
|
||||
int pal;
|
||||
uint16 bpp, trbpp, pal, fmt;
|
||||
GSVector2i bs, pgs;
|
||||
int* rowOffset[8];
|
||||
int* blockOffset;
|
||||
short* blockOffset;
|
||||
};
|
||||
|
||||
uint8 dummy[128];
|
||||
|
@ -81,29 +106,6 @@ public:
|
|||
|
||||
GSClut m_clut;
|
||||
|
||||
struct BlockOffset
|
||||
{
|
||||
int row[256]; // yn (n = 0 8 16 ...)
|
||||
int* col; // blockOffset*
|
||||
uint32 hash;
|
||||
};
|
||||
|
||||
struct PixelOffset
|
||||
{
|
||||
int row[2048]; // yn (n = 0 1 2 ...)
|
||||
int* col[8]; // rowOffset*
|
||||
uint32 hash;
|
||||
};
|
||||
|
||||
struct PixelOffset4
|
||||
{
|
||||
// 16 bit offsets (m_vm16[...])
|
||||
|
||||
GSVector2i row[2048]; // f yn | z yn (n = 0 1 2 ...)
|
||||
GSVector2i col[512]; // f xn | z xn (n = 0 4 8 ...)
|
||||
uint32 hash;
|
||||
};
|
||||
|
||||
protected:
|
||||
static uint32 pageOffset32[32][32][64];
|
||||
static uint32 pageOffset32Z[32][32][64];
|
||||
|
@ -123,14 +125,14 @@ protected:
|
|||
static int rowOffset8[2][2048];
|
||||
static int rowOffset4[2][2048];
|
||||
|
||||
static int blockOffset32[256];
|
||||
static int blockOffset32Z[256];
|
||||
static int blockOffset16[256];
|
||||
static int blockOffset16S[256];
|
||||
static int blockOffset16Z[256];
|
||||
static int blockOffset16SZ[256];
|
||||
static int blockOffset8[256];
|
||||
static int blockOffset4[256];
|
||||
static short blockOffset32[256];
|
||||
static short blockOffset32Z[256];
|
||||
static short blockOffset16[256];
|
||||
static short blockOffset16S[256];
|
||||
static short blockOffset16Z[256];
|
||||
static short blockOffset16SZ[256];
|
||||
static short blockOffset8[256];
|
||||
static short blockOffset4[256];
|
||||
|
||||
__forceinline static uint32 Expand24To32(uint32 c, const GIFRegTEXA& TEXA)
|
||||
{
|
||||
|
@ -148,17 +150,15 @@ protected:
|
|||
|
||||
//
|
||||
|
||||
hash_map<uint32, BlockOffset*> m_bomap;
|
||||
hash_map<uint32, PixelOffset*> m_pomap;
|
||||
hash_map<uint32, PixelOffset4*> m_po4map;
|
||||
hash_map<uint32, GSOffset*> m_omap;
|
||||
hash_map<uint32, GSPixelOffset4*> m_po4map;
|
||||
|
||||
public:
|
||||
GSLocalMemory();
|
||||
virtual ~GSLocalMemory();
|
||||
|
||||
BlockOffset* GetBlockOffset(uint32 bp, uint32 bw, uint32 psm);
|
||||
PixelOffset* GetPixelOffset(uint32 bp, uint32 bw, uint32 psm);
|
||||
PixelOffset4* GetPixelOffset4(const GIFRegFRAME& FRAME, const GIFRegZBUF& ZBUF);
|
||||
GSOffset* GetOffset(uint32 bp, uint32 bw, uint32 psm);
|
||||
GSPixelOffset4* GetPixelOffset4(const GIFRegFRAME& FRAME, const GIFRegZBUF& ZBUF);
|
||||
|
||||
// address
|
||||
|
||||
|
@ -635,73 +635,73 @@ public:
|
|||
WriteFrame16(PixelAddress16SZ(x, y, bp, bw), c);
|
||||
}
|
||||
|
||||
__forceinline void WritePixel32(uint8* RESTRICT src, uint32 pitch, PixelOffset* po, const GSVector4i& r)
|
||||
__forceinline void WritePixel32(uint8* RESTRICT src, uint32 pitch, GSOffset* o, const GSVector4i& r)
|
||||
{
|
||||
src -= r.left * sizeof(uint32);
|
||||
|
||||
for(int y = r.top; y < r.bottom; y++, src += pitch)
|
||||
{
|
||||
uint32* RESTRICT s = (uint32*)src;
|
||||
uint32* RESTRICT d = &m_vm32[po->row[y]];
|
||||
int* RESTRICT o = po->col[0];
|
||||
uint32* RESTRICT d = &m_vm32[o->pixel.row[y]];
|
||||
int* RESTRICT col = o->pixel.col[0];
|
||||
|
||||
for(int x = r.left; x < r.right; x++)
|
||||
{
|
||||
d[o[x]] = s[x];
|
||||
d[col[x]] = s[x];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__forceinline void WritePixel24(uint8* RESTRICT src, uint32 pitch, PixelOffset* po, const GSVector4i& r)
|
||||
__forceinline void WritePixel24(uint8* RESTRICT src, uint32 pitch, GSOffset* o, const GSVector4i& r)
|
||||
{
|
||||
src -= r.left * sizeof(uint32);
|
||||
|
||||
for(int y = r.top; y < r.bottom; y++, src += pitch)
|
||||
{
|
||||
uint32* RESTRICT s = (uint32*)src;
|
||||
uint32* RESTRICT d = &m_vm32[po->row[y]];
|
||||
int* RESTRICT o = po->col[0];
|
||||
uint32* RESTRICT d = &m_vm32[o->pixel.row[y]];
|
||||
int* RESTRICT col = o->pixel.col[0];
|
||||
|
||||
for(int x = r.left; x < r.right; x++)
|
||||
{
|
||||
d[o[x]] = (d[o[x]] & 0xff000000) | (s[x] & 0x00ffffff);
|
||||
d[col[x]] = (d[col[x]] & 0xff000000) | (s[x] & 0x00ffffff);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__forceinline void WritePixel16(uint8* RESTRICT src, uint32 pitch, PixelOffset* po, const GSVector4i& r)
|
||||
__forceinline void WritePixel16(uint8* RESTRICT src, uint32 pitch, GSOffset* o, const GSVector4i& r)
|
||||
{
|
||||
src -= r.left * sizeof(uint16);
|
||||
|
||||
for(int y = r.top; y < r.bottom; y++, src += pitch)
|
||||
{
|
||||
uint16* RESTRICT s = (uint16*)src;
|
||||
uint16* RESTRICT d = &m_vm16[po->row[y]];
|
||||
int* RESTRICT o = po->col[0];
|
||||
uint16* RESTRICT d = &m_vm16[o->pixel.row[y]];
|
||||
int* RESTRICT col = o->pixel.col[0];
|
||||
|
||||
for(int x = r.left; x < r.right; x++)
|
||||
{
|
||||
d[o[x]] = s[x];
|
||||
d[col[x]] = s[x];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__forceinline void WriteFrame16(uint8* RESTRICT src, uint32 pitch, PixelOffset* po, const GSVector4i& r)
|
||||
__forceinline void WriteFrame16(uint8* RESTRICT src, uint32 pitch, GSOffset* o, const GSVector4i& r)
|
||||
{
|
||||
src -= r.left * sizeof(uint32);
|
||||
|
||||
for(int y = r.top; y < r.bottom; y++, src += pitch)
|
||||
{
|
||||
uint32* RESTRICT s = (uint32*)src;
|
||||
uint16* RESTRICT d = &m_vm16[po->row[y]];
|
||||
int* RESTRICT o = po->col[0];
|
||||
uint16* RESTRICT d = &m_vm16[o->pixel.row[y]];
|
||||
int* RESTRICT col = o->pixel.col[0];
|
||||
|
||||
for(int x = r.left; x < r.right; x++)
|
||||
{
|
||||
uint32 rb = s[x] & 0x00f800f8;
|
||||
uint32 ga = s[x] & 0x8000f800;
|
||||
|
||||
d[o[x]] = (ga >> 16) | (rb >> 9) | (ga >> 6) | (rb >> 3);
|
||||
d[col[x]] = (uint16)((ga >> 16) | (rb >> 9) | (ga >> 6) | (rb >> 3));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -811,26 +811,6 @@ public:
|
|||
return ReadTexel16(PixelAddress16SZ(x, y, TEX0.TBP0, TEX0.TBW), TEXA);
|
||||
}
|
||||
|
||||
__forceinline uint32 ReadTexel16NP(int x, int y, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const
|
||||
{
|
||||
return ReadPixel16(x, y, TEX0.TBP0, TEX0.TBW);
|
||||
}
|
||||
|
||||
__forceinline uint32 ReadTexel16SNP(int x, int y, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const
|
||||
{
|
||||
return ReadPixel16S(x, y, TEX0.TBP0, TEX0.TBW);
|
||||
}
|
||||
|
||||
__forceinline uint32 ReadTexel16ZNP(int x, int y, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const
|
||||
{
|
||||
return ReadPixel16Z(x, y, TEX0.TBP0, TEX0.TBW);
|
||||
}
|
||||
|
||||
__forceinline uint32 ReadTexel16SZNP(int x, int y, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const
|
||||
{
|
||||
return ReadPixel16SZ(x, y, TEX0.TBP0, TEX0.TBW);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
template<int psm, int bsx, int bsy, bool aligned>
|
||||
|
@ -861,21 +841,21 @@ public:
|
|||
|
||||
// * => 32
|
||||
|
||||
void ReadTexture32(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA);
|
||||
void ReadTexture24(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA);
|
||||
void ReadTexture16(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA);
|
||||
void ReadTexture16S(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA);
|
||||
void ReadTexture8(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA);
|
||||
void ReadTexture4(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA);
|
||||
void ReadTexture8H(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA);
|
||||
void ReadTexture4HL(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA);
|
||||
void ReadTexture4HH(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA);
|
||||
void ReadTexture32Z(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA);
|
||||
void ReadTexture24Z(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA);
|
||||
void ReadTexture16Z(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA);
|
||||
void ReadTexture16SZ(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA);
|
||||
void ReadTexture32(const GSOffset* RESTRICT o, const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEXA& TEXA);
|
||||
void ReadTexture24(const GSOffset* RESTRICT o, const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEXA& TEXA);
|
||||
void ReadTexture16(const GSOffset* RESTRICT o, const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEXA& TEXA);
|
||||
void ReadTexture16S(const GSOffset* RESTRICT o, const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEXA& TEXA);
|
||||
void ReadTexture8(const GSOffset* RESTRICT o, const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEXA& TEXA);
|
||||
void ReadTexture4(const GSOffset* RESTRICT o, const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEXA& TEXA);
|
||||
void ReadTexture8H(const GSOffset* RESTRICT o, const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEXA& TEXA);
|
||||
void ReadTexture4HL(const GSOffset* RESTRICT o, const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEXA& TEXA);
|
||||
void ReadTexture4HH(const GSOffset* RESTRICT o, const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEXA& TEXA);
|
||||
void ReadTexture32Z(const GSOffset* RESTRICT o, const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEXA& TEXA);
|
||||
void ReadTexture24Z(const GSOffset* RESTRICT o, const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEXA& TEXA);
|
||||
void ReadTexture16Z(const GSOffset* RESTRICT o, const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEXA& TEXA);
|
||||
void ReadTexture16SZ(const GSOffset* RESTRICT o, const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEXA& TEXA);
|
||||
|
||||
void ReadTexture(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA);
|
||||
void ReadTexture(const GSOffset* RESTRICT o, const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEXA& TEXA);
|
||||
|
||||
void ReadTextureBlock32(uint32 bp, uint8* dst, int dstpitch, const GIFRegTEXA& TEXA) const;
|
||||
void ReadTextureBlock24(uint32 bp, uint8* dst, int dstpitch, const GIFRegTEXA& TEXA) const;
|
||||
|
@ -891,27 +871,13 @@ public:
|
|||
void ReadTextureBlock16Z(uint32 bp, uint8* dst, int dstpitch, const GIFRegTEXA& TEXA) const;
|
||||
void ReadTextureBlock16SZ(uint32 bp, uint8* dst, int dstpitch, const GIFRegTEXA& TEXA) const;
|
||||
|
||||
// * => 32/16
|
||||
|
||||
void ReadTexture16NP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA);
|
||||
void ReadTexture16SNP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA);
|
||||
void ReadTexture8NP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA);
|
||||
void ReadTexture4NP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA);
|
||||
void ReadTexture8HNP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA);
|
||||
void ReadTexture4HLNP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA);
|
||||
void ReadTexture4HHNP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA);
|
||||
void ReadTexture16ZNP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA);
|
||||
void ReadTexture16SZNP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA);
|
||||
|
||||
void ReadTextureNP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA);
|
||||
|
||||
// pal ? 8 : 32
|
||||
|
||||
void ReadTexture8P(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA);
|
||||
void ReadTexture4P(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA);
|
||||
void ReadTexture8HP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA);
|
||||
void ReadTexture4HLP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA);
|
||||
void ReadTexture4HHP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA);
|
||||
void ReadTexture8P(const GSOffset* RESTRICT o, const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEXA& TEXA);
|
||||
void ReadTexture4P(const GSOffset* RESTRICT o, const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEXA& TEXA);
|
||||
void ReadTexture8HP(const GSOffset* RESTRICT o, const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEXA& TEXA);
|
||||
void ReadTexture4HLP(const GSOffset* RESTRICT o, const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEXA& TEXA);
|
||||
void ReadTexture4HHP(const GSOffset* RESTRICT o, const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEXA& TEXA);
|
||||
|
||||
void ReadTextureBlock8P(uint32 bp, uint8* dst, int dstpitch, const GIFRegTEXA& TEXA) const;
|
||||
void ReadTextureBlock4P(uint32 bp, uint8* dst, int dstpitch, const GIFRegTEXA& TEXA) const;
|
||||
|
@ -921,7 +887,7 @@ public:
|
|||
|
||||
//
|
||||
|
||||
template<typename T> void ReadTexture(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, readTexel rt, readTexture rtx);
|
||||
template<typename T> void ReadTexture(const GSOffset* RESTRICT o, const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEXA& TEXA);
|
||||
|
||||
//
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ GSRenderer::GSRenderer(uint8* base, bool mt, void (*irq)(), GSDevice* dev)
|
|||
: GSState(base, mt, irq)
|
||||
, m_dev(dev)
|
||||
, m_shader(0)
|
||||
, m_vt(this)
|
||||
{
|
||||
m_interlace = theApp.GetConfig("interlace", 0);
|
||||
m_aspectratio = theApp.GetConfig("aspectratio", 1);
|
||||
|
@ -54,9 +55,9 @@ GSRenderer::~GSRenderer()
|
|||
delete m_dev;
|
||||
}
|
||||
|
||||
bool GSRenderer::Create(const string& title)
|
||||
bool GSRenderer::Create(const string& title, int w, int h)
|
||||
{
|
||||
if(!m_wnd.Create(title.c_str()))
|
||||
if(!m_wnd.Create(title.c_str(), w, h))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -325,7 +326,7 @@ void GSRenderer::VSync(int field)
|
|||
|
||||
// present
|
||||
|
||||
m_dev->Present(m_wnd.GetClientRect().fit(m_aspectratio), m_shader);
|
||||
m_dev->Present(m_wnd.GetClientRect().fit(m_aspectratio), m_shader, m_framelimit);
|
||||
|
||||
// snapshot
|
||||
|
||||
|
@ -554,9 +555,7 @@ void GSRenderer::GetTextureMinMax(GSVector4i& r, bool linear)
|
|||
}
|
||||
}
|
||||
|
||||
GSVector2i bs = GSLocalMemory::m_psm[context->TEX0.PSM].bs;
|
||||
|
||||
r = vr.ralign<GSVector4i::Outside>(bs).rintersect(tr);
|
||||
r = vr.rintersect(tr);
|
||||
}
|
||||
|
||||
void GSRenderer::GetAlphaMinMax()
|
||||
|
@ -573,28 +572,25 @@ void GSRenderer::GetAlphaMinMax()
|
|||
|
||||
if(PRIM->TME && context->TEX0.TCC)
|
||||
{
|
||||
uint32 bpp = GSLocalMemory::m_psm[context->TEX0.PSM].trbpp;
|
||||
uint32 cbpp = GSLocalMemory::m_psm[context->TEX0.CPSM].trbpp;
|
||||
uint32 pal = GSLocalMemory::m_psm[context->TEX0.PSM].pal;
|
||||
|
||||
if(bpp == 32)
|
||||
switch(GSLocalMemory::m_psm[context->TEX0.PSM].fmt)
|
||||
{
|
||||
case 0:
|
||||
a.y = 0;
|
||||
a.w = 0xff;
|
||||
}
|
||||
else if(bpp == 24)
|
||||
{
|
||||
break;
|
||||
case 1:
|
||||
a.y = env.TEXA.AEM ? 0 : env.TEXA.TA0;
|
||||
a.w = env.TEXA.TA0;
|
||||
}
|
||||
else if(bpp == 16)
|
||||
{
|
||||
break;
|
||||
case 2:
|
||||
a.y = env.TEXA.AEM ? 0 : min(env.TEXA.TA0, env.TEXA.TA1);
|
||||
a.w = max(env.TEXA.TA0, env.TEXA.TA1);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
case 3:
|
||||
m_mem.m_clut.GetAlphaMinMax32(a.y, a.w);
|
||||
break;
|
||||
default:
|
||||
__assume(0);
|
||||
}
|
||||
|
||||
switch(context->TEX0.TFX)
|
||||
|
@ -708,17 +704,29 @@ bool GSRenderer::TryAlphaTest(uint32& fm, uint32& zm)
|
|||
|
||||
bool GSRenderer::IsLinear()
|
||||
{
|
||||
float qmin = m_vt.m_min.t.z;
|
||||
float qmax = m_vt.m_max.t.z;
|
||||
const GIFRegTEX1& TEX1 = m_context->TEX1;
|
||||
|
||||
if(PRIM->FST)
|
||||
bool mmin = TEX1.IsMinLinear();
|
||||
bool mmag = TEX1.IsMagLinear();
|
||||
|
||||
if(mmag == mmin) return mmag;
|
||||
|
||||
if(!TEX1.LCM && !PRIM->FST) // if FST => assume Q = 1.0f (should not, but Q is very often bogus, 0 or DEN)
|
||||
{
|
||||
// assume Q = 1.0f => LOD > 0 (should not, but Q is very often bogus, 0 or DEN)
|
||||
float K = (float)TEX1.K / 16;
|
||||
float f = (float)(1 << TEX1.L) / log(2.0f);
|
||||
|
||||
qmin = qmax = 1.0f;
|
||||
// TODO: abs(Qmin) may not be <= abs(Qmax), check the sign
|
||||
|
||||
float LODmin = K + log(1.0f / abs(m_vt.m_max.t.z)) * f;
|
||||
float LODmax = K + log(1.0f / abs(m_vt.m_min.t.z)) * f;
|
||||
|
||||
return LODmax <= 0 ? mmag : LODmin > 0 ? mmin : mmag || mmin;
|
||||
}
|
||||
else
|
||||
{
|
||||
return TEX1.K <= 0 ? mmag : TEX1.K > 0 ? mmin : mmag || mmin;
|
||||
}
|
||||
|
||||
return m_context->TEX1.IsLinear(qmin, qmax);
|
||||
}
|
||||
|
||||
bool GSRenderer::IsOpaque()
|
||||
|
|
|
@ -73,7 +73,7 @@ public:
|
|||
GSRenderer(uint8* base, bool mt, void (*irq)(), GSDevice* dev);
|
||||
virtual ~GSRenderer();
|
||||
|
||||
virtual bool Create(const string& title);
|
||||
virtual bool Create(const string& title, int w, int h);
|
||||
virtual void VSync(int field);
|
||||
virtual bool MakeSnapshot(const string& path);
|
||||
virtual void KeyEvent(GSKeyEventData* e);
|
||||
|
@ -107,37 +107,23 @@ protected:
|
|||
|
||||
void FlushPrim()
|
||||
{
|
||||
if(m_count > 0)
|
||||
if(m_count == 0) return;
|
||||
|
||||
if(GSLocalMemory::m_psm[m_context->FRAME.PSM].fmt < 3 && GSLocalMemory::m_psm[m_context->ZBUF.PSM].fmt < 3)
|
||||
{
|
||||
/*
|
||||
TRACE(_T("[%d] Draw f %05x (%d) z %05x (%d %d %d %d) t %05x %05x (%d)\n"),
|
||||
(int)m_perfmon.GetFrame(),
|
||||
(int)m_context->FRAME.Block(),
|
||||
(int)m_context->FRAME.PSM,
|
||||
(int)m_context->ZBUF.Block(),
|
||||
(int)m_context->ZBUF.PSM,
|
||||
m_context->TEST.ZTE,
|
||||
m_context->TEST.ZTST,
|
||||
m_context->ZBUF.ZMSK,
|
||||
PRIM->TME ? (int)m_context->TEX0.TBP0 : 0xfffff,
|
||||
PRIM->TME && m_context->TEX0.PSM > PSM_PSMCT16S ? (int)m_context->TEX0.CBP : 0xfffff,
|
||||
PRIM->TME ? (int)m_context->TEX0.PSM : 0xff);
|
||||
*/
|
||||
// FIXME: berserk fpsm = 27 (8H)
|
||||
|
||||
if(GSUtil::EncodePSM(m_context->FRAME.PSM) != 3 && GSUtil::EncodePSM(m_context->ZBUF.PSM) != 3)
|
||||
if(!m_dev->IsLost())
|
||||
{
|
||||
// FIXME: berserk fpsm = 27 (8H)
|
||||
m_vt.Update(m_vertices, m_count, GSUtil::GetPrimClass(PRIM->PRIM));
|
||||
|
||||
if(!m_dev->IsLost())
|
||||
{
|
||||
Draw();
|
||||
}
|
||||
|
||||
m_perfmon.Put(GSPerfMon::Draw, 1);
|
||||
Draw();
|
||||
}
|
||||
|
||||
m_count = 0;
|
||||
m_perfmon.Put(GSPerfMon::Draw, 1);
|
||||
}
|
||||
|
||||
m_count = 0;
|
||||
}
|
||||
|
||||
void GrowVertexBuffer()
|
||||
|
|
|
@ -28,22 +28,22 @@ template<class Vertex>
|
|||
class GSRendererDX : public GSRendererHW<Vertex>
|
||||
{
|
||||
GSTextureFX* m_tfx;
|
||||
GSVector2 m_pixelcenter;
|
||||
bool m_logz;
|
||||
bool m_fba;
|
||||
|
||||
protected:
|
||||
int m_topology;
|
||||
GSVector2 m_pixelcenter;
|
||||
|
||||
virtual void SetupDATE(GSTexture* rt, GSTexture* ds) {}
|
||||
virtual void UpdateFBA(GSTexture* rt) {}
|
||||
|
||||
public:
|
||||
GSRendererDX(uint8* base, bool mt, void (*irq)(), GSDevice* dev, GSTextureCache* tc, GSTextureFX* tfx)
|
||||
GSRendererDX(uint8* base, bool mt, void (*irq)(), GSDevice* dev, GSTextureCache* tc, GSTextureFX* tfx, const GSVector2& pixelcenter = GSVector2(0, 0))
|
||||
: GSRendererHW<Vertex>(base, mt, irq, dev, tc)
|
||||
, m_tfx(tfx)
|
||||
, m_pixelcenter(pixelcenter)
|
||||
, m_topology(-1)
|
||||
, m_pixelcenter(0, 0)
|
||||
{
|
||||
m_logz = !!theApp.GetConfig("logz", 0);
|
||||
m_fba = !!theApp.GetConfig("fba", 1);
|
||||
|
@ -54,9 +54,9 @@ public:
|
|||
delete m_tfx;
|
||||
}
|
||||
|
||||
bool Create(const string& title)
|
||||
bool Create(const string& title, int w, int h)
|
||||
{
|
||||
if(!__super::Create(title))
|
||||
if(!__super::Create(title, w, h))
|
||||
return false;
|
||||
|
||||
if(!m_tfx->Create(m_dev))
|
||||
|
@ -65,7 +65,7 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
void Draw(GS_PRIM_CLASS primclass, GSTexture* rt, GSTexture* ds, GSTextureCache::Source* tex)
|
||||
void Draw(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* tex)
|
||||
{
|
||||
GSDrawingEnvironment& env = m_env;
|
||||
GSDrawingContext* context = m_context;
|
||||
|
@ -82,9 +82,21 @@ public:
|
|||
|
||||
GSTextureFX::OMDepthStencilSelector om_dssel;
|
||||
|
||||
if(context->TEST.ZTE)
|
||||
{
|
||||
om_dssel.ztst = context->TEST.ZTST;
|
||||
om_dssel.zwe = !context->ZBUF.ZMSK;
|
||||
}
|
||||
else
|
||||
{
|
||||
om_dssel.ztst = ZTST_ALWAYS;
|
||||
om_dssel.zwe = 0;
|
||||
}
|
||||
/*
|
||||
om_dssel.zte = context->TEST.ZTE;
|
||||
om_dssel.ztst = context->TEST.ZTST;
|
||||
om_dssel.zwe = !context->ZBUF.ZMSK;
|
||||
*/
|
||||
om_dssel.date = context->FRAME.PSM != PSM_PSMCT24 ? context->TEST.DATE : 0;
|
||||
om_dssel.fba = m_fba ? context->FBA.FBA : 0;
|
||||
|
||||
|
@ -115,22 +127,17 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
om_bsel.wr = (context->FRAME.FBMSK & 0x000000ff) != 0x000000ff;
|
||||
om_bsel.wg = (context->FRAME.FBMSK & 0x0000ff00) != 0x0000ff00;
|
||||
om_bsel.wb = (context->FRAME.FBMSK & 0x00ff0000) != 0x00ff0000;
|
||||
om_bsel.wa = (context->FRAME.FBMSK & 0xff000000) != 0xff000000;
|
||||
om_bsel.wrgba = ~GSVector4i::load((int)context->FRAME.FBMSK).eq8(GSVector4i::xffffffff()).mask();
|
||||
|
||||
// vs
|
||||
|
||||
GSTextureFX::VSSelector vs_sel;
|
||||
|
||||
vs_sel.bppz = 0;
|
||||
vs_sel.tme = PRIM->TME;
|
||||
vs_sel.fst = PRIM->FST;
|
||||
vs_sel.logz = m_logz ? 1 : 0;
|
||||
vs_sel.prim = primclass;
|
||||
|
||||
if(om_dssel.zte && om_dssel.ztst > 0 && om_dssel.zwe)
|
||||
if(om_dssel.ztst >= ZTST_ALWAYS && om_dssel.zwe)
|
||||
{
|
||||
if(context->ZBUF.PSM == PSM_PSMZ24)
|
||||
{
|
||||
|
@ -139,7 +146,7 @@ public:
|
|||
ASSERT(m_vt.m_min.p.z > 0xffffff);
|
||||
|
||||
vs_sel.bppz = 1;
|
||||
om_dssel.ztst = 1;
|
||||
om_dssel.ztst = ZTST_ALWAYS;
|
||||
}
|
||||
}
|
||||
else if(context->ZBUF.PSM == PSM_PSMZ16 || context->ZBUF.PSM == PSM_PSMZ16S)
|
||||
|
@ -149,76 +156,52 @@ public:
|
|||
ASSERT(m_vt.m_min.p.z > 0xffff); // sfex capcom logo
|
||||
|
||||
vs_sel.bppz = 2;
|
||||
om_dssel.ztst = 1;
|
||||
om_dssel.ztst = ZTST_ALWAYS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GSTextureFX::VSConstantBuffer vs_cb;
|
||||
|
||||
float sx = 2.0f * rt->m_scale.x / (rt->GetWidth() * 16);
|
||||
float sy = 2.0f * rt->m_scale.y / (rt->GetHeight() * 16);
|
||||
float sx = 2.0f * rt->m_scale.x / (rt->m_size.x << 4);
|
||||
float sy = 2.0f * rt->m_scale.y / (rt->m_size.y << 4);
|
||||
float ox = (float)(int)context->XYOFFSET.OFX;
|
||||
float oy = (float)(int)context->XYOFFSET.OFY;
|
||||
float ox2 = 2.0f * m_pixelcenter.x / rt->GetWidth();
|
||||
float oy2 = 2.0f * m_pixelcenter.y / rt->GetHeight();
|
||||
float ox2 = 2.0f * m_pixelcenter.x / rt->m_size.x;
|
||||
float oy2 = 2.0f * m_pixelcenter.y / rt->m_size.y;
|
||||
|
||||
vs_cb.VertexScale = GSVector4(sx, -sy, 1.0f / UINT_MAX, 0.0f);
|
||||
vs_cb.VertexOffset = GSVector4(ox * sx + ox2 + 1, -(oy * sy + oy2 + 1), 0.0f, -1.0f);
|
||||
|
||||
if(PRIM->TME)
|
||||
{
|
||||
if(PRIM->FST)
|
||||
{
|
||||
vs_cb.TextureScale.x = 1.0f / (16 << context->TEX0.TW);
|
||||
vs_cb.TextureScale.y = 1.0f / (16 << context->TEX0.TH);
|
||||
}
|
||||
else
|
||||
{
|
||||
vs_cb.TextureScale = GSVector2(1.0f, 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
// gs
|
||||
|
||||
GSTextureFX::GSSelector gs_sel;
|
||||
|
||||
gs_sel.iip = PRIM->IIP;
|
||||
gs_sel.prim = primclass;
|
||||
gs_sel.prim = m_vt.m_primclass;
|
||||
|
||||
// ps
|
||||
|
||||
GSTextureFX::PSSelector ps_sel;
|
||||
|
||||
ps_sel.fst = PRIM->FST;
|
||||
ps_sel.wms = context->CLAMP.WMS;
|
||||
ps_sel.wmt = context->CLAMP.WMT;
|
||||
ps_sel.aem = env.TEXA.AEM;
|
||||
ps_sel.tfx = context->TEX0.TFX;
|
||||
ps_sel.tcc = context->TEX0.TCC;
|
||||
ps_sel.ate = context->TEST.ATE;
|
||||
ps_sel.atst = context->TEST.ATST;
|
||||
ps_sel.fog = PRIM->FGE;
|
||||
ps_sel.clr1 = om_bsel.abe && om_bsel.a == 1 && om_bsel.b == 2 && om_bsel.d == 1;
|
||||
ps_sel.fba = context->FBA.FBA;
|
||||
ps_sel.aout = context->FRAME.PSM == PSM_PSMCT16 || context->FRAME.PSM == PSM_PSMCT16S || (context->FRAME.FBMSK & 0xff000000) == 0x7f000000 ? 1 : 0;
|
||||
ps_sel.ltf = m_filter == 2 ? IsLinear() : m_filter;
|
||||
|
||||
GSTextureFX::PSSamplerSelector ps_ssel;
|
||||
|
||||
ps_ssel.tau = 0;
|
||||
ps_ssel.tav = 0;
|
||||
ps_ssel.ltf = ps_sel.ltf;
|
||||
|
||||
GSTextureFX::PSConstantBuffer ps_cb;
|
||||
|
||||
if(ps_sel.fog)
|
||||
ps_sel.clr1 = om_bsel.IsCLR1();
|
||||
ps_sel.fba = context->FBA.FBA;
|
||||
ps_sel.aout = context->FRAME.PSM == PSM_PSMCT16 || context->FRAME.PSM == PSM_PSMCT16S || (context->FRAME.FBMSK & 0xff000000) == 0x7f000000 ? 1 : 0;
|
||||
|
||||
if(PRIM->FGE)
|
||||
{
|
||||
ps_cb.FogColor_AREF = GSVector4((int)env.FOGCOL.FCR, (int)env.FOGCOL.FCG, (int)env.FOGCOL.FCB, 0) / 255;
|
||||
ps_sel.fog = 1;
|
||||
|
||||
ps_cb.FogColor_AREF = GSVector4(env.FOGCOL.u32[0]) / 255;
|
||||
}
|
||||
|
||||
if(ps_sel.ate)
|
||||
if(context->TEST.ATE)
|
||||
{
|
||||
ps_sel.ate = 1;
|
||||
ps_sel.atst = context->TEST.ATST;
|
||||
|
||||
switch(ps_sel.atst)
|
||||
{
|
||||
case ATST_LESS:
|
||||
|
@ -235,62 +218,43 @@ public:
|
|||
|
||||
if(tex)
|
||||
{
|
||||
ps_sel.wms = context->CLAMP.WMS;
|
||||
ps_sel.wmt = context->CLAMP.WMT;
|
||||
ps_sel.fmt = tex->m_fmt;
|
||||
ps_sel.aem = env.TEXA.AEM;
|
||||
ps_sel.tfx = context->TEX0.TFX;
|
||||
ps_sel.tcc = context->TEX0.TCC;
|
||||
ps_sel.ltf = m_filter == 2 ? IsLinear() : m_filter;
|
||||
ps_sel.rt = tex->m_target;
|
||||
|
||||
int w = tex->m_texture->GetWidth();
|
||||
int h = tex->m_texture->GetHeight();
|
||||
int w = tex->m_texture->m_size.x;
|
||||
int h = tex->m_texture->m_size.y;
|
||||
|
||||
ps_cb.WH = GSVector4((int)(1 << context->TEX0.TW), (int)(1 << context->TEX0.TH), w, h);
|
||||
ps_cb.HalfTexel = GSVector4(-0.5f, 0.5f).xxyy() / GSVector4(w, h).xyxy();
|
||||
ps_cb.MinF_TA.z = (float)(int)env.TEXA.TA0 / 255;
|
||||
ps_cb.MinF_TA.w = (float)(int)env.TEXA.TA1 / 255;
|
||||
int tw = (int)(1 << context->TEX0.TW);
|
||||
int th = (int)(1 << context->TEX0.TH);
|
||||
|
||||
switch(context->CLAMP.WMS)
|
||||
GSVector4 WH(tw, th, w, h);
|
||||
|
||||
if(PRIM->FST)
|
||||
{
|
||||
case CLAMP_REPEAT:
|
||||
ps_ssel.tau = 1;
|
||||
break;
|
||||
case CLAMP_CLAMP:
|
||||
ps_ssel.tau = 0;
|
||||
break;
|
||||
case CLAMP_REGION_CLAMP:
|
||||
ps_cb.MinMax.x = ((float)(int)context->CLAMP.MINU) / (1 << context->TEX0.TW);
|
||||
ps_cb.MinMax.z = ((float)(int)context->CLAMP.MAXU) / (1 << context->TEX0.TW);
|
||||
ps_cb.MinF_TA.x = ((float)(int)context->CLAMP.MINU + 0.5f) / (1 << context->TEX0.TW);
|
||||
ps_ssel.tau = 0;
|
||||
break;
|
||||
case CLAMP_REGION_REPEAT:
|
||||
ps_cb.MskFix.x = context->CLAMP.MINU;
|
||||
ps_cb.MskFix.z = context->CLAMP.MAXU;
|
||||
ps_ssel.tau = 1;
|
||||
break;
|
||||
default:
|
||||
__assume(0);
|
||||
vs_cb.TextureScale = GSVector4(1.0f / 16) / WH.xyxy();
|
||||
|
||||
ps_sel.fst = 1;
|
||||
}
|
||||
|
||||
switch(context->CLAMP.WMT)
|
||||
{
|
||||
case CLAMP_REPEAT:
|
||||
ps_ssel.tav = 1;
|
||||
break;
|
||||
case CLAMP_CLAMP:
|
||||
ps_ssel.tav = 0;
|
||||
break;
|
||||
case CLAMP_REGION_CLAMP:
|
||||
ps_cb.MinMax.y = ((float)(int)context->CLAMP.MINV) / (1 << context->TEX0.TH);
|
||||
ps_cb.MinMax.w = ((float)(int)context->CLAMP.MAXV) / (1 << context->TEX0.TH);
|
||||
ps_cb.MinF_TA.y = ((float)(int)context->CLAMP.MINV + 0.5f) / (1 << context->TEX0.TH);
|
||||
ps_ssel.tav = 0;
|
||||
break;
|
||||
case CLAMP_REGION_REPEAT:
|
||||
ps_cb.MskFix.y = context->CLAMP.MINV;
|
||||
ps_cb.MskFix.w = context->CLAMP.MAXV;
|
||||
ps_ssel.tav = 1;
|
||||
break;
|
||||
default:
|
||||
__assume(0);
|
||||
}
|
||||
ps_cb.WH = WH;
|
||||
ps_cb.HalfTexel = GSVector4(-0.5f, 0.5f).xxyy() / WH.zwzw();
|
||||
ps_cb.MskFix = GSVector4i(context->CLAMP.MINU, context->CLAMP.MINV, context->CLAMP.MAXU, context->CLAMP.MAXV);
|
||||
|
||||
GSVector4 clamp(ps_cb.MskFix);
|
||||
GSVector4 ta(env.TEXA & GSVector4i::x000000ff());
|
||||
|
||||
ps_cb.MinMax = clamp / WH.xyxy();
|
||||
ps_cb.MinF_TA = (clamp + 0.5f).xyxy(ta) / WH.xyxy(GSVector4(255, 255));
|
||||
|
||||
ps_ssel.tau = (context->CLAMP.WMS + 3) >> 1;
|
||||
ps_ssel.tav = (context->CLAMP.WMT + 3) >> 1;
|
||||
ps_ssel.ltf = ps_sel.ltf;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -299,21 +263,18 @@ public:
|
|||
|
||||
// rs
|
||||
|
||||
int w = rt->GetWidth();
|
||||
int h = rt->GetHeight();
|
||||
GSVector4i scissor = GSVector4i(GSVector4(rt->m_scale).xyxy() * context->scissor.in).rintersect(GSVector4i(rt->GetSize()).zwxy());
|
||||
|
||||
GSVector4i scissor = GSVector4i(GSVector4(rt->m_scale).xyxy() * context->scissor.in).rintersect(GSVector4i(0, 0, w, h));
|
||||
|
||||
//
|
||||
m_dev->OMSetRenderTargets(rt, ds, &scissor);
|
||||
m_dev->PSSetShaderResources(tex ? tex->m_texture : NULL, tex ? tex->m_palette : NULL);
|
||||
|
||||
uint8 afix = context->ALPHA.FIX;
|
||||
|
||||
m_tfx->SetupOM(om_dssel, om_bsel, afix, rt, ds);
|
||||
m_tfx->SetupOM(om_dssel, om_bsel, afix);
|
||||
m_tfx->SetupIA(m_vertices, m_count, m_topology);
|
||||
m_tfx->SetupVS(vs_sel, &vs_cb);
|
||||
m_tfx->SetupGS(gs_sel);
|
||||
m_tfx->SetupPS(ps_sel, &ps_cb, ps_ssel, tex ? tex->m_texture : NULL, tex ? tex->m_palette : NULL);
|
||||
m_tfx->SetupRS(w, h, scissor);
|
||||
m_tfx->SetupPS(ps_sel, &ps_cb, ps_ssel);
|
||||
|
||||
// draw
|
||||
|
||||
|
@ -343,7 +304,7 @@ public:
|
|||
break;
|
||||
}
|
||||
|
||||
m_tfx->UpdatePS(ps_sel, &ps_cb, ps_ssel);
|
||||
m_tfx->SetupPS(ps_sel, &ps_cb, ps_ssel);
|
||||
|
||||
bool z = om_dssel.zwe;
|
||||
bool r = om_bsel.wr;
|
||||
|
@ -368,7 +329,7 @@ public:
|
|||
om_bsel.wb = b;
|
||||
om_bsel.wa = a;
|
||||
|
||||
m_tfx->UpdateOM(om_dssel, om_bsel, afix);
|
||||
m_tfx->SetupOM(om_dssel, om_bsel, afix);
|
||||
|
||||
m_dev->DrawPrimitive();
|
||||
}
|
||||
|
|
|
@ -25,16 +25,14 @@
|
|||
#include "resource.h"
|
||||
|
||||
GSRendererDX10::GSRendererDX10(uint8* base, bool mt, void (*irq)())
|
||||
: GSRendererDX<GSVertexHW10>(base, mt, irq, new GSDevice10(), new GSTextureCache10(this), new GSTextureFX10())
|
||||
: GSRendererDX<GSVertexHW10>(base, mt, irq, new GSDevice10(), new GSTextureCache10(this), new GSTextureFX10(), GSVector2(-0.5f, -0.5f))
|
||||
{
|
||||
InitVertexKick<GSRendererDX10>();
|
||||
|
||||
m_pixelcenter = GSVector2(-0.5f, -0.5f);
|
||||
}
|
||||
|
||||
bool GSRendererDX10::Create(const string& title)
|
||||
bool GSRendererDX10::Create(const string& title, int w, int h)
|
||||
{
|
||||
if(!__super::Create(title))
|
||||
if(!__super::Create(title, w, h))
|
||||
return false;
|
||||
|
||||
//
|
||||
|
@ -88,9 +86,11 @@ void GSRendererDX10::VertexKick(bool skip)
|
|||
{
|
||||
GSVector4i scissor = m_context->scissor.dx10;
|
||||
|
||||
GSVector4i pmin, pmax;
|
||||
|
||||
#if _M_SSE >= 0x401
|
||||
|
||||
GSVector4i pmin, pmax, v0, v1, v2;
|
||||
GSVector4i v0, v1, v2;
|
||||
|
||||
switch(prim)
|
||||
{
|
||||
|
@ -118,59 +118,60 @@ void GSRendererDX10::VertexKick(bool skip)
|
|||
break;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
switch(prim)
|
||||
{
|
||||
case GS_POINTLIST:
|
||||
pmin.x = v[0].p.x;
|
||||
pmin.y = v[0].p.y;
|
||||
pmax.x = v[0].p.x;
|
||||
pmax.y = v[0].p.y;
|
||||
break;
|
||||
case GS_LINELIST:
|
||||
case GS_LINESTRIP:
|
||||
case GS_SPRITE:
|
||||
pmin.x = std::min<uint16>(v[0].p.x, v[1].p.x);
|
||||
pmin.y = std::min<uint16>(v[0].p.y, v[1].p.y);
|
||||
pmax.x = std::max<uint16>(v[0].p.x, v[1].p.x);
|
||||
pmax.y = std::max<uint16>(v[0].p.y, v[1].p.y);
|
||||
break;
|
||||
case GS_TRIANGLELIST:
|
||||
case GS_TRIANGLESTRIP:
|
||||
case GS_TRIANGLEFAN:
|
||||
pmin.x = std::min<uint16>(std::min<uint16>(v[0].p.x, v[1].p.x), v[2].p.x);
|
||||
pmin.y = std::min<uint16>(std::min<uint16>(v[0].p.y, v[1].p.y), v[2].p.y);
|
||||
pmax.x = std::max<uint16>(std::max<uint16>(v[0].p.x, v[1].p.x), v[2].p.x);
|
||||
pmax.y = std::max<uint16>(std::max<uint16>(v[0].p.y, v[1].p.y), v[2].p.y);
|
||||
break;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
GSVector4i test = (pmax < scissor) | (pmin > scissor.zwxy());
|
||||
|
||||
switch(prim)
|
||||
{
|
||||
case GS_TRIANGLELIST:
|
||||
case GS_TRIANGLESTRIP:
|
||||
case GS_TRIANGLEFAN:
|
||||
case GS_SPRITE:
|
||||
test |= pmin == pmax;
|
||||
break;
|
||||
}
|
||||
|
||||
if(test.mask() & 0xff)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
switch(prim)
|
||||
{
|
||||
case GS_POINTLIST:
|
||||
if(v[0].p.x < scissor.x
|
||||
|| v[0].p.x > scissor.z
|
||||
|| v[0].p.y < scissor.y
|
||||
|| v[0].p.y > scissor.w)
|
||||
{
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case GS_LINELIST:
|
||||
case GS_LINESTRIP:
|
||||
case GS_SPRITE:
|
||||
if(v[0].p.x < scissor.x && v[1].p.x < scissor.x
|
||||
|| v[0].p.x > scissor.z && v[1].p.x > scissor.z
|
||||
|| v[0].p.y < scissor.y && v[1].p.y < scissor.y
|
||||
|| v[0].p.y > scissor.w && v[1].p.y > scissor.w)
|
||||
{
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case GS_TRIANGLELIST:
|
||||
case GS_TRIANGLESTRIP:
|
||||
case GS_TRIANGLEFAN:
|
||||
if(v[0].p.x < scissor.x && v[1].p.x < scissor.x && v[2].p.x < scissor.x
|
||||
|| v[0].p.x > scissor.z && v[1].p.x > scissor.z && v[2].p.x > scissor.z
|
||||
|| v[0].p.y < scissor.y && v[1].p.y < scissor.y && v[2].p.y < scissor.y
|
||||
|| v[0].p.y > scissor.w && v[1].p.y > scissor.w && v[2].p.y > scissor.w)
|
||||
{
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
m_count += count;
|
||||
}
|
||||
}
|
||||
|
||||
void GSRendererDX10::Draw(GS_PRIM_CLASS primclass, GSTexture* rt, GSTexture* ds, GSTextureCache::Source* tex)
|
||||
void GSRendererDX10::Draw(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* tex)
|
||||
{
|
||||
switch(primclass)
|
||||
switch(m_vt.m_primclass)
|
||||
{
|
||||
case GS_POINT_CLASS:
|
||||
m_topology = D3D10_PRIMITIVE_TOPOLOGY_POINTLIST;
|
||||
|
@ -189,7 +190,7 @@ void GSRendererDX10::Draw(GS_PRIM_CLASS primclass, GSTexture* rt, GSTexture* ds,
|
|||
__assume(0);
|
||||
}
|
||||
|
||||
__super::Draw(primclass, rt, ds, tex);
|
||||
__super::Draw(rt, ds, tex);
|
||||
}
|
||||
|
||||
void GSRendererDX10::SetupDATE(GSTexture* rt, GSTexture* ds)
|
||||
|
@ -198,10 +199,9 @@ void GSRendererDX10::SetupDATE(GSTexture* rt, GSTexture* ds)
|
|||
|
||||
GSDevice10* dev = (GSDevice10*)m_dev;
|
||||
|
||||
int w = rt->GetWidth();
|
||||
int h = rt->GetHeight();
|
||||
const GSVector2i& size = rt->m_size;
|
||||
|
||||
if(GSTexture* t = dev->CreateRenderTarget(w, h))
|
||||
if(GSTexture* t = dev->CreateRenderTarget(size.x, size.y))
|
||||
{
|
||||
// sfex3 (after the capcom logo), vf4 (first menu fading in), ffxii shadows, rumble roses shadows, persona4 shadows
|
||||
|
||||
|
@ -217,7 +217,7 @@ void GSRendererDX10::SetupDATE(GSTexture* rt, GSTexture* ds)
|
|||
|
||||
// ia
|
||||
|
||||
GSVector4 s = GSVector4(rt->m_scale.x / w, rt->m_scale.y / h);
|
||||
GSVector4 s = GSVector4(rt->m_scale.x / size.x, rt->m_scale.y / size.y);
|
||||
GSVector4 o = GSVector4(-1.0f, 1.0f);
|
||||
|
||||
GSVector4 src = ((m_vt.m_min.p.xyxy(m_vt.m_max.p) + o.xxyy()) * s.xyxy()).sat(o.zzyy());
|
||||
|
@ -249,11 +249,7 @@ void GSRendererDX10::SetupDATE(GSTexture* rt, GSTexture* ds)
|
|||
dev->PSSetShader(dev->m_convert.ps[m_context->TEST.DATM ? 2 : 3], NULL);
|
||||
dev->PSSetSamplerState(dev->m_convert.pt, NULL);
|
||||
|
||||
// rs
|
||||
|
||||
dev->RSSet(w, h);
|
||||
|
||||
// set
|
||||
//
|
||||
|
||||
dev->DrawPrimitive();
|
||||
|
||||
|
|
|
@ -35,13 +35,13 @@ protected:
|
|||
CComPtr<ID3D10BlendState> bs;
|
||||
} m_date;
|
||||
|
||||
void Draw(GS_PRIM_CLASS primclass, GSTexture* rt, GSTexture* ds, GSTextureCache::Source* tex);
|
||||
void Draw(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* tex);
|
||||
void SetupDATE(GSTexture* rt, GSTexture* ds);
|
||||
|
||||
public:
|
||||
GSRendererDX10(uint8* base, bool mt, void (*irq)());
|
||||
|
||||
bool Create(const string& title);
|
||||
bool Create(const string& title, int w, int h);
|
||||
|
||||
template<uint32 prim, uint32 tme, uint32 fst> void VertexKick(bool skip);
|
||||
};
|
|
@ -25,16 +25,14 @@
|
|||
#include "resource.h"
|
||||
|
||||
GSRendererDX11::GSRendererDX11(uint8* base, bool mt, void (*irq)())
|
||||
: GSRendererDX<GSVertexHW11>(base, mt, irq, new GSDevice11(), new GSTextureCache11(this), new GSTextureFX11())
|
||||
: GSRendererDX<GSVertexHW11>(base, mt, irq, new GSDevice11(), new GSTextureCache11(this), new GSTextureFX11(), GSVector2(-0.5f, -0.5f))
|
||||
{
|
||||
InitVertexKick<GSRendererDX11>();
|
||||
|
||||
m_pixelcenter = GSVector2(-0.5f, -0.5f);
|
||||
}
|
||||
|
||||
bool GSRendererDX11::Create(const string& title)
|
||||
bool GSRendererDX11::Create(const string& title, int w, int h)
|
||||
{
|
||||
if(!__super::Create(title))
|
||||
if(!__super::Create(title, w, h))
|
||||
return false;
|
||||
|
||||
//
|
||||
|
@ -88,9 +86,11 @@ void GSRendererDX11::VertexKick(bool skip)
|
|||
{
|
||||
GSVector4i scissor = m_context->scissor.dx10;
|
||||
|
||||
GSVector4i pmin, pmax;
|
||||
|
||||
#if _M_SSE >= 0x401
|
||||
|
||||
GSVector4i pmin, pmax, v0, v1, v2;
|
||||
GSVector4i v0, v1, v2;
|
||||
|
||||
switch(prim)
|
||||
{
|
||||
|
@ -118,59 +118,60 @@ void GSRendererDX11::VertexKick(bool skip)
|
|||
break;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
switch(prim)
|
||||
{
|
||||
case GS_POINTLIST:
|
||||
pmin.x = v[0].p.x;
|
||||
pmin.y = v[0].p.y;
|
||||
pmax.x = v[0].p.x;
|
||||
pmax.y = v[0].p.y;
|
||||
break;
|
||||
case GS_LINELIST:
|
||||
case GS_LINESTRIP:
|
||||
case GS_SPRITE:
|
||||
pmin.x = std::min<uint16>(v[0].p.x, v[1].p.x);
|
||||
pmin.y = std::min<uint16>(v[0].p.y, v[1].p.y);
|
||||
pmax.x = std::max<uint16>(v[0].p.x, v[1].p.x);
|
||||
pmax.y = std::max<uint16>(v[0].p.y, v[1].p.y);
|
||||
break;
|
||||
case GS_TRIANGLELIST:
|
||||
case GS_TRIANGLESTRIP:
|
||||
case GS_TRIANGLEFAN:
|
||||
pmin.x = std::min<uint16>(std::min<uint16>(v[0].p.x, v[1].p.x), v[2].p.x);
|
||||
pmin.y = std::min<uint16>(std::min<uint16>(v[0].p.y, v[1].p.y), v[2].p.y);
|
||||
pmax.x = std::max<uint16>(std::max<uint16>(v[0].p.x, v[1].p.x), v[2].p.x);
|
||||
pmax.y = std::max<uint16>(std::max<uint16>(v[0].p.y, v[1].p.y), v[2].p.y);
|
||||
break;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
GSVector4i test = (pmax < scissor) | (pmin > scissor.zwxy());
|
||||
|
||||
switch(prim)
|
||||
{
|
||||
case GS_TRIANGLELIST:
|
||||
case GS_TRIANGLESTRIP:
|
||||
case GS_TRIANGLEFAN:
|
||||
case GS_SPRITE:
|
||||
test |= pmin == pmax;
|
||||
break;
|
||||
}
|
||||
|
||||
if(test.mask() & 0xff)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
switch(prim)
|
||||
{
|
||||
case GS_POINTLIST:
|
||||
if(v[0].p.x < scissor.x
|
||||
|| v[0].p.x > scissor.z
|
||||
|| v[0].p.y < scissor.y
|
||||
|| v[0].p.y > scissor.w)
|
||||
{
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case GS_LINELIST:
|
||||
case GS_LINESTRIP:
|
||||
case GS_SPRITE:
|
||||
if(v[0].p.x < scissor.x && v[1].p.x < scissor.x
|
||||
|| v[0].p.x > scissor.z && v[1].p.x > scissor.z
|
||||
|| v[0].p.y < scissor.y && v[1].p.y < scissor.y
|
||||
|| v[0].p.y > scissor.w && v[1].p.y > scissor.w)
|
||||
{
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case GS_TRIANGLELIST:
|
||||
case GS_TRIANGLESTRIP:
|
||||
case GS_TRIANGLEFAN:
|
||||
if(v[0].p.x < scissor.x && v[1].p.x < scissor.x && v[2].p.x < scissor.x
|
||||
|| v[0].p.x > scissor.z && v[1].p.x > scissor.z && v[2].p.x > scissor.z
|
||||
|| v[0].p.y < scissor.y && v[1].p.y < scissor.y && v[2].p.y < scissor.y
|
||||
|| v[0].p.y > scissor.w && v[1].p.y > scissor.w && v[2].p.y > scissor.w)
|
||||
{
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
m_count += count;
|
||||
}
|
||||
}
|
||||
|
||||
void GSRendererDX11::Draw(GS_PRIM_CLASS primclass, GSTexture* rt, GSTexture* ds, GSTextureCache::Source* tex)
|
||||
void GSRendererDX11::Draw(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* tex)
|
||||
{
|
||||
switch(primclass)
|
||||
switch(m_vt.m_primclass)
|
||||
{
|
||||
case GS_POINT_CLASS:
|
||||
m_topology = D3D11_PRIMITIVE_TOPOLOGY_POINTLIST;
|
||||
|
@ -189,7 +190,7 @@ void GSRendererDX11::Draw(GS_PRIM_CLASS primclass, GSTexture* rt, GSTexture* ds,
|
|||
__assume(0);
|
||||
}
|
||||
|
||||
__super::Draw(primclass, rt, ds, tex);
|
||||
__super::Draw(rt, ds, tex);
|
||||
}
|
||||
|
||||
void GSRendererDX11::SetupDATE(GSTexture* rt, GSTexture* ds)
|
||||
|
@ -198,10 +199,9 @@ void GSRendererDX11::SetupDATE(GSTexture* rt, GSTexture* ds)
|
|||
|
||||
GSDevice11* dev = (GSDevice11*)m_dev;
|
||||
|
||||
int w = rt->GetWidth();
|
||||
int h = rt->GetHeight();
|
||||
const GSVector2i& size = rt->m_size;
|
||||
|
||||
if(GSTexture* t = dev->CreateRenderTarget(w, h))
|
||||
if(GSTexture* t = dev->CreateRenderTarget(size.x, size.y))
|
||||
{
|
||||
// sfex3 (after the capcom logo), vf4 (first menu fading in), ffxii shadows, rumble roses shadows, persona4 shadows
|
||||
|
||||
|
@ -217,7 +217,7 @@ void GSRendererDX11::SetupDATE(GSTexture* rt, GSTexture* ds)
|
|||
|
||||
// ia
|
||||
|
||||
GSVector4 s = GSVector4(rt->m_scale.x / w, rt->m_scale.y / h);
|
||||
GSVector4 s = GSVector4(rt->m_scale.x / size.x, rt->m_scale.y / size.y);
|
||||
GSVector4 o = GSVector4(-1.0f, 1.0f);
|
||||
|
||||
GSVector4 src = ((m_vt.m_min.p.xyxy(m_vt.m_max.p) + o.xxyy()) * s.xyxy()).sat(o.zzyy());
|
||||
|
@ -249,11 +249,7 @@ void GSRendererDX11::SetupDATE(GSTexture* rt, GSTexture* ds)
|
|||
dev->PSSetShader(dev->m_convert.ps[m_context->TEST.DATM ? 2 : 3], NULL);
|
||||
dev->PSSetSamplerState(dev->m_convert.pt, NULL);
|
||||
|
||||
// rs
|
||||
|
||||
dev->RSSet(w, h);
|
||||
|
||||
// set
|
||||
//
|
||||
|
||||
dev->DrawPrimitive();
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
class GSRendererDX11 : public GSRendererDX<GSVertexHW11>
|
||||
{
|
||||
protected:
|
||||
void Draw(GS_PRIM_CLASS primclass, GSTexture* rt, GSTexture* ds, GSTextureCache::Source* tex);
|
||||
void Draw(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* tex);
|
||||
|
||||
struct
|
||||
{
|
||||
|
@ -42,7 +42,7 @@ protected:
|
|||
public:
|
||||
GSRendererDX11(uint8* base, bool mt, void (*irq)());
|
||||
|
||||
bool Create(const string& title);
|
||||
bool Create(const string& title, int w, int h);
|
||||
|
||||
template<uint32 prim, uint32 tme, uint32 fst> void VertexKick(bool skip);
|
||||
};
|
|
@ -30,9 +30,9 @@ GSRendererDX9::GSRendererDX9(uint8* base, bool mt, void (*irq)())
|
|||
InitVertexKick<GSRendererDX9>();
|
||||
}
|
||||
|
||||
bool GSRendererDX9::Create(const string& title)
|
||||
bool GSRendererDX9::Create(const string& title, int w, int h)
|
||||
{
|
||||
if(!__super::Create(title))
|
||||
if(!__super::Create(title, w, h))
|
||||
return false;
|
||||
|
||||
//
|
||||
|
@ -135,6 +135,16 @@ void GSRendererDX9::VertexKick(bool skip)
|
|||
|
||||
GSVector4 test = (pmax < scissor) | (pmin > scissor.zwxy());
|
||||
|
||||
switch(prim)
|
||||
{
|
||||
case GS_TRIANGLELIST:
|
||||
case GS_TRIANGLESTRIP:
|
||||
case GS_TRIANGLEFAN:
|
||||
case GS_SPRITE:
|
||||
test |= pmin == pmax;
|
||||
break;
|
||||
}
|
||||
|
||||
if(test.mask() & 3)
|
||||
{
|
||||
return;
|
||||
|
@ -174,9 +184,9 @@ void GSRendererDX9::VertexKick(bool skip)
|
|||
}
|
||||
}
|
||||
|
||||
void GSRendererDX9::Draw(GS_PRIM_CLASS primclass, GSTexture* rt, GSTexture* ds, GSTextureCache::Source* tex)
|
||||
void GSRendererDX9::Draw(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* tex)
|
||||
{
|
||||
switch(primclass)
|
||||
switch(m_vt.m_primclass)
|
||||
{
|
||||
case GS_POINT_CLASS:
|
||||
m_topology = D3DPT_POINTLIST;
|
||||
|
@ -197,7 +207,7 @@ void GSRendererDX9::Draw(GS_PRIM_CLASS primclass, GSTexture* rt, GSTexture* ds,
|
|||
|
||||
(*(GSDevice9*)m_dev)->SetRenderState(D3DRS_SHADEMODE, PRIM->IIP ? D3DSHADE_GOURAUD : D3DSHADE_FLAT); // TODO
|
||||
|
||||
__super::Draw(primclass, rt, ds, tex);
|
||||
__super::Draw(rt, ds, tex);
|
||||
}
|
||||
|
||||
void GSRendererDX9::SetupDATE(GSTexture* rt, GSTexture* ds)
|
||||
|
@ -206,10 +216,9 @@ void GSRendererDX9::SetupDATE(GSTexture* rt, GSTexture* ds)
|
|||
|
||||
GSDevice9* dev = (GSDevice9*)m_dev;
|
||||
|
||||
int w = rt->GetWidth();
|
||||
int h = rt->GetHeight();
|
||||
const GSVector2i& size = rt->m_size;
|
||||
|
||||
if(GSTexture* t = dev->CreateRenderTarget(w, h))
|
||||
if(GSTexture* t = dev->CreateRenderTarget(size.x, size.y))
|
||||
{
|
||||
// sfex3 (after the capcom logo), vf4 (first menu fading in), ffxii shadows, rumble roses shadows, persona4 shadows
|
||||
|
||||
|
@ -225,7 +234,7 @@ void GSRendererDX9::SetupDATE(GSTexture* rt, GSTexture* ds)
|
|||
|
||||
// ia
|
||||
|
||||
GSVector4 s = GSVector4(rt->m_scale.x / w, rt->m_scale.y / h);
|
||||
GSVector4 s = GSVector4(rt->m_scale.x / size.x, rt->m_scale.y / size.y);
|
||||
GSVector4 o = GSVector4(-1.0f, 1.0f);
|
||||
|
||||
GSVector4 src = ((m_vt.m_min.p.xyxy(m_vt.m_max.p) + o.xxyy()) * s.xyxy()).sat(o.zzyy());
|
||||
|
@ -253,10 +262,6 @@ void GSRendererDX9::SetupDATE(GSTexture* rt, GSTexture* ds)
|
|||
dev->PSSetShader(dev->m_convert.ps[m_context->TEST.DATM ? 2 : 3], NULL, 0);
|
||||
dev->PSSetSamplerState(&dev->m_convert.pt);
|
||||
|
||||
// rs
|
||||
|
||||
dev->RSSet(w, h);
|
||||
|
||||
//
|
||||
|
||||
dev->DrawPrimitive();
|
||||
|
@ -282,7 +287,7 @@ void GSRendererDX9::UpdateFBA(GSTexture* rt)
|
|||
|
||||
// ia
|
||||
|
||||
GSVector4 s = GSVector4(rt->m_scale.x / rt->GetWidth(), rt->m_scale.y / rt->GetHeight());
|
||||
GSVector4 s = GSVector4(rt->m_scale.x / rt->m_size.x, rt->m_scale.y / rt->m_size.y);
|
||||
GSVector4 o = GSVector4(-1.0f, 1.0f);
|
||||
|
||||
GSVector4 src = ((m_vt.m_min.p.xyxy(m_vt.m_max.p) + o.xxyy()) * s.xyxy()).sat(o.zzyy());
|
||||
|
@ -308,10 +313,6 @@ void GSRendererDX9::UpdateFBA(GSTexture* rt)
|
|||
|
||||
dev->PSSetShader(dev->m_convert.ps[4], NULL, 0);
|
||||
|
||||
// rs
|
||||
|
||||
dev->RSSet(rt->GetWidth(), rt->GetHeight());
|
||||
|
||||
//
|
||||
|
||||
dev->DrawPrimitive();
|
||||
|
|
|
@ -41,14 +41,14 @@ protected:
|
|||
Direct3DBlendState9 bs;
|
||||
} m_fba;
|
||||
|
||||
void Draw(GS_PRIM_CLASS primclass, GSTexture* rt, GSTexture* ds, GSTextureCache::Source* tex);
|
||||
void Draw(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* tex);
|
||||
void SetupDATE(GSTexture* rt, GSTexture* ds);
|
||||
void UpdateFBA(GSTexture* rt);
|
||||
|
||||
public:
|
||||
GSRendererDX9(uint8* base, bool mt, void (*irq)());
|
||||
|
||||
bool Create(const string& title);
|
||||
bool Create(const string& title, int w, int h);
|
||||
|
||||
template<uint32 prim, uint32 tme, uint32 fst> void VertexKick(bool skip);
|
||||
};
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
#include "GSRenderer.h"
|
||||
#include "GSTextureCache.h"
|
||||
#include "GSCrc.h"
|
||||
#include "GSFunctionMap.h"
|
||||
|
||||
|
||||
template<class Vertex>
|
||||
class GSRendererHW : public GSRendererT<Vertex>
|
||||
|
@ -33,6 +35,418 @@ class GSRendererHW : public GSRendererT<Vertex>
|
|||
int m_skip;
|
||||
bool m_reset;
|
||||
|
||||
#pragma region hacks
|
||||
|
||||
typedef bool (GSRendererHW::*OI_Ptr)(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t);
|
||||
typedef void (GSRendererHW::*OO_Ptr)();
|
||||
typedef bool (GSRendererHW::*CU_Ptr)();
|
||||
|
||||
bool OI_FFXII(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t)
|
||||
{
|
||||
static uint32* video = NULL;
|
||||
static int lines = 0;
|
||||
|
||||
if(lines == 0)
|
||||
{
|
||||
if(m_vt.m_primclass == GS_LINE_CLASS && (m_count == 448 * 2 || m_count == 512 * 2))
|
||||
{
|
||||
lines = m_count / 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(m_vt.m_primclass == GS_POINT_CLASS)
|
||||
{
|
||||
if(m_count >= 16 * 512)
|
||||
{
|
||||
// incoming pixels are stored in columns, one column is 16x512, total res 448x512 or 448x454
|
||||
|
||||
if(!video) video = new uint32[512 * 512];
|
||||
|
||||
int ox = m_context->XYOFFSET.OFX;
|
||||
int oy = m_context->XYOFFSET.OFY;
|
||||
|
||||
for(int i = 0; i < m_count; i++)
|
||||
{
|
||||
int x = ((int)m_vertices[i].p.x - ox) >> 4;
|
||||
int y = ((int)m_vertices[i].p.y - oy) >> 4;
|
||||
|
||||
// video[y * 448 + x] = m_vertices[i].c0;
|
||||
video[(y << 8) + (y << 7) + (y << 6) + x] = m_vertices[i].c0;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
lines = 0;
|
||||
}
|
||||
}
|
||||
else if(m_vt.m_primclass == GS_LINE_CLASS)
|
||||
{
|
||||
if(m_count == lines * 2)
|
||||
{
|
||||
// normally, this step would copy the video onto screen with 512 texture mapped horizontal lines,
|
||||
// but we use the stored video data to create a new texture, and replace the lines with two triangles
|
||||
|
||||
m_dev->Recycle(t->m_texture);
|
||||
|
||||
t->m_texture = m_dev->CreateTexture(512, 512);
|
||||
|
||||
t->m_texture->Update(GSVector4i(0, 0, 448, lines), video, 448 * 4);
|
||||
|
||||
m_vertices[0] = m_vertices[0];
|
||||
m_vertices[1] = m_vertices[1];
|
||||
m_vertices[2] = m_vertices[m_count - 2];
|
||||
m_vertices[3] = m_vertices[1];
|
||||
m_vertices[4] = m_vertices[2];
|
||||
m_vertices[5] = m_vertices[m_count - 1];
|
||||
|
||||
m_count = 6;
|
||||
|
||||
m_vt.Update(m_vertices, m_count, GS_TRIANGLE_CLASS);
|
||||
}
|
||||
else
|
||||
{
|
||||
lines = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OI_FFX(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t)
|
||||
{
|
||||
uint32 FBP = m_context->FRAME.Block();
|
||||
uint32 ZBP = m_context->ZBUF.Block();
|
||||
uint32 TBP = m_context->TEX0.TBP0;
|
||||
|
||||
if((FBP == 0x00d00 || FBP == 0x00000) && ZBP == 0x02100 && PRIM->TME && TBP == 0x01a00 && m_context->TEX0.PSM == PSM_PSMCT16S)
|
||||
{
|
||||
// random battle transition (z buffer written directly, clear it now)
|
||||
|
||||
m_dev->ClearDepth(ds, 0);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OI_MetalSlug6(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t)
|
||||
{
|
||||
// missing red channel fix
|
||||
|
||||
for(int i = 0, j = m_count; i < j; i++)
|
||||
{
|
||||
if(m_vertices[i].r == 0 && m_vertices[i].g != 0 && m_vertices[i].b != 0)
|
||||
{
|
||||
m_vertices[i].r = (m_vertices[i].g + m_vertices[i].b) / 2;
|
||||
}
|
||||
}
|
||||
|
||||
m_vt.Update(m_vertices, m_count, m_vt.m_primclass);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OI_GodOfWar2(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t)
|
||||
{
|
||||
uint32 FBP = m_context->FRAME.Block();
|
||||
uint32 FBW = m_context->FRAME.FBW;
|
||||
uint32 FPSM = m_context->FRAME.PSM;
|
||||
|
||||
if((FBP == 0x00f00 || FBP == 0x00100) && FPSM == PSM_PSMZ24) // ntsc 0xf00, pal 0x100
|
||||
{
|
||||
// z buffer clear
|
||||
|
||||
GIFRegTEX0 TEX0;
|
||||
|
||||
TEX0.TBP0 = FBP;
|
||||
TEX0.TBW = FBW;
|
||||
TEX0.PSM = FPSM;
|
||||
|
||||
if(GSTextureCache::Target* ds = m_tc->LookupTarget(TEX0, m_width, m_height, GSTextureCache::DepthStencil, true))
|
||||
{
|
||||
m_dev->ClearDepth(ds->m_texture, 0);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OI_SimpsonsGame(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t)
|
||||
{
|
||||
uint32 FBP = m_context->FRAME.Block();
|
||||
uint32 FBW = m_context->FRAME.FBW;
|
||||
uint32 FPSM = m_context->FRAME.PSM;
|
||||
|
||||
if(FBP == 0x01800 && FPSM == PSM_PSMZ24)
|
||||
{
|
||||
// instead of just simply drawing a full height 512x512 sprite to clear the z buffer,
|
||||
// it uses a 512x256 sprite only, yet it is still able to fill the whole surface with zeros,
|
||||
// how? by using a render target that overlaps with the lower half of the z buffer...
|
||||
|
||||
m_dev->ClearDepth(ds, 0);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OI_RozenMaidenGebetGarden(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t)
|
||||
{
|
||||
if(!PRIM->TME)
|
||||
{
|
||||
uint32 FBP = m_context->FRAME.Block();
|
||||
uint32 ZBP = m_context->ZBUF.Block();
|
||||
|
||||
if(FBP == 0x008c0 && ZBP == 0x01a40)
|
||||
{
|
||||
// frame buffer clear, atst = fail, afail = write z only, z buffer points to frame buffer
|
||||
|
||||
GIFRegTEX0 TEX0;
|
||||
|
||||
TEX0.TBP0 = ZBP;
|
||||
TEX0.TBW = m_context->FRAME.FBW;
|
||||
TEX0.PSM = m_context->FRAME.PSM;
|
||||
|
||||
if(GSTextureCache::Target* rt = m_tc->LookupTarget(TEX0, m_width, m_height, GSTextureCache::RenderTarget, true))
|
||||
{
|
||||
m_dev->ClearRenderTarget(rt->m_texture, 0);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
else if(FBP == 0x00000 && m_context->ZBUF.Block() == 0x01180)
|
||||
{
|
||||
// z buffer clear, frame buffer now points to the z buffer (how can they be so clever?)
|
||||
|
||||
GIFRegTEX0 TEX0;
|
||||
|
||||
TEX0.TBP0 = FBP;
|
||||
TEX0.TBW = m_context->FRAME.FBW;
|
||||
TEX0.PSM = m_context->ZBUF.PSM;
|
||||
|
||||
if(GSTextureCache::Target* ds = m_tc->LookupTarget(TEX0, m_width, m_height, GSTextureCache::DepthStencil, true))
|
||||
{
|
||||
m_dev->ClearDepth(ds->m_texture, 0);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OI_PointListPalette(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t)
|
||||
{
|
||||
if(m_vt.m_primclass == GS_POINT_CLASS && !PRIM->TME)
|
||||
{
|
||||
uint32 FBP = m_context->FRAME.Block();
|
||||
uint32 FBW = m_context->FRAME.FBW;
|
||||
|
||||
if(FBP >= 0x03f40 && (FBP & 0x1f) == 0)
|
||||
{
|
||||
if(m_count == 16)
|
||||
{
|
||||
for(int i = 0; i < 16; i++)
|
||||
{
|
||||
m_vertices[i].a = m_vertices[i].a >= 0x80 ? 0xff : m_vertices[i].a * 2;
|
||||
|
||||
m_mem.WritePixel32(i & 7, i >> 3, m_vertices[i].c0, FBP, FBW);
|
||||
}
|
||||
|
||||
m_mem.m_clut.Invalidate();
|
||||
|
||||
return false;
|
||||
}
|
||||
else if(m_count == 256)
|
||||
{
|
||||
for(int i = 0; i < 256; i++)
|
||||
{
|
||||
m_vertices[i].a = m_vertices[i].a >= 0x80 ? 0xff : m_vertices[i].a * 2;
|
||||
|
||||
m_mem.WritePixel32(i & 15, i >> 4, m_vertices[i].c0, FBP, FBW);
|
||||
}
|
||||
|
||||
m_mem.m_clut.Invalidate();
|
||||
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void OO_DBZBT2()
|
||||
{
|
||||
// palette readback (cannot detect yet, when fetching the texture later)
|
||||
|
||||
uint32 FBP = m_context->FRAME.Block();
|
||||
uint32 TBP0 = m_context->TEX0.TBP0;
|
||||
|
||||
if(PRIM->TME && (FBP == 0x03c00 && TBP0 == 0x03c80 || FBP == 0x03ac0 && TBP0 == 0x03b40))
|
||||
{
|
||||
GIFRegBITBLTBUF BITBLTBUF;
|
||||
|
||||
BITBLTBUF.SBP = FBP;
|
||||
BITBLTBUF.SBW = 1;
|
||||
BITBLTBUF.SPSM = PSM_PSMCT32;
|
||||
|
||||
InvalidateLocalMem(BITBLTBUF, GSVector4i(0, 0, 64, 64));
|
||||
}
|
||||
}
|
||||
|
||||
void OO_MajokkoALaMode2()
|
||||
{
|
||||
// palette readback
|
||||
|
||||
uint32 FBP = m_context->FRAME.Block();
|
||||
|
||||
if(!PRIM->TME && FBP == 0x03f40)
|
||||
{
|
||||
GIFRegBITBLTBUF BITBLTBUF;
|
||||
|
||||
BITBLTBUF.SBP = FBP;
|
||||
BITBLTBUF.SBW = 1;
|
||||
BITBLTBUF.SPSM = PSM_PSMCT32;
|
||||
|
||||
InvalidateLocalMem(BITBLTBUF, GSVector4i(0, 0, 16, 16));
|
||||
}
|
||||
}
|
||||
|
||||
bool CU_DBZBT2()
|
||||
{
|
||||
// palette should stay 64 x 64
|
||||
|
||||
uint32 FBP = m_context->FRAME.Block();
|
||||
|
||||
return FBP != 0x03c00 && FBP != 0x03ac0;
|
||||
}
|
||||
|
||||
bool CU_MajokkoALaMode2()
|
||||
{
|
||||
// palette should stay 16 x 16
|
||||
|
||||
uint32 FBP = m_context->FRAME.Block();
|
||||
|
||||
return FBP != 0x03f40;
|
||||
}
|
||||
|
||||
bool CU_TalesOfAbyss()
|
||||
{
|
||||
// full image blur and brightening
|
||||
|
||||
uint32 FBP = m_context->FRAME.Block();
|
||||
|
||||
return FBP != 0x036e0 && FBP != 0x03560 && FBP != 0x038e0;
|
||||
}
|
||||
|
||||
class Hacks
|
||||
{
|
||||
template<class T> struct HackEntry
|
||||
{
|
||||
CRC::Title title;
|
||||
CRC::Region region;
|
||||
T func;
|
||||
|
||||
struct HackEntry(CRC::Title t, CRC::Region r, T f)
|
||||
{
|
||||
title = t;
|
||||
region = r;
|
||||
func = f;
|
||||
}
|
||||
};
|
||||
|
||||
template<class T> class FunctionMap : public GSFunctionMap<uint32, T>
|
||||
{
|
||||
list<HackEntry<T> >& m_tbl;
|
||||
|
||||
T GetDefaultFunction(uint32 key)
|
||||
{
|
||||
CRC::Title title = (CRC::Title)(key & 0xffffff);
|
||||
CRC::Region region = (CRC::Region)(key >> 24);
|
||||
|
||||
for(list<HackEntry<T> >::iterator i = m_tbl.begin(); i != m_tbl.end(); i++)
|
||||
{
|
||||
if(i->title == title && (i->region == CRC::RegionCount || i->region == region))
|
||||
{
|
||||
return i->func;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
public:
|
||||
FunctionMap(list<HackEntry<T> >& tbl) : m_tbl(tbl) {}
|
||||
};
|
||||
|
||||
list<HackEntry<OI_Ptr> > m_oi_list;
|
||||
list<HackEntry<OO_Ptr> > m_oo_list;
|
||||
list<HackEntry<CU_Ptr> > m_cu_list;
|
||||
|
||||
FunctionMap<OI_Ptr> m_oi_map;
|
||||
FunctionMap<OO_Ptr> m_oo_map;
|
||||
FunctionMap<CU_Ptr> m_cu_map;
|
||||
|
||||
public:
|
||||
OI_Ptr m_oi;
|
||||
OO_Ptr m_oo;
|
||||
CU_Ptr m_cu;
|
||||
|
||||
Hacks()
|
||||
: m_oi_map(m_oi_list)
|
||||
, m_oo_map(m_oo_list)
|
||||
, m_cu_map(m_cu_list)
|
||||
, m_oi(NULL)
|
||||
, m_oo(NULL)
|
||||
, m_cu(NULL)
|
||||
{
|
||||
m_oi_list.push_back(HackEntry<OI_Ptr>(CRC::FFXII, CRC::EU, &GSRendererHW::OI_FFXII));
|
||||
m_oi_list.push_back(HackEntry<OI_Ptr>(CRC::FFX, CRC::RegionCount, &GSRendererHW::OI_FFX));
|
||||
m_oi_list.push_back(HackEntry<OI_Ptr>(CRC::MetalSlug6, CRC::RegionCount, &GSRendererHW::OI_MetalSlug6));
|
||||
m_oi_list.push_back(HackEntry<OI_Ptr>(CRC::GodOfWar2, CRC::RegionCount, &GSRendererHW::OI_GodOfWar2));
|
||||
m_oi_list.push_back(HackEntry<OI_Ptr>(CRC::SimpsonsGame, CRC::RegionCount, &GSRendererHW::OI_SimpsonsGame));
|
||||
m_oi_list.push_back(HackEntry<OI_Ptr>(CRC::RozenMaidenGebetGarden, CRC::RegionCount, &GSRendererHW::OI_RozenMaidenGebetGarden));
|
||||
|
||||
m_oo_list.push_back(HackEntry<OO_Ptr>(CRC::DBZBT2, CRC::RegionCount, &GSRendererHW::OO_DBZBT2));
|
||||
m_oo_list.push_back(HackEntry<OO_Ptr>(CRC::MajokkoALaMode2, CRC::RegionCount, &GSRendererHW::OO_MajokkoALaMode2));
|
||||
|
||||
m_cu_list.push_back(HackEntry<CU_Ptr>(CRC::DBZBT2, CRC::RegionCount, &GSRendererHW::CU_DBZBT2));
|
||||
m_cu_list.push_back(HackEntry<CU_Ptr>(CRC::MajokkoALaMode2, CRC::RegionCount, &GSRendererHW::CU_MajokkoALaMode2));
|
||||
m_cu_list.push_back(HackEntry<CU_Ptr>(CRC::TalesOfAbyss, CRC::RegionCount, &GSRendererHW::CU_TalesOfAbyss));
|
||||
}
|
||||
|
||||
void SetGame(const CRC::Game& game)
|
||||
{
|
||||
uint32 hash = (uint32)((game.region << 24) | game.title);
|
||||
|
||||
m_oi = m_oi_map[hash];
|
||||
m_oo = m_oo_map[hash];
|
||||
m_cu = m_cu_map[hash];
|
||||
|
||||
if(game.flags & CRC::PointListPalette)
|
||||
{
|
||||
ASSERT(m_oi == NULL);
|
||||
|
||||
m_oi = &GSRendererHW::OI_PointListPalette;
|
||||
}
|
||||
}
|
||||
|
||||
} m_hacks;
|
||||
|
||||
#pragma endregion
|
||||
|
||||
protected:
|
||||
GSTextureCache* m_tc;
|
||||
|
||||
|
@ -103,22 +517,20 @@ protected:
|
|||
{
|
||||
// printf("[%d] InvalidateVideoMem %d,%d - %d,%d %05x (%d)\n", (int)m_perfmon.GetFrame(), r.left, r.top, r.right, r.bottom, (int)BITBLTBUF.DBP, (int)BITBLTBUF.DPSM);
|
||||
|
||||
m_tc->InvalidateVideoMem(BITBLTBUF, r);
|
||||
m_tc->InvalidateVideoMem(m_mem.GetOffset(BITBLTBUF.DBP, BITBLTBUF.DBW, BITBLTBUF.DPSM), r);
|
||||
}
|
||||
|
||||
void InvalidateLocalMem(const GIFRegBITBLTBUF& BITBLTBUF, const GSVector4i& r)
|
||||
{
|
||||
// printf("[%d] InvalidateLocalMem %d,%d - %d,%d %05x (%d)\n", (int)m_perfmon.GetFrame(), r.left, r.top, r.right, r.bottom, (int)BITBLTBUF.SBP, (int)BITBLTBUF.SPSM);
|
||||
|
||||
m_tc->InvalidateLocalMem(BITBLTBUF, r);
|
||||
m_tc->InvalidateLocalMem(m_mem.GetOffset(BITBLTBUF.SBP, BITBLTBUF.SBW, BITBLTBUF.SPSM), r);
|
||||
}
|
||||
|
||||
void Draw()
|
||||
{
|
||||
if(IsBadFrame(m_skip)) return;
|
||||
|
||||
m_vt.Update(m_vertices, m_count, GSUtil::GetPrimClass(PRIM->PRIM), PRIM, m_context);
|
||||
|
||||
GSDrawingEnvironment& env = m_env;
|
||||
GSDrawingContext* context = m_context;
|
||||
|
||||
|
@ -194,9 +606,7 @@ protected:
|
|||
s_n++;
|
||||
}
|
||||
|
||||
int prim = PRIM->PRIM;
|
||||
|
||||
if(!OverrideInput(prim, rt->m_texture, ds->m_texture, tex))
|
||||
if(m_hacks.m_oi && !(this->*m_hacks.m_oi)(rt->m_texture, ds->m_texture, tex))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -223,7 +633,7 @@ protected:
|
|||
|
||||
//
|
||||
|
||||
Draw(GSUtil::GetPrimClass(prim), rt->m_texture, ds->m_texture, tex);
|
||||
Draw(rt->m_texture, ds->m_texture, tex);
|
||||
|
||||
//
|
||||
|
||||
|
@ -235,29 +645,26 @@ protected:
|
|||
|
||||
GSVector4i r = GSVector4i(m_vt.m_min.p.xyxy(m_vt.m_max.p)).rintersect(GSVector4i(m_context->scissor.in));
|
||||
|
||||
GIFRegBITBLTBUF BITBLTBUF;
|
||||
|
||||
BITBLTBUF.DBW = context->FRAME.FBW;
|
||||
|
||||
if(fm != 0xffffffff)
|
||||
{
|
||||
BITBLTBUF.DBP = context->FRAME.Block();
|
||||
BITBLTBUF.DPSM = context->FRAME.PSM;
|
||||
rt->m_valid = rt->m_valid.runion(r);
|
||||
|
||||
m_tc->InvalidateVideoMem(BITBLTBUF, r, false);
|
||||
m_tc->InvalidateVideoMem(m_context->offset.fb, r, false);
|
||||
}
|
||||
|
||||
if(zm != 0xffffffff)
|
||||
{
|
||||
BITBLTBUF.DBP = context->ZBUF.Block();
|
||||
BITBLTBUF.DPSM = context->ZBUF.PSM;
|
||||
ds->m_valid = ds->m_valid.runion(r);
|
||||
|
||||
m_tc->InvalidateVideoMem(BITBLTBUF, r, false);
|
||||
m_tc->InvalidateVideoMem(m_context->offset.zb, r, false);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
OverrideOutput();
|
||||
if(m_hacks.m_oo)
|
||||
{
|
||||
(this->*m_hacks.m_oo)();
|
||||
}
|
||||
|
||||
if(s_dump)
|
||||
{
|
||||
|
@ -283,297 +690,15 @@ protected:
|
|||
}
|
||||
}
|
||||
|
||||
virtual void Draw(GS_PRIM_CLASS primclass, GSTexture* rt, GSTexture* ds, GSTextureCache::Source* tex) = 0;
|
||||
|
||||
virtual bool OverrideInput(int& prim, GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t)
|
||||
{
|
||||
#pragma region ffxii pal video conversion
|
||||
|
||||
if(m_game.title == CRC::FFXII && m_game.region == CRC::EU)
|
||||
{
|
||||
static uint32* video = NULL;
|
||||
static bool ok = false;
|
||||
|
||||
if(prim == GS_POINTLIST && m_count >= 448 * 448 && m_count <= 448 * 512)
|
||||
{
|
||||
// incoming pixels are stored in columns, one column is 16x512, total res 448x512 or 448x454
|
||||
|
||||
if(!video) video = new uint32[512 * 512];
|
||||
|
||||
for(int x = 0, i = 0, rows = m_count / 448; x < 448; x += 16)
|
||||
{
|
||||
uint32* dst = &video[x];
|
||||
|
||||
for(int y = 0; y < rows; y++, dst += 512)
|
||||
{
|
||||
for(int j = 0; j < 16; j++, i++)
|
||||
{
|
||||
dst[j] = m_vertices[i].c0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ok = true;
|
||||
|
||||
return false;
|
||||
}
|
||||
else if(prim == GS_LINELIST && m_count == 512 * 2 && ok)
|
||||
{
|
||||
// normally, this step would copy the video onto screen with 512 texture mapped horizontal lines,
|
||||
// but we use the stored video data to create a new texture, and replace the lines with two triangles
|
||||
|
||||
ok = false;
|
||||
|
||||
m_dev->Recycle(t->m_texture);
|
||||
|
||||
t->m_texture = m_dev->CreateTexture(512, 512);
|
||||
|
||||
t->m_texture->Update(GSVector4i(0, 0, 448, 512), video, 512 * 4);
|
||||
|
||||
m_vertices[0] = m_vertices[0];
|
||||
m_vertices[1] = m_vertices[1];
|
||||
m_vertices[2] = m_vertices[m_count - 2];
|
||||
m_vertices[3] = m_vertices[1];
|
||||
m_vertices[4] = m_vertices[2];
|
||||
m_vertices[5] = m_vertices[m_count - 1];
|
||||
|
||||
prim = GS_TRIANGLELIST;
|
||||
m_count = 6;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region ffx random battle transition (z buffer written directly, clear it now)
|
||||
|
||||
if(m_game.title == CRC::FFX)
|
||||
{
|
||||
uint32 FBP = m_context->FRAME.Block();
|
||||
uint32 ZBP = m_context->ZBUF.Block();
|
||||
uint32 TBP = m_context->TEX0.TBP0;
|
||||
|
||||
if((FBP == 0x00d00 || FBP == 0x00000) && ZBP == 0x02100 && PRIM->TME && TBP == 0x01a00 && m_context->TEX0.PSM == PSM_PSMCT16S)
|
||||
{
|
||||
m_dev->ClearDepth(ds, 0);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region metal slug missing red channel fix
|
||||
|
||||
if(m_game.title == CRC::MetalSlug6)
|
||||
{
|
||||
for(int i = 0, j = m_count; i < j; i++)
|
||||
{
|
||||
if(m_vertices[i].r == 0 && m_vertices[i].g != 0 && m_vertices[i].b != 0)
|
||||
{
|
||||
m_vertices[i].r = (m_vertices[i].g + m_vertices[i].b) / 2;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region palette uploaded in a point list, pure genius...
|
||||
|
||||
if(m_game.flags & CRC::PointListPalette)
|
||||
{
|
||||
if(prim == GS_POINTLIST && !PRIM->TME)
|
||||
{
|
||||
uint32 bp = m_context->FRAME.Block();
|
||||
uint32 bw = m_context->FRAME.FBW;
|
||||
|
||||
if(bp >= 0x03f40 && (bp & 0x1f) == 0)
|
||||
{
|
||||
if(m_count == 16)
|
||||
{
|
||||
for(int i = 0; i < 16; i++)
|
||||
{
|
||||
m_vertices[i].a = m_vertices[i].a >= 0x80 ? 0xff : m_vertices[i].a * 2;
|
||||
|
||||
m_mem.WritePixel32(i & 7, i >> 3, m_vertices[i].c0, bp, bw);
|
||||
}
|
||||
|
||||
m_mem.m_clut.Invalidate();
|
||||
|
||||
return false;
|
||||
}
|
||||
else if(m_count == 256)
|
||||
{
|
||||
for(int i = 0; i < 256; i++)
|
||||
{
|
||||
m_vertices[i].a = m_vertices[i].a >= 0x80 ? 0xff : m_vertices[i].a * 2;
|
||||
|
||||
m_mem.WritePixel32(i & 15, i >> 4, m_vertices[i].c0, bp, bw);
|
||||
}
|
||||
|
||||
m_mem.m_clut.Invalidate();
|
||||
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region GoW2 z buffer clear
|
||||
|
||||
if(m_game.title == CRC::GodOfWar2)
|
||||
{
|
||||
uint32 FBP = m_context->FRAME.Block();
|
||||
uint32 FBW = m_context->FRAME.FBW;
|
||||
uint32 FPSM = m_context->FRAME.PSM;
|
||||
|
||||
if((FBP == 0x00f00 || FBP == 0x00100) && FPSM == PSM_PSMZ24) // ntsc 0xf00, pal 0x100
|
||||
{
|
||||
GIFRegTEX0 TEX0;
|
||||
|
||||
TEX0.TBP0 = FBP;
|
||||
TEX0.TBW = FBW;
|
||||
TEX0.PSM = FPSM;
|
||||
|
||||
if(GSTextureCache::Target* ds = m_tc->LookupTarget(TEX0, m_width, m_height, GSTextureCache::DepthStencil, true))
|
||||
{
|
||||
m_dev->ClearDepth(ds->m_texture, 0);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Simpsons Game z buffer clear
|
||||
|
||||
if(m_game.title == CRC::SimpsonsGame)
|
||||
{
|
||||
uint32 FBP = m_context->FRAME.Block();
|
||||
uint32 FBW = m_context->FRAME.FBW;
|
||||
uint32 FPSM = m_context->FRAME.PSM;
|
||||
|
||||
if(FBP == 0x01800 && FPSM == PSM_PSMZ24)
|
||||
{
|
||||
// instead of just simply drawing a full height 512x512 sprite to clear the z buffer,
|
||||
// it uses a 512x256 sprite only, yet it is still able to fill the whole surface with zeros,
|
||||
// how? by using a render target that overlaps with the lower half of the z buffer...
|
||||
|
||||
m_dev->ClearDepth(ds, 0);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void OverrideOutput()
|
||||
{
|
||||
#pragma region dbzbt2 palette readback (cannot detect yet, when fetching the texture later)
|
||||
|
||||
if(m_game.title == CRC::DBZBT2)
|
||||
{
|
||||
uint32 FBP = m_context->FRAME.Block();
|
||||
uint32 TBP0 = m_context->TEX0.TBP0;
|
||||
|
||||
if(PRIM->TME && (FBP == 0x03c00 && TBP0 == 0x03c80 || FBP == 0x03ac0 && TBP0 == 0x03b40))
|
||||
{
|
||||
GIFRegBITBLTBUF BITBLTBUF;
|
||||
|
||||
BITBLTBUF.SBP = FBP;
|
||||
BITBLTBUF.SBW = 1;
|
||||
BITBLTBUF.SPSM = PSM_PSMCT32;
|
||||
|
||||
InvalidateLocalMem(BITBLTBUF, GSVector4i(0, 0, 64, 64));
|
||||
}
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region MajokkoALaMode2 palette readback
|
||||
|
||||
if(m_game.title == CRC::MajokkoALaMode2)
|
||||
{
|
||||
uint32 FBP = m_context->FRAME.Block();
|
||||
|
||||
if(!PRIM->TME && FBP == 0x03f40)
|
||||
{
|
||||
GIFRegBITBLTBUF BITBLTBUF;
|
||||
|
||||
BITBLTBUF.SBP = FBP;
|
||||
BITBLTBUF.SBW = 1;
|
||||
BITBLTBUF.SPSM = PSM_PSMCT32;
|
||||
|
||||
InvalidateLocalMem(BITBLTBUF, GSVector4i(0, 0, 16, 16));
|
||||
}
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
}
|
||||
virtual void Draw(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* tex) = 0;
|
||||
|
||||
bool CanUpscale()
|
||||
{
|
||||
#pragma region dbzbt2 palette should stay 64 x 64
|
||||
|
||||
if(m_game.title == CRC::DBZBT2)
|
||||
if(m_hacks.m_cu && !(this->*m_hacks.m_cu)())
|
||||
{
|
||||
uint32 FBP = m_context->FRAME.Block();
|
||||
|
||||
if(FBP == 0x03c00 || FBP == 0x03ac0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region MajokkoALaMode2 palette should stay 16 x 16
|
||||
|
||||
if(m_game.title == CRC::MajokkoALaMode2)
|
||||
{
|
||||
uint32 FBP = m_context->FRAME.Block();
|
||||
|
||||
if(FBP == 0x03f40)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region TalesOfAbyss full image blur and brightening
|
||||
|
||||
if(m_game.title == CRC::TalesOfAbyss)
|
||||
{
|
||||
uint32 FBP = m_context->FRAME.Block();
|
||||
|
||||
if(FBP == 0x036e0 || FBP == 0x03560 || FBP == 0x038e0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
return __super::CanUpscale();
|
||||
}
|
||||
|
||||
|
@ -602,6 +727,8 @@ public:
|
|||
{
|
||||
__super::SetGameCRC(crc, options);
|
||||
|
||||
m_hacks.SetGame(m_game);
|
||||
|
||||
if(m_game.title == CRC::JackieChanAdv)
|
||||
{
|
||||
m_width = 1280; // TODO: uses a 1280px wide 16 bit render target, but this only fixes half of the problem
|
||||
|
|
|
@ -30,9 +30,9 @@ GSRendererOGL::GSRendererOGL(uint8* base, bool mt, void (*irq)())
|
|||
InitVertexKick<GSRendererOGL>();
|
||||
}
|
||||
|
||||
bool GSRendererOGL::Create(const string& title)
|
||||
bool GSRendererOGL::Create(const string& title, int w, int h)
|
||||
{
|
||||
if(!__super::Create(title))
|
||||
if(!__super::Create(title, w, h))
|
||||
return false;
|
||||
|
||||
// TODO
|
||||
|
@ -64,7 +64,7 @@ void GSRendererOGL::VertexKick(bool skip)
|
|||
}
|
||||
}
|
||||
|
||||
void GSRendererOGL::Draw(int prim, GSTexture* rt, GSTexture* ds, GSTextureCache::Source* tex)
|
||||
void GSRendererOGL::Draw(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* tex)
|
||||
{
|
||||
GSDrawingEnvironment& env = m_env;
|
||||
GSDrawingContext* context = m_context;
|
||||
|
|
|
@ -29,12 +29,12 @@
|
|||
class GSRendererOGL : public GSRendererHW<GSVertexOGL>
|
||||
{
|
||||
protected:
|
||||
void Draw(int prim, GSTexture* rt, GSTexture* ds, GSTextureCache::Source* tex);
|
||||
void Draw(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* tex);
|
||||
|
||||
public:
|
||||
GSRendererOGL(uint8* base, bool mt, void (*irq)());
|
||||
|
||||
bool Create(const string& title);
|
||||
bool Create(const string& title, int w, int h);
|
||||
|
||||
template<uint32 prim, uint32 tme, uint32 fst> void VertexKick(bool skip);
|
||||
};
|
|
@ -86,13 +86,7 @@ GSTexture* GSRendererSW::GetOutput(int i)
|
|||
{
|
||||
const GSRegDISPFB& DISPFB = m_regs->DISP[i].DISPFB;
|
||||
|
||||
GIFRegTEX0 TEX0;
|
||||
|
||||
TEX0.TBP0 = DISPFB.Block();
|
||||
TEX0.TBW = DISPFB.FBW;
|
||||
TEX0.PSM = DISPFB.PSM;
|
||||
|
||||
int w = TEX0.TBW * 64;
|
||||
int w = DISPFB.FBW * 64;
|
||||
int h = GetFrameRect(i).bottom;
|
||||
|
||||
// TODO: round up bottom
|
||||
|
@ -105,7 +99,9 @@ GSTexture* GSRendererSW::GetOutput(int i)
|
|||
|
||||
GSVector4i r(0, 0, w, h);
|
||||
|
||||
m_mem.ReadTexture(r, buff, pitch, TEX0, m_env.TEXA);
|
||||
const GSLocalMemory::psm_t& psm = GSLocalMemory::m_psm[DISPFB.PSM];
|
||||
|
||||
(m_mem.*psm.rtx)(m_mem.GetOffset(DISPFB.Block(), DISPFB.FBW, DISPFB.PSM), r.ralign<GSVector4i::Outside>(psm.bs), buff, pitch, m_env.TEXA);
|
||||
|
||||
m_texture[i]->Update(r, buff, pitch);
|
||||
|
||||
|
@ -113,7 +109,7 @@ GSTexture* GSRendererSW::GetOutput(int i)
|
|||
{
|
||||
if(s_save && s_n >= s_saven)
|
||||
{
|
||||
m_texture[i]->Save(format("c:\\temp1\\_%05d_f%I64d_fr%d_%05x_%d.bmp", s_n, m_perfmon.GetFrame(), i, (int)TEX0.TBP0, (int)TEX0.PSM));
|
||||
m_texture[i]->Save(format("c:\\temp1\\_%05d_f%I64d_fr%d_%05x_%d.bmp", s_n, m_perfmon.GetFrame(), i, (int)DISPFB.Block(), (int)DISPFB.PSM));
|
||||
}
|
||||
|
||||
s_n++;
|
||||
|
@ -125,18 +121,14 @@ GSTexture* GSRendererSW::GetOutput(int i)
|
|||
|
||||
void GSRendererSW::Draw()
|
||||
{
|
||||
GS_PRIM_CLASS primclass = GSUtil::GetPrimClass(PRIM->PRIM);
|
||||
|
||||
m_vt.Update(m_vertices, m_count, primclass, PRIM, m_context);
|
||||
|
||||
if(m_dump)
|
||||
{
|
||||
m_dump.Object(m_vertices, m_count, primclass);
|
||||
m_dump.Object(m_vertices, m_count, m_vt.m_primclass);
|
||||
}
|
||||
|
||||
GSScanlineParam p;
|
||||
|
||||
GetScanlineParam(p, primclass);
|
||||
GetScanlineParam(p, m_vt.m_primclass);
|
||||
|
||||
if((p.fm & p.zm) == 0xffffffff)
|
||||
{
|
||||
|
@ -179,7 +171,7 @@ void GSRendererSW::Draw()
|
|||
|
||||
data.scissor = GSVector4i(m_context->scissor.in);
|
||||
data.scissor.z = min(data.scissor.z, (int)m_context->FRAME.FBW * 64); // TODO: find a game that overflows and check which one is the right behaviour
|
||||
data.primclass = primclass;
|
||||
data.primclass = m_vt.m_primclass;
|
||||
data.vertices = m_vertices;
|
||||
data.count = m_count;
|
||||
data.param = &p;
|
||||
|
@ -190,30 +182,19 @@ void GSRendererSW::Draw()
|
|||
|
||||
m_rl.GetStats(stats);
|
||||
|
||||
m_perfmon.Put(GSPerfMon::Draw, 1);
|
||||
m_perfmon.Put(GSPerfMon::Prim, stats.prims);
|
||||
m_perfmon.Put(GSPerfMon::Fillrate, stats.pixels);
|
||||
|
||||
GSVector4i r = GSVector4i(m_vt.m_min.p.xyxy(m_vt.m_max.p)).rintersect(data.scissor);
|
||||
|
||||
GIFRegBITBLTBUF BITBLTBUF;
|
||||
|
||||
BITBLTBUF.DBW = m_context->FRAME.FBW;
|
||||
|
||||
if(p.fm != 0xffffffff)
|
||||
{
|
||||
BITBLTBUF.DBP = m_context->FRAME.Block();
|
||||
BITBLTBUF.DPSM = m_context->FRAME.PSM;
|
||||
|
||||
m_tc->InvalidateVideoMem(BITBLTBUF, r);
|
||||
m_tc->InvalidateVideoMem(m_context->offset.fb, r);
|
||||
}
|
||||
|
||||
if(p.zm != 0xffffffff)
|
||||
{
|
||||
BITBLTBUF.DBP = m_context->ZBUF.Block();
|
||||
BITBLTBUF.DPSM = m_context->ZBUF.PSM;
|
||||
|
||||
m_tc->InvalidateVideoMem(BITBLTBUF, r);
|
||||
m_tc->InvalidateVideoMem(m_context->offset.zb, r);
|
||||
}
|
||||
|
||||
if(s_dump)
|
||||
|
@ -251,7 +232,7 @@ void GSRendererSW::Draw()
|
|||
|
||||
void GSRendererSW::InvalidateVideoMem(const GIFRegBITBLTBUF& BITBLTBUF, const GSVector4i& r)
|
||||
{
|
||||
m_tc->InvalidateVideoMem(BITBLTBUF, r);
|
||||
m_tc->InvalidateVideoMem(m_mem.GetOffset(BITBLTBUF.DBP, BITBLTBUF.DBW, BITBLTBUF.DPSM), r);
|
||||
}
|
||||
|
||||
void GSRendererSW::GetScanlineParam(GSScanlineParam& p, GS_PRIM_CLASS primclass)
|
||||
|
@ -261,9 +242,9 @@ void GSRendererSW::GetScanlineParam(GSScanlineParam& p, GS_PRIM_CLASS primclass)
|
|||
|
||||
p.vm = m_mem.m_vm8;
|
||||
|
||||
p.fbo = m_mem.GetPixelOffset(context->FRAME.Block(), context->FRAME.FBW, context->FRAME.PSM);
|
||||
p.zbo = m_mem.GetPixelOffset(context->ZBUF.Block(), context->FRAME.FBW, context->ZBUF.PSM);
|
||||
p.fzbo = m_mem.GetPixelOffset4(context->FRAME, context->ZBUF);
|
||||
p.fbo = context->offset.fb;
|
||||
p.zbo = context->offset.zb;
|
||||
p.fzbo = context->offset.fzb;
|
||||
|
||||
p.sel.key = 0;
|
||||
|
||||
|
@ -305,7 +286,7 @@ void GSRendererSW::GetScanlineParam(GSScanlineParam& p, GS_PRIM_CLASS primclass)
|
|||
|
||||
if(fwrite || ftest)
|
||||
{
|
||||
p.sel.fpsm = GSUtil::EncodePSM(context->FRAME.PSM);
|
||||
p.sel.fpsm = GSLocalMemory::m_psm[context->FRAME.PSM].fmt;
|
||||
|
||||
if((primclass == GS_LINE_CLASS || primclass == GS_TRIANGLE_CLASS) && m_vt.m_eq.rgba != 0xffff)
|
||||
{
|
||||
|
@ -322,7 +303,7 @@ void GSRendererSW::GetScanlineParam(GSScanlineParam& p, GS_PRIM_CLASS primclass)
|
|||
p.sel.wms = context->CLAMP.WMS;
|
||||
p.sel.wmt = context->CLAMP.WMT;
|
||||
|
||||
if(/*p.sel.iip == 0 &&*/ p.sel.tfx == TFX_MODULATE && p.sel.tcc && m_vt.m_eq.rgba == 0xffff && m_vt.m_min.c.eq(GSVector4i(128)))
|
||||
if(p.sel.tfx == TFX_MODULATE && p.sel.tcc && m_vt.m_eq.rgba == 0xffff && m_vt.m_min.c.eq(GSVector4i(128)))
|
||||
{
|
||||
// modulate does not do anything when vertex color is 0x80
|
||||
|
||||
|
@ -433,15 +414,15 @@ void GSRendererSW::GetScanlineParam(GSScanlineParam& p, GS_PRIM_CLASS primclass)
|
|||
}
|
||||
|
||||
bool zwrite = p.zm != 0xffffffff;
|
||||
bool ztest = context->TEST.ZTE && context->TEST.ZTST > 1;
|
||||
bool ztest = context->TEST.ZTE && context->TEST.ZTST > ZTST_ALWAYS;
|
||||
|
||||
p.sel.zwrite = zwrite;
|
||||
p.sel.ztest = ztest;
|
||||
|
||||
if(zwrite || ztest)
|
||||
{
|
||||
p.sel.zpsm = GSUtil::EncodePSM(context->ZBUF.PSM);
|
||||
p.sel.ztst = ztest ? context->TEST.ZTST : 1;
|
||||
p.sel.zpsm = GSLocalMemory::m_psm[context->ZBUF.PSM].fmt;
|
||||
p.sel.ztst = ztest ? context->TEST.ZTST : ZTST_ALWAYS;
|
||||
p.sel.zoverflow = GSVector4i(m_vt.m_max.p).z == 0x80000000;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -108,9 +108,9 @@ __declspec(align(16)) struct GSScanlineParam
|
|||
const uint32* clut;
|
||||
uint32 tw;
|
||||
|
||||
GSLocalMemory::PixelOffset* fbo;
|
||||
GSLocalMemory::PixelOffset* zbo;
|
||||
GSLocalMemory::PixelOffset4* fzbo;
|
||||
GSOffset* fbo;
|
||||
GSOffset* zbo;
|
||||
GSPixelOffset4* fzbo;
|
||||
|
||||
uint32 fm, zm;
|
||||
};
|
||||
|
|
|
@ -79,7 +79,7 @@ void GSSettingsDlg::OnInit()
|
|||
memset(&mode, 0, sizeof(mode));
|
||||
m_modes.push_back(mode);
|
||||
|
||||
ComboBoxAppend(IDC_RESOLUTION, "Windowed", (LPARAM)&m_modes.back(), true);
|
||||
ComboBoxAppend(IDC_RESOLUTION, "Please select...", (LPARAM)&m_modes.back(), true);
|
||||
|
||||
if(CComPtr<IDirect3D9> d3d = Direct3DCreate9(D3D_SDK_VERSION))
|
||||
{
|
||||
|
@ -120,6 +120,7 @@ void GSSettingsDlg::OnInit()
|
|||
ComboBoxInit(IDC_INTERLACE, g_interlace, countof(g_interlace), theApp.GetConfig("Interlace", 0));
|
||||
ComboBoxInit(IDC_ASPECTRATIO, g_aspectratio, countof(g_aspectratio), theApp.GetConfig("AspectRatio", 1));
|
||||
|
||||
CheckDlgButton(m_hWnd, IDC_WINDOWED, theApp.GetConfig("windowed", 1));
|
||||
CheckDlgButton(m_hWnd, IDC_FILTER, theApp.GetConfig("filter", 2));
|
||||
CheckDlgButton(m_hWnd, IDC_PALTEX, theApp.GetConfig("paltex", 1));
|
||||
CheckDlgButton(m_hWnd, IDC_VSYNC, theApp.GetConfig("vsync", 0));
|
||||
|
@ -179,6 +180,7 @@ bool GSSettingsDlg::OnCommand(HWND hWnd, UINT id, UINT code)
|
|||
theApp.SetConfig("AspectRatio", (int)data);
|
||||
}
|
||||
|
||||
theApp.SetConfig("windowed", (int)IsDlgButtonChecked(m_hWnd, IDC_WINDOWED));
|
||||
theApp.SetConfig("filter", (int)IsDlgButtonChecked(m_hWnd, IDC_FILTER));
|
||||
theApp.SetConfig("paltex", (int)IsDlgButtonChecked(m_hWnd, IDC_PALTEX));
|
||||
theApp.SetConfig("vsync", (int)IsDlgButtonChecked(m_hWnd, IDC_VSYNC));
|
||||
|
@ -215,7 +217,7 @@ void GSSettingsDlg::UpdateControls()
|
|||
// TODO: ShowWindow(GetDlgItem(m_hWnd, IDC_LOGO11), dx11 ? SW_SHOW : SW_HIDE);
|
||||
// TODO: ShowWindow(GetDlgItem(m_hWnd, IDC_LOGO_OGL), ogl ? SW_SHOW : SW_HIDE);
|
||||
|
||||
EnableWindow(GetDlgItem(m_hWnd, IDC_RESOLUTION), dx9);
|
||||
EnableWindow(GetDlgItem(m_hWnd, IDC_WINDOWED), dx9);
|
||||
EnableWindow(GetDlgItem(m_hWnd, IDC_RESX), hw && !native);
|
||||
EnableWindow(GetDlgItem(m_hWnd, IDC_RESX_EDIT), hw && !native);
|
||||
EnableWindow(GetDlgItem(m_hWnd, IDC_RESY), hw && !native);
|
||||
|
|
|
@ -32,6 +32,7 @@ GSState::GSState(uint8* base, bool mt, void (*irq)())
|
|||
, m_vprim(1)
|
||||
, m_version(5)
|
||||
, m_frameskip(0)
|
||||
, m_framelimit(true)
|
||||
, m_vkf(NULL)
|
||||
{
|
||||
m_sssize = 0;
|
||||
|
@ -421,7 +422,7 @@ void GSState::GIFRegHandlerPRIM(GIFReg* r)
|
|||
|
||||
if(GSUtil::GetPrimClass(m_env.PRIM.PRIM) == GSUtil::GetPrimClass(r->PRIM.PRIM))
|
||||
{
|
||||
if(((m_env.PRIM.u64 ^ r->PRIM.u64) & ~7) != 0)
|
||||
if((m_env.PRIM.u32[0] ^ r->PRIM.u32[0]) & 0x7f8) // all fields except PRIM
|
||||
{
|
||||
Flush();
|
||||
}
|
||||
|
@ -489,18 +490,23 @@ template<int i> void GSState::GIFRegHandlerTEX0(GIFReg* r)
|
|||
Flush();
|
||||
}
|
||||
|
||||
m_env.CTXT[i].TEX0 = (GSVector4i)r->TEX0;
|
||||
if(r->TEX0.TW > 10) r->TEX0.TW = 10;
|
||||
if(r->TEX0.TH > 10) r->TEX0.TH = 10;
|
||||
|
||||
if(m_env.CTXT[i].TEX0.TW > 10) m_env.CTXT[i].TEX0.TW = 10;
|
||||
if(m_env.CTXT[i].TEX0.TH > 10) m_env.CTXT[i].TEX0.TH = 10;
|
||||
r->TEX0.CPSM &= 0xa; // 1010b
|
||||
|
||||
m_env.CTXT[i].TEX0.CPSM &= 0xa; // 1010b
|
||||
|
||||
if((m_env.CTXT[i].TEX0.TBW & 1) && (m_env.CTXT[i].TEX0.PSM == PSM_PSMT8 || m_env.CTXT[i].TEX0.PSM == PSM_PSMT4))
|
||||
if((r->TEX0.TBW & 1) && (r->TEX0.PSM == PSM_PSMT8 || r->TEX0.PSM == PSM_PSMT4))
|
||||
{
|
||||
m_env.CTXT[i].TEX0.TBW &= ~1; // GS User 2.6
|
||||
r->TEX0.TBW &= ~1; // GS User 2.6
|
||||
}
|
||||
|
||||
if((r->TEX0.u32[0] ^ m_env.CTXT[i].TEX0.u32[0]) & 0x3ffffff) // TBP0 TBW PSM
|
||||
{
|
||||
m_env.CTXT[i].offset.tex = m_mem.GetOffset(r->TEX0.TBP0, r->TEX0.TBW, r->TEX0.PSM);
|
||||
}
|
||||
|
||||
m_env.CTXT[i].TEX0 = (GSVector4i)r->TEX0;
|
||||
|
||||
if(wt)
|
||||
{
|
||||
m_mem.m_clut.Write(m_env.CTXT[i].TEX0, m_env.TEXCLUT);
|
||||
|
@ -791,6 +797,13 @@ template<int i> void GSState::GIFRegHandlerFRAME(GIFReg* r)
|
|||
Flush();
|
||||
}
|
||||
|
||||
if((m_env.CTXT[i].FRAME.u32[0] ^ r->FRAME.u32[0]) & 0x3f3f01ff) // FBP FBW PSM
|
||||
{
|
||||
m_env.CTXT[i].offset.fb = m_mem.GetOffset(r->FRAME.Block(), r->FRAME.FBW, r->FRAME.PSM);
|
||||
m_env.CTXT[i].offset.zb = m_mem.GetOffset(m_env.CTXT[i].ZBUF.Block(), r->FRAME.FBW, m_env.CTXT[i].ZBUF.PSM);
|
||||
m_env.CTXT[i].offset.fzb = m_mem.GetPixelOffset4(r->FRAME, m_env.CTXT[i].ZBUF);
|
||||
}
|
||||
|
||||
m_env.CTXT[i].FRAME = (GSVector4i)r->FRAME;
|
||||
}
|
||||
|
||||
|
@ -805,20 +818,26 @@ template<int i> void GSState::GIFRegHandlerZBUF(GIFReg* r)
|
|||
|
||||
r->ZBUF.PSM |= 0x30;
|
||||
|
||||
if(r->ZBUF.PSM != PSM_PSMZ32
|
||||
&& r->ZBUF.PSM != PSM_PSMZ24
|
||||
&& r->ZBUF.PSM != PSM_PSMZ16
|
||||
&& r->ZBUF.PSM != PSM_PSMZ16S)
|
||||
{
|
||||
r->ZBUF.PSM = PSM_PSMZ32;
|
||||
}
|
||||
|
||||
if(PRIM->CTXT == i && r->ZBUF != m_env.CTXT[i].ZBUF)
|
||||
{
|
||||
Flush();
|
||||
}
|
||||
|
||||
m_env.CTXT[i].ZBUF = (GSVector4i)r->ZBUF;
|
||||
|
||||
if(m_env.CTXT[i].ZBUF.PSM != PSM_PSMZ32
|
||||
&& m_env.CTXT[i].ZBUF.PSM != PSM_PSMZ24
|
||||
&& m_env.CTXT[i].ZBUF.PSM != PSM_PSMZ16
|
||||
&& m_env.CTXT[i].ZBUF.PSM != PSM_PSMZ16S)
|
||||
if((m_env.CTXT[i].ZBUF.u32[0] ^ r->ZBUF.u32[0]) & 0x3f0001ff) // ZBP PSM
|
||||
{
|
||||
m_env.CTXT[i].ZBUF.PSM = PSM_PSMZ32;
|
||||
m_env.CTXT[i].offset.zb = m_mem.GetOffset(r->ZBUF.Block(), m_env.CTXT[i].FRAME.FBW, r->ZBUF.PSM);
|
||||
m_env.CTXT[i].offset.fzb = m_mem.GetPixelOffset4(m_env.CTXT[i].FRAME, r->ZBUF);
|
||||
}
|
||||
|
||||
m_env.CTXT[i].ZBUF = (GSVector4i)r->ZBUF;
|
||||
}
|
||||
|
||||
void GSState::GIFRegHandlerBITBLTBUF(GIFReg* r)
|
||||
|
@ -1083,13 +1102,13 @@ void GSState::Move()
|
|||
|
||||
// TODO: unroll inner loops (width has special size requirement, must be multiples of 1 << n, depending on the format)
|
||||
|
||||
GSLocalMemory::PixelOffset* RESTRICT spo = m_mem.GetPixelOffset(m_env.BITBLTBUF.SBP, m_env.BITBLTBUF.SBW, m_env.BITBLTBUF.SPSM);
|
||||
GSLocalMemory::PixelOffset* RESTRICT dpo = m_mem.GetPixelOffset(m_env.BITBLTBUF.DBP, m_env.BITBLTBUF.DBW, m_env.BITBLTBUF.DPSM);
|
||||
GSOffset* RESTRICT spo = m_mem.GetOffset(m_env.BITBLTBUF.SBP, m_env.BITBLTBUF.SBW, m_env.BITBLTBUF.SPSM);
|
||||
GSOffset* RESTRICT dpo = m_mem.GetOffset(m_env.BITBLTBUF.DBP, m_env.BITBLTBUF.DBW, m_env.BITBLTBUF.DPSM);
|
||||
|
||||
if(spsm.trbpp == dpsm.trbpp && spsm.trbpp >= 16)
|
||||
{
|
||||
int* RESTRICT scol = &spo->col[0][sx];
|
||||
int* RESTRICT dcol = &dpo->col[0][dx];
|
||||
int* RESTRICT scol = &spo->pixel.col[0][sx];
|
||||
int* RESTRICT dcol = &dpo->pixel.col[0][dx];
|
||||
|
||||
if(spsm.trbpp == 32)
|
||||
{
|
||||
|
@ -1097,8 +1116,8 @@ void GSState::Move()
|
|||
{
|
||||
for(int y = 0; y < h; y++, sy += yinc, dy += yinc)
|
||||
{
|
||||
uint32* RESTRICT s = &m_mem.m_vm32[spo->row[sy]];
|
||||
uint32* RESTRICT d = &m_mem.m_vm32[dpo->row[dy]];
|
||||
uint32* RESTRICT s = &m_mem.m_vm32[spo->pixel.row[sy]];
|
||||
uint32* RESTRICT d = &m_mem.m_vm32[dpo->pixel.row[dy]];
|
||||
|
||||
for(int x = 0; x < w; x++) d[dcol[x]] = s[scol[x]];
|
||||
}
|
||||
|
@ -1107,8 +1126,8 @@ void GSState::Move()
|
|||
{
|
||||
for(int y = 0; y < h; y++, sy += yinc, dy += yinc)
|
||||
{
|
||||
uint32* RESTRICT s = &m_mem.m_vm32[spo->row[sy]];
|
||||
uint32* RESTRICT d = &m_mem.m_vm32[dpo->row[dy]];
|
||||
uint32* RESTRICT s = &m_mem.m_vm32[spo->pixel.row[sy]];
|
||||
uint32* RESTRICT d = &m_mem.m_vm32[dpo->pixel.row[dy]];
|
||||
|
||||
for(int x = 0; x > -w; x--) d[dcol[x]] = s[scol[x]];
|
||||
}
|
||||
|
@ -1120,8 +1139,8 @@ void GSState::Move()
|
|||
{
|
||||
for(int y = 0; y < h; y++, sy += yinc, dy += yinc)
|
||||
{
|
||||
uint32* RESTRICT s = &m_mem.m_vm32[spo->row[sy]];
|
||||
uint32* RESTRICT d = &m_mem.m_vm32[dpo->row[dy]];
|
||||
uint32* RESTRICT s = &m_mem.m_vm32[spo->pixel.row[sy]];
|
||||
uint32* RESTRICT d = &m_mem.m_vm32[dpo->pixel.row[dy]];
|
||||
|
||||
for(int x = 0; x < w; x++) d[dcol[x]] = (d[dcol[x]] & 0xff000000) | (s[scol[x]] & 0x00ffffff);
|
||||
}
|
||||
|
@ -1130,8 +1149,8 @@ void GSState::Move()
|
|||
{
|
||||
for(int y = 0; y < h; y++, sy += yinc, dy += yinc)
|
||||
{
|
||||
uint32* RESTRICT s = &m_mem.m_vm32[spo->row[sy]];
|
||||
uint32* RESTRICT d = &m_mem.m_vm32[dpo->row[dy]];
|
||||
uint32* RESTRICT s = &m_mem.m_vm32[spo->pixel.row[sy]];
|
||||
uint32* RESTRICT d = &m_mem.m_vm32[dpo->pixel.row[dy]];
|
||||
|
||||
for(int x = 0; x > -w; x--) d[dcol[x]] = (d[dcol[x]] & 0xff000000) | (s[scol[x]] & 0x00ffffff);
|
||||
}
|
||||
|
@ -1143,8 +1162,8 @@ void GSState::Move()
|
|||
{
|
||||
for(int y = 0; y < h; y++, sy += yinc, dy += yinc)
|
||||
{
|
||||
uint16* RESTRICT s = &m_mem.m_vm16[spo->row[sy]];
|
||||
uint16* RESTRICT d = &m_mem.m_vm16[dpo->row[dy]];
|
||||
uint16* RESTRICT s = &m_mem.m_vm16[spo->pixel.row[sy]];
|
||||
uint16* RESTRICT d = &m_mem.m_vm16[dpo->pixel.row[dy]];
|
||||
|
||||
for(int x = 0; x < w; x++) d[dcol[x]] = s[scol[x]];
|
||||
}
|
||||
|
@ -1153,8 +1172,8 @@ void GSState::Move()
|
|||
{
|
||||
for(int y = 0; y < h; y++, sy += yinc, dy += yinc)
|
||||
{
|
||||
uint16* RESTRICT s = &m_mem.m_vm16[spo->row[sy]];
|
||||
uint16* RESTRICT d = &m_mem.m_vm16[dpo->row[dy]];
|
||||
uint16* RESTRICT s = &m_mem.m_vm16[spo->pixel.row[sy]];
|
||||
uint16* RESTRICT d = &m_mem.m_vm16[dpo->pixel.row[dy]];
|
||||
|
||||
for(int x = 0; x > -w; x--) d[dcol[x]] = s[scol[x]];
|
||||
}
|
||||
|
@ -1167,11 +1186,11 @@ void GSState::Move()
|
|||
{
|
||||
for(int y = 0; y < h; y++, sy += yinc, dy += yinc)
|
||||
{
|
||||
uint8* RESTRICT s = &m_mem.m_vm8[spo->row[sy]];
|
||||
uint8* RESTRICT d = &m_mem.m_vm8[dpo->row[dy]];
|
||||
uint8* RESTRICT s = &m_mem.m_vm8[spo->pixel.row[sy]];
|
||||
uint8* RESTRICT d = &m_mem.m_vm8[dpo->pixel.row[dy]];
|
||||
|
||||
int* RESTRICT scol = &spo->col[sy & 7][sx];
|
||||
int* RESTRICT dcol = &dpo->col[dy & 7][dx];
|
||||
int* RESTRICT scol = &spo->pixel.col[sy & 7][sx];
|
||||
int* RESTRICT dcol = &dpo->pixel.col[dy & 7][dx];
|
||||
|
||||
for(int x = 0; x < w; x++) d[dcol[x]] = s[scol[x]];
|
||||
}
|
||||
|
@ -1180,11 +1199,11 @@ void GSState::Move()
|
|||
{
|
||||
for(int y = 0; y < h; y++, sy += yinc, dy += yinc)
|
||||
{
|
||||
uint8* RESTRICT s = &m_mem.m_vm8[spo->row[sy]];
|
||||
uint8* RESTRICT d = &m_mem.m_vm8[dpo->row[dy]];
|
||||
uint8* RESTRICT s = &m_mem.m_vm8[spo->pixel.row[sy]];
|
||||
uint8* RESTRICT d = &m_mem.m_vm8[dpo->pixel.row[dy]];
|
||||
|
||||
int* RESTRICT scol = &spo->col[sy & 7][sx];
|
||||
int* RESTRICT dcol = &dpo->col[dy & 7][dx];
|
||||
int* RESTRICT scol = &spo->pixel.col[sy & 7][sx];
|
||||
int* RESTRICT dcol = &dpo->pixel.col[dy & 7][dx];
|
||||
|
||||
for(int x = 0; x > -w; x--) d[dcol[x]] = s[scol[x]];
|
||||
}
|
||||
|
@ -1196,11 +1215,11 @@ void GSState::Move()
|
|||
{
|
||||
for(int y = 0; y < h; y++, sy += yinc, dy += yinc)
|
||||
{
|
||||
uint32 sbase = spo->row[sy];
|
||||
uint32 dbase = dpo->row[dy];
|
||||
uint32 sbase = spo->pixel.row[sy];
|
||||
uint32 dbase = dpo->pixel.row[dy];
|
||||
|
||||
int* RESTRICT scol = &spo->col[sy & 7][sx];
|
||||
int* RESTRICT dcol = &dpo->col[dy & 7][dx];
|
||||
int* RESTRICT scol = &spo->pixel.col[sy & 7][sx];
|
||||
int* RESTRICT dcol = &dpo->pixel.col[dy & 7][dx];
|
||||
|
||||
for(int x = 0; x < w; x++) m_mem.WritePixel4(dbase + dcol[x], m_mem.ReadPixel4(sbase + scol[x]));
|
||||
}
|
||||
|
@ -1209,11 +1228,11 @@ void GSState::Move()
|
|||
{
|
||||
for(int y = 0; y < h; y++, sy += yinc, dy += yinc)
|
||||
{
|
||||
uint32 sbase = spo->row[sy];
|
||||
uint32 dbase = dpo->row[dy];
|
||||
uint32 sbase = spo->pixel.row[sy];
|
||||
uint32 dbase = dpo->pixel.row[dy];
|
||||
|
||||
int* RESTRICT scol = &spo->col[sy & 7][sx];
|
||||
int* RESTRICT dcol = &dpo->col[dy & 7][dx];
|
||||
int* RESTRICT scol = &spo->pixel.col[sy & 7][sx];
|
||||
int* RESTRICT dcol = &dpo->pixel.col[dy & 7][dx];
|
||||
|
||||
for(int x = 0; x > -w; x--) m_mem.WritePixel4(dbase + dcol[x], m_mem.ReadPixel4(sbase + scol[x]));
|
||||
}
|
||||
|
@ -1225,11 +1244,11 @@ void GSState::Move()
|
|||
{
|
||||
for(int y = 0; y < h; y++, sy += yinc, dy += yinc)
|
||||
{
|
||||
uint32 sbase = spo->row[sy];
|
||||
uint32 dbase = dpo->row[dy];
|
||||
uint32 sbase = spo->pixel.row[sy];
|
||||
uint32 dbase = dpo->pixel.row[dy];
|
||||
|
||||
int* RESTRICT scol = &spo->col[sy & 7][sx];
|
||||
int* RESTRICT dcol = &dpo->col[dy & 7][dx];
|
||||
int* RESTRICT scol = &spo->pixel.col[sy & 7][sx];
|
||||
int* RESTRICT dcol = &dpo->pixel.col[dy & 7][dx];
|
||||
|
||||
for(int x = 0; x < w; x++) (m_mem.*dpsm.wpa)(dbase + dcol[x], (m_mem.*spsm.rpa)(sbase + scol[x]));
|
||||
}
|
||||
|
@ -1238,11 +1257,11 @@ void GSState::Move()
|
|||
{
|
||||
for(int y = 0; y < h; y++, sy += yinc, dy += yinc)
|
||||
{
|
||||
uint32 sbase = spo->row[sy];
|
||||
uint32 dbase = dpo->row[dy];
|
||||
uint32 sbase = spo->pixel.row[sy];
|
||||
uint32 dbase = dpo->pixel.row[dy];
|
||||
|
||||
int* RESTRICT scol = &spo->col[sy & 7][sx];
|
||||
int* RESTRICT dcol = &dpo->col[dy & 7][dx];
|
||||
int* RESTRICT scol = &spo->pixel.col[sy & 7][sx];
|
||||
int* RESTRICT dcol = &dpo->pixel.col[dy & 7][dx];
|
||||
|
||||
for(int x = 0; x > -w; x--) (m_mem.*dpsm.wpa)(dbase + dcol[x], (m_mem.*spsm.rpa)(sbase + scol[x]));
|
||||
}
|
||||
|
@ -1648,8 +1667,15 @@ int GSState::Defrost(const GSFreezeData* fd)
|
|||
|
||||
m_env.UpdateDIMX();
|
||||
|
||||
m_env.CTXT[0].UpdateScissor();
|
||||
m_env.CTXT[1].UpdateScissor();
|
||||
for(int i = 0; i < 2; i++)
|
||||
{
|
||||
m_env.CTXT[i].UpdateScissor();
|
||||
|
||||
m_env.CTXT[i].offset.fb = m_mem.GetOffset(m_env.CTXT[i].FRAME.Block(), m_env.CTXT[i].FRAME.FBW, m_env.CTXT[i].FRAME.PSM);
|
||||
m_env.CTXT[i].offset.zb = m_mem.GetOffset(m_env.CTXT[i].ZBUF.Block(), m_env.CTXT[i].FRAME.FBW, m_env.CTXT[i].ZBUF.PSM);
|
||||
m_env.CTXT[i].offset.tex = m_mem.GetOffset(m_env.CTXT[i].TEX0.TBP0, m_env.CTXT[i].TEX0.TBW, m_env.CTXT[i].TEX0.PSM);
|
||||
m_env.CTXT[i].offset.fzb = m_mem.GetPixelOffset4(m_env.CTXT[i].FRAME, m_env.CTXT[i].ZBUF);
|
||||
}
|
||||
|
||||
m_perfmon.SetFrame(5000);
|
||||
|
||||
|
@ -1663,13 +1689,13 @@ void GSState::SetGameCRC(uint32 crc, int options)
|
|||
m_game = CRC::Lookup(crc);
|
||||
}
|
||||
|
||||
void GSState::SetFrameSkip(int frameskip)
|
||||
void GSState::SetFrameSkip(int skip)
|
||||
{
|
||||
if(m_frameskip != frameskip)
|
||||
if(m_frameskip != skip)
|
||||
{
|
||||
m_frameskip = frameskip;
|
||||
m_frameskip = skip;
|
||||
|
||||
if(frameskip)
|
||||
if(skip)
|
||||
{
|
||||
m_fpGIFPackedRegHandlers[GIF_REG_PRIM] = &GSState::GIFPackedRegHandlerNOP;
|
||||
m_fpGIFPackedRegHandlers[GIF_REG_RGBA] = &GSState::GIFPackedRegHandlerNOP;
|
||||
|
@ -1722,6 +1748,11 @@ void GSState::SetFrameSkip(int frameskip)
|
|||
}
|
||||
}
|
||||
|
||||
void GSState::SetFrameLimit(bool limit)
|
||||
{
|
||||
m_framelimit = limit;
|
||||
}
|
||||
|
||||
// GSTransferBuffer
|
||||
|
||||
GSState::GSTransferBuffer::GSTransferBuffer()
|
||||
|
@ -1941,9 +1972,9 @@ bool GSC_OnePieceGrandAdventure(const GSFrameInfo& fi, int& skip)
|
|||
{
|
||||
if(skip == 0)
|
||||
{
|
||||
if(fi.TME && fi.FBP == 0x02d00 && fi.FPSM == PSM_PSMCT16 && (fi.TBP0 == 0x00000 || fi.TBP0 == 0x00e00) && fi.TPSM == PSM_PSMCT16)
|
||||
if(fi.TME && fi.FBP == 0x02d00 && fi.FPSM == PSM_PSMCT16 && (fi.TBP0 == 0x00000 || fi.TBP0 == 0x00e00 || fi.TBP0 == 0x00f00) && fi.TPSM == PSM_PSMCT16)
|
||||
{
|
||||
skip = 3;
|
||||
skip = 4;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -210,6 +210,7 @@ public:
|
|||
uint32 m_crc;
|
||||
int m_options;
|
||||
int m_frameskip;
|
||||
bool m_framelimit;
|
||||
CRC::Game m_game;
|
||||
GSDump m_dump;
|
||||
|
||||
|
@ -247,6 +248,7 @@ public:
|
|||
int Defrost(const GSFreezeData* fd);
|
||||
void GetLastTag(uint32* tag) {*tag = m_path3hack; m_path3hack = 0;}
|
||||
virtual void SetGameCRC(uint32 crc, int options);
|
||||
void SetFrameSkip(int frameskip);
|
||||
void SetFrameSkip(int skip);
|
||||
void SetFrameLimit(bool limit);
|
||||
};
|
||||
|
||||
|
|
|
@ -27,20 +27,19 @@ class GSTexture
|
|||
{
|
||||
public:
|
||||
GSVector2 m_scale;
|
||||
GSVector2i m_size;
|
||||
|
||||
struct GSMap {uint8* bits; int pitch;};
|
||||
|
||||
enum {None, RenderTarget, DepthStencil, Texture, Offscreen};
|
||||
|
||||
public:
|
||||
GSTexture() : m_scale(1, 1) {}
|
||||
GSTexture() : m_scale(1, 1), m_size(0, 0) {}
|
||||
virtual ~GSTexture() {}
|
||||
|
||||
virtual operator bool() {ASSERT(0); return false;}
|
||||
|
||||
virtual int GetType() const = 0;
|
||||
virtual int GetWidth() const = 0;
|
||||
virtual int GetHeight() const = 0;
|
||||
virtual int GetFormat() const = 0;
|
||||
|
||||
virtual bool Update(const GSVector4i& r, const void* data, int pitch) = 0;
|
||||
|
@ -48,5 +47,8 @@ public:
|
|||
virtual void Unmap() = 0;
|
||||
virtual bool Save(const string& fn, bool dds = false) = 0;
|
||||
|
||||
GSVector2i GetSize() const {return GSVector2i(GetWidth(), GetHeight());}
|
||||
int GetWidth() const {return m_size.x;}
|
||||
int GetHeight() const {return m_size.y;}
|
||||
|
||||
GSVector2i GetSize() const {return m_size;}
|
||||
};
|
||||
|
|
|
@ -29,6 +29,9 @@ GSTexture10::GSTexture10(ID3D10Texture2D* texture)
|
|||
|
||||
m_texture->GetDevice(&m_dev);
|
||||
m_texture->GetDesc(&m_desc);
|
||||
|
||||
m_size.x = (int)m_desc.Width;
|
||||
m_size.y = (int)m_desc.Height;
|
||||
}
|
||||
|
||||
int GSTexture10::GetType() const
|
||||
|
@ -40,16 +43,6 @@ int GSTexture10::GetType() const
|
|||
return GSTexture::None;
|
||||
}
|
||||
|
||||
int GSTexture10::GetWidth() const
|
||||
{
|
||||
return m_desc.Width;
|
||||
}
|
||||
|
||||
int GSTexture10::GetHeight() const
|
||||
{
|
||||
return m_desc.Height;
|
||||
}
|
||||
|
||||
int GSTexture10::GetFormat() const
|
||||
{
|
||||
return m_desc.Format;
|
||||
|
|
|
@ -36,8 +36,6 @@ public:
|
|||
explicit GSTexture10(ID3D10Texture2D* texture);
|
||||
|
||||
int GetType() const;
|
||||
int GetWidth() const;
|
||||
int GetHeight() const;
|
||||
int GetFormat() const;
|
||||
|
||||
bool Update(const GSVector4i& r, const void* data, int pitch);
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue