Merge branch 'master' into wii-network
Conflicts: Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE.cpp
This commit is contained in:
+1
-1
@@ -466,7 +466,7 @@ else(SDL2_FOUND)
|
|||||||
else(SDL_FOUND)
|
else(SDL_FOUND)
|
||||||
# TODO: Use the prebuilt one on Windows
|
# TODO: Use the prebuilt one on Windows
|
||||||
message("Using static SDL from Externals")
|
message("Using static SDL from Externals")
|
||||||
include_directories(Externals/SDL Externals/SDL/include)
|
include_directories(Externals/SDL/SDL Externals/SDL Externals/SDL/include)
|
||||||
add_subdirectory(Externals/SDL)
|
add_subdirectory(Externals/SDL)
|
||||||
endif(SDL_FOUND)
|
endif(SDL_FOUND)
|
||||||
endif(SDL2_FOUND)
|
endif(SDL2_FOUND)
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
# GSSE8P - Sega Soccer Slam
|
# GSSE8P - Sega Soccer Slam
|
||||||
[Core] Values set here will override the main dolphin settings.
|
[Core] Values set here will override the main dolphin settings.
|
||||||
TLBHack = 0
|
|
||||||
[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set.
|
[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set.
|
||||||
EmulationIssues =
|
EmulationIssues = Needs real xfb for the videos to display.
|
||||||
|
EmulationStateId = 4
|
||||||
[OnFrame] Add memory patches to be applied every frame here.
|
[OnFrame] Add memory patches to be applied every frame here.
|
||||||
[ActionReplay] Add action replay cheats here.
|
[ActionReplay] Add action replay cheats here.
|
||||||
$Master Code
|
$Master Code
|
||||||
@@ -19,3 +19,14 @@ $SubZero Have Tons Of Cash
|
|||||||
0423C204 05F5E0FF
|
0423C204 05F5E0FF
|
||||||
$Volta Have Tons Of Cash
|
$Volta Have Tons Of Cash
|
||||||
0423CEA8 05F5E0FF
|
0423CEA8 05F5E0FF
|
||||||
|
[Video]
|
||||||
|
ProjectionHack = 0
|
||||||
|
PH_SZNear = 0
|
||||||
|
PH_SZFar = 0
|
||||||
|
PH_ExtraParam = 0
|
||||||
|
PH_ZNear =
|
||||||
|
PH_ZFar =
|
||||||
|
[Gecko]
|
||||||
|
[Video_Settings]
|
||||||
|
UseXFB = True
|
||||||
|
UseRealXFB = True
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
# GSSJ8P - Sega Soccer Slam
|
||||||
|
[Core] Values set here will override the main dolphin settings.
|
||||||
|
[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set.
|
||||||
|
EmulationIssues = Needs real xfb for the videos to display.
|
||||||
|
EmulationStateId = 4
|
||||||
|
[OnFrame] Add memory patches to be applied every frame here.
|
||||||
|
[ActionReplay] Add action replay cheats here.
|
||||||
|
[Video]
|
||||||
|
ProjectionHack = 0
|
||||||
|
PH_SZNear = 0
|
||||||
|
PH_SZFar = 0
|
||||||
|
PH_ExtraParam = 0
|
||||||
|
PH_ZNear =
|
||||||
|
PH_ZFar =
|
||||||
|
[Gecko]
|
||||||
|
[Video_Settings]
|
||||||
|
UseXFB = True
|
||||||
|
UseRealXFB = True
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
# GSSP70 - Sega Soccer Slam
|
||||||
|
[Core] Values set here will override the main dolphin settings.
|
||||||
|
[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set.
|
||||||
|
EmulationIssues = Needs real xfb for the videos to display.
|
||||||
|
EmulationStateId = 4
|
||||||
|
[OnFrame] Add memory patches to be applied every frame here.
|
||||||
|
[ActionReplay] Add action replay cheats here.
|
||||||
|
[Video]
|
||||||
|
ProjectionHack = 0
|
||||||
|
PH_SZNear = 0
|
||||||
|
PH_SZFar = 0
|
||||||
|
PH_ExtraParam = 0
|
||||||
|
PH_ZNear =
|
||||||
|
PH_ZFar =
|
||||||
|
[Gecko]
|
||||||
|
[Video_Settings]
|
||||||
|
UseXFB = True
|
||||||
|
UseRealXFB = True
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
# GSSP8P - Sega Soccer Slam
|
||||||
|
[Core] Values set here will override the main dolphin settings.
|
||||||
|
[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set.
|
||||||
|
EmulationIssues = Needs real xfb for the videos to display.
|
||||||
|
EmulationStateId = 4
|
||||||
|
[OnFrame] Add memory patches to be applied every frame here.
|
||||||
|
[ActionReplay] Add action replay cheats here.
|
||||||
|
[Video]
|
||||||
|
ProjectionHack = 0
|
||||||
|
PH_SZNear = 0
|
||||||
|
PH_SZFar = 0
|
||||||
|
PH_ExtraParam = 0
|
||||||
|
PH_ZNear =
|
||||||
|
PH_ZFar =
|
||||||
|
[Gecko]
|
||||||
|
[Video_Settings]
|
||||||
|
UseXFB = True
|
||||||
|
UseRealXFB = True
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
# GZPE70 - Zapper
|
||||||
|
[Core] Values set here will override the main dolphin settings.
|
||||||
|
[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set.
|
||||||
|
EmulationStateId = 4
|
||||||
|
EmulationIssues = Needs real xfb for the videos to display.
|
||||||
|
[OnFrame] Add memory patches to be applied every frame here.
|
||||||
|
[ActionReplay] Add action replay cheats here.
|
||||||
|
[Video]
|
||||||
|
ProjectionHack = 0
|
||||||
|
PH_SZNear = 0
|
||||||
|
PH_SZFar = 0
|
||||||
|
PH_ExtraParam = 0
|
||||||
|
PH_ZNear =
|
||||||
|
PH_ZFar =
|
||||||
|
[Gecko]
|
||||||
|
[Video_Settings]
|
||||||
|
UseXFB = True
|
||||||
|
UseRealXFB = True
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
# GZPP70 - Zapper
|
||||||
|
[Core] Values set here will override the main dolphin settings.
|
||||||
|
[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set.
|
||||||
|
EmulationStateId = 4
|
||||||
|
EmulationIssues = Needs real xfb for the videos to display.
|
||||||
|
[OnFrame] Add memory patches to be applied every frame here.
|
||||||
|
[ActionReplay] Add action replay cheats here.
|
||||||
|
[Video]
|
||||||
|
ProjectionHack = 0
|
||||||
|
PH_SZNear = 0
|
||||||
|
PH_SZFar = 0
|
||||||
|
PH_ExtraParam = 0
|
||||||
|
PH_ZNear =
|
||||||
|
PH_ZFar =
|
||||||
|
[Gecko]
|
||||||
|
[Video_Settings]
|
||||||
|
UseXFB = True
|
||||||
|
UseRealXFB = True
|
||||||
@@ -33,8 +33,7 @@ PH_ExtraParam = 1
|
|||||||
|
|
||||||
[5]
|
[5]
|
||||||
Title = Tales of Symphonia GC
|
Title = Tales of Symphonia GC
|
||||||
PH_ZNear = 0.5
|
PH_ZNear = 0.0002
|
||||||
PH_ZFar = 1
|
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------
|
# ---------------------------------------------------
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
# RH8E4F - Tomb Raider Underworld
|
||||||
|
[Core] Values set here will override the main dolphin settings.
|
||||||
|
[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set.
|
||||||
|
EmulationStateId = 4
|
||||||
|
EmulationIssues = Needs real Xfb for the videos to display.
|
||||||
|
[OnFrame] Add memory patches to be applied every frame here.
|
||||||
|
[ActionReplay] Add action replay cheats here.
|
||||||
|
[Video]
|
||||||
|
ProjectionHack = 0
|
||||||
|
PH_SZNear = 0
|
||||||
|
PH_SZFar = 0
|
||||||
|
PH_ExtraParam = 0
|
||||||
|
PH_ZNear =
|
||||||
|
PH_ZFar =
|
||||||
|
[Gecko]
|
||||||
|
[Video_Settings]
|
||||||
|
UseXFB = True
|
||||||
|
UseRealXFB = True
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
# RH8JEL - Tomb Raider Underworld
|
||||||
|
[Core] Values set here will override the main dolphin settings.
|
||||||
|
[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set.
|
||||||
|
EmulationStateId = 4
|
||||||
|
EmulationIssues = Needs real Xfb for the videos to display.
|
||||||
|
[OnFrame] Add memory patches to be applied every frame here.
|
||||||
|
[ActionReplay] Add action replay cheats here.
|
||||||
|
[Video]
|
||||||
|
ProjectionHack = 0
|
||||||
|
PH_SZNear = 0
|
||||||
|
PH_SZFar = 0
|
||||||
|
PH_ExtraParam = 0
|
||||||
|
PH_ZNear =
|
||||||
|
PH_ZFar =
|
||||||
|
[Gecko]
|
||||||
|
[Video_Settings]
|
||||||
|
UseXFB = True
|
||||||
|
UseRealXFB = True
|
||||||
@@ -1,9 +1,18 @@
|
|||||||
# RH8P4F - Tomb Raider Eight
|
# RH8P4F - Tomb Raider Underworld
|
||||||
[Core] Values set here will override the main dolphin settings.
|
[Core] Values set here will override the main dolphin settings.
|
||||||
[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set.
|
[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set.
|
||||||
EmulationStateId = 4
|
EmulationStateId = 4
|
||||||
EmulationIssues =
|
EmulationIssues = Needs real Xfb for the videos to display.
|
||||||
[OnFrame] Add memory patches to be applied every frame here.
|
[OnFrame] Add memory patches to be applied every frame here.
|
||||||
[ActionReplay] Add action replay cheats here.
|
[ActionReplay] Add action replay cheats here.
|
||||||
[Video]
|
[Video]
|
||||||
ProjectionHack = 0
|
ProjectionHack = 0
|
||||||
|
PH_SZNear = 0
|
||||||
|
PH_SZFar = 0
|
||||||
|
PH_ExtraParam = 0
|
||||||
|
PH_ZNear =
|
||||||
|
PH_ZFar =
|
||||||
|
[Gecko]
|
||||||
|
[Video_Settings]
|
||||||
|
UseXFB = True
|
||||||
|
UseRealXFB = True
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
# RH8X4F - Tomb Raider Underworld
|
||||||
|
[Core] Values set here will override the main dolphin settings.
|
||||||
|
[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set.
|
||||||
|
EmulationStateId = 4
|
||||||
|
EmulationIssues = Needs real Xfb for the videos to display.
|
||||||
|
[OnFrame] Add memory patches to be applied every frame here.
|
||||||
|
[ActionReplay] Add action replay cheats here.
|
||||||
|
[Video]
|
||||||
|
ProjectionHack = 0
|
||||||
|
PH_SZNear = 0
|
||||||
|
PH_SZFar = 0
|
||||||
|
PH_ExtraParam = 0
|
||||||
|
PH_ZNear =
|
||||||
|
PH_ZFar =
|
||||||
|
[Gecko]
|
||||||
|
[Video_Settings]
|
||||||
|
UseXFB = True
|
||||||
|
UseRealXFB = True
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
# RS5EC8 - SAMURAI WARRIORS KATANA
|
||||||
|
[Core] Values set here will override the main dolphin settings.
|
||||||
|
[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set.
|
||||||
|
EmulationStateId = 4
|
||||||
|
EmulationIssues =
|
||||||
|
[OnFrame] Add memory patches to be applied every frame here.
|
||||||
|
[ActionReplay] Add action replay cheats here.
|
||||||
|
[Video]
|
||||||
|
ProjectionHack = 0
|
||||||
|
PH_SZNear = 0
|
||||||
|
PH_SZFar = 0
|
||||||
|
PH_ExtraParam = 0
|
||||||
|
PH_ZNear =
|
||||||
|
PH_ZFar =
|
||||||
|
[Gecko]
|
||||||
|
[Video_Hacks]
|
||||||
|
EFBEmulateFormatChanges = True
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
# RS5JC8 - Sengoku Musou KATANA
|
||||||
|
[Core] Values set here will override the main dolphin settings.
|
||||||
|
[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set.
|
||||||
|
EmulationStateId = 4
|
||||||
|
EmulationIssues =
|
||||||
|
[OnFrame] Add memory patches to be applied every frame here.
|
||||||
|
[ActionReplay] Add action replay cheats here.
|
||||||
|
[Video]
|
||||||
|
ProjectionHack = 0
|
||||||
|
PH_SZNear = 0
|
||||||
|
PH_SZFar = 0
|
||||||
|
PH_ExtraParam = 0
|
||||||
|
PH_ZNear =
|
||||||
|
PH_ZFar =
|
||||||
|
[Gecko]
|
||||||
|
[Video_Hacks]
|
||||||
|
EFBEmulateFormatChanges = True
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
# RS5PC8 - SAMURAI WARRIORS KATANA
|
||||||
|
[Core] Values set here will override the main dolphin settings.
|
||||||
|
[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set.
|
||||||
|
EmulationStateId = 4
|
||||||
|
EmulationIssues =
|
||||||
|
[OnFrame] Add memory patches to be applied every frame here.
|
||||||
|
[ActionReplay] Add action replay cheats here.
|
||||||
|
[Video]
|
||||||
|
ProjectionHack = 0
|
||||||
|
PH_SZNear = 0
|
||||||
|
PH_SZFar = 0
|
||||||
|
PH_ExtraParam = 0
|
||||||
|
PH_ZNear =
|
||||||
|
PH_ZFar =
|
||||||
|
[Gecko]
|
||||||
|
[Video_Hacks]
|
||||||
|
EFBEmulateFormatChanges = True
|
||||||
@@ -7,7 +7,11 @@ CPP_FILE_LIST=$(find $SRCDIR \( -name '*.cpp' -o -name '*.h' -o -name '*.c' \) \
|
|||||||
xgettext -d dolphin-emu -s --keyword=_ --keyword=wxTRANSLATE --keyword=SuccessAlertT \
|
xgettext -d dolphin-emu -s --keyword=_ --keyword=wxTRANSLATE --keyword=SuccessAlertT \
|
||||||
--keyword=PanicAlertT --keyword=PanicYesNoT --keyword=AskYesNoT --keyword=_trans \
|
--keyword=PanicAlertT --keyword=PanicYesNoT --keyword=AskYesNoT --keyword=_trans \
|
||||||
--keyword=CriticalAlertT --add-comments=i18n -p ./Languages/po -o dolphin-emu.pot \
|
--keyword=CriticalAlertT --add-comments=i18n -p ./Languages/po -o dolphin-emu.pot \
|
||||||
$CPP_FILE_LIST --package-name="Dolphin Emu"
|
$CPP_FILE_LIST --package-name="Dolphin Emulator"
|
||||||
|
|
||||||
|
sed -i "s/SOME DESCRIPTIVE TITLE\./Translation of dolphin-emu.pot to LANGUAGE/" Languages/po/dolphin-emu.pot
|
||||||
|
sed -i "s/YEAR THE PACKAGE'S COPYRIGHT HOLDER/2003-2013/" Languages/po/dolphin-emu.pot
|
||||||
|
sed -i "s/license as the PACKAGE package/license as the dolphin-emu package/" Languages/po/dolphin-emu.pot
|
||||||
|
|
||||||
POTFILE=./Languages/po/dolphin-emu.pot
|
POTFILE=./Languages/po/dolphin-emu.pot
|
||||||
PO_FILES=$(find ./Languages/po -name '*.po')
|
PO_FILES=$(find ./Languages/po -name '*.po')
|
||||||
|
|||||||
+291
-293
File diff suppressed because it is too large
Load Diff
+220
-201
File diff suppressed because it is too large
Load Diff
+221
-201
File diff suppressed because it is too large
Load Diff
+219
-201
File diff suppressed because it is too large
Load Diff
+211
-202
File diff suppressed because it is too large
Load Diff
+221
-201
File diff suppressed because it is too large
Load Diff
+207
-198
File diff suppressed because it is too large
Load Diff
+275
-251
File diff suppressed because it is too large
Load Diff
+220
-200
File diff suppressed because it is too large
Load Diff
+243
-214
File diff suppressed because it is too large
Load Diff
+207
-198
File diff suppressed because it is too large
Load Diff
+220
-201
File diff suppressed because it is too large
Load Diff
+220
-202
File diff suppressed because it is too large
Load Diff
+247
-219
File diff suppressed because it is too large
Load Diff
+245
-218
File diff suppressed because it is too large
Load Diff
+220
-201
File diff suppressed because it is too large
Load Diff
+220
-201
File diff suppressed because it is too large
Load Diff
+221
-201
File diff suppressed because it is too large
Load Diff
+220
-201
File diff suppressed because it is too large
Load Diff
+243
-215
File diff suppressed because it is too large
Load Diff
+218
-200
File diff suppressed because it is too large
Load Diff
+207
-198
File diff suppressed because it is too large
Load Diff
+220
-201
File diff suppressed because it is too large
Load Diff
+219
-201
File diff suppressed because it is too large
Load Diff
+218
-200
File diff suppressed because it is too large
Load Diff
@@ -43,7 +43,8 @@ void MemArena::GrabLowMemSpace(size_t size)
|
|||||||
mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
|
mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
|
||||||
fd = open(ram_temp_file, O_RDWR | O_CREAT, mode);
|
fd = open(ram_temp_file, O_RDWR | O_CREAT, mode);
|
||||||
unlink(ram_temp_file);
|
unlink(ram_temp_file);
|
||||||
ftruncate(fd, size);
|
if (ftruncate(fd, size) < 0)
|
||||||
|
ERROR_LOG(MEMMAP, "Failed to allocate low memory space");
|
||||||
return;
|
return;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -117,7 +117,8 @@ void* AllocateAlignedMemory(size_t size,size_t alignment)
|
|||||||
void* ptr = _aligned_malloc(size,alignment);
|
void* ptr = _aligned_malloc(size,alignment);
|
||||||
#else
|
#else
|
||||||
void* ptr = NULL;
|
void* ptr = NULL;
|
||||||
posix_memalign(&ptr, alignment, size);
|
if (posix_memalign(&ptr, alignment, size) != 0)
|
||||||
|
ERROR_LOG(MEMMAP, "Failed to allocate aligned memory");
|
||||||
;
|
;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -69,7 +69,8 @@ std::string StringFromFormat(const char* format, ...)
|
|||||||
delete[] buf;
|
delete[] buf;
|
||||||
#else
|
#else
|
||||||
va_start(args, format);
|
va_start(args, format);
|
||||||
vasprintf(&buf, format, args);
|
if (vasprintf(&buf, format, args) < 0)
|
||||||
|
ERROR_LOG(COMMON, "Unable to allocate memory for string");
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
std::string temp = buf;
|
std::string temp = buf;
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ namespace BootManager
|
|||||||
struct ConfigCache
|
struct ConfigCache
|
||||||
{
|
{
|
||||||
bool valid, bCPUThread, bSkipIdle, bEnableFPRF, bMMU, bDCBZOFF,
|
bool valid, bCPUThread, bSkipIdle, bEnableFPRF, bMMU, bDCBZOFF,
|
||||||
bVBeam, bFastDiscSpeed, bMergeBlocks, bDSPHLE, bDisableWiimoteSpeaker, bHLE_BS2;
|
bVBeam, bFastDiscSpeed, bMergeBlocks, bDSPHLE, bHLE_BS2;
|
||||||
int iTLBHack, iCPUCore;
|
int iTLBHack, iCPUCore;
|
||||||
std::string strBackend;
|
std::string strBackend;
|
||||||
};
|
};
|
||||||
@@ -98,7 +98,6 @@ bool BootCore(const std::string& _rFilename)
|
|||||||
config_cache.bFastDiscSpeed = StartUp.bFastDiscSpeed;
|
config_cache.bFastDiscSpeed = StartUp.bFastDiscSpeed;
|
||||||
config_cache.bMergeBlocks = StartUp.bMergeBlocks;
|
config_cache.bMergeBlocks = StartUp.bMergeBlocks;
|
||||||
config_cache.bDSPHLE = StartUp.bDSPHLE;
|
config_cache.bDSPHLE = StartUp.bDSPHLE;
|
||||||
config_cache.bDisableWiimoteSpeaker = StartUp.bDisableWiimoteSpeaker;
|
|
||||||
config_cache.strBackend = StartUp.m_strVideoBackend;
|
config_cache.strBackend = StartUp.m_strVideoBackend;
|
||||||
config_cache.bHLE_BS2 = StartUp.bHLE_BS2;
|
config_cache.bHLE_BS2 = StartUp.bHLE_BS2;
|
||||||
|
|
||||||
@@ -113,7 +112,6 @@ bool BootCore(const std::string& _rFilename)
|
|||||||
game_ini.Get("Core", "FastDiscSpeed", &StartUp.bFastDiscSpeed, StartUp.bFastDiscSpeed);
|
game_ini.Get("Core", "FastDiscSpeed", &StartUp.bFastDiscSpeed, StartUp.bFastDiscSpeed);
|
||||||
game_ini.Get("Core", "BlockMerging", &StartUp.bMergeBlocks, StartUp.bMergeBlocks);
|
game_ini.Get("Core", "BlockMerging", &StartUp.bMergeBlocks, StartUp.bMergeBlocks);
|
||||||
game_ini.Get("Core", "DSPHLE", &StartUp.bDSPHLE, StartUp.bDSPHLE);
|
game_ini.Get("Core", "DSPHLE", &StartUp.bDSPHLE, StartUp.bDSPHLE);
|
||||||
game_ini.Get("Wii", "DisableWiimoteSpeaker",&StartUp.bDisableWiimoteSpeaker, StartUp.bDisableWiimoteSpeaker);
|
|
||||||
game_ini.Get("Core", "GFXBackend", &StartUp.m_strVideoBackend, StartUp.m_strVideoBackend.c_str());
|
game_ini.Get("Core", "GFXBackend", &StartUp.m_strVideoBackend, StartUp.m_strVideoBackend.c_str());
|
||||||
game_ini.Get("Core", "CPUCore", &StartUp.iCPUCore, StartUp.iCPUCore);
|
game_ini.Get("Core", "CPUCore", &StartUp.iCPUCore, StartUp.iCPUCore);
|
||||||
game_ini.Get("Core", "HLE_BS2", &StartUp.bHLE_BS2, StartUp.bHLE_BS2);
|
game_ini.Get("Core", "HLE_BS2", &StartUp.bHLE_BS2, StartUp.bHLE_BS2);
|
||||||
@@ -173,7 +171,6 @@ void Stop()
|
|||||||
StartUp.bFastDiscSpeed = config_cache.bFastDiscSpeed;
|
StartUp.bFastDiscSpeed = config_cache.bFastDiscSpeed;
|
||||||
StartUp.bMergeBlocks = config_cache.bMergeBlocks;
|
StartUp.bMergeBlocks = config_cache.bMergeBlocks;
|
||||||
StartUp.bDSPHLE = config_cache.bDSPHLE;
|
StartUp.bDSPHLE = config_cache.bDSPHLE;
|
||||||
StartUp.bDisableWiimoteSpeaker = config_cache.bDisableWiimoteSpeaker;
|
|
||||||
StartUp.m_strVideoBackend = config_cache.strBackend;
|
StartUp.m_strVideoBackend = config_cache.strBackend;
|
||||||
VideoBackend::ActivateBackend(StartUp.m_strVideoBackend);
|
VideoBackend::ActivateBackend(StartUp.m_strVideoBackend);
|
||||||
StartUp.bHLE_BS2 = config_cache.bHLE_BS2;
|
StartUp.bHLE_BS2 = config_cache.bHLE_BS2;
|
||||||
|
|||||||
@@ -51,8 +51,8 @@ SCoreStartupParameter::SCoreStartupParameter()
|
|||||||
bRunCompareServer(false), bRunCompareClient(false),
|
bRunCompareServer(false), bRunCompareClient(false),
|
||||||
bMMU(false), bDCBZOFF(false), iTLBHack(0), bVBeam(false),
|
bMMU(false), bDCBZOFF(false), iTLBHack(0), bVBeam(false),
|
||||||
bFastDiscSpeed(false),
|
bFastDiscSpeed(false),
|
||||||
SelectedLanguage(0), bWii(false), bDisableWiimoteSpeaker(false),
|
SelectedLanguage(0), bWii(false),
|
||||||
bConfirmStop(false), bHideCursor(false),
|
bConfirmStop(false), bHideCursor(false),
|
||||||
bAutoHideCursor(false), bUsePanicHandlers(true), bOnScreenDisplayMessages(true),
|
bAutoHideCursor(false), bUsePanicHandlers(true), bOnScreenDisplayMessages(true),
|
||||||
iRenderWindowXPos(-1), iRenderWindowYPos(-1),
|
iRenderWindowXPos(-1), iRenderWindowYPos(-1),
|
||||||
iRenderWindowWidth(640), iRenderWindowHeight(480),
|
iRenderWindowWidth(640), iRenderWindowHeight(480),
|
||||||
@@ -102,8 +102,6 @@ void SCoreStartupParameter::LoadDefaults()
|
|||||||
bJITPairedOff = false;
|
bJITPairedOff = false;
|
||||||
bJITSystemRegistersOff = false;
|
bJITSystemRegistersOff = false;
|
||||||
|
|
||||||
bDisableWiimoteSpeaker = false;
|
|
||||||
|
|
||||||
m_strName = "NONE";
|
m_strName = "NONE";
|
||||||
m_strUniqueID = "00000000";
|
m_strUniqueID = "00000000";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -124,7 +124,6 @@ struct SCoreStartupParameter
|
|||||||
int SelectedLanguage;
|
int SelectedLanguage;
|
||||||
|
|
||||||
bool bWii;
|
bool bWii;
|
||||||
bool bDisableWiimoteSpeaker;
|
|
||||||
|
|
||||||
// Interface settings
|
// Interface settings
|
||||||
bool bConfirmStop, bHideCursor, bAutoHideCursor, bUsePanicHandlers, bOnScreenDisplayMessages;
|
bool bConfirmStop, bHideCursor, bAutoHideCursor, bUsePanicHandlers, bOnScreenDisplayMessages;
|
||||||
|
|||||||
@@ -251,12 +251,11 @@ void Init()
|
|||||||
// Now the 1500 is a pure assumption
|
// Now the 1500 is a pure assumption
|
||||||
// We need to figure out the real frequency though
|
// We need to figure out the real frequency though
|
||||||
|
|
||||||
// FIXME: does Wiimote Speaker support really require a different interval? (issue 4608)
|
// FYI, WII_IPC_HLE_Interface::Update is also called in WII_IPCInterface::Write32
|
||||||
const int interval = SConfig::GetInstance().m_LocalCoreStartupParameter.
|
const int freq = 1500;
|
||||||
bDisableWiimoteSpeaker ? 15000 : 4000;
|
|
||||||
const int fields = SConfig::GetInstance().m_LocalCoreStartupParameter.
|
const int fields = SConfig::GetInstance().m_LocalCoreStartupParameter.
|
||||||
bVBeam ? 2 : 1;
|
bVBeam ? 2 : 1;
|
||||||
IPC_HLE_PERIOD = GetTicksPerSecond() / (interval * fields);
|
IPC_HLE_PERIOD = GetTicksPerSecond() / (freq * fields);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -221,6 +221,7 @@ void Write32(const u32 _Value, const u32 _Address)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WII_IPC_HLE_Interface::Update();
|
||||||
UpdateInterrupts();
|
UpdateInterrupts();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -184,7 +184,7 @@ int FindWiimotes(Wiimote** wm, int max_wiimotes)
|
|||||||
bool found = false;
|
bool found = false;
|
||||||
for(int i = 0; i < MAX_WIIMOTES; i++)
|
for(int i = 0; i < MAX_WIIMOTES; i++)
|
||||||
{
|
{
|
||||||
if(wm[i] && strcmp(wm[i]->devicepath, detail_data->DevicePath) == 0)
|
if(wm[i] && (wm[i]->devicepath == detail_data->DevicePath))
|
||||||
{
|
{
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
@@ -210,7 +210,7 @@ int FindWiimotes(Wiimote** wm, int max_wiimotes)
|
|||||||
for (; k < MAX_WIIMOTES && !(WIIMOTE_SRC_REAL & g_wiimote_sources[k] && !wm[k]); ++k);
|
for (; k < MAX_WIIMOTES && !(WIIMOTE_SRC_REAL & g_wiimote_sources[k] && !wm[k]); ++k);
|
||||||
wm[k] = new Wiimote(k);
|
wm[k] = new Wiimote(k);
|
||||||
wm[k]->dev_handle = dev;
|
wm[k]->dev_handle = dev;
|
||||||
memcpy(wm[k]->devicepath, detail_data->DevicePath, 197);
|
wm[k]->devicepath = detail_data->DevicePath;
|
||||||
|
|
||||||
if (!wm[k]->Connect())
|
if (!wm[k]->Connect())
|
||||||
{
|
{
|
||||||
@@ -240,7 +240,7 @@ bool Wiimote::Connect()
|
|||||||
|
|
||||||
if (!dev_handle)
|
if (!dev_handle)
|
||||||
{
|
{
|
||||||
dev_handle = CreateFile(devicepath,
|
dev_handle = CreateFile(devicepath.c_str(),
|
||||||
(GENERIC_READ | GENERIC_WRITE),
|
(GENERIC_READ | GENERIC_WRITE),
|
||||||
(FILE_SHARE_READ | FILE_SHARE_WRITE),
|
(FILE_SHARE_READ | FILE_SHARE_WRITE),
|
||||||
NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
|
NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
|
||||||
|
|||||||
@@ -181,23 +181,23 @@ bool Wiimote::Read()
|
|||||||
bool Wiimote::Write()
|
bool Wiimote::Write()
|
||||||
{
|
{
|
||||||
Report rpt;
|
Report rpt;
|
||||||
bool audio_written = false;
|
|
||||||
|
|
||||||
if (m_audio_reports.Pop(rpt))
|
if (last_audio_report.GetTimeDifference() > 5 && m_audio_reports.Pop(rpt))
|
||||||
{
|
{
|
||||||
IOWrite(rpt.first, rpt.second);
|
IOWrite(rpt.first, rpt.second);
|
||||||
|
last_audio_report.Update();
|
||||||
|
|
||||||
delete[] rpt.first;
|
delete[] rpt.first;
|
||||||
audio_written = true;
|
return true;
|
||||||
}
|
}
|
||||||
|
else if (m_write_reports.Pop(rpt))
|
||||||
if (m_write_reports.Pop(rpt))
|
|
||||||
{
|
{
|
||||||
IOWrite(rpt.first, rpt.second);
|
IOWrite(rpt.first, rpt.second);
|
||||||
delete[] rpt.first;
|
delete[] rpt.first;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return audio_written;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the next report that should be sent
|
// Returns the next report that should be sent
|
||||||
@@ -319,14 +319,9 @@ void Wiimote::ThreadFunc()
|
|||||||
while (Write()) {}
|
while (Write()) {}
|
||||||
Common::SleepCurrentThread(1);
|
Common::SleepCurrentThread(1);
|
||||||
#else
|
#else
|
||||||
bool read = false;
|
bool const did_something = Write() || Read();
|
||||||
while (Write() || (read = true, IsOpen() && Read()))
|
if (!did_something)
|
||||||
{
|
Common::SleepCurrentThread(1);
|
||||||
if (m_audio_reports.Size() && !read)
|
|
||||||
Read();
|
|
||||||
Common::SleepCurrentThread(m_audio_reports.Size() ? 5 : 2);
|
|
||||||
read = false;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
#include "ChunkFile.h"
|
#include "ChunkFile.h"
|
||||||
#include "Thread.h"
|
#include "Thread.h"
|
||||||
#include "FifoQueue.h"
|
#include "FifoQueue.h"
|
||||||
|
#include "Timer.h"
|
||||||
|
|
||||||
#include "../Wiimote.h"
|
#include "../Wiimote.h"
|
||||||
#include "../WiimoteEmu/WiimoteEmu.h"
|
#include "../WiimoteEmu/WiimoteEmu.h"
|
||||||
@@ -77,7 +78,7 @@ public:
|
|||||||
void Close();
|
void Close();
|
||||||
|
|
||||||
#elif defined(_WIN32)
|
#elif defined(_WIN32)
|
||||||
char devicepath[255]; // Unique wiimote reference
|
std::string devicepath; // Unique wiimote reference
|
||||||
//ULONGLONG btaddr; // Bluetooth address
|
//ULONGLONG btaddr; // Bluetooth address
|
||||||
HANDLE dev_handle; // HID handle
|
HANDLE dev_handle; // HID handle
|
||||||
OVERLAPPED hid_overlap; // Overlap handle
|
OVERLAPPED hid_overlap; // Overlap handle
|
||||||
@@ -103,6 +104,8 @@ private:
|
|||||||
Common::FifoQueue<Report> m_read_reports;
|
Common::FifoQueue<Report> m_read_reports;
|
||||||
Common::FifoQueue<Report> m_write_reports;
|
Common::FifoQueue<Report> m_write_reports;
|
||||||
Common::FifoQueue<Report> m_audio_reports;
|
Common::FifoQueue<Report> m_audio_reports;
|
||||||
|
|
||||||
|
Common::Timer last_audio_report;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern std::mutex g_refresh_lock;
|
extern std::mutex g_refresh_lock;
|
||||||
|
|||||||
@@ -64,6 +64,8 @@ They will also generate a true or false return for UpdateInterrupts() in WII_IPC
|
|||||||
#include "../HW/WII_IPC.h"
|
#include "../HW/WII_IPC.h"
|
||||||
#include "../Debugger/Debugger_SymbolMap.h"
|
#include "../Debugger/Debugger_SymbolMap.h"
|
||||||
#include "../PowerPC/PowerPC.h"
|
#include "../PowerPC/PowerPC.h"
|
||||||
|
#include "../HW/SystemTimers.h"
|
||||||
|
#include "CoreTiming.h"
|
||||||
|
|
||||||
|
|
||||||
namespace WII_IPC_HLE_Interface
|
namespace WII_IPC_HLE_Interface
|
||||||
@@ -87,8 +89,20 @@ static ipc_msg_queue request_queue; // ppc -> arm
|
|||||||
static ipc_msg_queue reply_queue; // arm -> ppc
|
static ipc_msg_queue reply_queue; // arm -> ppc
|
||||||
static std::mutex s_reply_queue;
|
static std::mutex s_reply_queue;
|
||||||
|
|
||||||
|
static int enque_reply;
|
||||||
|
|
||||||
|
static u64 last_reply_time;
|
||||||
|
|
||||||
|
void EnqueReplyCallback(u64 userdata, int)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lk(s_reply_queue);
|
||||||
|
reply_queue.push_back(userdata);
|
||||||
|
}
|
||||||
|
|
||||||
void Init()
|
void Init()
|
||||||
{
|
{
|
||||||
|
enque_reply = CoreTiming::RegisterEvent("IPCReply", EnqueReplyCallback);
|
||||||
|
|
||||||
_dbg_assert_msg_(WII_IPC_HLE, g_DeviceMap.empty(), "DeviceMap isnt empty on init");
|
_dbg_assert_msg_(WII_IPC_HLE, g_DeviceMap.empty(), "DeviceMap isnt empty on init");
|
||||||
CWII_IPC_HLE_Device_es::m_ContentFile = "";
|
CWII_IPC_HLE_Device_es::m_ContentFile = "";
|
||||||
u32 i;
|
u32 i;
|
||||||
@@ -170,6 +184,7 @@ void Reset(bool _bHard)
|
|||||||
std::lock_guard<std::mutex> lk(s_reply_queue);
|
std::lock_guard<std::mutex> lk(s_reply_queue);
|
||||||
reply_queue.clear();
|
reply_queue.clear();
|
||||||
}
|
}
|
||||||
|
last_reply_time = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shutdown()
|
void Shutdown()
|
||||||
@@ -255,6 +270,7 @@ void DoState(PointerWrap &p)
|
|||||||
|
|
||||||
p.Do(request_queue);
|
p.Do(request_queue);
|
||||||
p.Do(reply_queue);
|
p.Do(reply_queue);
|
||||||
|
p.Do(last_reply_time);
|
||||||
|
|
||||||
TDeviceMap::const_iterator itr;
|
TDeviceMap::const_iterator itr;
|
||||||
|
|
||||||
@@ -402,18 +418,19 @@ void ExecuteCommand(u32 _Address)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
IWII_IPC_HLE_Device* _pDevice = CreateFileIO(DeviceID, DeviceName);
|
pDevice = CreateFileIO(DeviceID, DeviceName);
|
||||||
CmdSuccess = _pDevice->Open(_Address, Mode);
|
CmdSuccess = pDevice->Open(_Address, Mode);
|
||||||
|
|
||||||
INFO_LOG(WII_IPC_FILEIO, "IOP: Open File (Device=%s, ID=%08x, Mode=%i)",
|
INFO_LOG(WII_IPC_FILEIO, "IOP: Open File (Device=%s, ID=%08x, Mode=%i)",
|
||||||
_pDevice->GetDeviceName().c_str(), DeviceID, Mode);
|
pDevice->GetDeviceName().c_str(), DeviceID, Mode);
|
||||||
if (Memory::Read_U32(_Address + 4) == (u32)DeviceID)
|
if (Memory::Read_U32(_Address + 4) == (u32)DeviceID)
|
||||||
{
|
{
|
||||||
g_FdMap[DeviceID] = _pDevice;
|
g_FdMap[DeviceID] = pDevice;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
delete _pDevice;
|
delete pDevice;
|
||||||
|
pDevice = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -444,7 +461,10 @@ void ExecuteCommand(u32 _Address)
|
|||||||
|
|
||||||
// Don't delete hardware
|
// Don't delete hardware
|
||||||
if (!pDevice->IsHardware())
|
if (!pDevice->IsHardware())
|
||||||
|
{
|
||||||
delete pDevice;
|
delete pDevice;
|
||||||
|
pDevice = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -523,8 +543,19 @@ void ExecuteCommand(u32 _Address)
|
|||||||
// IOS seems to write back the command that was responded to
|
// IOS seems to write back the command that was responded to
|
||||||
Memory::Write_U32(Command, _Address + 8);
|
Memory::Write_U32(Command, _Address + 8);
|
||||||
|
|
||||||
|
// Ensure replies happen in order, fairly ugly
|
||||||
|
// Without this, tons of games fail now that DI commads have different reply delays
|
||||||
|
int reply_delay = pDevice ? pDevice->GetCmdDelay(_Address) : 0;
|
||||||
|
|
||||||
|
const s64 ticks_til_last_reply = last_reply_time - CoreTiming::GetTicks();
|
||||||
|
|
||||||
|
if (ticks_til_last_reply > 0)
|
||||||
|
reply_delay = ticks_til_last_reply;
|
||||||
|
|
||||||
|
last_reply_time = CoreTiming::GetTicks() + reply_delay;
|
||||||
|
|
||||||
// Generate a reply to the IPC command
|
// Generate a reply to the IPC command
|
||||||
EnqReply(_Address);
|
EnqReply(_Address, reply_delay);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -546,10 +577,9 @@ void EnqRequest(u32 _Address)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Called when IOS module has some reply
|
// Called when IOS module has some reply
|
||||||
void EnqReply(u32 _Address)
|
void EnqReply(u32 _Address, int cycles_in_future)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lk(s_reply_queue);
|
CoreTiming::ScheduleEvent(cycles_in_future, enque_reply, _Address);
|
||||||
reply_queue.push_back(_Address);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is called every IPC_HLE_PERIOD from SystemTimers.cpp
|
// This is called every IPC_HLE_PERIOD from SystemTimers.cpp
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ void UpdateDevices();
|
|||||||
void ExecuteCommand(u32 _Address);
|
void ExecuteCommand(u32 _Address);
|
||||||
|
|
||||||
void EnqRequest(u32 _Address);
|
void EnqRequest(u32 _Address);
|
||||||
void EnqReply(u32 _Address);
|
void EnqReply(u32 _Address, int cycles_in_future = 0);
|
||||||
|
|
||||||
enum ECommandType
|
enum ECommandType
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -95,6 +95,8 @@ public:
|
|||||||
virtual bool IOCtlV (u32) { UNIMPLEMENTED_CMD(IOCtlV) }
|
virtual bool IOCtlV (u32) { UNIMPLEMENTED_CMD(IOCtlV) }
|
||||||
#undef UNIMPLEMENTED_CMD
|
#undef UNIMPLEMENTED_CMD
|
||||||
|
|
||||||
|
virtual int GetCmdDelay(u32) { return 0; }
|
||||||
|
|
||||||
virtual u32 Update() { return 0; }
|
virtual u32 Update() { return 0; }
|
||||||
|
|
||||||
virtual bool IsHardware() { return m_Hardware; }
|
virtual bool IsHardware() { return m_Hardware; }
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
#include "VolumeCreator.h"
|
#include "VolumeCreator.h"
|
||||||
#include "Filesystem.h"
|
#include "Filesystem.h"
|
||||||
#include "LogManager.h"
|
#include "LogManager.h"
|
||||||
|
#include "../HW/SystemTimers.h"
|
||||||
|
|
||||||
#include "../../DiscIO/Src/FileMonitor.h"
|
#include "../../DiscIO/Src/FileMonitor.h"
|
||||||
|
|
||||||
@@ -460,3 +461,44 @@ u32 CWII_IPC_HLE_Device_di::ExecuteCommand(u32 _BufferIn, u32 _BufferInSize, u32
|
|||||||
// i dunno but prolly 1 is okay all the time :)
|
// i dunno but prolly 1 is okay all the time :)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int CWII_IPC_HLE_Device_di::GetCmdDelay(u32 _CommandAddress)
|
||||||
|
{
|
||||||
|
u32 BufferIn = Memory::Read_U32(_CommandAddress + 0x10);
|
||||||
|
u32 Command = Memory::Read_U32(BufferIn) >> 24;
|
||||||
|
|
||||||
|
// Hacks below
|
||||||
|
|
||||||
|
switch (Command)
|
||||||
|
{
|
||||||
|
case DVDLowRead:
|
||||||
|
case DVDLowUnencryptedRead:
|
||||||
|
{
|
||||||
|
u32 const Size = Memory::Read_U32(BufferIn + 0x04);
|
||||||
|
// Delay depends on size of read, that makes sense, right?
|
||||||
|
// More than ~1150K "bytes / sec" hangs NSMBWii on boot.
|
||||||
|
// Less than ~800K "bytes / sec" hangs DKCR randomly.
|
||||||
|
return SystemTimers::GetTicksPerSecond() / 975000 * Size;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case DVDLowClearCoverInterrupt:
|
||||||
|
// Less than ~1/155th of a second hangs Oregon Trail at "loading wheel".
|
||||||
|
// More than ~1/140th of a second hangs Resident Evil Archives: Resident Evil Zero.
|
||||||
|
return SystemTimers::GetTicksPerSecond() / 146;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// case DVDLowAudioBufferConfig:
|
||||||
|
// case DVDLowInquiry:
|
||||||
|
// case DVDLowReadDiskID:
|
||||||
|
// case DVDLowWaitForCoverClose:
|
||||||
|
// case DVDLowGetCoverReg:
|
||||||
|
// case DVDLowGetCoverStatus:
|
||||||
|
// case DVDLowReset:
|
||||||
|
// case DVDLowClosePartition:
|
||||||
|
default:
|
||||||
|
// ranom numbers here!
|
||||||
|
return SystemTimers::GetTicksPerSecond() / 1500;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -38,6 +38,8 @@ public:
|
|||||||
|
|
||||||
bool IOCtl(u32 _CommandAddress);
|
bool IOCtl(u32 _CommandAddress);
|
||||||
bool IOCtlV(u32 _CommandAddress);
|
bool IOCtlV(u32 _CommandAddress);
|
||||||
|
|
||||||
|
int GetCmdDelay(u32);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
#include "FileUtil.h"
|
#include "FileUtil.h"
|
||||||
#include "NandPaths.h"
|
#include "NandPaths.h"
|
||||||
#include "ChunkFile.h"
|
#include "ChunkFile.h"
|
||||||
|
#include "../HW/SystemTimers.h"
|
||||||
|
|
||||||
#include "../VolumeHandler.h"
|
#include "../VolumeHandler.h"
|
||||||
|
|
||||||
@@ -504,6 +505,13 @@ s32 CWII_IPC_HLE_Device_fs::ExecuteCommand(u32 _Parameter, u32 _BufferIn, u32 _B
|
|||||||
return FS_RESULT_FATAL;
|
return FS_RESULT_FATAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int CWII_IPC_HLE_Device_fs::GetCmdDelay(u32)
|
||||||
|
{
|
||||||
|
// ~1/1000th of a second is too short and causes hangs in Wii Party
|
||||||
|
// Play it safe at 1/500th
|
||||||
|
return SystemTimers::GetTicksPerSecond() / 500;
|
||||||
|
}
|
||||||
|
|
||||||
void CWII_IPC_HLE_Device_fs::DoState(PointerWrap& p)
|
void CWII_IPC_HLE_Device_fs::DoState(PointerWrap& p)
|
||||||
{
|
{
|
||||||
DoStateShared(p);
|
DoStateShared(p);
|
||||||
|
|||||||
@@ -55,6 +55,8 @@ public:
|
|||||||
|
|
||||||
virtual bool IOCtl(u32 _CommandAddress);
|
virtual bool IOCtl(u32 _CommandAddress);
|
||||||
virtual bool IOCtlV(u32 _CommandAddress);
|
virtual bool IOCtlV(u32 _CommandAddress);
|
||||||
|
|
||||||
|
virtual int GetCmdDelay(u32);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|||||||
@@ -336,23 +336,23 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::SendToDevice(u16 _ConnectionHandle, u8
|
|||||||
pWiiMote->ExecuteL2capCmd(_pData, _Size);
|
pWiiMote->ExecuteL2capCmd(_pData, _Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Here we send ACL packets to CPU. They will consist of header + data.
|
|
||||||
// The header is for example 07 00 41 00 which means size 0x0007 and channel 0x0041.
|
|
||||||
// ---------------------------------------------------
|
|
||||||
// AyuanX: Basically, our WII_IPC_HLE is efficient enough to send the packet immediately
|
|
||||||
// rather than enqueue it to some other memory
|
|
||||||
// But...the only exception comes from the Wiimote_Plugin
|
|
||||||
void CWII_IPC_HLE_Device_usb_oh1_57e_305::IncDataPacket(u16 _ConnectionHandle)
|
void CWII_IPC_HLE_Device_usb_oh1_57e_305::IncDataPacket(u16 _ConnectionHandle)
|
||||||
{
|
{
|
||||||
m_PacketCount[_ConnectionHandle & 0xff]++;
|
m_PacketCount[_ConnectionHandle & 0xff]++;
|
||||||
|
|
||||||
|
// I don't think this makes sense or should be necessary
|
||||||
|
// m_PacketCount refers to "completed" packets and is not related to some buffer size, yes?
|
||||||
|
#if 0
|
||||||
if (m_PacketCount[_ConnectionHandle & 0xff] > (unsigned int)m_acl_pkts_num)
|
if (m_PacketCount[_ConnectionHandle & 0xff] > (unsigned int)m_acl_pkts_num)
|
||||||
{
|
{
|
||||||
DEBUG_LOG(WII_IPC_WIIMOTE, "ACL buffer overflow");
|
DEBUG_LOG(WII_IPC_WIIMOTE, "ACL buffer overflow");
|
||||||
m_PacketCount[_ConnectionHandle & 0xff] = m_acl_pkts_num;
|
m_PacketCount[_ConnectionHandle & 0xff] = m_acl_pkts_num;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Here we send ACL packets to CPU. They will consist of header + data.
|
||||||
|
// The header is for example 07 00 41 00 which means size 0x0007 and channel 0x0041.
|
||||||
void CWII_IPC_HLE_Device_usb_oh1_57e_305::SendACLPacket(u16 _ConnectionHandle, u8* _pData, u32 _Size)
|
void CWII_IPC_HLE_Device_usb_oh1_57e_305::SendACLPacket(u16 _ConnectionHandle, u8* _pData, u32 _Size)
|
||||||
{
|
{
|
||||||
DEBUG_LOG(WII_IPC_WIIMOTE, "ACL packet from %x ready to send to stack...", _ConnectionHandle);
|
DEBUG_LOG(WII_IPC_WIIMOTE, "ACL packet from %x ready to send to stack...", _ConnectionHandle);
|
||||||
@@ -374,8 +374,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::SendACLPacket(u16 _ConnectionHandle, u
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DEBUG_LOG(WII_IPC_WIIMOTE, "ACL endpoint not currently valid, "
|
DEBUG_LOG(WII_IPC_WIIMOTE, "ACL endpoint not currently valid, queueing...");
|
||||||
"queueing(%d)...", m_acl_pool.GetWritePos());
|
|
||||||
m_acl_pool.Store(_pData, _Size, _ConnectionHandle);
|
m_acl_pool.Store(_pData, _Size, _ConnectionHandle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -486,18 +485,8 @@ u32 CWII_IPC_HLE_Device_usb_oh1_57e_305::Update()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The Real Wiimote sends report every ~6.66ms (150 Hz).
|
// The Real Wiimote sends report every ~5ms (200 Hz).
|
||||||
// However, we don't actually reach here at dependable intervals, so we
|
const u64 interval = SystemTimers::GetTicksPerSecond() / 200;
|
||||||
// instead just timeslice in such a way that makes the stack think we have
|
|
||||||
// perfect "radio quality" (WPADGetRadioSensitivity) and yet still have some
|
|
||||||
// idle time.
|
|
||||||
// Somehow, Dolphin's Wiimote Speaker support requires using an update interval
|
|
||||||
// of 5ms (200 Hz) for its output to work. This increased frequency tends to
|
|
||||||
// fill the ACL queue (even) quicker than it can be processed by Dolphin,
|
|
||||||
// especially during simultaneous requests involving many (emulated) Wiimotes...
|
|
||||||
// Thus, we only use that interval when the option is enabled. See issue 4608.
|
|
||||||
const u64 interval = SystemTimers::GetTicksPerSecond() / (SConfig::GetInstance().
|
|
||||||
m_LocalCoreStartupParameter.bDisableWiimoteSpeaker ? 150 : 200);
|
|
||||||
const u64 each_wiimote_interval = interval / m_WiiMotes.size();
|
const u64 each_wiimote_interval = interval / m_WiiMotes.size();
|
||||||
const u64 now = CoreTiming::GetTicks();
|
const u64 now = CoreTiming::GetTicks();
|
||||||
|
|
||||||
@@ -518,25 +507,47 @@ u32 CWII_IPC_HLE_Device_usb_oh1_57e_305::Update()
|
|||||||
return packet_transferred;
|
return packet_transferred;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CWII_IPC_HLE_Device_usb_oh1_57e_305::ACLPool::Store(const u8* data, const u16 size, const u16 conn_handle)
|
||||||
|
{
|
||||||
|
if (m_queue.size() >= 100)
|
||||||
|
{
|
||||||
|
// Many simultaneous exchanges of ACL packets tend to cause the queue to fill up.
|
||||||
|
ERROR_LOG(WII_IPC_WIIMOTE, "ACL queue size reached 100 - current packet will be dropped!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_dbg_assert_msg_(WII_IPC_WIIMOTE,
|
||||||
|
size < m_acl_pkt_size, "acl packet too large for pool");
|
||||||
|
|
||||||
|
m_queue.push_back(Packet());
|
||||||
|
auto& packet = m_queue.back();
|
||||||
|
|
||||||
|
std::copy(data, data + size, packet.data);
|
||||||
|
packet.size = size;
|
||||||
|
packet.conn_handle = conn_handle;
|
||||||
|
}
|
||||||
|
|
||||||
void CWII_IPC_HLE_Device_usb_oh1_57e_305::ACLPool::WriteToEndpoint(CtrlBuffer& endpoint)
|
void CWII_IPC_HLE_Device_usb_oh1_57e_305::ACLPool::WriteToEndpoint(CtrlBuffer& endpoint)
|
||||||
{
|
{
|
||||||
const u8 *data = m_pool + m_acl_pkt_size * m_read_ptr;
|
auto& packet = m_queue.front();
|
||||||
const u16 size = m_info[m_read_ptr].size;
|
|
||||||
const u16 conn_handle = m_info[m_read_ptr].conn_handle;
|
const u8* const data = packet.data;
|
||||||
|
const u16 size = packet.size;
|
||||||
|
const u16 conn_handle = packet.conn_handle;
|
||||||
|
|
||||||
DEBUG_LOG(WII_IPC_WIIMOTE, "ACL packet being written from "
|
DEBUG_LOG(WII_IPC_WIIMOTE, "ACL packet being written from "
|
||||||
"queue(%d) to %08x", GetReadPos(), endpoint.m_address);
|
"queue to %08x", endpoint.m_address);
|
||||||
|
|
||||||
hci_acldata_hdr_t* pHeader = (hci_acldata_hdr_t*)Memory::GetPointer(endpoint.m_buffer);
|
hci_acldata_hdr_t* pHeader = (hci_acldata_hdr_t*)Memory::GetPointer(endpoint.m_buffer);
|
||||||
pHeader->con_handle = HCI_MK_CON_HANDLE(conn_handle, HCI_PACKET_START, HCI_POINT2POINT);
|
pHeader->con_handle = HCI_MK_CON_HANDLE(conn_handle, HCI_PACKET_START, HCI_POINT2POINT);
|
||||||
pHeader->length = size;
|
pHeader->length = size;
|
||||||
|
|
||||||
// Write the packet to the buffer
|
// Write the packet to the buffer
|
||||||
memcpy((u8*)pHeader + sizeof(hci_acldata_hdr_t), data, pHeader->length);
|
std::copy(data, data + size, (u8*)pHeader + sizeof(hci_acldata_hdr_t));
|
||||||
|
|
||||||
endpoint.SetRetVal(sizeof(hci_acldata_hdr_t) + size);
|
endpoint.SetRetVal(sizeof(hci_acldata_hdr_t) + size);
|
||||||
|
|
||||||
m_read_ptr = (m_read_ptr + 1) % m_acl_pkts_num;
|
m_queue.pop_front();
|
||||||
|
|
||||||
WII_IPC_HLE_Interface::EnqReply(endpoint.m_address);
|
WII_IPC_HLE_Interface::EnqReply(endpoint.m_address);
|
||||||
endpoint.Invalidate();
|
endpoint.Invalidate();
|
||||||
|
|||||||
@@ -17,9 +17,11 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "hci.h"
|
#include <algorithm>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
|
||||||
|
#include "hci.h"
|
||||||
#include "WII_IPC_HLE.h"
|
#include "WII_IPC_HLE.h"
|
||||||
#include "WII_IPC_HLE_Device.h"
|
#include "WII_IPC_HLE_Device.h"
|
||||||
#include "WII_IPC_HLE_WiiMote.h"
|
#include "WII_IPC_HLE_WiiMote.h"
|
||||||
@@ -168,70 +170,33 @@ private:
|
|||||||
|
|
||||||
class ACLPool
|
class ACLPool
|
||||||
{
|
{
|
||||||
u8 m_pool[m_acl_pkt_size * m_acl_pkts_num];
|
struct Packet
|
||||||
int m_read_ptr;
|
|
||||||
int m_write_ptr;
|
|
||||||
|
|
||||||
struct
|
|
||||||
{
|
{
|
||||||
|
u8 data[m_acl_pkt_size];
|
||||||
u16 size;
|
u16 size;
|
||||||
u16 conn_handle;
|
u16 conn_handle;
|
||||||
} m_info[m_acl_pkts_num];
|
};
|
||||||
|
|
||||||
|
std::deque<Packet> m_queue;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ACLPool()
|
ACLPool()
|
||||||
: m_read_ptr(0)
|
: m_queue()
|
||||||
, m_write_ptr(0)
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void Store(const u8* data, const u16 size, const u16 conn_handle)
|
void Store(const u8* data, const u16 size, const u16 conn_handle);
|
||||||
{
|
|
||||||
_dbg_assert_msg_(WII_IPC_WIIMOTE,
|
|
||||||
size < m_acl_pkt_size, "acl packet too large for pool");
|
|
||||||
|
|
||||||
const int next_write_ptr = (m_write_ptr + 1) % m_acl_pkts_num;
|
|
||||||
if (next_write_ptr == m_read_ptr)
|
|
||||||
{
|
|
||||||
// Many simultaneous exchanges of ACL packets tend to cause the
|
|
||||||
// 10-packet limit to be exceeded. Typically, this occurs when
|
|
||||||
// many emulated Wiimotes are requesting connections at once.
|
|
||||||
// See issue 4608 for more info.
|
|
||||||
ERROR_LOG(WII_IPC_WIIMOTE, "ACL queue is full - current packet will be "
|
|
||||||
"dropped! (m_write_ptr(%d) was about to overlap m_read_ptr(%d))",
|
|
||||||
m_write_ptr, m_read_ptr);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(m_pool + m_acl_pkt_size * m_write_ptr, data, size);
|
|
||||||
m_info[m_write_ptr].size = size;
|
|
||||||
m_info[m_write_ptr].conn_handle = conn_handle;
|
|
||||||
m_write_ptr = next_write_ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WriteToEndpoint(CtrlBuffer& endpoint);
|
void WriteToEndpoint(CtrlBuffer& endpoint);
|
||||||
|
|
||||||
bool IsEmpty() const
|
bool IsEmpty() const
|
||||||
{
|
{
|
||||||
return m_write_ptr == m_read_ptr;
|
return m_queue.empty();
|
||||||
}
|
|
||||||
|
|
||||||
int GetWritePos() const
|
|
||||||
{
|
|
||||||
return m_write_ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
int GetReadPos() const
|
|
||||||
{
|
|
||||||
return m_read_ptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// For SaveStates
|
// For SaveStates
|
||||||
void DoState(PointerWrap &p)
|
void DoState(PointerWrap &p)
|
||||||
{
|
{
|
||||||
p.Do(m_write_ptr);
|
p.Do(m_queue);
|
||||||
p.Do(m_read_ptr);
|
|
||||||
p.DoArray((u8 *)m_pool, sizeof(m_pool));
|
|
||||||
p.DoArray((u8 *)m_info, sizeof(m_info));
|
|
||||||
}
|
}
|
||||||
} m_acl_pool;
|
} m_acl_pool;
|
||||||
|
|
||||||
|
|||||||
@@ -70,8 +70,8 @@ static Common::Event g_compressAndDumpStateSyncEvent;
|
|||||||
|
|
||||||
static std::thread g_save_thread;
|
static std::thread g_save_thread;
|
||||||
|
|
||||||
// Don't forget to increase this after doing changes on the savestate system
|
// Don't forget to increase this after doing changes on the savestate system
|
||||||
static const u32 STATE_VERSION = 10;
|
static const u32 STATE_VERSION = 12;
|
||||||
|
|
||||||
struct StateHeader
|
struct StateHeader
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -222,7 +222,7 @@ bool CompressFileToBlob(const char* infile, const char* outfile, u32 sub_type,
|
|||||||
// u64 size = header.block_size;
|
// u64 size = header.block_size;
|
||||||
std::fill(in_buf, in_buf + header.block_size, 0);
|
std::fill(in_buf, in_buf + header.block_size, 0);
|
||||||
if (scrubbing)
|
if (scrubbing)
|
||||||
DiscScrubber::GetNextBlock(inf.GetHandle(), in_buf);
|
DiscScrubber::GetNextBlock(inf, in_buf);
|
||||||
else
|
else
|
||||||
inf.ReadBytes(in_buf, header.block_size);
|
inf.ReadBytes(in_buf, header.block_size);
|
||||||
z_stream z;
|
z_stream z;
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ bool SetupScrub(const char* filename, int block_size)
|
|||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GetNextBlock(FILE* in, u8* buffer)
|
void GetNextBlock(File::IOFile& in, u8* buffer)
|
||||||
{
|
{
|
||||||
u64 CurrentOffset = m_BlockCount * m_BlockSize;
|
u64 CurrentOffset = m_BlockCount * m_BlockSize;
|
||||||
u64 i = CurrentOffset / CLUSTER_SIZE;
|
u64 i = CurrentOffset / CLUSTER_SIZE;
|
||||||
@@ -136,12 +136,12 @@ void GetNextBlock(FILE* in, u8* buffer)
|
|||||||
{
|
{
|
||||||
DEBUG_LOG(DISCIO, "Freeing 0x%016llx", CurrentOffset);
|
DEBUG_LOG(DISCIO, "Freeing 0x%016llx", CurrentOffset);
|
||||||
std::fill(buffer, buffer + m_BlockSize, 0xFF);
|
std::fill(buffer, buffer + m_BlockSize, 0xFF);
|
||||||
fseeko(in, m_BlockSize, SEEK_CUR);
|
in.Seek(m_BlockSize, SEEK_CUR);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DEBUG_LOG(DISCIO, "Used 0x%016llx", CurrentOffset);
|
DEBUG_LOG(DISCIO, "Used 0x%016llx", CurrentOffset);
|
||||||
fread(buffer, m_BlockSize, 1, in);
|
in.ReadBytes(buffer, m_BlockSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_BlockCount++;
|
m_BlockCount++;
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ namespace DiscScrubber
|
|||||||
{
|
{
|
||||||
|
|
||||||
bool SetupScrub(const char* filename, int block_size);
|
bool SetupScrub(const char* filename, int block_size);
|
||||||
void GetNextBlock(FILE* in, u8* buffer);
|
void GetNextBlock(File::IOFile& in, u8* buffer);
|
||||||
void Cleanup();
|
void Cleanup();
|
||||||
|
|
||||||
} // namespace DiscScrubber
|
} // namespace DiscScrubber
|
||||||
|
|||||||
@@ -137,6 +137,7 @@
|
|||||||
<Command>xcopy "$(SolutionDir)..\Data" "$(TargetDir)" /e /s /y /d
|
<Command>xcopy "$(SolutionDir)..\Data" "$(TargetDir)" /e /s /y /d
|
||||||
echo Copying External .dlls
|
echo Copying External .dlls
|
||||||
xcopy "$(SolutionDir)..\Externals\Cg\*.dll" "$(TargetDir)" /e /s /y /q /d
|
xcopy "$(SolutionDir)..\Externals\Cg\*.dll" "$(TargetDir)" /e /s /y /q /d
|
||||||
|
xcopy "$(SolutionDir)..\Externals\OpenAL\Win32\*.dll" "$(TargetDir)" /e /s /y /q /d
|
||||||
xcopy "$(SolutionDir)..\Externals\SDL\$(PlatformName)\*.dll" "$(TargetDir)" /e /s /y /q /d
|
xcopy "$(SolutionDir)..\Externals\SDL\$(PlatformName)\*.dll" "$(TargetDir)" /e /s /y /q /d
|
||||||
</Command>
|
</Command>
|
||||||
<Message>Copying Data\* to $(TargetDir)</Message>
|
<Message>Copying Data\* to $(TargetDir)</Message>
|
||||||
@@ -151,6 +152,7 @@ xcopy "$(SolutionDir)..\Externals\SDL\$(PlatformName)\*.dll" "$(TargetDir)" /e /
|
|||||||
<Command>xcopy "$(SolutionDir)..\Data" "$(TargetDir)" /e /s /y /d
|
<Command>xcopy "$(SolutionDir)..\Data" "$(TargetDir)" /e /s /y /d
|
||||||
echo Copying External .dlls
|
echo Copying External .dlls
|
||||||
xcopy "$(SolutionDir)..\Externals\Cg64\*.dll" "$(TargetDir)" /e /s /y /q /d
|
xcopy "$(SolutionDir)..\Externals\Cg64\*.dll" "$(TargetDir)" /e /s /y /q /d
|
||||||
|
xcopy "$(SolutionDir)..\Externals\OpenAL\Win64\*.dll" "$(TargetDir)" /e /s /y /q /d
|
||||||
xcopy "$(SolutionDir)..\Externals\SDL\$(PlatformName)\*.dll" "$(TargetDir)" /e /s /y /q /d
|
xcopy "$(SolutionDir)..\Externals\SDL\$(PlatformName)\*.dll" "$(TargetDir)" /e /s /y /q /d
|
||||||
</Command>
|
</Command>
|
||||||
<Message>Copying Data\* to $(TargetDir)</Message>
|
<Message>Copying Data\* to $(TargetDir)</Message>
|
||||||
@@ -167,6 +169,7 @@ xcopy "$(SolutionDir)..\Externals\SDL\$(PlatformName)\*.dll" "$(TargetDir)" /e /
|
|||||||
<Command>xcopy "$(SolutionDir)..\Data" "$(TargetDir)" /e /s /y /d
|
<Command>xcopy "$(SolutionDir)..\Data" "$(TargetDir)" /e /s /y /d
|
||||||
echo Copying External .dlls
|
echo Copying External .dlls
|
||||||
xcopy "$(SolutionDir)..\Externals\Cg\*.dll" "$(TargetDir)" /e /s /y /q /d
|
xcopy "$(SolutionDir)..\Externals\Cg\*.dll" "$(TargetDir)" /e /s /y /q /d
|
||||||
|
xcopy "$(SolutionDir)..\Externals\OpenAL\Win32\*.dll" "$(TargetDir)" /e /s /y /q /d
|
||||||
xcopy "$(SolutionDir)..\Externals\SDL\$(PlatformName)\*.dll" "$(TargetDir)" /e /s /y /q /d
|
xcopy "$(SolutionDir)..\Externals\SDL\$(PlatformName)\*.dll" "$(TargetDir)" /e /s /y /q /d
|
||||||
</Command>
|
</Command>
|
||||||
<Message>Copying Data\* to $(TargetDir)</Message>
|
<Message>Copying Data\* to $(TargetDir)</Message>
|
||||||
@@ -181,6 +184,7 @@ xcopy "$(SolutionDir)..\Externals\SDL\$(PlatformName)\*.dll" "$(TargetDir)" /e /
|
|||||||
<Command>xcopy "$(SolutionDir)..\Data" "$(TargetDir)" /e /s /y /d
|
<Command>xcopy "$(SolutionDir)..\Data" "$(TargetDir)" /e /s /y /d
|
||||||
echo Copying External .dlls
|
echo Copying External .dlls
|
||||||
xcopy "$(SolutionDir)..\Externals\Cg\*.dll" "$(TargetDir)" /e /s /y /q /d
|
xcopy "$(SolutionDir)..\Externals\Cg\*.dll" "$(TargetDir)" /e /s /y /q /d
|
||||||
|
xcopy "$(SolutionDir)..\Externals\OpenAL\Win32\*.dll" "$(TargetDir)" /e /s /y /q /d
|
||||||
xcopy "$(SolutionDir)..\Externals\SDL\$(PlatformName)\*.dll" "$(TargetDir)" /e /s /y /q /d
|
xcopy "$(SolutionDir)..\Externals\SDL\$(PlatformName)\*.dll" "$(TargetDir)" /e /s /y /q /d
|
||||||
</Command>
|
</Command>
|
||||||
<Message>Copying Data\* to $(TargetDir)</Message>
|
<Message>Copying Data\* to $(TargetDir)</Message>
|
||||||
@@ -197,6 +201,7 @@ xcopy "$(SolutionDir)..\Externals\SDL\$(PlatformName)\*.dll" "$(TargetDir)" /e /
|
|||||||
<Command>xcopy "$(SolutionDir)..\Data" "$(TargetDir)" /e /s /y /d
|
<Command>xcopy "$(SolutionDir)..\Data" "$(TargetDir)" /e /s /y /d
|
||||||
echo Copying External .dlls
|
echo Copying External .dlls
|
||||||
xcopy "$(SolutionDir)..\Externals\Cg64\*.dll" "$(TargetDir)" /e /s /y /q /d
|
xcopy "$(SolutionDir)..\Externals\Cg64\*.dll" "$(TargetDir)" /e /s /y /q /d
|
||||||
|
xcopy "$(SolutionDir)..\Externals\OpenAL\Win64\*.dll" "$(TargetDir)" /e /s /y /q /d
|
||||||
xcopy "$(SolutionDir)..\Externals\SDL\$(PlatformName)\*.dll" "$(TargetDir)" /e /s /y /q /d
|
xcopy "$(SolutionDir)..\Externals\SDL\$(PlatformName)\*.dll" "$(TargetDir)" /e /s /y /q /d
|
||||||
</Command>
|
</Command>
|
||||||
<Message>Copying Data\* to $(TargetDir)</Message>
|
<Message>Copying Data\* to $(TargetDir)</Message>
|
||||||
@@ -213,6 +218,7 @@ xcopy "$(SolutionDir)..\Externals\SDL\$(PlatformName)\*.dll" "$(TargetDir)" /e /
|
|||||||
<Command>xcopy "$(SolutionDir)..\Data" "$(TargetDir)" /e /s /y /d
|
<Command>xcopy "$(SolutionDir)..\Data" "$(TargetDir)" /e /s /y /d
|
||||||
echo Copying External .dlls
|
echo Copying External .dlls
|
||||||
xcopy "$(SolutionDir)..\Externals\Cg64\*.dll" "$(TargetDir)" /e /s /y /q /d
|
xcopy "$(SolutionDir)..\Externals\Cg64\*.dll" "$(TargetDir)" /e /s /y /q /d
|
||||||
|
xcopy "$(SolutionDir)..\Externals\OpenAL\Win64\*.dll" "$(TargetDir)" /e /s /y /q /d
|
||||||
xcopy "$(SolutionDir)..\Externals\SDL\$(PlatformName)\*.dll" "$(TargetDir)" /e /s /y /q /d
|
xcopy "$(SolutionDir)..\Externals\SDL\$(PlatformName)\*.dll" "$(TargetDir)" /e /s /y /q /d
|
||||||
</Command>
|
</Command>
|
||||||
<Message>Copying Data\* to $(TargetDir)</Message>
|
<Message>Copying Data\* to $(TargetDir)</Message>
|
||||||
|
|||||||
@@ -1566,6 +1566,8 @@ void CFrame::UpdateGUI()
|
|||||||
if (m_ToolBar)
|
if (m_ToolBar)
|
||||||
m_ToolBar->EnableTool(IDM_PLAY, true);
|
m_ToolBar->EnableTool(IDM_PLAY, true);
|
||||||
GetMenuBar()->FindItem(IDM_PLAY)->Enable(true);
|
GetMenuBar()->FindItem(IDM_PLAY)->Enable(true);
|
||||||
|
GetMenuBar()->FindItem(IDM_RECORD)->Enable(true);
|
||||||
|
GetMenuBar()->FindItem(IDM_PLAYRECORD)->Enable(true);
|
||||||
}
|
}
|
||||||
// Prepare to load last selected file, enable play button
|
// Prepare to load last selected file, enable play button
|
||||||
else if (!SConfig::GetInstance().m_LastFilename.empty()
|
else if (!SConfig::GetInstance().m_LastFilename.empty()
|
||||||
@@ -1574,6 +1576,8 @@ void CFrame::UpdateGUI()
|
|||||||
if (m_ToolBar)
|
if (m_ToolBar)
|
||||||
m_ToolBar->EnableTool(IDM_PLAY, true);
|
m_ToolBar->EnableTool(IDM_PLAY, true);
|
||||||
GetMenuBar()->FindItem(IDM_PLAY)->Enable(true);
|
GetMenuBar()->FindItem(IDM_PLAY)->Enable(true);
|
||||||
|
GetMenuBar()->FindItem(IDM_RECORD)->Enable(true);
|
||||||
|
GetMenuBar()->FindItem(IDM_PLAYRECORD)->Enable(true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1581,6 +1585,8 @@ void CFrame::UpdateGUI()
|
|||||||
if (m_ToolBar)
|
if (m_ToolBar)
|
||||||
m_ToolBar->EnableTool(IDM_PLAY, false);
|
m_ToolBar->EnableTool(IDM_PLAY, false);
|
||||||
GetMenuBar()->FindItem(IDM_PLAY)->Enable(false);
|
GetMenuBar()->FindItem(IDM_PLAY)->Enable(false);
|
||||||
|
GetMenuBar()->FindItem(IDM_RECORD)->Enable(false);
|
||||||
|
GetMenuBar()->FindItem(IDM_PLAYRECORD)->Enable(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1596,6 +1602,8 @@ void CFrame::UpdateGUI()
|
|||||||
if (m_ToolBar)
|
if (m_ToolBar)
|
||||||
m_ToolBar->EnableTool(IDM_PLAY, true);
|
m_ToolBar->EnableTool(IDM_PLAY, true);
|
||||||
GetMenuBar()->FindItem(IDM_PLAY)->Enable(true);
|
GetMenuBar()->FindItem(IDM_PLAY)->Enable(true);
|
||||||
|
GetMenuBar()->FindItem(IDM_RECORD)->Enable(true);
|
||||||
|
GetMenuBar()->FindItem(IDM_PLAYRECORD)->Enable(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (Initialized)
|
else if (Initialized)
|
||||||
|
|||||||
@@ -57,6 +57,8 @@ size_t CGameListCtrl::m_numberItem = 0;
|
|||||||
std::string CGameListCtrl::m_currentFilename;
|
std::string CGameListCtrl::m_currentFilename;
|
||||||
bool sorted = false;
|
bool sorted = false;
|
||||||
|
|
||||||
|
extern CFrame* main_frame;
|
||||||
|
|
||||||
static int CompareGameListItems(const GameListItem* iso1, const GameListItem* iso2,
|
static int CompareGameListItems(const GameListItem* iso1, const GameListItem* iso2,
|
||||||
long sortData = CGameListCtrl::COLUMN_TITLE)
|
long sortData = CGameListCtrl::COLUMN_TITLE)
|
||||||
{
|
{
|
||||||
@@ -373,7 +375,8 @@ void CGameListCtrl::Update()
|
|||||||
SetItemFont(index, *wxITALIC_FONT);
|
SetItemFont(index, *wxITALIC_FONT);
|
||||||
SetColumnWidth(0, wxLIST_AUTOSIZE);
|
SetColumnWidth(0, wxLIST_AUTOSIZE);
|
||||||
}
|
}
|
||||||
|
if (GetSelectedISO() == NULL)
|
||||||
|
main_frame->UpdateGUI();
|
||||||
Show();
|
Show();
|
||||||
|
|
||||||
AutomaticColumnWidth();
|
AutomaticColumnWidth();
|
||||||
@@ -975,7 +978,7 @@ const GameListItem * CGameListCtrl::GetSelectedISO()
|
|||||||
{
|
{
|
||||||
long item = GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
|
long item = GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
|
||||||
if (item == wxNOT_FOUND)
|
if (item == wxNOT_FOUND)
|
||||||
return new GameListItem(""); // TODO: wtf is this
|
return NULL;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Here is a little workaround for multiselections:
|
// Here is a little workaround for multiselections:
|
||||||
|
|||||||
@@ -328,8 +328,6 @@ void CISOProperties::CreateGUIControls(bool IsWad)
|
|||||||
|
|
||||||
// Wii Console
|
// Wii Console
|
||||||
EnableWideScreen = new wxCheckBox(m_GameConfig, ID_ENABLEWIDESCREEN, _("Enable WideScreen"), wxDefaultPosition, wxDefaultSize, wxCHK_3STATE|wxCHK_ALLOW_3RD_STATE_FOR_USER, wxDefaultValidator);
|
EnableWideScreen = new wxCheckBox(m_GameConfig, ID_ENABLEWIDESCREEN, _("Enable WideScreen"), wxDefaultPosition, wxDefaultSize, wxCHK_3STATE|wxCHK_ALLOW_3RD_STATE_FOR_USER, wxDefaultValidator);
|
||||||
DisableWiimoteSpeaker = new wxCheckBox(m_GameConfig, ID_DISABLEWIIMOTESPEAKER, _("Alternate Wiimote Timing"), wxDefaultPosition, wxDefaultSize, wxCHK_3STATE|wxCHK_ALLOW_3RD_STATE_FOR_USER, wxDefaultValidator);
|
|
||||||
DisableWiimoteSpeaker->SetToolTip(_("Mutes the Wiimote speaker. Fixes random disconnections on real wiimotes. No effect on emulated wiimotes."));
|
|
||||||
|
|
||||||
// Video
|
// Video
|
||||||
UseBBox = new wxCheckBox(m_GameConfig, ID_USE_BBOX, _("Enable Bounding Box Calculation"), wxDefaultPosition, wxDefaultSize, wxCHK_3STATE|wxCHK_ALLOW_3RD_STATE_FOR_USER);
|
UseBBox = new wxCheckBox(m_GameConfig, ID_USE_BBOX, _("Enable Bounding Box Calculation"), wxDefaultPosition, wxDefaultSize, wxCHK_3STATE|wxCHK_ALLOW_3RD_STATE_FOR_USER);
|
||||||
@@ -377,10 +375,8 @@ void CISOProperties::CreateGUIControls(bool IsWad)
|
|||||||
{
|
{
|
||||||
sbWiiOverrides->ShowItems(false);
|
sbWiiOverrides->ShowItems(false);
|
||||||
EnableWideScreen->Hide();
|
EnableWideScreen->Hide();
|
||||||
DisableWiimoteSpeaker->Hide();
|
|
||||||
}
|
}
|
||||||
sbWiiOverrides->Add(EnableWideScreen, 0, wxLEFT, 5);
|
sbWiiOverrides->Add(EnableWideScreen, 0, wxLEFT, 5);
|
||||||
sbWiiOverrides->Add(DisableWiimoteSpeaker, 0, wxLEFT, 5);
|
|
||||||
|
|
||||||
wxStaticBoxSizer * const sbVideoOverrides =
|
wxStaticBoxSizer * const sbVideoOverrides =
|
||||||
new wxStaticBoxSizer(wxVERTICAL, m_GameConfig, _("Video"));
|
new wxStaticBoxSizer(wxVERTICAL, m_GameConfig, _("Video"));
|
||||||
@@ -966,11 +962,6 @@ void CISOProperties::LoadGameConfig()
|
|||||||
else
|
else
|
||||||
EnableWideScreen->Set3StateValue(wxCHK_UNDETERMINED);
|
EnableWideScreen->Set3StateValue(wxCHK_UNDETERMINED);
|
||||||
|
|
||||||
if (GameIni.Get("Wii", "DisableWiimoteSpeaker", &bTemp))
|
|
||||||
DisableWiimoteSpeaker->Set3StateValue((wxCheckBoxState)bTemp);
|
|
||||||
else
|
|
||||||
DisableWiimoteSpeaker->Set3StateValue(wxCHK_UNDETERMINED);
|
|
||||||
|
|
||||||
if (GameIni.Get("Video", "UseBBox", &bTemp))
|
if (GameIni.Get("Video", "UseBBox", &bTemp))
|
||||||
UseBBox->Set3StateValue((wxCheckBoxState)bTemp);
|
UseBBox->Set3StateValue((wxCheckBoxState)bTemp);
|
||||||
else
|
else
|
||||||
@@ -1059,11 +1050,6 @@ bool CISOProperties::SaveGameConfig()
|
|||||||
else
|
else
|
||||||
GameIni.Set("Wii", "Widescreen", EnableWideScreen->Get3StateValue());
|
GameIni.Set("Wii", "Widescreen", EnableWideScreen->Get3StateValue());
|
||||||
|
|
||||||
if (DisableWiimoteSpeaker->Get3StateValue() == wxCHK_UNDETERMINED)
|
|
||||||
GameIni.DeleteKey("Wii", "DisableWiimoteSpeaker");
|
|
||||||
else
|
|
||||||
GameIni.Set("Wii", "DisableWiimoteSpeaker", DisableWiimoteSpeaker->Get3StateValue());
|
|
||||||
|
|
||||||
if (UseBBox->Get3StateValue() == wxCHK_UNDETERMINED)
|
if (UseBBox->Get3StateValue() == wxCHK_UNDETERMINED)
|
||||||
GameIni.DeleteKey("Video", "UseBBox");
|
GameIni.DeleteKey("Video", "UseBBox");
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ private:
|
|||||||
wxCheckBox *CPUThread, *SkipIdle, *MMU, *DCBZOFF, *TLBHack;
|
wxCheckBox *CPUThread, *SkipIdle, *MMU, *DCBZOFF, *TLBHack;
|
||||||
wxCheckBox *VBeam, *FastDiscSpeed, *BlockMerging, *DSPHLE;
|
wxCheckBox *VBeam, *FastDiscSpeed, *BlockMerging, *DSPHLE;
|
||||||
// Wii
|
// Wii
|
||||||
wxCheckBox *EnableWideScreen, *DisableWiimoteSpeaker;
|
wxCheckBox *EnableWideScreen;
|
||||||
// Video
|
// Video
|
||||||
wxCheckBox *UseZTPSpeedupHack, *PHackEnable, *UseBBox;
|
wxCheckBox *UseZTPSpeedupHack, *PHackEnable, *UseBBox;
|
||||||
wxButton *PHSettings;
|
wxButton *PHSettings;
|
||||||
@@ -139,7 +139,6 @@ private:
|
|||||||
ID_PHSETTINGS,
|
ID_PHSETTINGS,
|
||||||
ID_ENABLEPROGRESSIVESCAN,
|
ID_ENABLEPROGRESSIVESCAN,
|
||||||
ID_ENABLEWIDESCREEN,
|
ID_ENABLEWIDESCREEN,
|
||||||
ID_DISABLEWIIMOTESPEAKER,
|
|
||||||
ID_EDITCONFIG,
|
ID_EDITCONFIG,
|
||||||
ID_EMUSTATE,
|
ID_EMUSTATE,
|
||||||
ID_EMU_ISSUES,
|
ID_EMU_ISSUES,
|
||||||
|
|||||||
@@ -121,7 +121,9 @@ Joystick::Axis::Axis(IOHIDElementRef element, IOHIDDeviceRef device, direction d
|
|||||||
// Need to parse the element a bit first
|
// Need to parse the element a bit first
|
||||||
std::string description("unk");
|
std::string description("unk");
|
||||||
|
|
||||||
switch (IOHIDElementGetUsage(m_element)) {
|
int const usage = IOHIDElementGetUsage(m_element);
|
||||||
|
switch (usage)
|
||||||
|
{
|
||||||
case kHIDUsage_GD_X:
|
case kHIDUsage_GD_X:
|
||||||
description = "X";
|
description = "X";
|
||||||
break;
|
break;
|
||||||
@@ -146,6 +148,13 @@ Joystick::Axis::Axis(IOHIDElementRef element, IOHIDDeviceRef device, direction d
|
|||||||
case kHIDUsage_Csmr_ACPan:
|
case kHIDUsage_Csmr_ACPan:
|
||||||
description = "Pan";
|
description = "Pan";
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
std::ostringstream s;
|
||||||
|
s << usage;
|
||||||
|
description = s.str();
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_name = std::string("Axis ") + description;
|
m_name = std::string("Axis ") + description;
|
||||||
|
|||||||
@@ -17,6 +17,15 @@ namespace ciface
|
|||||||
{
|
{
|
||||||
namespace SDL
|
namespace SDL
|
||||||
{
|
{
|
||||||
|
|
||||||
|
std::string GetJoystickName(int index)
|
||||||
|
{
|
||||||
|
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||||
|
return SDL_JoystickNameForIndex(index);
|
||||||
|
#else
|
||||||
|
return SDL_JoystickName(index);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void Init( std::vector<ControllerInterface::Device*>& devices )
|
void Init( std::vector<ControllerInterface::Device*>& devices )
|
||||||
{
|
{
|
||||||
@@ -32,7 +41,7 @@ void Init( std::vector<ControllerInterface::Device*>& devices )
|
|||||||
SDL_Joystick* dev = SDL_JoystickOpen(i);
|
SDL_Joystick* dev = SDL_JoystickOpen(i);
|
||||||
if (dev)
|
if (dev)
|
||||||
{
|
{
|
||||||
Joystick* js = new Joystick(dev, i, name_counts[SDL_JoystickName(i)]++);
|
Joystick* js = new Joystick(dev, i, name_counts[GetJoystickName(i)]++);
|
||||||
// only add if it has some inputs/outputs
|
// only add if it has some inputs/outputs
|
||||||
if (js->Inputs().size() || js->Outputs().size())
|
if (js->Inputs().size() || js->Outputs().size())
|
||||||
devices.push_back( js );
|
devices.push_back( js );
|
||||||
@@ -325,7 +334,7 @@ bool Joystick::UpdateOutput()
|
|||||||
|
|
||||||
std::string Joystick::GetName() const
|
std::string Joystick::GetName() const
|
||||||
{
|
{
|
||||||
return StripSpaces(SDL_JoystickName(m_sdl_index));
|
return StripSpaces(GetJoystickName(m_sdl_index));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Joystick::GetSource() const
|
std::string Joystick::GetSource() const
|
||||||
|
|||||||
@@ -5,22 +5,14 @@
|
|||||||
|
|
||||||
#include <list>
|
#include <list>
|
||||||
|
|
||||||
#ifdef _WIN32
|
#include <SDL.h>
|
||||||
#include <SDL.h>
|
|
||||||
#else
|
|
||||||
#include <SDL/SDL.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if SDL_VERSION_ATLEAST(1, 3, 0)
|
#if SDL_VERSION_ATLEAST(1, 3, 0)
|
||||||
#define USE_SDL_HAPTIC
|
#define USE_SDL_HAPTIC
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_SDL_HAPTIC
|
#ifdef USE_SDL_HAPTIC
|
||||||
#ifdef _WIN32
|
#include <SDL_haptic.h>
|
||||||
#include <SDL_haptic.h>
|
|
||||||
#else
|
|
||||||
#include <SDL/SDL_haptic.h>
|
|
||||||
#endif
|
|
||||||
#define SDL_INIT_FLAGS SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC
|
#define SDL_INIT_FLAGS SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC
|
||||||
#else
|
#else
|
||||||
#define SDL_INIT_FLAGS SDL_INIT_JOYSTICK
|
#define SDL_INIT_FLAGS SDL_INIT_JOYSTICK
|
||||||
|
|||||||
@@ -456,6 +456,7 @@ void BPWritten(const BPCmd& bp)
|
|||||||
|
|
||||||
case BPMEM_ZCOMPARE: // Set the Z-Compare and EFB pixel format
|
case BPMEM_ZCOMPARE: // Set the Z-Compare and EFB pixel format
|
||||||
g_renderer->SetColorMask(); // alpha writing needs to be disabled if the new pixel format doesn't have an alpha channel
|
g_renderer->SetColorMask(); // alpha writing needs to be disabled if the new pixel format doesn't have an alpha channel
|
||||||
|
g_renderer->SetBlendMode(true);
|
||||||
OnPixelFormatChange();
|
OnPixelFormatChange();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
@@ -218,6 +218,9 @@ void TextureCache::ClearRenderTargets()
|
|||||||
|
|
||||||
bool TextureCache::CheckForCustomTextureLODs(u64 tex_hash, int texformat, unsigned int levels)
|
bool TextureCache::CheckForCustomTextureLODs(u64 tex_hash, int texformat, unsigned int levels)
|
||||||
{
|
{
|
||||||
|
if (levels == 1)
|
||||||
|
return false;
|
||||||
|
|
||||||
// Just checking if the necessary files exist, if they can't be loaded or have incorrect dimensions LODs will be black
|
// Just checking if the necessary files exist, if they can't be loaded or have incorrect dimensions LODs will be black
|
||||||
char texBasePathTemp[MAX_PATH];
|
char texBasePathTemp[MAX_PATH];
|
||||||
char texPathTemp[MAX_PATH];
|
char texPathTemp[MAX_PATH];
|
||||||
@@ -300,7 +303,7 @@ void TextureCache::DumpTexture(TCacheEntryBase* entry, unsigned int level)
|
|||||||
|
|
||||||
TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage,
|
TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage,
|
||||||
u32 address, unsigned int width, unsigned int height, int texformat,
|
u32 address, unsigned int width, unsigned int height, int texformat,
|
||||||
unsigned int tlutaddr, int tlutfmt, bool UseNativeMips, unsigned int maxlevel, bool from_tmem)
|
unsigned int tlutaddr, int tlutfmt, bool use_mipmaps, unsigned int maxlevel, bool from_tmem)
|
||||||
{
|
{
|
||||||
if (0 == address)
|
if (0 == address)
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -372,7 +375,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage,
|
|||||||
|
|
||||||
// 2. b) For normal textures, all texture parameters need to match
|
// 2. b) For normal textures, all texture parameters need to match
|
||||||
if (address == entry->addr && tex_hash == entry->hash && full_format == entry->format &&
|
if (address == entry->addr && tex_hash == entry->hash && full_format == entry->format &&
|
||||||
entry->num_mipmaps == maxlevel && entry->native_width == nativeW && entry->native_height == nativeH)
|
entry->num_mipmaps > maxlevel && entry->native_width == nativeW && entry->native_height == nativeH)
|
||||||
{
|
{
|
||||||
goto return_entry;
|
goto return_entry;
|
||||||
}
|
}
|
||||||
@@ -382,7 +385,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage,
|
|||||||
//
|
//
|
||||||
// TODO: Don't we need to force texture decoding to RGBA8 for dynamic EFB copies?
|
// TODO: Don't we need to force texture decoding to RGBA8 for dynamic EFB copies?
|
||||||
// TODO: Actually, it should be enough if the internal texture format matches...
|
// TODO: Actually, it should be enough if the internal texture format matches...
|
||||||
if ((entry->type == TCET_NORMAL && width == entry->virtual_width && height == entry->virtual_height && full_format == entry->format && entry->num_mipmaps == maxlevel)
|
if ((entry->type == TCET_NORMAL && width == entry->virtual_width && height == entry->virtual_height && full_format == entry->format && entry->num_mipmaps > maxlevel)
|
||||||
|| (entry->type == TCET_EC_DYNAMIC && entry->native_width == width && entry->native_height == height))
|
|| (entry->type == TCET_EC_DYNAMIC && entry->native_width == width && entry->native_height == height))
|
||||||
{
|
{
|
||||||
// reuse the texture
|
// reuse the texture
|
||||||
@@ -428,15 +431,12 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Cleanup. Plus, we still autogenerate mipmaps in certain cases (we shouldn't do that)
|
|
||||||
bool isPow2;
|
|
||||||
unsigned int texLevels;
|
unsigned int texLevels;
|
||||||
isPow2 = !((width & (width - 1)) || (height & (height - 1)));
|
bool use_native_mips;
|
||||||
texLevels = (isPow2 && maxlevel) ? GetPow2(std::max(width, height)) : !isPow2;
|
texLevels = use_mipmaps ? (maxlevel + 1) : 1;
|
||||||
texLevels = maxlevel ? std::min(texLevels, maxlevel + 1) : texLevels;
|
|
||||||
using_custom_lods = using_custom_texture && CheckForCustomTextureLODs(tex_hash, texformat, texLevels);
|
using_custom_lods = using_custom_texture && CheckForCustomTextureLODs(tex_hash, texformat, texLevels);
|
||||||
UseNativeMips = UseNativeMips && !using_custom_lods && (width == nativeW && height == nativeH); // Only load native mips if their dimensions fit to our virtual texture dimensions
|
use_native_mips = use_mipmaps && !using_custom_lods && (width == nativeW && height == nativeH); // Only load native mips if their dimensions fit to our virtual texture dimensions
|
||||||
texLevels = (UseNativeMips || using_custom_lods) ? texLevels : !isPow2;
|
texLevels = (use_native_mips || using_custom_lods) ? texLevels : 1;
|
||||||
|
|
||||||
// create the entry/texture
|
// create the entry/texture
|
||||||
if (NULL == entry) {
|
if (NULL == entry) {
|
||||||
@@ -445,9 +445,8 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage,
|
|||||||
// Sometimes, we can get around recreating a texture if only the number of mip levels changes
|
// Sometimes, we can get around recreating a texture if only the number of mip levels changes
|
||||||
// e.g. if our texture cache entry got too many mipmap levels we can limit the number of used levels by setting the appropriate render states
|
// e.g. if our texture cache entry got too many mipmap levels we can limit the number of used levels by setting the appropriate render states
|
||||||
// Thus, we don't update this member for every Load, but just whenever the texture gets recreated
|
// Thus, we don't update this member for every Load, but just whenever the texture gets recreated
|
||||||
//
|
// TODO: D3D9 doesn't support min_lod. We should add a workaround for that here!
|
||||||
// TODO: Won't we end up recreating textures all the time because maxlevel doesn't necessarily equal texLevels?
|
entry->num_mipmaps = maxlevel + 1;
|
||||||
entry->num_mipmaps = maxlevel; // TODO: Does this actually work? We can't really adjust mipmap settings per-stage...
|
|
||||||
entry->type = TCET_NORMAL;
|
entry->type = TCET_NORMAL;
|
||||||
|
|
||||||
GFX_DEBUGGER_PAUSE_AT(NEXT_NEW_TEXTURE, true);
|
GFX_DEBUGGER_PAUSE_AT(NEXT_NEW_TEXTURE, true);
|
||||||
@@ -460,13 +459,13 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage,
|
|||||||
else entry->type = TCET_NORMAL;
|
else entry->type = TCET_NORMAL;
|
||||||
|
|
||||||
// load texture
|
// load texture
|
||||||
entry->Load(width, height, expandedWidth, 0, (texLevels == 0));
|
entry->Load(width, height, expandedWidth, 0);
|
||||||
|
|
||||||
if (g_ActiveConfig.bDumpTextures && !using_custom_texture)
|
if (g_ActiveConfig.bDumpTextures && !using_custom_texture)
|
||||||
DumpTexture(entry, 0);
|
DumpTexture(entry, 0);
|
||||||
|
|
||||||
// load mips - TODO: Loading mipmaps from tmem is untested!
|
// load mips - TODO: Loading mipmaps from tmem is untested!
|
||||||
if (texLevels > 1 && pcfmt != PC_TEX_FMT_NONE && UseNativeMips)
|
if (texLevels > 1 && pcfmt != PC_TEX_FMT_NONE && use_native_mips)
|
||||||
{
|
{
|
||||||
const unsigned int bsdepth = TexDecoder_GetTexelSizeInNibbles(texformat);
|
const unsigned int bsdepth = TexDecoder_GetTexelSizeInNibbles(texformat);
|
||||||
|
|
||||||
@@ -495,7 +494,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage,
|
|||||||
expandedHeight = (currentHeight + bsh) & (~bsh);
|
expandedHeight = (currentHeight + bsh) & (~bsh);
|
||||||
|
|
||||||
TexDecoder_Decode(temp, *ptr, expandedWidth, expandedHeight, texformat, tlutaddr, tlutfmt, g_ActiveConfig.backend_info.bUseRGBATextures);
|
TexDecoder_Decode(temp, *ptr, expandedWidth, expandedHeight, texformat, tlutaddr, tlutfmt, g_ActiveConfig.backend_info.bUseRGBATextures);
|
||||||
entry->Load(currentWidth, currentHeight, expandedWidth, level, false);
|
entry->Load(currentWidth, currentHeight, expandedWidth, level);
|
||||||
|
|
||||||
if (g_ActiveConfig.bDumpTextures)
|
if (g_ActiveConfig.bDumpTextures)
|
||||||
DumpTexture(entry, level);
|
DumpTexture(entry, level);
|
||||||
@@ -518,7 +517,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage,
|
|||||||
unsigned int currentHeight = (mipHeight > 0) ? mipHeight : 1;
|
unsigned int currentHeight = (mipHeight > 0) ? mipHeight : 1;
|
||||||
|
|
||||||
LoadCustomTexture(tex_hash, texformat, level, currentWidth, currentHeight);
|
LoadCustomTexture(tex_hash, texformat, level, currentWidth, currentHeight);
|
||||||
entry->Load(currentWidth, currentHeight, currentWidth, level, false);
|
entry->Load(currentWidth, currentHeight, currentWidth, level);
|
||||||
|
|
||||||
mipWidth >>= 1;
|
mipWidth >>= 1;
|
||||||
mipHeight >>= 1;
|
mipHeight >>= 1;
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ public:
|
|||||||
virtual bool Save(const char filename[], unsigned int level) = 0;
|
virtual bool Save(const char filename[], unsigned int level) = 0;
|
||||||
|
|
||||||
virtual void Load(unsigned int width, unsigned int height,
|
virtual void Load(unsigned int width, unsigned int height,
|
||||||
unsigned int expanded_width, unsigned int level, bool autogen_mips) = 0;
|
unsigned int expanded_width, unsigned int level) = 0;
|
||||||
virtual void FromRenderTarget(u32 dstAddr, unsigned int dstFormat,
|
virtual void FromRenderTarget(u32 dstAddr, unsigned int dstFormat,
|
||||||
unsigned int srcFormat, const EFBRectangle& srcRect,
|
unsigned int srcFormat, const EFBRectangle& srcRect,
|
||||||
bool isIntensity, bool scaleByHalf, unsigned int cbufid,
|
bool isIntensity, bool scaleByHalf, unsigned int cbufid,
|
||||||
@@ -116,7 +116,7 @@ public:
|
|||||||
virtual TCacheEntryBase* CreateRenderTargetTexture(unsigned int scaled_tex_w, unsigned int scaled_tex_h) = 0;
|
virtual TCacheEntryBase* CreateRenderTargetTexture(unsigned int scaled_tex_w, unsigned int scaled_tex_h) = 0;
|
||||||
|
|
||||||
static TCacheEntryBase* Load(unsigned int stage, u32 address, unsigned int width, unsigned int height,
|
static TCacheEntryBase* Load(unsigned int stage, u32 address, unsigned int width, unsigned int height,
|
||||||
int format, unsigned int tlutaddr, int tlutfmt, bool UseNativeMips, unsigned int maxlevel, bool from_tmem);
|
int format, unsigned int tlutaddr, int tlutfmt, bool use_mipmaps, unsigned int maxlevel, bool from_tmem);
|
||||||
static void CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat, unsigned int srcFormat,
|
static void CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat, unsigned int srcFormat,
|
||||||
const EFBRectangle& srcRect, bool isIntensity, bool scaleByHalf);
|
const EFBRectangle& srcRect, bool isIntensity, bool scaleByHalf);
|
||||||
|
|
||||||
|
|||||||
@@ -54,8 +54,6 @@ static int s_fps = 0;
|
|||||||
|
|
||||||
static u32 s_LastAA = 0;
|
static u32 s_LastAA = 0;
|
||||||
|
|
||||||
static u32 s_blendMode;
|
|
||||||
|
|
||||||
static Television s_television;
|
static Television s_television;
|
||||||
|
|
||||||
ID3D11Buffer* access_efb_cbuf = NULL;
|
ID3D11Buffer* access_efb_cbuf = NULL;
|
||||||
@@ -76,151 +74,6 @@ struct
|
|||||||
D3D11_RASTERIZER_DESC rastdc;
|
D3D11_RASTERIZER_DESC rastdc;
|
||||||
} gx_state;
|
} gx_state;
|
||||||
|
|
||||||
// State translation lookup tables
|
|
||||||
static const D3D11_BLEND d3dSrcFactors[8] =
|
|
||||||
{
|
|
||||||
D3D11_BLEND_ZERO,
|
|
||||||
D3D11_BLEND_ONE,
|
|
||||||
D3D11_BLEND_DEST_COLOR,
|
|
||||||
D3D11_BLEND_INV_DEST_COLOR,
|
|
||||||
D3D11_BLEND_SRC_ALPHA,
|
|
||||||
D3D11_BLEND_INV_SRC_ALPHA, // NOTE: Use SRC1_ALPHA if dst alpha is enabled!
|
|
||||||
D3D11_BLEND_DEST_ALPHA,
|
|
||||||
D3D11_BLEND_INV_DEST_ALPHA
|
|
||||||
};
|
|
||||||
|
|
||||||
static const D3D11_BLEND d3dDestFactors[8] =
|
|
||||||
{
|
|
||||||
D3D11_BLEND_ZERO,
|
|
||||||
D3D11_BLEND_ONE,
|
|
||||||
D3D11_BLEND_SRC_COLOR,
|
|
||||||
D3D11_BLEND_INV_SRC_COLOR,
|
|
||||||
D3D11_BLEND_SRC_ALPHA,
|
|
||||||
D3D11_BLEND_INV_SRC_ALPHA, // NOTE: Use SRC1_ALPHA if dst alpha is enabled!
|
|
||||||
D3D11_BLEND_DEST_ALPHA,
|
|
||||||
D3D11_BLEND_INV_DEST_ALPHA
|
|
||||||
};
|
|
||||||
|
|
||||||
// 0 0x00
|
|
||||||
// 1 Source & destination
|
|
||||||
// 2 Source & ~destination
|
|
||||||
// 3 Source
|
|
||||||
// 4 ~Source & destination
|
|
||||||
// 5 Destination
|
|
||||||
// 6 Source ^ destination = Source & ~destination | ~Source & destination
|
|
||||||
// 7 Source | destination
|
|
||||||
|
|
||||||
// 8 ~(Source | destination)
|
|
||||||
// 9 ~(Source ^ destination) = ~Source & ~destination | Source & destination
|
|
||||||
// 10 ~Destination
|
|
||||||
// 11 Source | ~destination
|
|
||||||
// 12 ~Source
|
|
||||||
// 13 ~Source | destination
|
|
||||||
// 14 ~(Source & destination)
|
|
||||||
// 15 0xff
|
|
||||||
|
|
||||||
static const D3D11_BLEND_OP d3dLogicOps[16] =
|
|
||||||
{
|
|
||||||
D3D11_BLEND_OP_ADD,//0
|
|
||||||
D3D11_BLEND_OP_ADD,//1
|
|
||||||
D3D11_BLEND_OP_SUBTRACT,//2
|
|
||||||
D3D11_BLEND_OP_ADD,//3
|
|
||||||
D3D11_BLEND_OP_REV_SUBTRACT,//4
|
|
||||||
D3D11_BLEND_OP_ADD,//5
|
|
||||||
D3D11_BLEND_OP_MAX,//6
|
|
||||||
D3D11_BLEND_OP_ADD,//7
|
|
||||||
|
|
||||||
D3D11_BLEND_OP_MAX,//8
|
|
||||||
D3D11_BLEND_OP_MAX,//9
|
|
||||||
D3D11_BLEND_OP_ADD,//10
|
|
||||||
D3D11_BLEND_OP_ADD,//11
|
|
||||||
D3D11_BLEND_OP_ADD,//12
|
|
||||||
D3D11_BLEND_OP_ADD,//13
|
|
||||||
D3D11_BLEND_OP_ADD,//14
|
|
||||||
D3D11_BLEND_OP_ADD//15
|
|
||||||
};
|
|
||||||
|
|
||||||
static const D3D11_BLEND d3dLogicOpSrcFactors[16] =
|
|
||||||
{
|
|
||||||
D3D11_BLEND_ZERO,//0
|
|
||||||
D3D11_BLEND_DEST_COLOR,//1
|
|
||||||
D3D11_BLEND_ONE,//2
|
|
||||||
D3D11_BLEND_ONE,//3
|
|
||||||
D3D11_BLEND_DEST_COLOR,//4
|
|
||||||
D3D11_BLEND_ZERO,//5
|
|
||||||
D3D11_BLEND_INV_DEST_COLOR,//6
|
|
||||||
D3D11_BLEND_INV_DEST_COLOR,//7
|
|
||||||
|
|
||||||
D3D11_BLEND_INV_SRC_COLOR,//8
|
|
||||||
D3D11_BLEND_INV_SRC_COLOR,//9
|
|
||||||
D3D11_BLEND_INV_DEST_COLOR,//10
|
|
||||||
D3D11_BLEND_ONE,//11
|
|
||||||
D3D11_BLEND_INV_SRC_COLOR,//12
|
|
||||||
D3D11_BLEND_INV_SRC_COLOR,//13
|
|
||||||
D3D11_BLEND_INV_DEST_COLOR,//14
|
|
||||||
D3D11_BLEND_ONE//15
|
|
||||||
};
|
|
||||||
|
|
||||||
static const D3D11_BLEND d3dLogicOpDestFactors[16] =
|
|
||||||
{
|
|
||||||
D3D11_BLEND_ZERO,//0
|
|
||||||
D3D11_BLEND_ZERO,//1
|
|
||||||
D3D11_BLEND_INV_SRC_COLOR,//2
|
|
||||||
D3D11_BLEND_ZERO,//3
|
|
||||||
D3D11_BLEND_ONE,//4
|
|
||||||
D3D11_BLEND_ONE,//5
|
|
||||||
D3D11_BLEND_INV_SRC_COLOR,//6
|
|
||||||
D3D11_BLEND_ONE,//7
|
|
||||||
|
|
||||||
D3D11_BLEND_INV_DEST_COLOR,//8
|
|
||||||
D3D11_BLEND_SRC_COLOR,//9
|
|
||||||
D3D11_BLEND_INV_DEST_COLOR,//10
|
|
||||||
D3D11_BLEND_INV_DEST_COLOR,//11
|
|
||||||
D3D11_BLEND_INV_SRC_COLOR,//12
|
|
||||||
D3D11_BLEND_ONE,//13
|
|
||||||
D3D11_BLEND_INV_SRC_COLOR,//14
|
|
||||||
D3D11_BLEND_ONE//15
|
|
||||||
};
|
|
||||||
|
|
||||||
static const D3D11_CULL_MODE d3dCullModes[4] =
|
|
||||||
{
|
|
||||||
D3D11_CULL_NONE,
|
|
||||||
D3D11_CULL_BACK,
|
|
||||||
D3D11_CULL_FRONT,
|
|
||||||
D3D11_CULL_BACK
|
|
||||||
};
|
|
||||||
|
|
||||||
static const D3D11_COMPARISON_FUNC d3dCmpFuncs[8] =
|
|
||||||
{
|
|
||||||
D3D11_COMPARISON_NEVER,
|
|
||||||
D3D11_COMPARISON_LESS,
|
|
||||||
D3D11_COMPARISON_EQUAL,
|
|
||||||
D3D11_COMPARISON_LESS_EQUAL,
|
|
||||||
D3D11_COMPARISON_GREATER,
|
|
||||||
D3D11_COMPARISON_NOT_EQUAL,
|
|
||||||
D3D11_COMPARISON_GREATER_EQUAL,
|
|
||||||
D3D11_COMPARISON_ALWAYS
|
|
||||||
};
|
|
||||||
|
|
||||||
#define TEXF_NONE 0
|
|
||||||
#define TEXF_POINT 1
|
|
||||||
#define TEXF_LINEAR 2
|
|
||||||
static const unsigned int d3dMipFilters[4] =
|
|
||||||
{
|
|
||||||
TEXF_NONE,
|
|
||||||
TEXF_POINT,
|
|
||||||
TEXF_LINEAR,
|
|
||||||
TEXF_NONE, //reserved
|
|
||||||
};
|
|
||||||
|
|
||||||
static const D3D11_TEXTURE_ADDRESS_MODE d3dClamps[4] =
|
|
||||||
{
|
|
||||||
D3D11_TEXTURE_ADDRESS_CLAMP,
|
|
||||||
D3D11_TEXTURE_ADDRESS_WRAP,
|
|
||||||
D3D11_TEXTURE_ADDRESS_MIRROR,
|
|
||||||
D3D11_TEXTURE_ADDRESS_WRAP //reserved
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
void SetupDeviceObjects()
|
void SetupDeviceObjects()
|
||||||
{
|
{
|
||||||
@@ -338,7 +191,6 @@ void CreateScreenshotTexture()
|
|||||||
Renderer::Renderer()
|
Renderer::Renderer()
|
||||||
{
|
{
|
||||||
int x, y, w_temp, h_temp;
|
int x, y, w_temp, h_temp;
|
||||||
s_blendMode = 0;
|
|
||||||
|
|
||||||
InitFPSCounter();
|
InitFPSCounter();
|
||||||
|
|
||||||
@@ -833,6 +685,32 @@ void SetBlendOp(D3D11_BLEND_OP val)
|
|||||||
|
|
||||||
void Renderer::SetBlendMode(bool forceUpdate)
|
void Renderer::SetBlendMode(bool forceUpdate)
|
||||||
{
|
{
|
||||||
|
// Our render target always uses an alpha channel, so we need to override the blend functions to assume a destination alpha of 1 if the render target isn't supposed to have an alpha channel
|
||||||
|
// Example: D3DBLEND_DESTALPHA needs to be D3DBLEND_ONE since the result without an alpha channel is assumed to always be 1.
|
||||||
|
bool target_has_alpha = bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24;
|
||||||
|
const D3D11_BLEND d3dSrcFactors[8] =
|
||||||
|
{
|
||||||
|
D3D11_BLEND_ZERO,
|
||||||
|
D3D11_BLEND_ONE,
|
||||||
|
D3D11_BLEND_DEST_COLOR,
|
||||||
|
D3D11_BLEND_INV_DEST_COLOR,
|
||||||
|
D3D11_BLEND_SRC_ALPHA,
|
||||||
|
D3D11_BLEND_INV_SRC_ALPHA, // NOTE: Use SRC1_ALPHA if dst alpha is enabled!
|
||||||
|
(target_has_alpha) ? D3D11_BLEND_DEST_ALPHA : D3D11_BLEND_ONE,
|
||||||
|
(target_has_alpha) ? D3D11_BLEND_INV_DEST_ALPHA : D3D11_BLEND_ZERO
|
||||||
|
};
|
||||||
|
const D3D11_BLEND d3dDestFactors[8] =
|
||||||
|
{
|
||||||
|
D3D11_BLEND_ZERO,
|
||||||
|
D3D11_BLEND_ONE,
|
||||||
|
D3D11_BLEND_SRC_COLOR,
|
||||||
|
D3D11_BLEND_INV_SRC_COLOR,
|
||||||
|
D3D11_BLEND_SRC_ALPHA,
|
||||||
|
D3D11_BLEND_INV_SRC_ALPHA, // NOTE: Use SRC1_ALPHA if dst alpha is enabled!
|
||||||
|
(target_has_alpha) ? D3D11_BLEND_DEST_ALPHA : D3D11_BLEND_ONE,
|
||||||
|
(target_has_alpha) ? D3D11_BLEND_INV_DEST_ALPHA : D3D11_BLEND_ZERO
|
||||||
|
};
|
||||||
|
|
||||||
if (bpmem.blendmode.logicopenable && !forceUpdate)
|
if (bpmem.blendmode.logicopenable && !forceUpdate)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -845,8 +723,8 @@ void Renderer::SetBlendMode(bool forceUpdate)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
gx_state.blenddc.RenderTarget[0].BlendEnable = bpmem.blendmode.blendenable && (!( bpmem.blendmode.srcfactor == 1 && bpmem.blendmode.dstfactor == 0));
|
gx_state.blenddc.RenderTarget[0].BlendEnable = bpmem.blendmode.blendenable;
|
||||||
if (bpmem.blendmode.blendenable && (!( bpmem.blendmode.srcfactor == 1 && bpmem.blendmode.dstfactor == 0)))
|
if (bpmem.blendmode.blendenable)
|
||||||
{
|
{
|
||||||
SetBlendOp(D3D11_BLEND_OP_ADD);
|
SetBlendOp(D3D11_BLEND_OP_ADD);
|
||||||
SetSrcBlend(d3dSrcFactors[bpmem.blendmode.srcfactor]);
|
SetSrcBlend(d3dSrcFactors[bpmem.blendmode.srcfactor]);
|
||||||
@@ -1331,12 +1209,32 @@ void Renderer::RestoreCull()
|
|||||||
|
|
||||||
void Renderer::SetGenerationMode()
|
void Renderer::SetGenerationMode()
|
||||||
{
|
{
|
||||||
|
const D3D11_CULL_MODE d3dCullModes[4] =
|
||||||
|
{
|
||||||
|
D3D11_CULL_NONE,
|
||||||
|
D3D11_CULL_BACK,
|
||||||
|
D3D11_CULL_FRONT,
|
||||||
|
D3D11_CULL_BACK
|
||||||
|
};
|
||||||
|
|
||||||
// rastdc.FrontCounterClockwise must be false for this to work
|
// rastdc.FrontCounterClockwise must be false for this to work
|
||||||
gx_state.rastdc.CullMode = d3dCullModes[bpmem.genMode.cullmode];
|
gx_state.rastdc.CullMode = d3dCullModes[bpmem.genMode.cullmode];
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::SetDepthMode()
|
void Renderer::SetDepthMode()
|
||||||
{
|
{
|
||||||
|
const D3D11_COMPARISON_FUNC d3dCmpFuncs[8] =
|
||||||
|
{
|
||||||
|
D3D11_COMPARISON_NEVER,
|
||||||
|
D3D11_COMPARISON_LESS,
|
||||||
|
D3D11_COMPARISON_EQUAL,
|
||||||
|
D3D11_COMPARISON_LESS_EQUAL,
|
||||||
|
D3D11_COMPARISON_GREATER,
|
||||||
|
D3D11_COMPARISON_NOT_EQUAL,
|
||||||
|
D3D11_COMPARISON_GREATER_EQUAL,
|
||||||
|
D3D11_COMPARISON_ALWAYS
|
||||||
|
};
|
||||||
|
|
||||||
if (bpmem.zmode.testenable)
|
if (bpmem.zmode.testenable)
|
||||||
{
|
{
|
||||||
gx_state.depthdc.DepthEnable = TRUE;
|
gx_state.depthdc.DepthEnable = TRUE;
|
||||||
@@ -1353,9 +1251,85 @@ void Renderer::SetDepthMode()
|
|||||||
|
|
||||||
void Renderer::SetLogicOpMode()
|
void Renderer::SetLogicOpMode()
|
||||||
{
|
{
|
||||||
if (bpmem.blendmode.logicopenable && bpmem.blendmode.logicmode != 3)
|
// D3D11 doesn't support logic blending, so this is a huge hack
|
||||||
|
// TODO: Make use of D3D11.1's logic blending support
|
||||||
|
|
||||||
|
// 0 0x00
|
||||||
|
// 1 Source & destination
|
||||||
|
// 2 Source & ~destination
|
||||||
|
// 3 Source
|
||||||
|
// 4 ~Source & destination
|
||||||
|
// 5 Destination
|
||||||
|
// 6 Source ^ destination = Source & ~destination | ~Source & destination
|
||||||
|
// 7 Source | destination
|
||||||
|
// 8 ~(Source | destination)
|
||||||
|
// 9 ~(Source ^ destination) = ~Source & ~destination | Source & destination
|
||||||
|
// 10 ~Destination
|
||||||
|
// 11 Source | ~destination
|
||||||
|
// 12 ~Source
|
||||||
|
// 13 ~Source | destination
|
||||||
|
// 14 ~(Source & destination)
|
||||||
|
// 15 0xff
|
||||||
|
const D3D11_BLEND_OP d3dLogicOps[16] =
|
||||||
|
{
|
||||||
|
D3D11_BLEND_OP_ADD,//0
|
||||||
|
D3D11_BLEND_OP_ADD,//1
|
||||||
|
D3D11_BLEND_OP_SUBTRACT,//2
|
||||||
|
D3D11_BLEND_OP_ADD,//3
|
||||||
|
D3D11_BLEND_OP_REV_SUBTRACT,//4
|
||||||
|
D3D11_BLEND_OP_ADD,//5
|
||||||
|
D3D11_BLEND_OP_MAX,//6
|
||||||
|
D3D11_BLEND_OP_ADD,//7
|
||||||
|
D3D11_BLEND_OP_MAX,//8
|
||||||
|
D3D11_BLEND_OP_MAX,//9
|
||||||
|
D3D11_BLEND_OP_ADD,//10
|
||||||
|
D3D11_BLEND_OP_ADD,//11
|
||||||
|
D3D11_BLEND_OP_ADD,//12
|
||||||
|
D3D11_BLEND_OP_ADD,//13
|
||||||
|
D3D11_BLEND_OP_ADD,//14
|
||||||
|
D3D11_BLEND_OP_ADD//15
|
||||||
|
};
|
||||||
|
const D3D11_BLEND d3dLogicOpSrcFactors[16] =
|
||||||
|
{
|
||||||
|
D3D11_BLEND_ZERO,//0
|
||||||
|
D3D11_BLEND_DEST_COLOR,//1
|
||||||
|
D3D11_BLEND_ONE,//2
|
||||||
|
D3D11_BLEND_ONE,//3
|
||||||
|
D3D11_BLEND_DEST_COLOR,//4
|
||||||
|
D3D11_BLEND_ZERO,//5
|
||||||
|
D3D11_BLEND_INV_DEST_COLOR,//6
|
||||||
|
D3D11_BLEND_INV_DEST_COLOR,//7
|
||||||
|
D3D11_BLEND_INV_SRC_COLOR,//8
|
||||||
|
D3D11_BLEND_INV_SRC_COLOR,//9
|
||||||
|
D3D11_BLEND_INV_DEST_COLOR,//10
|
||||||
|
D3D11_BLEND_ONE,//11
|
||||||
|
D3D11_BLEND_INV_SRC_COLOR,//12
|
||||||
|
D3D11_BLEND_INV_SRC_COLOR,//13
|
||||||
|
D3D11_BLEND_INV_DEST_COLOR,//14
|
||||||
|
D3D11_BLEND_ONE//15
|
||||||
|
};
|
||||||
|
const D3D11_BLEND d3dLogicOpDestFactors[16] =
|
||||||
|
{
|
||||||
|
D3D11_BLEND_ZERO,//0
|
||||||
|
D3D11_BLEND_ZERO,//1
|
||||||
|
D3D11_BLEND_INV_SRC_COLOR,//2
|
||||||
|
D3D11_BLEND_ZERO,//3
|
||||||
|
D3D11_BLEND_ONE,//4
|
||||||
|
D3D11_BLEND_ONE,//5
|
||||||
|
D3D11_BLEND_INV_SRC_COLOR,//6
|
||||||
|
D3D11_BLEND_ONE,//7
|
||||||
|
D3D11_BLEND_INV_DEST_COLOR,//8
|
||||||
|
D3D11_BLEND_SRC_COLOR,//9
|
||||||
|
D3D11_BLEND_INV_DEST_COLOR,//10
|
||||||
|
D3D11_BLEND_INV_DEST_COLOR,//11
|
||||||
|
D3D11_BLEND_INV_SRC_COLOR,//12
|
||||||
|
D3D11_BLEND_ONE,//13
|
||||||
|
D3D11_BLEND_INV_SRC_COLOR,//14
|
||||||
|
D3D11_BLEND_ONE//15
|
||||||
|
};
|
||||||
|
|
||||||
|
if (bpmem.blendmode.logicopenable)
|
||||||
{
|
{
|
||||||
s_blendMode = 0;
|
|
||||||
gx_state.blenddc.RenderTarget[0].BlendEnable = true;
|
gx_state.blenddc.RenderTarget[0].BlendEnable = true;
|
||||||
SetBlendOp(d3dLogicOps[bpmem.blendmode.logicmode]);
|
SetBlendOp(d3dLogicOps[bpmem.blendmode.logicmode]);
|
||||||
SetSrcBlend(d3dLogicOpSrcFactors[bpmem.blendmode.logicmode]);
|
SetSrcBlend(d3dLogicOpSrcFactors[bpmem.blendmode.logicmode]);
|
||||||
@@ -1379,18 +1353,32 @@ void Renderer::SetLineWidth()
|
|||||||
|
|
||||||
void Renderer::SetSamplerState(int stage, int texindex)
|
void Renderer::SetSamplerState(int stage, int texindex)
|
||||||
{
|
{
|
||||||
|
#define TEXF_NONE 0
|
||||||
|
#define TEXF_POINT 1
|
||||||
|
#define TEXF_LINEAR 2
|
||||||
|
const unsigned int d3dMipFilters[4] =
|
||||||
|
{
|
||||||
|
TEXF_NONE,
|
||||||
|
TEXF_POINT,
|
||||||
|
TEXF_LINEAR,
|
||||||
|
TEXF_NONE, //reserved
|
||||||
|
};
|
||||||
|
const D3D11_TEXTURE_ADDRESS_MODE d3dClamps[4] =
|
||||||
|
{
|
||||||
|
D3D11_TEXTURE_ADDRESS_CLAMP,
|
||||||
|
D3D11_TEXTURE_ADDRESS_WRAP,
|
||||||
|
D3D11_TEXTURE_ADDRESS_MIRROR,
|
||||||
|
D3D11_TEXTURE_ADDRESS_WRAP //reserved
|
||||||
|
};
|
||||||
|
|
||||||
const FourTexUnits &tex = bpmem.tex[texindex];
|
const FourTexUnits &tex = bpmem.tex[texindex];
|
||||||
const TexMode0 &tm0 = tex.texMode0[stage];
|
const TexMode0 &tm0 = tex.texMode0[stage];
|
||||||
const TexMode1 &tm1 = tex.texMode1[stage];
|
const TexMode1 &tm1 = tex.texMode1[stage];
|
||||||
|
|
||||||
unsigned int mip;
|
unsigned int mip = d3dMipFilters[tm0.min_filter & 3];
|
||||||
mip = (tm0.min_filter == 8) ? TEXF_NONE:d3dMipFilters[tm0.min_filter & 3];
|
|
||||||
if ((tm0.min_filter & 3) && (tm0.min_filter != 8) && ((tm1.max_lod >> 4) == 0)) mip = TEXF_NONE;
|
|
||||||
|
|
||||||
if (texindex) stage += 4;
|
if (texindex) stage += 4;
|
||||||
|
|
||||||
// TODO: Clarify whether these values are correct
|
|
||||||
// NOTE: since there's no "no filter" in DX11 we're using point filters in these cases
|
|
||||||
if (g_ActiveConfig.bForceFiltering)
|
if (g_ActiveConfig.bForceFiltering)
|
||||||
{
|
{
|
||||||
gx_state.sampdc[stage].Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
|
gx_state.sampdc[stage].Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
|
||||||
@@ -1432,7 +1420,7 @@ void Renderer::SetSamplerState(int stage, int texindex)
|
|||||||
// When mipfilter is set to "none", just disable mipmapping altogether
|
// When mipfilter is set to "none", just disable mipmapping altogether
|
||||||
gx_state.sampdc[stage].MaxLOD = (mip == TEXF_NONE) ? 0.0f : (float)tm1.max_lod/16.f;
|
gx_state.sampdc[stage].MaxLOD = (mip == TEXF_NONE) ? 0.0f : (float)tm1.max_lod/16.f;
|
||||||
gx_state.sampdc[stage].MinLOD = (float)tm1.min_lod/16.f;
|
gx_state.sampdc[stage].MinLOD = (float)tm1.min_lod/16.f;
|
||||||
gx_state.sampdc[stage].MipLODBias = (float)tm0.lod_bias/32.0f;
|
gx_state.sampdc[stage].MipLODBias = (s32)tm0.lod_bias/32.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::SetInterlacingMode()
|
void Renderer::SetInterlacingMode()
|
||||||
|
|||||||
@@ -59,12 +59,9 @@ bool TextureCache::TCacheEntry::Save(const char filename[], unsigned int level)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height,
|
void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height,
|
||||||
unsigned int expanded_width, unsigned int level, bool autogen_mips)
|
unsigned int expanded_width, unsigned int level)
|
||||||
{
|
{
|
||||||
D3D::ReplaceRGBATexture2D(texture->GetTex(), TextureCache::temp, width, height, expanded_width, level, usage);
|
D3D::ReplaceRGBATexture2D(texture->GetTex(), TextureCache::temp, width, height, expanded_width, level, usage);
|
||||||
|
|
||||||
if (autogen_mips)
|
|
||||||
PD3DX11FilterTexture(D3D::context, texture->GetTex(), 0, D3DX11_DEFAULT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TextureCache::TCacheEntryBase* TextureCache::CreateTexture(unsigned int width,
|
TextureCache::TCacheEntryBase* TextureCache::CreateTexture(unsigned int width,
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ private:
|
|||||||
~TCacheEntry();
|
~TCacheEntry();
|
||||||
|
|
||||||
void Load(unsigned int width, unsigned int height,
|
void Load(unsigned int width, unsigned int height,
|
||||||
unsigned int expanded_width, unsigned int levels, bool autogen_mips = false);
|
unsigned int expanded_width, unsigned int levels);
|
||||||
|
|
||||||
void FromRenderTarget(u32 dstAddr, unsigned int dstFormat,
|
void FromRenderTarget(u32 dstAddr, unsigned int dstFormat,
|
||||||
unsigned int srcFormat, const EFBRectangle& srcRect,
|
unsigned int srcFormat, const EFBRectangle& srcRect,
|
||||||
|
|||||||
@@ -237,8 +237,8 @@ void VertexManager::vFlush()
|
|||||||
tex.texImage0[i&3].width + 1, tex.texImage0[i&3].height + 1,
|
tex.texImage0[i&3].width + 1, tex.texImage0[i&3].height + 1,
|
||||||
tex.texImage0[i&3].format, tex.texTlut[i&3].tmem_offset<<9,
|
tex.texImage0[i&3].format, tex.texTlut[i&3].tmem_offset<<9,
|
||||||
tex.texTlut[i&3].tlut_format,
|
tex.texTlut[i&3].tlut_format,
|
||||||
(tex.texMode0[i&3].min_filter & 3) && (tex.texMode0[i&3].min_filter != 8),
|
(tex.texMode0[i&3].min_filter & 3),
|
||||||
tex.texMode1[i&3].max_lod >> 4,
|
ceil(tex.texMode1[i&3].max_lod / 16.f),
|
||||||
tex.texImage1[i&3].image_type);
|
tex.texImage1[i&3].image_type);
|
||||||
|
|
||||||
if (tentry)
|
if (tentry)
|
||||||
|
|||||||
@@ -73,148 +73,6 @@ static char *st;
|
|||||||
static LPDIRECT3DSURFACE9 ScreenShootMEMSurface = NULL;
|
static LPDIRECT3DSURFACE9 ScreenShootMEMSurface = NULL;
|
||||||
|
|
||||||
|
|
||||||
// State translation lookup tables
|
|
||||||
static const D3DBLEND d3dSrcFactors[8] =
|
|
||||||
{
|
|
||||||
D3DBLEND_ZERO,
|
|
||||||
D3DBLEND_ONE,
|
|
||||||
D3DBLEND_DESTCOLOR,
|
|
||||||
D3DBLEND_INVDESTCOLOR,
|
|
||||||
D3DBLEND_SRCALPHA,
|
|
||||||
D3DBLEND_INVSRCALPHA,
|
|
||||||
D3DBLEND_DESTALPHA,
|
|
||||||
D3DBLEND_INVDESTALPHA
|
|
||||||
};
|
|
||||||
|
|
||||||
static const D3DBLEND d3dDestFactors[8] =
|
|
||||||
{
|
|
||||||
D3DBLEND_ZERO,
|
|
||||||
D3DBLEND_ONE,
|
|
||||||
D3DBLEND_SRCCOLOR,
|
|
||||||
D3DBLEND_INVSRCCOLOR,
|
|
||||||
D3DBLEND_SRCALPHA,
|
|
||||||
D3DBLEND_INVSRCALPHA,
|
|
||||||
D3DBLEND_DESTALPHA,
|
|
||||||
D3DBLEND_INVDESTALPHA
|
|
||||||
};
|
|
||||||
|
|
||||||
// 0 0x00
|
|
||||||
// 1 Source & destination
|
|
||||||
// 2 Source & ~destination
|
|
||||||
// 3 Source
|
|
||||||
// 4 ~Source & destination
|
|
||||||
// 5 Destination
|
|
||||||
// 6 Source ^ destination = Source & ~destination | ~Source & destination
|
|
||||||
// 7 Source | destination
|
|
||||||
|
|
||||||
// 8 ~(Source | destination)
|
|
||||||
// 9 ~(Source ^ destination) = ~Source & ~destination | Source & destination
|
|
||||||
// 10 ~Destination
|
|
||||||
// 11 Source | ~destination
|
|
||||||
// 12 ~Source
|
|
||||||
// 13 ~Source | destination
|
|
||||||
// 14 ~(Source & destination)
|
|
||||||
// 15 0xff
|
|
||||||
|
|
||||||
static const D3DBLENDOP d3dLogicOpop[16] =
|
|
||||||
{
|
|
||||||
D3DBLENDOP_ADD,
|
|
||||||
D3DBLENDOP_ADD,
|
|
||||||
D3DBLENDOP_SUBTRACT,
|
|
||||||
D3DBLENDOP_ADD,
|
|
||||||
D3DBLENDOP_REVSUBTRACT,
|
|
||||||
D3DBLENDOP_ADD,
|
|
||||||
D3DBLENDOP_MAX,
|
|
||||||
D3DBLENDOP_ADD,
|
|
||||||
|
|
||||||
D3DBLENDOP_MAX,
|
|
||||||
D3DBLENDOP_MAX,
|
|
||||||
D3DBLENDOP_ADD,
|
|
||||||
D3DBLENDOP_ADD,
|
|
||||||
D3DBLENDOP_ADD,
|
|
||||||
D3DBLENDOP_ADD,
|
|
||||||
D3DBLENDOP_ADD,
|
|
||||||
D3DBLENDOP_ADD
|
|
||||||
};
|
|
||||||
|
|
||||||
static const D3DBLEND d3dLogicOpSrcFactors[16] =
|
|
||||||
{
|
|
||||||
D3DBLEND_ZERO,
|
|
||||||
D3DBLEND_DESTCOLOR,
|
|
||||||
D3DBLEND_ONE,
|
|
||||||
D3DBLEND_ONE,
|
|
||||||
D3DBLEND_DESTCOLOR,
|
|
||||||
D3DBLEND_ZERO,
|
|
||||||
D3DBLEND_INVDESTCOLOR,
|
|
||||||
D3DBLEND_INVDESTCOLOR,
|
|
||||||
|
|
||||||
D3DBLEND_INVSRCCOLOR,
|
|
||||||
D3DBLEND_INVSRCCOLOR,
|
|
||||||
D3DBLEND_INVDESTCOLOR,
|
|
||||||
D3DBLEND_ONE,
|
|
||||||
D3DBLEND_INVSRCCOLOR,
|
|
||||||
D3DBLEND_INVSRCCOLOR,
|
|
||||||
D3DBLEND_INVDESTCOLOR,
|
|
||||||
D3DBLEND_ONE
|
|
||||||
};
|
|
||||||
|
|
||||||
static const D3DBLEND d3dLogicOpDestFactors[16] =
|
|
||||||
{
|
|
||||||
D3DBLEND_ZERO,
|
|
||||||
D3DBLEND_ZERO,
|
|
||||||
D3DBLEND_INVSRCCOLOR,
|
|
||||||
D3DBLEND_ZERO,
|
|
||||||
D3DBLEND_ONE,
|
|
||||||
D3DBLEND_ONE,
|
|
||||||
D3DBLEND_INVSRCCOLOR,
|
|
||||||
D3DBLEND_ONE,
|
|
||||||
|
|
||||||
D3DBLEND_INVDESTCOLOR,
|
|
||||||
D3DBLEND_SRCCOLOR,
|
|
||||||
D3DBLEND_INVDESTCOLOR,
|
|
||||||
D3DBLEND_INVDESTCOLOR,
|
|
||||||
D3DBLEND_INVSRCCOLOR,
|
|
||||||
D3DBLEND_ONE,
|
|
||||||
D3DBLEND_INVSRCCOLOR,
|
|
||||||
D3DBLEND_ONE
|
|
||||||
};
|
|
||||||
|
|
||||||
static const D3DCULL d3dCullModes[4] =
|
|
||||||
{
|
|
||||||
D3DCULL_NONE,
|
|
||||||
D3DCULL_CCW,
|
|
||||||
D3DCULL_CW,
|
|
||||||
D3DCULL_CCW
|
|
||||||
};
|
|
||||||
|
|
||||||
static const D3DCMPFUNC d3dCmpFuncs[8] =
|
|
||||||
{
|
|
||||||
D3DCMP_NEVER,
|
|
||||||
D3DCMP_LESS,
|
|
||||||
D3DCMP_EQUAL,
|
|
||||||
D3DCMP_LESSEQUAL,
|
|
||||||
D3DCMP_GREATER,
|
|
||||||
D3DCMP_NOTEQUAL,
|
|
||||||
D3DCMP_GREATEREQUAL,
|
|
||||||
D3DCMP_ALWAYS
|
|
||||||
};
|
|
||||||
|
|
||||||
static const D3DTEXTUREFILTERTYPE d3dMipFilters[4] =
|
|
||||||
{
|
|
||||||
D3DTEXF_NONE,
|
|
||||||
D3DTEXF_POINT,
|
|
||||||
D3DTEXF_LINEAR,
|
|
||||||
D3DTEXF_NONE, //reserved
|
|
||||||
};
|
|
||||||
|
|
||||||
static const D3DTEXTUREADDRESS d3dClamps[4] =
|
|
||||||
{
|
|
||||||
D3DTADDRESS_CLAMP,
|
|
||||||
D3DTADDRESS_WRAP,
|
|
||||||
D3DTADDRESS_MIRROR,
|
|
||||||
D3DTADDRESS_WRAP //reserved
|
|
||||||
};
|
|
||||||
|
|
||||||
void SetupDeviceObjects()
|
void SetupDeviceObjects()
|
||||||
{
|
{
|
||||||
D3D::font.Init();
|
D3D::font.Init();
|
||||||
@@ -796,6 +654,32 @@ void Renderer::ReinterpretPixelData(unsigned int convtype)
|
|||||||
|
|
||||||
void Renderer::SetBlendMode(bool forceUpdate)
|
void Renderer::SetBlendMode(bool forceUpdate)
|
||||||
{
|
{
|
||||||
|
// Our render target always uses an alpha channel, so we need to override the blend functions to assume a destination alpha of 1 if the render target isn't supposed to have an alpha channel
|
||||||
|
// Example: D3DBLEND_DESTALPHA needs to be D3DBLEND_ONE since the result without an alpha channel is assumed to always be 1.
|
||||||
|
bool target_has_alpha = bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24;
|
||||||
|
const D3DBLEND d3dSrcFactors[8] =
|
||||||
|
{
|
||||||
|
D3DBLEND_ZERO,
|
||||||
|
D3DBLEND_ONE,
|
||||||
|
D3DBLEND_DESTCOLOR,
|
||||||
|
D3DBLEND_INVDESTCOLOR,
|
||||||
|
D3DBLEND_SRCALPHA,
|
||||||
|
D3DBLEND_INVSRCALPHA,
|
||||||
|
(target_has_alpha) ? D3DBLEND_DESTALPHA : D3DBLEND_ONE,
|
||||||
|
(target_has_alpha) ? D3DBLEND_INVDESTALPHA : D3DBLEND_ZERO
|
||||||
|
};
|
||||||
|
const D3DBLEND d3dDestFactors[8] =
|
||||||
|
{
|
||||||
|
D3DBLEND_ZERO,
|
||||||
|
D3DBLEND_ONE,
|
||||||
|
D3DBLEND_SRCCOLOR,
|
||||||
|
D3DBLEND_INVSRCCOLOR,
|
||||||
|
D3DBLEND_SRCALPHA,
|
||||||
|
D3DBLEND_INVSRCALPHA,
|
||||||
|
(target_has_alpha) ? D3DBLEND_DESTALPHA : D3DBLEND_ONE,
|
||||||
|
(target_has_alpha) ? D3DBLEND_INVDESTALPHA : D3DBLEND_ZERO
|
||||||
|
};
|
||||||
|
|
||||||
if (bpmem.blendmode.logicopenable && !forceUpdate)
|
if (bpmem.blendmode.logicopenable && !forceUpdate)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -808,8 +692,8 @@ void Renderer::SetBlendMode(bool forceUpdate)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
D3D::SetRenderState(D3DRS_ALPHABLENDENABLE, bpmem.blendmode.blendenable && (!( bpmem.blendmode.srcfactor == 1 && bpmem.blendmode.dstfactor == 0)));
|
D3D::SetRenderState(D3DRS_ALPHABLENDENABLE, bpmem.blendmode.blendenable);
|
||||||
if (bpmem.blendmode.blendenable && (!( bpmem.blendmode.srcfactor == 1 && bpmem.blendmode.dstfactor == 0)))
|
if (bpmem.blendmode.blendenable)
|
||||||
{
|
{
|
||||||
D3D::SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
|
D3D::SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
|
||||||
D3D::SetRenderState(D3DRS_SRCBLEND, d3dSrcFactors[bpmem.blendmode.srcfactor]);
|
D3D::SetRenderState(D3DRS_SRCBLEND, d3dSrcFactors[bpmem.blendmode.srcfactor]);
|
||||||
@@ -1261,11 +1145,31 @@ void Renderer::RestoreAPIState()
|
|||||||
|
|
||||||
void Renderer::SetGenerationMode()
|
void Renderer::SetGenerationMode()
|
||||||
{
|
{
|
||||||
|
const D3DCULL d3dCullModes[4] =
|
||||||
|
{
|
||||||
|
D3DCULL_NONE,
|
||||||
|
D3DCULL_CCW,
|
||||||
|
D3DCULL_CW,
|
||||||
|
D3DCULL_CCW
|
||||||
|
};
|
||||||
|
|
||||||
D3D::SetRenderState(D3DRS_CULLMODE, d3dCullModes[bpmem.genMode.cullmode]);
|
D3D::SetRenderState(D3DRS_CULLMODE, d3dCullModes[bpmem.genMode.cullmode]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::SetDepthMode()
|
void Renderer::SetDepthMode()
|
||||||
{
|
{
|
||||||
|
const D3DCMPFUNC d3dCmpFuncs[8] =
|
||||||
|
{
|
||||||
|
D3DCMP_NEVER,
|
||||||
|
D3DCMP_LESS,
|
||||||
|
D3DCMP_EQUAL,
|
||||||
|
D3DCMP_LESSEQUAL,
|
||||||
|
D3DCMP_GREATER,
|
||||||
|
D3DCMP_NOTEQUAL,
|
||||||
|
D3DCMP_GREATEREQUAL,
|
||||||
|
D3DCMP_ALWAYS
|
||||||
|
};
|
||||||
|
|
||||||
if (bpmem.zmode.testenable)
|
if (bpmem.zmode.testenable)
|
||||||
{
|
{
|
||||||
D3D::SetRenderState(D3DRS_ZENABLE, TRUE);
|
D3D::SetRenderState(D3DRS_ZENABLE, TRUE);
|
||||||
@@ -1282,7 +1186,83 @@ void Renderer::SetDepthMode()
|
|||||||
|
|
||||||
void Renderer::SetLogicOpMode()
|
void Renderer::SetLogicOpMode()
|
||||||
{
|
{
|
||||||
if (bpmem.blendmode.logicopenable && bpmem.blendmode.logicmode != 3)
|
// D3D9 doesn't support logic blending, so this is a huge hack
|
||||||
|
|
||||||
|
// 0 0x00
|
||||||
|
// 1 Source & destination
|
||||||
|
// 2 Source & ~destination
|
||||||
|
// 3 Source
|
||||||
|
// 4 ~Source & destination
|
||||||
|
// 5 Destination
|
||||||
|
// 6 Source ^ destination = Source & ~destination | ~Source & destination
|
||||||
|
// 7 Source | destination
|
||||||
|
// 8 ~(Source | destination)
|
||||||
|
// 9 ~(Source ^ destination) = ~Source & ~destination | Source & destination
|
||||||
|
// 10 ~Destination
|
||||||
|
// 11 Source | ~destination
|
||||||
|
// 12 ~Source
|
||||||
|
// 13 ~Source | destination
|
||||||
|
// 14 ~(Source & destination)
|
||||||
|
// 15 0xff
|
||||||
|
const D3DBLENDOP d3dLogicOpop[16] =
|
||||||
|
{
|
||||||
|
D3DBLENDOP_ADD,
|
||||||
|
D3DBLENDOP_ADD,
|
||||||
|
D3DBLENDOP_SUBTRACT,
|
||||||
|
D3DBLENDOP_ADD,
|
||||||
|
D3DBLENDOP_REVSUBTRACT,
|
||||||
|
D3DBLENDOP_ADD,
|
||||||
|
D3DBLENDOP_MAX,
|
||||||
|
D3DBLENDOP_ADD,
|
||||||
|
D3DBLENDOP_MAX,
|
||||||
|
D3DBLENDOP_MAX,
|
||||||
|
D3DBLENDOP_ADD,
|
||||||
|
D3DBLENDOP_ADD,
|
||||||
|
D3DBLENDOP_ADD,
|
||||||
|
D3DBLENDOP_ADD,
|
||||||
|
D3DBLENDOP_ADD,
|
||||||
|
D3DBLENDOP_ADD
|
||||||
|
};
|
||||||
|
const D3DBLEND d3dLogicOpSrcFactors[16] =
|
||||||
|
{
|
||||||
|
D3DBLEND_ZERO,
|
||||||
|
D3DBLEND_DESTCOLOR,
|
||||||
|
D3DBLEND_ONE,
|
||||||
|
D3DBLEND_ONE,
|
||||||
|
D3DBLEND_DESTCOLOR,
|
||||||
|
D3DBLEND_ZERO,
|
||||||
|
D3DBLEND_INVDESTCOLOR,
|
||||||
|
D3DBLEND_INVDESTCOLOR,
|
||||||
|
D3DBLEND_INVSRCCOLOR,
|
||||||
|
D3DBLEND_INVSRCCOLOR,
|
||||||
|
D3DBLEND_INVDESTCOLOR,
|
||||||
|
D3DBLEND_ONE,
|
||||||
|
D3DBLEND_INVSRCCOLOR,
|
||||||
|
D3DBLEND_INVSRCCOLOR,
|
||||||
|
D3DBLEND_INVDESTCOLOR,
|
||||||
|
D3DBLEND_ONE
|
||||||
|
};
|
||||||
|
const D3DBLEND d3dLogicOpDestFactors[16] =
|
||||||
|
{
|
||||||
|
D3DBLEND_ZERO,
|
||||||
|
D3DBLEND_ZERO,
|
||||||
|
D3DBLEND_INVSRCCOLOR,
|
||||||
|
D3DBLEND_ZERO,
|
||||||
|
D3DBLEND_ONE,
|
||||||
|
D3DBLEND_ONE,
|
||||||
|
D3DBLEND_INVSRCCOLOR,
|
||||||
|
D3DBLEND_ONE,
|
||||||
|
D3DBLEND_INVDESTCOLOR,
|
||||||
|
D3DBLEND_SRCCOLOR,
|
||||||
|
D3DBLEND_INVDESTCOLOR,
|
||||||
|
D3DBLEND_INVDESTCOLOR,
|
||||||
|
D3DBLEND_INVSRCCOLOR,
|
||||||
|
D3DBLEND_ONE,
|
||||||
|
D3DBLEND_INVSRCCOLOR,
|
||||||
|
D3DBLEND_ONE
|
||||||
|
};
|
||||||
|
|
||||||
|
if (bpmem.blendmode.logicopenable)
|
||||||
{
|
{
|
||||||
D3D::SetRenderState(D3DRS_ALPHABLENDENABLE, true);
|
D3D::SetRenderState(D3DRS_ALPHABLENDENABLE, true);
|
||||||
D3D::SetRenderState(D3DRS_BLENDOP, d3dLogicOpop[bpmem.blendmode.logicmode]);
|
D3D::SetRenderState(D3DRS_BLENDOP, d3dLogicOpop[bpmem.blendmode.logicmode]);
|
||||||
@@ -1310,6 +1290,21 @@ void Renderer::SetLineWidth()
|
|||||||
|
|
||||||
void Renderer::SetSamplerState(int stage, int texindex)
|
void Renderer::SetSamplerState(int stage, int texindex)
|
||||||
{
|
{
|
||||||
|
const D3DTEXTUREFILTERTYPE d3dMipFilters[4] =
|
||||||
|
{
|
||||||
|
D3DTEXF_NONE,
|
||||||
|
D3DTEXF_POINT,
|
||||||
|
D3DTEXF_LINEAR,
|
||||||
|
D3DTEXF_NONE, //reserved
|
||||||
|
};
|
||||||
|
const D3DTEXTUREADDRESS d3dClamps[4] =
|
||||||
|
{
|
||||||
|
D3DTADDRESS_CLAMP,
|
||||||
|
D3DTADDRESS_WRAP,
|
||||||
|
D3DTADDRESS_MIRROR,
|
||||||
|
D3DTADDRESS_WRAP //reserved
|
||||||
|
};
|
||||||
|
|
||||||
const FourTexUnits &tex = bpmem.tex[texindex];
|
const FourTexUnits &tex = bpmem.tex[texindex];
|
||||||
const TexMode0 &tm0 = tex.texMode0[stage];
|
const TexMode0 &tm0 = tex.texMode0[stage];
|
||||||
const TexMode1 &tm1 = tex.texMode1[stage];
|
const TexMode1 &tm1 = tex.texMode1[stage];
|
||||||
@@ -1323,13 +1318,11 @@ void Renderer::SetSamplerState(int stage, int texindex)
|
|||||||
{
|
{
|
||||||
min = (tm0.min_filter & 4) ? D3DTEXF_LINEAR : D3DTEXF_POINT;
|
min = (tm0.min_filter & 4) ? D3DTEXF_LINEAR : D3DTEXF_POINT;
|
||||||
mag = tm0.mag_filter ? D3DTEXF_LINEAR : D3DTEXF_POINT;
|
mag = tm0.mag_filter ? D3DTEXF_LINEAR : D3DTEXF_POINT;
|
||||||
mip = (tm0.min_filter == 8) ? D3DTEXF_NONE : d3dMipFilters[tm0.min_filter & 3];
|
mip = d3dMipFilters[tm0.min_filter & 3];
|
||||||
if((tm0.min_filter & 3) && (tm0.min_filter != 8) && ((tm1.max_lod >> 4) == 0))
|
|
||||||
mip = D3DTEXF_NONE;
|
|
||||||
}
|
}
|
||||||
if (texindex)
|
if (texindex)
|
||||||
stage += 4;
|
stage += 4;
|
||||||
|
|
||||||
if (mag == D3DTEXF_LINEAR && min == D3DTEXF_LINEAR && g_ActiveConfig.iMaxAnisotropy)
|
if (mag == D3DTEXF_LINEAR && min == D3DTEXF_LINEAR && g_ActiveConfig.iMaxAnisotropy)
|
||||||
{
|
{
|
||||||
min = D3DTEXF_ANISOTROPIC;
|
min = D3DTEXF_ANISOTROPIC;
|
||||||
@@ -1340,8 +1333,8 @@ void Renderer::SetSamplerState(int stage, int texindex)
|
|||||||
|
|
||||||
D3D::SetSamplerState(stage, D3DSAMP_ADDRESSU, d3dClamps[tm0.wrap_s]);
|
D3D::SetSamplerState(stage, D3DSAMP_ADDRESSU, d3dClamps[tm0.wrap_s]);
|
||||||
D3D::SetSamplerState(stage, D3DSAMP_ADDRESSV, d3dClamps[tm0.wrap_t]);
|
D3D::SetSamplerState(stage, D3DSAMP_ADDRESSV, d3dClamps[tm0.wrap_t]);
|
||||||
//float SuperSampleCoeficient = (s_LastAA < 3)? s_LastAA + 1 : s_LastAA - 1;// uncoment this changes to conserve detail when incresing ssaa level
|
|
||||||
float lodbias = (tm0.lod_bias / 32.0f);// + (s_LastAA)?(log(SuperSampleCoeficient) / log(2.0f)):0;
|
float lodbias = (s32)tm0.lod_bias / 32.0f;
|
||||||
D3D::SetSamplerState(stage, D3DSAMP_MIPMAPLODBIAS, *(DWORD*)&lodbias);
|
D3D::SetSamplerState(stage, D3DSAMP_MIPMAPLODBIAS, *(DWORD*)&lodbias);
|
||||||
D3D::SetSamplerState(stage, D3DSAMP_MAXMIPLEVEL, tm1.min_lod >> 4);
|
D3D::SetSamplerState(stage, D3DSAMP_MAXMIPLEVEL, tm1.min_lod >> 4);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,10 +72,9 @@ bool TextureCache::TCacheEntry::Save(const char filename[], unsigned int level)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height,
|
void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height,
|
||||||
unsigned int expanded_width, unsigned int level, bool autogen_mips)
|
unsigned int expanded_width, unsigned int level)
|
||||||
{
|
{
|
||||||
D3D::ReplaceTexture2D(texture, temp, width, height, expanded_width, d3d_fmt, swap_r_b, level);
|
D3D::ReplaceTexture2D(texture, temp, width, height, expanded_width, d3d_fmt, swap_r_b, level);
|
||||||
// D3D9 will automatically generate mip maps if necessary
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFormat,
|
void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFormat,
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ private:
|
|||||||
~TCacheEntry();
|
~TCacheEntry();
|
||||||
|
|
||||||
void Load(unsigned int width, unsigned int height,
|
void Load(unsigned int width, unsigned int height,
|
||||||
unsigned int expanded_width, unsigned int levels, bool autogen_mips = false);
|
unsigned int expanded_width, unsigned int levels);
|
||||||
|
|
||||||
void FromRenderTarget(u32 dstAddr, unsigned int dstFormat,
|
void FromRenderTarget(u32 dstAddr, unsigned int dstFormat,
|
||||||
unsigned int srcFormat, const EFBRectangle& srcRect,
|
unsigned int srcFormat, const EFBRectangle& srcRect,
|
||||||
|
|||||||
@@ -333,8 +333,8 @@ void VertexManager::vFlush()
|
|||||||
tex.texImage0[i&3].width + 1, tex.texImage0[i&3].height + 1,
|
tex.texImage0[i&3].width + 1, tex.texImage0[i&3].height + 1,
|
||||||
tex.texImage0[i&3].format, tex.texTlut[i&3].tmem_offset<<9,
|
tex.texImage0[i&3].format, tex.texTlut[i&3].tmem_offset<<9,
|
||||||
tex.texTlut[i&3].tlut_format,
|
tex.texTlut[i&3].tlut_format,
|
||||||
(tex.texMode0[i&3].min_filter & 3) && (tex.texMode0[i&3].min_filter != 8),
|
(tex.texMode0[i&3].min_filter & 3),
|
||||||
tex.texMode1[i&3].max_lod >> 4,
|
ceil(tex.texMode1[i&3].max_lod / 16.f),
|
||||||
tex.texImage1[i&3].image_type);
|
tex.texImage1[i&3].image_type);
|
||||||
|
|
||||||
if (tentry)
|
if (tentry)
|
||||||
|
|||||||
@@ -132,58 +132,6 @@ const u32 EFB_CACHE_HEIGHT = (EFB_HEIGHT + EFB_CACHE_RECT_SIZE - 1) / EFB_CACHE_
|
|||||||
static bool s_efbCacheValid[2][EFB_CACHE_WIDTH * EFB_CACHE_HEIGHT];
|
static bool s_efbCacheValid[2][EFB_CACHE_WIDTH * EFB_CACHE_HEIGHT];
|
||||||
static std::vector<u32> s_efbCache[2][EFB_CACHE_WIDTH * EFB_CACHE_HEIGHT]; // 2 for PEEK_Z and PEEK_COLOR
|
static std::vector<u32> s_efbCache[2][EFB_CACHE_WIDTH * EFB_CACHE_HEIGHT]; // 2 for PEEK_Z and PEEK_COLOR
|
||||||
|
|
||||||
static const GLenum glSrcFactors[8] =
|
|
||||||
{
|
|
||||||
GL_ZERO,
|
|
||||||
GL_ONE,
|
|
||||||
GL_DST_COLOR,
|
|
||||||
GL_ONE_MINUS_DST_COLOR,
|
|
||||||
GL_SRC_ALPHA,
|
|
||||||
GL_ONE_MINUS_SRC_ALPHA, // NOTE: If dual-source blending is enabled, use SRC1_ALPHA
|
|
||||||
GL_DST_ALPHA,
|
|
||||||
GL_ONE_MINUS_DST_ALPHA
|
|
||||||
};
|
|
||||||
|
|
||||||
static const GLenum glDestFactors[8] = {
|
|
||||||
GL_ZERO,
|
|
||||||
GL_ONE,
|
|
||||||
GL_SRC_COLOR,
|
|
||||||
GL_ONE_MINUS_SRC_COLOR,
|
|
||||||
GL_SRC_ALPHA,
|
|
||||||
GL_ONE_MINUS_SRC_ALPHA, // NOTE: If dual-source blending is enabled, use SRC1_ALPHA
|
|
||||||
GL_DST_ALPHA,
|
|
||||||
GL_ONE_MINUS_DST_ALPHA
|
|
||||||
};
|
|
||||||
|
|
||||||
static const GLenum glCmpFuncs[8] = {
|
|
||||||
GL_NEVER,
|
|
||||||
GL_LESS,
|
|
||||||
GL_EQUAL,
|
|
||||||
GL_LEQUAL,
|
|
||||||
GL_GREATER,
|
|
||||||
GL_NOTEQUAL,
|
|
||||||
GL_GEQUAL,
|
|
||||||
GL_ALWAYS
|
|
||||||
};
|
|
||||||
|
|
||||||
static const GLenum glLogicOpCodes[16] = {
|
|
||||||
GL_CLEAR,
|
|
||||||
GL_AND,
|
|
||||||
GL_AND_REVERSE,
|
|
||||||
GL_COPY,
|
|
||||||
GL_AND_INVERTED,
|
|
||||||
GL_NOOP,
|
|
||||||
GL_XOR,
|
|
||||||
GL_OR,
|
|
||||||
GL_NOR,
|
|
||||||
GL_EQUIV,
|
|
||||||
GL_INVERT,
|
|
||||||
GL_OR_REVERSE,
|
|
||||||
GL_COPY_INVERTED,
|
|
||||||
GL_OR_INVERTED,
|
|
||||||
GL_NAND,
|
|
||||||
GL_SET
|
|
||||||
};
|
|
||||||
|
|
||||||
#if defined HAVE_CG && HAVE_CG
|
#if defined HAVE_CG && HAVE_CG
|
||||||
void HandleCgError(CGcontext ctx, CGerror err, void* appdata)
|
void HandleCgError(CGcontext ctx, CGerror err, void* appdata)
|
||||||
@@ -908,6 +856,32 @@ void Renderer::ReinterpretPixelData(unsigned int convtype)
|
|||||||
|
|
||||||
void Renderer::SetBlendMode(bool forceUpdate)
|
void Renderer::SetBlendMode(bool forceUpdate)
|
||||||
{
|
{
|
||||||
|
// Our render target always uses an alpha channel, so we need to override the blend functions to assume a destination alpha of 1 if the render target isn't supposed to have an alpha channel
|
||||||
|
// Example: D3DBLEND_DESTALPHA needs to be D3DBLEND_ONE since the result without an alpha channel is assumed to always be 1.
|
||||||
|
bool target_has_alpha = bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24;
|
||||||
|
const GLenum glSrcFactors[8] =
|
||||||
|
{
|
||||||
|
GL_ZERO,
|
||||||
|
GL_ONE,
|
||||||
|
GL_DST_COLOR,
|
||||||
|
GL_ONE_MINUS_DST_COLOR,
|
||||||
|
GL_SRC_ALPHA,
|
||||||
|
GL_ONE_MINUS_SRC_ALPHA, // NOTE: If dual-source blending is enabled, use SRC1_ALPHA
|
||||||
|
(target_has_alpha) ? GL_DST_ALPHA : (GLenum)GL_ONE,
|
||||||
|
(target_has_alpha) ? GL_ONE_MINUS_DST_ALPHA : (GLenum)GL_ZERO
|
||||||
|
};
|
||||||
|
const GLenum glDestFactors[8] =
|
||||||
|
{
|
||||||
|
GL_ZERO,
|
||||||
|
GL_ONE,
|
||||||
|
GL_SRC_COLOR,
|
||||||
|
GL_ONE_MINUS_SRC_COLOR,
|
||||||
|
GL_SRC_ALPHA,
|
||||||
|
GL_ONE_MINUS_SRC_ALPHA, // NOTE: If dual-source blending is enabled, use SRC1_ALPHA
|
||||||
|
(target_has_alpha) ? GL_DST_ALPHA : (GLenum)GL_ONE,
|
||||||
|
(target_has_alpha) ? GL_ONE_MINUS_DST_ALPHA : (GLenum)GL_ZERO
|
||||||
|
};
|
||||||
|
|
||||||
// blend mode bit mask
|
// blend mode bit mask
|
||||||
// 0 - blend enable
|
// 0 - blend enable
|
||||||
// 2 - reverse subtract enable (else add)
|
// 2 - reverse subtract enable (else add)
|
||||||
@@ -951,10 +925,10 @@ void Renderer::SetBlendMode(bool forceUpdate)
|
|||||||
|
|
||||||
if (changes & 0x1F8)
|
if (changes & 0x1F8)
|
||||||
{
|
{
|
||||||
#ifdef USE_DUAL_SOURCE_BLEND
|
|
||||||
GLenum srcFactor = glSrcFactors[(newval >> 3) & 7];
|
GLenum srcFactor = glSrcFactors[(newval >> 3) & 7];
|
||||||
GLenum srcFactorAlpha = srcFactor;
|
|
||||||
GLenum dstFactor = glDestFactors[(newval >> 6) & 7];
|
GLenum dstFactor = glDestFactors[(newval >> 6) & 7];
|
||||||
|
#ifdef USE_DUAL_SOURCE_BLEND
|
||||||
|
GLenum srcFactorAlpha = srcFactor;
|
||||||
GLenum dstFactorAlpha = dstFactor;
|
GLenum dstFactorAlpha = dstFactor;
|
||||||
if (useDualSource)
|
if (useDualSource)
|
||||||
{
|
{
|
||||||
@@ -975,7 +949,7 @@ void Renderer::SetBlendMode(bool forceUpdate)
|
|||||||
// blend RGB change
|
// blend RGB change
|
||||||
glBlendFuncSeparate(srcFactor, dstFactor, srcFactorAlpha, dstFactorAlpha);
|
glBlendFuncSeparate(srcFactor, dstFactor, srcFactorAlpha, dstFactorAlpha);
|
||||||
#else
|
#else
|
||||||
glBlendFunc(glSrcFactors[(newval >> 3) & 7], glDestFactors[(newval >> 6) & 7]);
|
glBlendFunc(srcFactor, dstFactor);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1438,6 +1412,18 @@ void Renderer::SetGenerationMode()
|
|||||||
|
|
||||||
void Renderer::SetDepthMode()
|
void Renderer::SetDepthMode()
|
||||||
{
|
{
|
||||||
|
const GLenum glCmpFuncs[8] =
|
||||||
|
{
|
||||||
|
GL_NEVER,
|
||||||
|
GL_LESS,
|
||||||
|
GL_EQUAL,
|
||||||
|
GL_LEQUAL,
|
||||||
|
GL_GREATER,
|
||||||
|
GL_NOTEQUAL,
|
||||||
|
GL_GEQUAL,
|
||||||
|
GL_ALWAYS
|
||||||
|
};
|
||||||
|
|
||||||
if (bpmem.zmode.testenable)
|
if (bpmem.zmode.testenable)
|
||||||
{
|
{
|
||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
@@ -1454,7 +1440,27 @@ void Renderer::SetDepthMode()
|
|||||||
|
|
||||||
void Renderer::SetLogicOpMode()
|
void Renderer::SetLogicOpMode()
|
||||||
{
|
{
|
||||||
if (bpmem.blendmode.logicopenable && bpmem.blendmode.logicmode != 3)
|
const GLenum glLogicOpCodes[16] =
|
||||||
|
{
|
||||||
|
GL_CLEAR,
|
||||||
|
GL_AND,
|
||||||
|
GL_AND_REVERSE,
|
||||||
|
GL_COPY,
|
||||||
|
GL_AND_INVERTED,
|
||||||
|
GL_NOOP,
|
||||||
|
GL_XOR,
|
||||||
|
GL_OR,
|
||||||
|
GL_NOR,
|
||||||
|
GL_EQUIV,
|
||||||
|
GL_INVERT,
|
||||||
|
GL_OR_REVERSE,
|
||||||
|
GL_COPY_INVERTED,
|
||||||
|
GL_OR_INVERTED,
|
||||||
|
GL_NAND,
|
||||||
|
GL_SET
|
||||||
|
};
|
||||||
|
|
||||||
|
if (bpmem.blendmode.logicopenable)
|
||||||
{
|
{
|
||||||
glEnable(GL_COLOR_LOGIC_OP);
|
glEnable(GL_COLOR_LOGIC_OP);
|
||||||
glLogicOp(glLogicOpCodes[bpmem.blendmode.logicmode]);
|
glLogicOp(glLogicOpCodes[bpmem.blendmode.logicmode]);
|
||||||
|
|||||||
@@ -58,24 +58,6 @@ namespace OGL
|
|||||||
|
|
||||||
static u32 s_TempFramebuffer = 0;
|
static u32 s_TempFramebuffer = 0;
|
||||||
|
|
||||||
static const GLint c_MinLinearFilter[8] = {
|
|
||||||
GL_NEAREST,
|
|
||||||
GL_NEAREST_MIPMAP_NEAREST,
|
|
||||||
GL_NEAREST_MIPMAP_LINEAR,
|
|
||||||
GL_NEAREST,
|
|
||||||
GL_LINEAR,
|
|
||||||
GL_LINEAR_MIPMAP_NEAREST,
|
|
||||||
GL_LINEAR_MIPMAP_LINEAR,
|
|
||||||
GL_LINEAR,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const GLint c_WrapSettings[4] = {
|
|
||||||
GL_CLAMP_TO_EDGE,
|
|
||||||
GL_REPEAT,
|
|
||||||
GL_MIRRORED_REPEAT,
|
|
||||||
GL_REPEAT,
|
|
||||||
};
|
|
||||||
|
|
||||||
bool SaveTexture(const char* filename, u32 textarget, u32 tex, int virtual_width, int virtual_height, unsigned int level)
|
bool SaveTexture(const char* filename, u32 textarget, u32 tex, int virtual_width, int virtual_height, unsigned int level)
|
||||||
{
|
{
|
||||||
int width = std::max(virtual_width >> level, 1);
|
int width = std::max(virtual_width >> level, 1);
|
||||||
@@ -201,7 +183,7 @@ TextureCache::TCacheEntryBase* TextureCache::CreateTexture(unsigned int width,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height,
|
void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height,
|
||||||
unsigned int expanded_width, unsigned int level, bool autogen_mips)
|
unsigned int expanded_width, unsigned int level)
|
||||||
{
|
{
|
||||||
//glEnable(GL_TEXTURE_2D);
|
//glEnable(GL_TEXTURE_2D);
|
||||||
glBindTexture(GL_TEXTURE_2D, texture);
|
glBindTexture(GL_TEXTURE_2D, texture);
|
||||||
@@ -212,16 +194,7 @@ void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height,
|
|||||||
if (expanded_width != width)
|
if (expanded_width != width)
|
||||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, expanded_width);
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, expanded_width);
|
||||||
|
|
||||||
if (bHaveMipMaps && autogen_mips)
|
glTexImage2D(GL_TEXTURE_2D, level, gl_iformat, width, height, 0, gl_format, gl_type, temp);
|
||||||
{
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, level, gl_iformat, width, height, 0, gl_format, gl_type, temp);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_FALSE);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, level, gl_iformat, width, height, 0, gl_format, gl_type, temp);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (expanded_width != width)
|
if (expanded_width != width)
|
||||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||||
@@ -357,35 +330,43 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo
|
|||||||
|
|
||||||
void TextureCache::TCacheEntry::SetTextureParameters(const TexMode0 &newmode, const TexMode1 &newmode1)
|
void TextureCache::TCacheEntry::SetTextureParameters(const TexMode0 &newmode, const TexMode1 &newmode1)
|
||||||
{
|
{
|
||||||
// TODO: not used anywhere
|
const GLint c_MinLinearFilter[8] =
|
||||||
TexMode0 mode = newmode;
|
|
||||||
//mode1 = newmode1;
|
|
||||||
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
|
|
||||||
(newmode.mag_filter || g_Config.bForceFiltering) ? GL_LINEAR : GL_NEAREST);
|
|
||||||
|
|
||||||
if (bHaveMipMaps)
|
|
||||||
{
|
{
|
||||||
// TODO: not used anywhere
|
GL_NEAREST,
|
||||||
if (g_ActiveConfig.bForceFiltering && newmode.min_filter < 4)
|
GL_NEAREST_MIPMAP_NEAREST,
|
||||||
mode.min_filter += 4; // take equivalent forced linear
|
GL_NEAREST_MIPMAP_LINEAR,
|
||||||
|
GL_NEAREST,
|
||||||
|
GL_LINEAR,
|
||||||
|
GL_LINEAR_MIPMAP_NEAREST,
|
||||||
|
GL_LINEAR_MIPMAP_LINEAR,
|
||||||
|
GL_LINEAR,
|
||||||
|
};
|
||||||
|
const GLint c_WrapSettings[4] =
|
||||||
|
{
|
||||||
|
GL_CLAMP_TO_EDGE,
|
||||||
|
GL_REPEAT,
|
||||||
|
GL_MIRRORED_REPEAT,
|
||||||
|
GL_REPEAT,
|
||||||
|
};
|
||||||
|
|
||||||
int filt = newmode.min_filter;
|
int filt = newmode.min_filter;
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, c_MinLinearFilter[filt & 7]);
|
if (g_ActiveConfig.bForceFiltering && newmode.min_filter < 4)
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, newmode1.min_lod >> 4);
|
filt += 4; // take equivalent forced linear
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, newmode1.max_lod >> 4);
|
|
||||||
glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, (newmode.lod_bias / 32.0f));
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, c_MinLinearFilter[filt & 7]);
|
||||||
}
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (newmode.mag_filter || g_Config.bForceFiltering) ? GL_LINEAR : GL_NEAREST);
|
||||||
else
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, newmode1.min_lod / 16.f);
|
||||||
(g_ActiveConfig.bForceFiltering || newmode.min_filter >= 4) ? GL_LINEAR : GL_NEAREST);
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, newmode1.max_lod / 16.f);
|
||||||
|
glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, (s32)newmode.lod_bias / 32.0f);
|
||||||
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, c_WrapSettings[newmode.wrap_s]);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, c_WrapSettings[newmode.wrap_s]);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, c_WrapSettings[newmode.wrap_t]);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, c_WrapSettings[newmode.wrap_t]);
|
||||||
|
|
||||||
|
// TODO: Reset anisotrop when changed to 1
|
||||||
if (g_Config.iMaxAnisotropy >= 1)
|
if (g_Config.iMaxAnisotropy >= 1)
|
||||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT,
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT,
|
||||||
(float)(1 << g_ActiveConfig.iMaxAnisotropy));
|
(float)(1 << g_ActiveConfig.iMaxAnisotropy));
|
||||||
}
|
}
|
||||||
|
|
||||||
TextureCache::~TextureCache()
|
TextureCache::~TextureCache()
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ private:
|
|||||||
~TCacheEntry();
|
~TCacheEntry();
|
||||||
|
|
||||||
void Load(unsigned int width, unsigned int height,
|
void Load(unsigned int width, unsigned int height,
|
||||||
unsigned int expanded_width, unsigned int level, bool autogen_mips = false);
|
unsigned int expanded_width, unsigned int level);
|
||||||
|
|
||||||
void FromRenderTarget(u32 dstAddr, unsigned int dstFormat,
|
void FromRenderTarget(u32 dstAddr, unsigned int dstFormat,
|
||||||
unsigned int srcFormat, const EFBRectangle& srcRect,
|
unsigned int srcFormat, const EFBRectangle& srcRect,
|
||||||
|
|||||||
@@ -164,8 +164,8 @@ void VertexManager::vFlush()
|
|||||||
tex.texImage0[i&3].width + 1, tex.texImage0[i&3].height + 1,
|
tex.texImage0[i&3].width + 1, tex.texImage0[i&3].height + 1,
|
||||||
tex.texImage0[i&3].format, tex.texTlut[i&3].tmem_offset<<9,
|
tex.texImage0[i&3].format, tex.texTlut[i&3].tmem_offset<<9,
|
||||||
tex.texTlut[i&3].tlut_format,
|
tex.texTlut[i&3].tlut_format,
|
||||||
(tex.texMode0[i&3].min_filter & 3) && (tex.texMode0[i&3].min_filter != 8),
|
(tex.texMode0[i&3].min_filter & 3),
|
||||||
tex.texMode1[i&3].max_lod >> 4,
|
ceil(tex.texMode1[i&3].max_lod / 16.f),
|
||||||
tex.texImage1[i&3].image_type);
|
tex.texImage1[i&3].image_type);
|
||||||
|
|
||||||
if (tentry)
|
if (tentry)
|
||||||
|
|||||||
@@ -431,7 +431,7 @@ static bool AlphaCompare(int alpha, int ref, int comp)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool AlphaTest(int alpha)
|
static bool TevAlphaTest(int alpha)
|
||||||
{
|
{
|
||||||
bool comp0 = AlphaCompare(alpha, bpmem.alpha_test.ref0, bpmem.alpha_test.comp0);
|
bool comp0 = AlphaCompare(alpha, bpmem.alpha_test.ref0, bpmem.alpha_test.comp0);
|
||||||
bool comp1 = AlphaCompare(alpha, bpmem.alpha_test.ref1, bpmem.alpha_test.comp1);
|
bool comp1 = AlphaCompare(alpha, bpmem.alpha_test.ref1, bpmem.alpha_test.comp1);
|
||||||
@@ -700,7 +700,7 @@ void Tev::Draw()
|
|||||||
// convert to 8 bits per component
|
// convert to 8 bits per component
|
||||||
u8 output[4] = {(u8)Reg[0][ALP_C], (u8)Reg[0][BLU_C], (u8)Reg[0][GRN_C], (u8)Reg[0][RED_C]};
|
u8 output[4] = {(u8)Reg[0][ALP_C], (u8)Reg[0][BLU_C], (u8)Reg[0][GRN_C], (u8)Reg[0][RED_C]};
|
||||||
|
|
||||||
if (!AlphaTest(output[ALP_C]))
|
if (!TevAlphaTest(output[ALP_C]))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// z texture
|
// z texture
|
||||||
|
|||||||
Reference in New Issue
Block a user