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:
Jake.Stine 2009-07-23 14:58:17 +00:00
commit 3751c928d3
145 changed files with 7446 additions and 14899 deletions

View File

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

12
clean_msvc.cmd Normal file
View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

534
pcsx2/CDVD/CDVDaccess.cpp Normal file
View File

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

34
pcsx2/CDVD/CDVDaccess.h Normal file
View File

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

View File

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

View File

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

View File

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

View File

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

54
pcsx2/CDVD/IsoFScdvd.h Normal file
View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

109
pcsx2/CDVD/IsoFileFormats.h Normal file
View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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