diff --git a/CMakeLists.txt b/CMakeLists.txt index b7123f23d7..d350fdeb2d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -524,11 +524,16 @@ else() set(LZO lzo2) endif() -if(ANDROID) +if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin" AND NOT ANDROID) + check_lib(PNG png png.h QUIET) +endif() +if (PNG_FOUND) + message("Using shared libpng") +else() message("Using static libpng from Externals") add_subdirectory(Externals/libpng) include_directories(Externals/libpng) - set(PNG libpng) + set(PNG png) endif() if(OPENAL_FOUND) diff --git a/Data/Sys/GameSettings/G5TE69.ini b/Data/Sys/GameSettings/G5TE69.ini new file mode 100644 index 0000000000..58b5724821 --- /dev/null +++ b/Data/Sys/GameSettings/G5TE69.ini @@ -0,0 +1,34 @@ +# G5TE69 - Tiger Woods PGA TOUR 2005 + +[Core] +# Values set here will override the main dolphin settings. +TLBHack = 1 + +[EmuState] +# The Emulation State. 1 is worst, 5 is best, 0 is not set. +EmulationIssues = +EmulationStateId = 4 + +[OnLoad] +# Add memory patches to be loaded once on boot here. + +[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 = + +[Video_Hacks] +EFBCopyEnable = True +EFBToTextureEnable = False + +[Video_Settings] +SafeTextureCacheColorSamples = 512 diff --git a/Data/Sys/GameSettings/G5TP69.ini b/Data/Sys/GameSettings/G5TP69.ini new file mode 100644 index 0000000000..0f6c6542f5 --- /dev/null +++ b/Data/Sys/GameSettings/G5TP69.ini @@ -0,0 +1,34 @@ +# G5TP69 - Tiger Woods PGA TOUR 2005 + +[Core] +# Values set here will override the main dolphin settings. +TLBHack = 1 + +[EmuState] +# The Emulation State. 1 is worst, 5 is best, 0 is not set. +EmulationIssues = +EmulationStateId = 4 + +[OnLoad] +# Add memory patches to be loaded once on boot here. + +[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 = + +[Video_Hacks] +EFBCopyEnable = True +EFBToTextureEnable = False + +[Video_Settings] +SafeTextureCacheColorSamples = 512 diff --git a/Data/Sys/GameSettings/G6WE69.ini b/Data/Sys/GameSettings/G6WE69.ini new file mode 100644 index 0000000000..f621c8367f --- /dev/null +++ b/Data/Sys/GameSettings/G6WE69.ini @@ -0,0 +1,31 @@ +# G6WE69 - Tiger Woods PGA TOUR 06 + +[Core] +# Values set here will override the main dolphin settings. +TLBHack = 1 + +[EmuState] +# The Emulation State. 1 is worst, 5 is best, 0 is not set. +EmulationIssues = +EmulationStateId = 4 + +[OnLoad] +# Add memory patches to be loaded once on boot here. + +[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 = + +[Video_Hacks] +EFBCopyEnable = True +EFBToTextureEnable = False diff --git a/Data/Sys/GameSettings/G6WP69.ini b/Data/Sys/GameSettings/G6WP69.ini new file mode 100644 index 0000000000..179f8cdd0d --- /dev/null +++ b/Data/Sys/GameSettings/G6WP69.ini @@ -0,0 +1,31 @@ +# G6WP69 - Tiger Woods PGA TOUR 06 + +[Core] +# Values set here will override the main dolphin settings. +TLBHack = 1 + +[EmuState] +# The Emulation State. 1 is worst, 5 is best, 0 is not set. +EmulationIssues = +EmulationStateId = 4 + +[OnLoad] +# Add memory patches to be loaded once on boot here. + +[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 = + +[Video_Hacks] +EFBCopyEnable = True +EFBToTextureEnable = False diff --git a/Data/Sys/GameSettings/GAKE5D.ini b/Data/Sys/GameSettings/GAKE5D.ini new file mode 100644 index 0000000000..cb4e4fe176 --- /dev/null +++ b/Data/Sys/GameSettings/GAKE5D.ini @@ -0,0 +1,23 @@ +# GAKE5D - Midway Arcade Treasures + +[Core] +# Values set here will override the main dolphin settings. +TLBHack = 1 + +[EmuState] +# The Emulation State. 1 is worst, 5 is best, 0 is not set. +EmulationStateId = 4 +EmulationIssues = + +[OnLoad] +# Add memory patches to be loaded once on boot here. + +[OnFrame] +# Add memory patches to be applied every frame here. + +[ActionReplay] +# Add action replay cheats here. + +[Video_Settings] +SafeTextureCacheColorSamples = 0 + diff --git a/Data/Sys/GameSettings/GAYE5D.ini b/Data/Sys/GameSettings/GAYE5D.ini new file mode 100644 index 0000000000..2574e01f7c --- /dev/null +++ b/Data/Sys/GameSettings/GAYE5D.ini @@ -0,0 +1,24 @@ +# GAYE5D - Midway Arcade Treasures 2 + +[Core] +# Values set here will override the main dolphin settings. +TLBHack = 1 + +[EmuState] +# The Emulation State. 1 is worst, 5 is best, 0 is not set. +EmulationStateId = 4 +EmulationIssues = + +[OnLoad] +# Add memory patches to be loaded once on boot here. + +[OnFrame] +# Add memory patches to be applied every frame here. + +[ActionReplay] +# Add action replay cheats here. + +[Video_Settings] +SafeTextureCacheColorSamples = 0 +UseXFB = True +UseRealXFB = True diff --git a/Data/Sys/GameSettings/GCCJ01.ini b/Data/Sys/GameSettings/GCCJ01.ini new file mode 100644 index 0000000000..b755e51275 --- /dev/null +++ b/Data/Sys/GameSettings/GCCJ01.ini @@ -0,0 +1,33 @@ +# GCCJ01 - FINAL FANTASY Crystal Chronicles + +[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 = + +[OnLoad] +# Add memory patches to be loaded once on boot here. + +[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 = + +[Video_Settings] +SafeTextureCacheColorSamples = 512 + +[Video_Hacks] +EFBEmulateFormatChanges = True + diff --git a/Data/Sys/GameSettings/GCCJGC.ini b/Data/Sys/GameSettings/GCCJGC.ini new file mode 100644 index 0000000000..99b8a2ee9d --- /dev/null +++ b/Data/Sys/GameSettings/GCCJGC.ini @@ -0,0 +1,32 @@ +# GCCJGC - FINAL FANTASY Crystal Chronicles + +[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 = + +[OnLoad] +# Add memory patches to be loaded once on boot here. + +[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 = + +[Video_Settings] +SafeTextureCacheColorSamples = 512 + +[Video_Hacks] +EFBEmulateFormatChanges = True diff --git a/Data/Sys/GameSettings/GE3E5D.ini b/Data/Sys/GameSettings/GE3E5D.ini new file mode 100644 index 0000000000..f518a0b5af --- /dev/null +++ b/Data/Sys/GameSettings/GE3E5D.ini @@ -0,0 +1,31 @@ +# GE3E5D - Midway Arcade Treasures 3 + +[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 = + +[OnLoad] +# Add memory patches to be loaded once on boot here. + +[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 = + +[Video_Settings] +SafeTextureCacheColorSamples = 0 +UseXFB = True +UseRealXFB = False diff --git a/Data/Sys/GameSettings/GFXE5D.ini b/Data/Sys/GameSettings/GFXE5D.ini new file mode 100644 index 0000000000..5a00719935 --- /dev/null +++ b/Data/Sys/GameSettings/GFXE5D.ini @@ -0,0 +1,19 @@ +# GFXE5D - Freestyle Metal X + +[Core] +# Values set here will override the main dolphin settings. +TLBHack = 1 + +[EmuState] +# The Emulation State. 1 is worst, 5 is best, 0 is not set. +EmulationStateId = 4 + +[OnLoad] +# Add memory patches to be loaded once on boot here. + +[OnFrame] +# Add memory patches to be applied every frame here. + +[ActionReplay] +# Add action replay cheats here. + diff --git a/Data/Sys/GameSettings/GGEE41.ini b/Data/Sys/GameSettings/GGEE41.ini index 4f3fe0e90a..313ae3cdf3 100644 --- a/Data/Sys/GameSettings/GGEE41.ini +++ b/Data/Sys/GameSettings/GGEE41.ini @@ -26,7 +26,8 @@ PH_ZNear = PH_ZFar = [Video_Settings] -VSync = False +UseXFB = True +UseRealXFB = False [Video_Hacks] DlistCachingEnable = False diff --git a/Data/Sys/GameSettings/GGEP41.ini b/Data/Sys/GameSettings/GGEP41.ini index c00f5cc92a..6ef2027d2a 100644 --- a/Data/Sys/GameSettings/GGEP41.ini +++ b/Data/Sys/GameSettings/GGEP41.ini @@ -26,7 +26,8 @@ PH_ZNear = PH_ZFar = [Video_Settings] -VSync = False +UseXFB = True +UseRealXFB = False [Video_Hacks] DlistCachingEnable = False diff --git a/Data/Sys/GameSettings/GGEY41.ini b/Data/Sys/GameSettings/GGEY41.ini index 550c18e832..4f46c1c19d 100644 --- a/Data/Sys/GameSettings/GGEY41.ini +++ b/Data/Sys/GameSettings/GGEY41.ini @@ -26,7 +26,8 @@ PH_ZNear = PH_ZFar = [Video_Settings] -VSync = False +UseXFB = True +UseRealXFB = False [Video_Hacks] DlistCachingEnable = False diff --git a/Data/Sys/GameSettings/GHNE71.ini b/Data/Sys/GameSettings/GHNE71.ini index 1901f25d2c..fa603507dd 100644 --- a/Data/Sys/GameSettings/GHNE71.ini +++ b/Data/Sys/GameSettings/GHNE71.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 4 -EmulationIssues = Slow and cutscenes are black +EmulationIssues = Needs real xfb for the videos to show up. [OnLoad] # Add memory patches to be loaded once on boot here. @@ -17,3 +17,6 @@ EmulationIssues = Slow and cutscenes are black [ActionReplay] # Add action replay cheats here. +[Video_Settings] +UseXFB = True +UseRealXFB = True diff --git a/Data/Sys/GameSettings/GHNX71.ini b/Data/Sys/GameSettings/GHNX71.ini new file mode 100644 index 0000000000..33084f79e9 --- /dev/null +++ b/Data/Sys/GameSettings/GHNX71.ini @@ -0,0 +1,22 @@ +# GHNX71 - Hunter: The Reckoning + +[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 show up. + +[OnLoad] +# Add memory patches to be loaded once on boot here. + +[OnFrame] +# Add memory patches to be applied every frame here. + +[ActionReplay] +# Add action replay cheats here. + +[Video_Settings] +UseXFB = True +UseRealXFB = True diff --git a/Data/Sys/GameSettings/GNED78.ini b/Data/Sys/GameSettings/GNED78.ini new file mode 100644 index 0000000000..317761c127 --- /dev/null +++ b/Data/Sys/GameSettings/GNED78.ini @@ -0,0 +1,22 @@ +# GNED78 - Finding Nemo + +[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 show up. + +[OnLoad] +# Add memory patches to be loaded once on boot here. + +[OnFrame] +# Add memory patches to be applied every frame here. + +[ActionReplay] +# Add action replay cheats here. + +[Video_Settings] +UseXFB = True +UseRealXFB = True diff --git a/Data/Sys/GameSettings/GNEE78.ini b/Data/Sys/GameSettings/GNEE78.ini new file mode 100644 index 0000000000..af49d7e664 --- /dev/null +++ b/Data/Sys/GameSettings/GNEE78.ini @@ -0,0 +1,22 @@ +# GNEE78 - Finding Nemo + +[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 show up. + +[OnLoad] +# Add memory patches to be loaded once on boot here. + +[OnFrame] +# Add memory patches to be applied every frame here. + +[ActionReplay] +# Add action replay cheats here. + +[Video_Settings] +UseXFB = True +UseRealXFB = True diff --git a/Data/Sys/GameSettings/GNEF78.ini b/Data/Sys/GameSettings/GNEF78.ini new file mode 100644 index 0000000000..b0303ea9cf --- /dev/null +++ b/Data/Sys/GameSettings/GNEF78.ini @@ -0,0 +1,22 @@ +# GNEF78 - Finding Nemo + +[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 show up. + +[OnLoad] +# Add memory patches to be loaded once on boot here. + +[OnFrame] +# Add memory patches to be applied every frame here. + +[ActionReplay] +# Add action replay cheats here. + +[Video_Settings] +UseXFB = True +UseRealXFB = True diff --git a/Data/Sys/GameSettings/GNEP78.ini b/Data/Sys/GameSettings/GNEP78.ini new file mode 100644 index 0000000000..5bf28ebd07 --- /dev/null +++ b/Data/Sys/GameSettings/GNEP78.ini @@ -0,0 +1,22 @@ +# GNEP78 - Finding Nemo + +[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 show up. + +[OnLoad] +# Add memory patches to be loaded once on boot here. + +[OnFrame] +# Add memory patches to be applied every frame here. + +[ActionReplay] +# Add action replay cheats here. + +[Video_Settings] +UseXFB = True +UseRealXFB = True diff --git a/Data/Sys/GameSettings/GNES78.ini b/Data/Sys/GameSettings/GNES78.ini new file mode 100644 index 0000000000..b29379ab2e --- /dev/null +++ b/Data/Sys/GameSettings/GNES78.ini @@ -0,0 +1,22 @@ +# GNES78 - Finding Nemo + +[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 show up. + +[OnLoad] +# Add memory patches to be loaded once on boot here. + +[OnFrame] +# Add memory patches to be applied every frame here. + +[ActionReplay] +# Add action replay cheats here. + +[Video_Settings] +UseXFB = True +UseRealXFB = True diff --git a/Data/Sys/GameSettings/GT4D52.ini b/Data/Sys/GameSettings/GT4D52.ini new file mode 100644 index 0000000000..25e55b1d98 --- /dev/null +++ b/Data/Sys/GameSettings/GT4D52.ini @@ -0,0 +1,22 @@ +# GT4D52 - Tony Hawk's Pro Skater 4 + +[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 = + +[OnLoad] +# Add memory patches to be loaded once on boot here. + +[OnFrame] +# Add memory patches to be applied every frame here. + +[ActionReplay] +# Add action replay cheats here. + +[Video_Hacks] +EFBCopyEnable = True +EFBToTextureEnable = False diff --git a/Data/Sys/GameSettings/GT4E52.ini b/Data/Sys/GameSettings/GT4E52.ini new file mode 100644 index 0000000000..4c3d483359 --- /dev/null +++ b/Data/Sys/GameSettings/GT4E52.ini @@ -0,0 +1,22 @@ +# GT4E52 - Tony Hawk's Pro Skater 4 + +[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 = + +[OnLoad] +# Add memory patches to be loaded once on boot here. + +[OnFrame] +# Add memory patches to be applied every frame here. + +[ActionReplay] +# Add action replay cheats here. + +[Video_Hacks] +EFBCopyEnable = True +EFBToTextureEnable = False diff --git a/Data/Sys/GameSettings/GT4F52.ini b/Data/Sys/GameSettings/GT4F52.ini new file mode 100644 index 0000000000..c30970c8f6 --- /dev/null +++ b/Data/Sys/GameSettings/GT4F52.ini @@ -0,0 +1,22 @@ +# GT4F52 - Tony Hawk's Pro Skater 4 + +[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 = + +[OnLoad] +# Add memory patches to be loaded once on boot here. + +[OnFrame] +# Add memory patches to be applied every frame here. + +[ActionReplay] +# Add action replay cheats here. + +[Video_Hacks] +EFBCopyEnable = True +EFBToTextureEnable = False diff --git a/Data/Sys/GameSettings/GT4P52.ini b/Data/Sys/GameSettings/GT4P52.ini new file mode 100644 index 0000000000..2a7e1958f1 --- /dev/null +++ b/Data/Sys/GameSettings/GT4P52.ini @@ -0,0 +1,22 @@ +# GT4P52 - Tony Hawk's Pro Skater 4 + +[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 = + +[OnLoad] +# Add memory patches to be loaded once on boot here. + +[OnFrame] +# Add memory patches to be applied every frame here. + +[ActionReplay] +# Add action replay cheats here. + +[Video_Hacks] +EFBCopyEnable = True +EFBToTextureEnable = False diff --git a/Data/Sys/GameSettings/GYQE01.ini b/Data/Sys/GameSettings/GYQE01.ini new file mode 100644 index 0000000000..f2eeac9819 --- /dev/null +++ b/Data/Sys/GameSettings/GYQE01.ini @@ -0,0 +1,33 @@ +# GYQE01 - Mario Superstar Baseball + +[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 = Player's shadow needs efb to ram and texture cache set to safe to appear properly. + +[OnLoad] +# Add memory patches to be loaded once on boot here. + +[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 = + +[Video_Settings] +SafeTextureCacheColorSamples = 0 + +[Video_Hacks] +EFBToTextureEnable = False +EFBCopyEnable = True diff --git a/Data/Sys/GameSettings/GYQJ01.ini b/Data/Sys/GameSettings/GYQJ01.ini index 414e4fed0a..2241ed691f 100644 --- a/Data/Sys/GameSettings/GYQJ01.ini +++ b/Data/Sys/GameSettings/GYQJ01.ini @@ -6,6 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 4 +EmulationIssues = Player's shadow needs efb to ram and texture cache set to safe to appear properly. [OnLoad] # Add memory patches to be loaded once on boot here. @@ -16,3 +17,17 @@ EmulationStateId = 4 [ActionReplay] # Add action replay cheats here. +[Video] +ProjectionHack = 0 +PH_SZNear = 0 +PH_SZFar = 0 +PH_ExtraParam = 0 +PH_ZNear = +PH_ZFar = + +[Video_Settings] +SafeTextureCacheColorSamples = 0 + +[Video_Hacks] +EFBToTextureEnable = False +EFBCopyEnable = True diff --git a/Data/Sys/GameSettings/GYQP01.ini b/Data/Sys/GameSettings/GYQP01.ini index 89f76c202c..bbbe591b09 100644 --- a/Data/Sys/GameSettings/GYQP01.ini +++ b/Data/Sys/GameSettings/GYQP01.ini @@ -6,6 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 4 +EmulationIssues = Player's shadow needs efb to ram and texture cache set to safe to appear properly. [OnLoad] # Add memory patches to be loaded once on boot here. @@ -16,3 +17,17 @@ EmulationStateId = 4 [ActionReplay] # Add action replay cheats here. +[Video] +ProjectionHack = 0 +PH_SZNear = 0 +PH_SZFar = 0 +PH_ExtraParam = 0 +PH_ZNear = +PH_ZFar = + +[Video_Settings] +SafeTextureCacheColorSamples = 0 + +[Video_Hacks] +EFBToTextureEnable = False +EFBCopyEnable = True diff --git a/Data/Sys/GameSettings/SG8EG9.ini b/Data/Sys/GameSettings/SG8EG9.ini new file mode 100644 index 0000000000..53dc722915 --- /dev/null +++ b/Data/Sys/GameSettings/SG8EG9.ini @@ -0,0 +1,34 @@ +# SG8EG9 - Yogi Bear + +[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 = +EmulationStateId = 4 + +[OnLoad] +# Add memory patches to be loaded once on boot here. + +[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 = + +[Video_Settings] +UseXFB = True +UseRealXFB = False + +[Video_Hacks] +EFBToTextureEnable = False +EFBCopyEnable = True diff --git a/Data/Sys/GameSettings/SG8PAF.ini b/Data/Sys/GameSettings/SG8PAF.ini new file mode 100644 index 0000000000..93f5bd5f52 --- /dev/null +++ b/Data/Sys/GameSettings/SG8PAF.ini @@ -0,0 +1,34 @@ +# SG8PAF - Yogi Bear + +[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 = +EmulationStateId = 4 + +[OnLoad] +# Add memory patches to be loaded once on boot here. + +[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 = + +[Video_Settings] +UseXFB = True +UseRealXFB = False + +[Video_Hacks] +EFBToTextureEnable = False +EFBCopyEnable = True diff --git a/Data/Sys/GameSettings/WHFETY.ini b/Data/Sys/GameSettings/WHFETY.ini index 242d398951..bc351b7767 100644 --- a/Data/Sys/GameSettings/WHFETY.ini +++ b/Data/Sys/GameSettings/WHFETY.ini @@ -6,7 +6,7 @@ [EmuState] # The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 4 -EmulationIssues = +EmulationIssues = [OnLoad] # Add memory patches to be loaded once on boot here. @@ -20,3 +20,6 @@ EmulationIssues = [Video] ProjectionHack = 0 +[Video_Settings] +UseXFB = True +UseRealXFB = False diff --git a/Data/Sys/GameSettings/WHUEGL.ini b/Data/Sys/GameSettings/WHUEGL.ini new file mode 100644 index 0000000000..5422ff12a6 --- /dev/null +++ b/Data/Sys/GameSettings/WHUEGL.ini @@ -0,0 +1,30 @@ +# WHUEGL - Ghost Mansion Party + +[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 = + +[OnLoad] +# Add memory patches to be loaded once on boot here. + +[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 = + +[Video_Settings] +UseXFB = True +UseRealXFB = False diff --git a/Externals/wxWidgets3/CMakeLists.txt b/Externals/wxWidgets3/CMakeLists.txt index 1ce7a73418..6629d0865e 100644 --- a/Externals/wxWidgets3/CMakeLists.txt +++ b/Externals/wxWidgets3/CMakeLists.txt @@ -868,8 +868,6 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") ${SRCS_GENERICOSX} ${SRCS_OSX} ${SRCS_UNIX}) - include_directories(../libpng) - add_subdirectory(../libpng ../libpng) set(LIBS png iconv diff --git a/Source/Android/res/layout/gamelist_folderbrowser_list.xml b/Source/Android/res/layout/gamelist_folderbrowser_list_item.xml similarity index 100% rename from Source/Android/res/layout/gamelist_folderbrowser_list.xml rename to Source/Android/res/layout/gamelist_folderbrowser_list_item.xml diff --git a/Source/Android/res/menu/emuwindow_overlay.xml b/Source/Android/res/menu/emuwindow_overlay.xml index 88b50f907d..7c103d831f 100644 --- a/Source/Android/res/menu/emuwindow_overlay.xml +++ b/Source/Android/res/menu/emuwindow_overlay.xml @@ -8,8 +8,12 @@ + ビルドのバージョン サポートのOpenGL ES 3 + サポートのNEON 現在のディレクトリ: %1$s @@ -25,12 +26,17 @@ 設定 について + + デバイスの互換性の警告 + この電話は、NEON拡張をサポートしていません。 おそらくDolphinを実行することはできません。\nあなたはとにかくそれを実行してみますか? + クリックされたファイル: %1$s 入力オーバーレイを有効 入力オーバーレイを無効 + スクリーンショットを撮る ステートセーブ ステートロード 終了 diff --git a/Source/Android/res/values/strings.xml b/Source/Android/res/values/strings.xml index 86cba61763..3e95b5abb0 100644 --- a/Source/Android/res/values/strings.xml +++ b/Source/Android/res/values/strings.xml @@ -11,6 +11,7 @@ Build Revision Supports OpenGL ES 3 + Supports NEON Current Dir: %1$s @@ -25,12 +26,17 @@ Settings About + + Device Compatibility Warning + Your phone doesn\'t support NEON which makes it incapable of running Dolphin Mobile?\nDo you want to try anyway? + File clicked: %1$s Enable Input Overlay Disable Input Overlay + Take Screenshot Save State Load State Exit diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/AboutFragment.java b/Source/Android/src/org/dolphinemu/dolphinemu/AboutFragment.java index 922dab0e8d..6ca90a2577 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/AboutFragment.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/AboutFragment.java @@ -29,21 +29,21 @@ public final class AboutFragment extends ListFragment @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - View rootView = inflater.inflate(R.layout.gamelist_listview, container, false); - ListView mMainList = (ListView) rootView.findViewById(R.id.gamelist); + ListView rootView = (ListView) inflater.inflate(R.layout.gamelist_listview, container, false); - String yes = getString(R.string.yes); - String no = getString(R.string.no); + final String yes = getString(R.string.yes); + final String no = getString(R.string.no); List Input = new ArrayList(); Input.add(new AboutFragmentItem(getString(R.string.build_revision), NativeLibrary.GetVersionString())); Input.add(new AboutFragmentItem(getString(R.string.supports_gles3), VideoSettingsFragment.SupportsGLES3() ? yes : no)); + Input.add(new AboutFragmentItem(getString(R.string.supports_neon), NativeLibrary.SupportsNEON() ? yes : no)); AboutFragmentAdapter adapter = new AboutFragmentAdapter(getActivity(), R.layout.about_layout, Input); - mMainList.setAdapter(adapter); - mMainList.setEnabled(false); // Makes the list view non-clickable. + rootView.setAdapter(adapter); + rootView.setEnabled(false); // Makes the list view non-clickable. - return mMainList; + return rootView; } // Represents an item in the AboutFragment. @@ -94,18 +94,17 @@ public final class AboutFragment extends ListFragment @Override public View getView(int position, View convertView, ViewGroup parent) { - View v = convertView; - if (v == null) + if (convertView == null) { - LayoutInflater vi = (LayoutInflater) ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - v = vi.inflate(id, parent, false); + LayoutInflater vi = LayoutInflater.from(ctx); + convertView = vi.inflate(id, parent, false); } final AboutFragmentItem item = items.get(position); if (item != null) { - TextView title = (TextView) v.findViewById(R.id.AboutItemTitle); - TextView subtitle = (TextView) v.findViewById(R.id.AboutItemSubTitle); + TextView title = (TextView) convertView.findViewById(R.id.AboutItemTitle); + TextView subtitle = (TextView) convertView.findViewById(R.id.AboutItemSubTitle); if (title != null) title.setText(item.getTitle()); @@ -114,7 +113,7 @@ public final class AboutFragment extends ListFragment subtitle.setText(item.getSubTitle()); } - return v; + return convertView; } } } diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/DolphinEmulator.java b/Source/Android/src/org/dolphinemu/dolphinemu/DolphinEmulator.java index b06669f8f7..bdbe53dfcb 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/DolphinEmulator.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/DolphinEmulator.java @@ -86,4 +86,9 @@ public final class DolphinEmulator extends Activity UserPreferences.LoadIniToPrefs(this); } } + protected void onRestart() + { + super.onRestart(); + finish(); // If we are ever returning to this activity then we are exiting. + } } \ No newline at end of file diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/NativeLibrary.java b/Source/Android/src/org/dolphinemu/dolphinemu/NativeLibrary.java index ac6275301d..1289ff7d01 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/NativeLibrary.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/NativeLibrary.java @@ -152,6 +152,19 @@ public final class NativeLibrary */ public static native String GetVersionString(); + /** + * Returns if the phone supports NEON or not + * + * @return true if it supports NEON, false otherwise. + */ + public static native boolean SupportsNEON(); + + /** + * Saves a screen capture of the game + * + */ + public static native void SaveScreenShot(); + /** * Saves a game state to the slot number. * diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/emulation/EmulationActivity.java b/Source/Android/src/org/dolphinemu/dolphinemu/emulation/EmulationActivity.java index dff9d09b22..9232cfe5fa 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/emulation/EmulationActivity.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/emulation/EmulationActivity.java @@ -64,12 +64,14 @@ public final class EmulationActivity extends Activity // // Due to a bug in Adreno, it renders the screen rotated 90 degrees when using OpenGL // Flip the width and height when on Adreno to work around this. + // This bug is fixed in Qualcomm driver v53 // Mali isn't affected by this bug. sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this); if (sharedPrefs.getString("gpuPref", "Software Rendering").equals("OGL") && VideoSettingsFragment.SupportsGLES3() && VideoSettingsFragment.m_GLVendor != null - && VideoSettingsFragment.m_GLVendor.equals("Qualcomm")) + && VideoSettingsFragment.m_GLVendor.equals("Qualcomm") + && VideoSettingsFragment.m_QualcommVersion < 53.0f) NativeLibrary.SetDimensions((int)screenHeight, (int)screenWidth); else NativeLibrary.SetDimensions((int)screenWidth, (int)screenHeight); @@ -204,6 +206,11 @@ public final class EmulationActivity extends Activity return true; } + // Screenshot capturing + case R.id.takeScreenshot: + NativeLibrary.SaveScreenShot(); + return true; + // Save state slots case R.id.saveSlot1: NativeLibrary.SaveState(0); diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/folderbrowser/FolderBrowser.java b/Source/Android/src/org/dolphinemu/dolphinemu/folderbrowser/FolderBrowser.java index 2258bdb41f..8aa561376a 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/folderbrowser/FolderBrowser.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/folderbrowser/FolderBrowser.java @@ -37,16 +37,17 @@ import org.dolphinemu.dolphinemu.gamelist.GameListActivity; public final class FolderBrowser extends ListFragment { private FolderBrowserAdapter adapter; - private ListView mFolderBrowserList; - private ListView rootView; private static File currentDir = null; // Populates the FolderView with the given currDir's contents. private void Fill(File currDir) { - // Change the activity title to reflect the current directory the FolderBrowser is in. + // Clear the adapter of previous items. + adapter.clear(); + + // Set the activity title to the current directory the FolderBrowser is in. getActivity().setTitle(String.format(getString(R.string.current_dir), currDir.getName())); - + File[] dirs = currDir.listFiles(); List dir = new ArrayList(); List fls = new ArrayList(); @@ -96,9 +97,9 @@ public final class FolderBrowser extends ListFragment if (!currDir.getPath().equalsIgnoreCase("/")) dir.add(0, new FolderBrowserItem("..", getString(R.string.parent_directory), currDir.getParent())); - adapter = new FolderBrowserAdapter(getActivity(), R.layout.gamelist_folderbrowser_list, dir); - mFolderBrowserList = (ListView) rootView.findViewById(R.id.gamelist); - mFolderBrowserList.setAdapter(adapter); + // Add the items to the adapter and notify the adapter users of its new contents. + adapter.addAll(dir); + adapter.notifyDataSetChanged(); } @Override @@ -122,10 +123,12 @@ public final class FolderBrowser extends ListFragment if(currentDir == null) currentDir = new File(Environment.getExternalStorageDirectory().getPath()); - rootView = (ListView) inflater.inflate(R.layout.gamelist_listview, container, false); + ListView rootView = (ListView) inflater.inflate(R.layout.gamelist_listview, container, false); + adapter = new FolderBrowserAdapter(getActivity(), R.layout.gamelist_folderbrowser_list_item); + rootView.setAdapter(adapter); Fill(currentDir); - return mFolderBrowserList; + return rootView; } private void FolderSelected() diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/folderbrowser/FolderBrowserAdapter.java b/Source/Android/src/org/dolphinemu/dolphinemu/folderbrowser/FolderBrowserAdapter.java index 8d96a8232c..f97799e6e4 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/folderbrowser/FolderBrowserAdapter.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/folderbrowser/FolderBrowserAdapter.java @@ -6,15 +6,12 @@ package org.dolphinemu.dolphinemu.folderbrowser; -import java.util.List; - import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.ImageView; -import android.widget.ListView; import android.widget.TextView; import org.dolphinemu.dolphinemu.R; @@ -27,79 +24,89 @@ import org.dolphinemu.dolphinemu.R; */ public final class FolderBrowserAdapter extends ArrayAdapter { + // ViewHolder which is used to hold onto + // items within a listview. This is done + // so that findViewById is not needed to + // be excessively called over and over. + private static final class ViewHolder + { + TextView title; + TextView subtitle; + ImageView icon; + } + private final Context context; private final int id; - private final List items; + private ViewHolder viewHolder; /** * Constructor * * @param context The current {@link Context}. * @param resourceId The resource ID for a layout file containing a layout to use when instantiating views. - * @param objects The objects to represent in the {@link ListView}. */ - public FolderBrowserAdapter(Context context, int resourceId, List objects) + public FolderBrowserAdapter(Context context, int resourceId) { - super(context, resourceId, objects); + super(context, resourceId); this.context = context; this.id = resourceId; - this.items = objects; - } - - @Override - public FolderBrowserItem getItem(int i) - { - return items.get(i); } @Override public View getView(int position, View convertView, ViewGroup parent) { - View v = convertView; - if (v == null) + if (convertView == null) { LayoutInflater vi = LayoutInflater.from(context); - v = vi.inflate(id, parent, false); + convertView = vi.inflate(id, parent, false); + + // Initialize the ViewHolder and store it. + viewHolder = new ViewHolder(); + viewHolder.title = (TextView) convertView.findViewById(R.id.ListItemTitle); + viewHolder.subtitle = (TextView) convertView.findViewById(R.id.ListItemSubTitle); + viewHolder.icon = (ImageView) convertView.findViewById(R.id.ListItemIcon); + convertView.setTag(viewHolder); + } + else // Can recover the holder. + { + viewHolder = (ViewHolder) convertView.getTag(); } - final FolderBrowserItem item = items.get(position); + final FolderBrowserItem item = getItem(position); if (item != null) { - ImageView icon = (ImageView) v.findViewById(R.id.ListItemIcon); - TextView title = (TextView) v.findViewById(R.id.ListItemTitle); - TextView subtitle = (TextView) v.findViewById(R.id.ListItemSubTitle); - - if(title != null) + if (viewHolder.title != null) { - title.setText(item.getName()); + viewHolder.title.setText(item.getName()); } - if(subtitle != null) + if (viewHolder.subtitle != null) { // Remove the subtitle for all folders, except for the parent directory folder. if (item.isDirectory() && !item.getSubtitle().equals(context.getString(R.string.parent_directory))) { - subtitle.setVisibility(View.GONE); + viewHolder.subtitle.setVisibility(View.GONE); } else { - subtitle.setText(item.getSubtitle()); + viewHolder.subtitle.setVisibility(View.VISIBLE); + viewHolder.subtitle.setText(item.getSubtitle()); } } - if (icon != null) + if (viewHolder.icon != null) { if (item.isDirectory()) { - icon.setImageResource(R.drawable.ic_menu_folder); + viewHolder.icon.setImageResource(R.drawable.ic_menu_folder); } else { - icon.setImageResource(R.drawable.ic_menu_file); + viewHolder.icon.setImageResource(R.drawable.ic_menu_file); } } } - return v; + return convertView; } } diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListActivity.java b/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListActivity.java index c24d21a74b..85fa9a62da 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListActivity.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListActivity.java @@ -9,10 +9,11 @@ package org.dolphinemu.dolphinemu.gamelist; import android.app.Activity; import android.app.AlertDialog; import android.app.Fragment; -import android.app.FragmentManager; +import android.app.FragmentTransaction; import android.content.DialogInterface; import android.content.Intent; import android.content.res.Configuration; +import android.os.Build; import android.os.Bundle; import android.support.v4.app.ActionBarDrawerToggle; import android.support.v4.widget.DrawerLayout; @@ -41,7 +42,6 @@ public final class GameListActivity extends Activity implements GameListFragment.OnGameListZeroListener { private int mCurFragmentNum = 0; - private Fragment mCurFragment; private ActionBarDrawerToggle mDrawerToggle; private DrawerLayout mDrawerLayout; @@ -102,10 +102,36 @@ public final class GameListActivity extends Activity }; mDrawerLayout.setDrawerListener(mDrawerToggle); - // Display the game list fragment. - mCurFragment = new GameListFragment(); - FragmentManager fragmentManager = getFragmentManager(); - fragmentManager.beginTransaction().replace(R.id.content_frame, mCurFragment).commit(); + // Display the game list fragment on activity creation, + // but only if no previous states have been saved. + if (savedInstanceState == null) + { + final GameListFragment gameList = new GameListFragment(); + FragmentTransaction ft = getFragmentManager().beginTransaction(); + ft.replace(R.id.content_frame, gameList); + ft.commit(); + } + + + // Create an alert telling them that their phone sucks + if (Build.CPU_ABI.contains("arm") && !NativeLibrary.SupportsNEON()) + { + AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setTitle(R.string.device_compat_warning); + builder.setMessage(R.string.device_compat_warning_msg); + builder.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + // Do Nothing. Just create the Yes button + } + }); + builder.setNegativeButton(R.string.no, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) + { + finish(); + } + }); + builder.show(); + } } /** @@ -129,9 +155,10 @@ public final class GameListActivity extends Activity setTitle(R.string.app_name); mCurFragmentNum = 0; - mCurFragment = new GameListFragment(); - FragmentManager fragmentManager = getFragmentManager(); - fragmentManager.beginTransaction().replace(R.id.content_frame, mCurFragment).commit(); + final GameListFragment gameList = new GameListFragment(); + FragmentTransaction ft = getFragmentManager().beginTransaction(); + ft.replace(R.id.content_frame, gameList); + ft.commit(); invalidateOptionsMenu(); } break; @@ -139,9 +166,11 @@ public final class GameListActivity extends Activity case 1: // Folder Browser { mCurFragmentNum = 1; - mCurFragment = new FolderBrowser(); - FragmentManager fragmentManager = getFragmentManager(); - fragmentManager.beginTransaction().replace(R.id.content_frame, mCurFragment).commit(); + final FolderBrowser folderBrowser = new FolderBrowser(); + FragmentTransaction ft = getFragmentManager().beginTransaction(); + ft.replace(R.id.content_frame, folderBrowser); + ft.addToBackStack(null); + ft.commit(); invalidateOptionsMenu(); } break; @@ -156,9 +185,11 @@ public final class GameListActivity extends Activity case 3: // About { mCurFragmentNum = 3; - mCurFragment = new AboutFragment(); - FragmentManager fragmentManager = getFragmentManager(); - fragmentManager.beginTransaction().replace(R.id.content_frame, mCurFragment).commit(); + final AboutFragment aboutFragment = new AboutFragment(); + FragmentTransaction ft = getFragmentManager().beginTransaction(); + ft.replace(R.id.content_frame, aboutFragment); + ft.addToBackStack(null); + ft.commit(); invalidateOptionsMenu(); } break; @@ -245,7 +276,7 @@ public final class GameListActivity extends Activity NativeLibrary.SetConfig("Dolphin.ini", "General", "GCMPathes", "0"); // Now finally, clear the game list. - ((GameListFragment) mCurFragment).clearGameList(); + ((GameListFragment) getFragmentManager().findFragmentById(R.id.content_frame)).clearGameList(); } }); builder.setNegativeButton(R.string.no, new DialogInterface.OnClickListener() { @@ -260,7 +291,23 @@ public final class GameListActivity extends Activity return super.onOptionsItemSelected(item); } - + + @Override + public void onSaveInstanceState(Bundle outState) + { + super.onSaveInstanceState(outState); + + outState.putInt("currentFragmentNum", mCurFragmentNum); + } + + @Override + public void onRestoreInstanceState(Bundle savedInstanceState) + { + super.onRestoreInstanceState(savedInstanceState); + + mCurFragmentNum = savedInstanceState.getInt("currentFragmentNum"); + } + @Override public void onBackPressed() { diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListAdapter.java b/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListAdapter.java index d0b3642ffe..d4dedd29aa 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListAdapter.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListAdapter.java @@ -12,11 +12,8 @@ import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.ImageView; -import android.widget.ListView; import android.widget.TextView; -import java.util.List; - import org.dolphinemu.dolphinemu.R; /** @@ -28,46 +25,36 @@ public final class GameListAdapter extends ArrayAdapter { private final Context context; private final int id; - private final Listitems; /** * Constructor * * @param context The current {@link Context}. * @param resourceId The resource ID for a layout file containing a layout to use when instantiating views. - * @param objects The objects to represent in the {@link ListView}. */ - public GameListAdapter(Context context, int resourceId, List objects) + public GameListAdapter(Context context, int resourceId) { - super(context, resourceId, objects); + super(context, resourceId); this.context = context; this.id = resourceId; - this.items = objects; - } - - @Override - public GameListItem getItem(int i) - { - return items.get(i); } @Override public View getView(int position, View convertView, ViewGroup parent) { - View v = convertView; - if (v == null) + if (convertView == null) { LayoutInflater vi = LayoutInflater.from(context); - v = vi.inflate(id, parent, false); + convertView = vi.inflate(id, parent, false); } - final GameListItem item = items.get(position); + final GameListItem item = getItem(position); if (item != null) { - TextView title = (TextView) v.findViewById(R.id.ListItemTitle); - TextView subtitle = (TextView) v.findViewById(R.id.ListItemSubTitle); - ImageView icon = (ImageView) v.findViewById(R.id.ListItemIcon); + TextView title = (TextView) convertView.findViewById(R.id.ListItemTitle); + TextView subtitle = (TextView) convertView.findViewById(R.id.ListItemSubTitle); + ImageView icon = (ImageView) convertView.findViewById(R.id.ListItemIcon); if (title != null) title.setText(item.getName()); @@ -83,7 +70,7 @@ public final class GameListAdapter extends ArrayAdapter } } - return v; + return convertView; } } diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListFragment.java b/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListFragment.java index 41eb271b99..9dedf914dc 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListFragment.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListFragment.java @@ -35,7 +35,6 @@ import org.dolphinemu.dolphinemu.emulation.EmulationActivity; public final class GameListFragment extends ListFragment { private GameListAdapter mGameAdapter; - private static GameListActivity mMe; private OnGameListZeroListener mCallback; /** @@ -84,7 +83,7 @@ public final class GameListFragment extends ListFragment if (!entry.isHidden() && !entry.isDirectory()) { if (exts.contains(entryName.toLowerCase().substring(entryName.lastIndexOf('.')))) - fls.add(new GameListItem(mMe, entryName, String.format(getString(R.string.file_size), entry.length()), entry.getAbsolutePath())); + fls.add(new GameListItem(getActivity(), entryName, String.format(getString(R.string.file_size), entry.length()), entry.getAbsolutePath())); } } } @@ -94,8 +93,9 @@ public final class GameListFragment extends ListFragment } Collections.sort(fls); - mGameAdapter = new GameListAdapter(mMe, R.layout.gamelist_folderbrowser_list, fls); - setListAdapter(mGameAdapter); + // Add all the items to the adapter + mGameAdapter.addAll(fls); + mGameAdapter.notifyDataSetChanged(); if (fls.isEmpty()) { @@ -106,12 +106,13 @@ public final class GameListFragment extends ListFragment @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - View rootView = inflater.inflate(R.layout.gamelist_listview, container, false); - ListView mMainList = (ListView) rootView.findViewById(R.id.gamelist); + ListView rootView = (ListView) inflater.inflate(R.layout.gamelist_listview, container, false); + mGameAdapter = new GameListAdapter(getActivity(), R.layout.gamelist_folderbrowser_list_item); + rootView.setAdapter(mGameAdapter); Fill(); - return mMainList; + return rootView; } @Override @@ -120,12 +121,12 @@ public final class GameListFragment extends ListFragment GameListItem item = mGameAdapter.getItem(position); // Show a toast indicating which game was clicked. - Toast.makeText(mMe, String.format(getString(R.string.file_clicked), item.getPath()), Toast.LENGTH_SHORT).show(); + Toast.makeText(getActivity(), String.format(getString(R.string.file_clicked), item.getPath()), Toast.LENGTH_SHORT).show(); // Start the emulation activity and send the path of the clicked ROM to it. - Intent intent = new Intent(mMe, EmulationActivity.class); + Intent intent = new Intent(getActivity(), EmulationActivity.class); intent.putExtra("SelectedGame", item.getPath()); - mMe.startActivity(intent); + startActivity(intent); } @Override @@ -138,7 +139,6 @@ public final class GameListFragment extends ListFragment try { mCallback = (OnGameListZeroListener) activity; - mMe = (GameListActivity) activity; } catch (ClassCastException e) { diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/settings/video/VideoSettingsFragment.java b/Source/Android/src/org/dolphinemu/dolphinemu/settings/video/VideoSettingsFragment.java index 69b647a45c..40c814397b 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/settings/video/VideoSettingsFragment.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/settings/video/VideoSettingsFragment.java @@ -27,6 +27,7 @@ public final class VideoSettingsFragment extends PreferenceFragment public static String m_GLVendor; public static String m_GLRenderer; public static String m_GLExtensions; + public static float m_QualcommVersion; /** * Class which provides a means to retrieve various @@ -163,7 +164,6 @@ public final class VideoSettingsFragment extends PreferenceFragment { int mVStart = m_GLVersion.indexOf("V@") + 2; int mVEnd = 0; - float mVersion; for (int a = mVStart; a < m_GLVersion.length(); ++a) { @@ -174,20 +174,12 @@ public final class VideoSettingsFragment extends PreferenceFragment } } - mVersion = Float.parseFloat(m_GLVersion.substring(mVStart, mVEnd)); + m_QualcommVersion = Float.parseFloat(m_GLVersion.substring(mVStart, mVEnd)); - if (mVersion >= 14.0f) + if (m_QualcommVersion >= 14.0f) mSupportsGLES3 = true; } } - if (!mSupportsGLES3 && - m_GLVendor != null && m_GLVendor.equals("NVIDIA Corporation") && - m_GLRenderer != null && m_GLRenderer.equals("NVIDIA Tegra") && - m_GLExtensions != null && m_GLExtensions.contains("GL_OES_depth24")) - { - // Is a Tegra 4 since it supports 24bit depth - mSupportsGLES3 = true; - } return mSupportsGLES3; } diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/sidemenu/SideMenuAdapter.java b/Source/Android/src/org/dolphinemu/dolphinemu/sidemenu/SideMenuAdapter.java index 6ea97e3f66..60fd8b56f3 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/sidemenu/SideMenuAdapter.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/sidemenu/SideMenuAdapter.java @@ -54,23 +54,22 @@ public final class SideMenuAdapter extends ArrayAdapter @Override public View getView(int position, View convertView, ViewGroup parent) { - View v = convertView; - if (v == null) + if (convertView == null) { LayoutInflater vi = LayoutInflater.from(context); - v = vi.inflate(id, null); + convertView = vi.inflate(id, null); } final SideMenuItem item = items.get(position); if (item != null) { - TextView title = (TextView) v.findViewById(R.id.SideMenuTitle); + TextView title = (TextView) convertView.findViewById(R.id.SideMenuTitle); if (title != null) title.setText(item.getName()); } - return v; + return convertView; } } diff --git a/Source/Core/Common/Src/CPUDetect.h b/Source/Core/Common/Src/CPUDetect.h index e93a902d63..967be0949b 100644 --- a/Source/Core/Common/Src/CPUDetect.h +++ b/Source/Core/Common/Src/CPUDetect.h @@ -43,6 +43,12 @@ struct CPUInfo bool bAVX; bool bFMA; bool bAES; + // FXSAVE/FXRSTOR + bool bFXSR; + // This flag indicates that the hardware supports some mode + // in which denormal inputs _and_ outputs are automatically set to (signed) zero. + // TODO: ARM + bool bFlushToZero; bool bLAHFSAHF64; bool bLongMode; diff --git a/Source/Core/Common/Src/FPURoundMode.h b/Source/Core/Common/Src/FPURoundMode.h index fad4d5d6aa..c552ad7ff0 100644 --- a/Source/Core/Common/Src/FPURoundMode.h +++ b/Source/Core/Common/Src/FPURoundMode.h @@ -36,7 +36,7 @@ namespace FPURoundMode void SetPrecisionMode(u32 mode); - void SetSIMDMode(u32 mode); + void SetSIMDMode(u32 roundingMode, u32 nonIEEEMode); /* * There are two different flavors of float to int conversion: diff --git a/Source/Core/Common/Src/GenericFPURoundMode.cpp b/Source/Core/Common/Src/GenericFPURoundMode.cpp index cc878291a1..c8e70a4990 100644 --- a/Source/Core/Common/Src/GenericFPURoundMode.cpp +++ b/Source/Core/Common/Src/GenericFPURoundMode.cpp @@ -26,7 +26,7 @@ namespace FPURoundMode void SetPrecisionMode(u32 mode) { } - void SetSIMDMode(u32 mode) + void SetSIMDMode(u32 mode, u32 nonIEEEMode) { } void SaveSIMDState() diff --git a/Source/Core/Common/Src/MathUtil.h b/Source/Core/Common/Src/MathUtil.h index 31772c3c60..f085c6ed2b 100644 --- a/Source/Core/Common/Src/MathUtil.h +++ b/Source/Core/Common/Src/MathUtil.h @@ -64,10 +64,10 @@ inline float FlushToZero(float f) return x.f; } -inline double FlushToZeroAsFloat(double d) +inline double FlushToZero(double d) { IntDouble x; x.d = d; - if ((x.i & DOUBLE_EXP) < 0x3800000000000000ULL) + if ((x.i & DOUBLE_EXP) == 0) x.i &= DOUBLE_SIGN; // turn into signed zero return x.d; } diff --git a/Source/Core/Common/Src/x64CPUDetect.cpp b/Source/Core/Common/Src/x64CPUDetect.cpp index 2b434ad2b6..2fa25e8074 100644 --- a/Source/Core/Common/Src/x64CPUDetect.cpp +++ b/Source/Core/Common/Src/x64CPUDetect.cpp @@ -162,6 +162,34 @@ void CPUInfo::Detect() if ((cpu_id[2] >> 20) & 1) bSSE4_2 = true; if ((cpu_id[2] >> 25) & 1) bAES = true; + // To check DAZ support, we first need to check FXSAVE support. + if ((cpu_id[3] >> 24) & 1) + { + // We can use FXSAVE. + bFXSR = true; + + GC_ALIGNED16(u8 fx_state[512]); + memset(fx_state, 0, sizeof(fx_state)); +#ifdef _WIN32 +#ifdef _M_IX86 + _fxsave(fx_state); +#elif defined (_M_X64) + _fxsave64(fx_state); +#endif +#else + __asm__("fxsave %0" : "=m" (fx_state)); +#endif + + // lowest byte of MXCSR_MASK + if ((fx_state[0x1C] >> 6) & 1) + { + // On x86, the FTZ field (supported since SSE1) only flushes denormal _outputs_ to zero, + // now that we checked DAZ support (flushing denormal _inputs_ to zero), + // we can set our generic flag. + bFlushToZero = true; + } + } + // AVX support requires 3 separate checks: // - Is the AVX bit set in CPUID? // - Is the XSAVE bit set in CPUID? @@ -222,7 +250,12 @@ std::string CPUInfo::Summarize() { std::string sum(cpu_string); if (bSSE) sum += ", SSE"; - if (bSSE2) sum += ", SSE2"; + if (bSSE2) + { + sum += ", SSE2"; + if (!bFlushToZero) + sum += " (but not DAZ!)"; + } if (bSSE3) sum += ", SSE3"; if (bSSSE3) sum += ", SSSE3"; if (bSSE4_1) sum += ", SSE4.1"; diff --git a/Source/Core/Common/Src/x64FPURoundMode.cpp b/Source/Core/Common/Src/x64FPURoundMode.cpp index 2c950ade96..f46c6000eb 100644 --- a/Source/Core/Common/Src/x64FPURoundMode.cpp +++ b/Source/Core/Common/Src/x64FPURoundMode.cpp @@ -4,6 +4,7 @@ #include "Common.h" #include "FPURoundMode.h" +#include "CPUDetect.h" #ifndef _WIN32 static const unsigned short FPU_ROUND_NEAR = 0 << 10; @@ -14,8 +15,11 @@ static const unsigned short FPU_ROUND_MASK = 3 << 10; #include #endif -const u32 MASKS = 0x1F80; // mask away the interrupts. +// OR-mask for disabling FPU exceptions (bits 7-12 in the MXCSR register) +const u32 EXCEPTION_MASK = 0x1F80; +// Denormals-Are-Zero (non-IEEE mode: denormal inputs are set to +/- 0) const u32 DAZ = 0x40; +// Flush-To-Zero (non-IEEE mode: denormal outputs are set to +/- 0) const u32 FTZ = 0x8000; namespace FPURoundMode @@ -79,16 +83,28 @@ namespace FPURoundMode //but still - set any useful sse options here #endif } - void SetSIMDMode(u32 mode) + + void SetSIMDMode(u32 roundingMode, u32 nonIEEEMode) { - static const u32 ssetable[4] = + // lookup table for FPSCR.RN-to-MXCSR.RC translation + static const u32 roundingModeLUT[4] = { - (0 << 13) | MASKS, - (3 << 13) | MASKS, - (2 << 13) | MASKS, - (1 << 13) | MASKS, + (0 << 13) | EXCEPTION_MASK, // nearest + (3 << 13) | EXCEPTION_MASK, // -inf + (2 << 13) | EXCEPTION_MASK, // +inf + (1 << 13) | EXCEPTION_MASK, // zero }; - u32 csr = ssetable[mode]; + u32 csr = roundingModeLUT[roundingMode]; + + static const u32 denormalLUT[2] = + { + FTZ, // flush-to-zero only + FTZ | DAZ, // flush-to-zero and denormals-are-zero (may not be supported) + }; + if (nonIEEEMode) + { + csr |= denormalLUT[cpu_info.bFlushToZero]; + } _mm_setcsr(csr); } diff --git a/Source/Core/Core/Src/Console.cpp b/Source/Core/Core/Src/Console.cpp index 15a19b4b74..2d48d0b5c6 100644 --- a/Source/Core/Core/Src/Console.cpp +++ b/Source/Core/Core/Src/Console.cpp @@ -17,8 +17,8 @@ #include "PowerPCDisasm.h" #include "Console.h" -#define CASE1(x) if (memcmp(cmd, x, 2*sizeof(TCHAR))==0) -#define CASE(x) else if (memcmp(cmd, x, 4*sizeof(TCHAR))==0) +#define CASE1(x) if (!strcmp(cmd, (x))) +#define CASE(x) else if (!strcmp(cmd, (x))) void Console_Submit(const char *cmd) { @@ -27,7 +27,7 @@ void Console_Submit(const char *cmd) Core::StartTrace(false); INFO_LOG(CONSOLE, "Read tracing started."); } - CASE1("w") + CASE("w") { Core::StartTrace(true); INFO_LOG(CONSOLE, "Write tracing started."); @@ -141,3 +141,6 @@ void Console_Submit(const char *cmd) ERROR_LOG(CONSOLE, "Invalid command"); } } + +#undef CASE1 +#undef CASE diff --git a/Source/Core/Core/Src/DSP/DSPCore.cpp b/Source/Core/Core/Src/DSP/DSPCore.cpp index 377e21fba8..ff05dcb3fa 100644 --- a/Source/Core/Core/Src/DSP/DSPCore.cpp +++ b/Source/Core/Core/Src/DSP/DSPCore.cpp @@ -113,13 +113,17 @@ static bool VerifyRoms(const char *irom_filename, const char *coef_filename) } if (rom_idx == 1) - PanicAlertT("You are using an old free DSP ROM made by the Dolphin Team.\n" - "Only games using the Zelda UCode will work correctly.\n"); + { + DSPHost_OSD_AddMessage("You are using an old free DSP ROM made by the Dolphin Team.", 6000); + DSPHost_OSD_AddMessage("Only games using the Zelda UCode will work correctly.", 6000); + } if (rom_idx == 2) - PanicAlertT("You are using a free DSP ROM made by the Dolphin Team.\n" - "All Wii games will work correctly, and most GC games should " - "also work fine, but the GBA/IPL/CARD UCodes will not work.\n"); + { + DSPHost_OSD_AddMessage("You are using a free DSP ROM made by the Dolphin Team.", 8000); + DSPHost_OSD_AddMessage("All Wii games will work correctly, and most GC games should ", 8000); + DSPHost_OSD_AddMessage("also work fine, but the GBA/IPL/CARD UCodes will not work.\n", 8000); + } return true; } diff --git a/Source/Core/Core/Src/DSP/DSPHost.h b/Source/Core/Core/Src/DSP/DSPHost.h index cef329a7ec..18ba5ec447 100644 --- a/Source/Core/Core/Src/DSP/DSPHost.h +++ b/Source/Core/Core/Src/DSP/DSPHost.h @@ -12,6 +12,7 @@ u8 DSPHost_ReadHostMemory(u32 addr); void DSPHost_WriteHostMemory(u8 value, u32 addr); +void DSPHost_OSD_AddMessage(const std::string& str, u32 ms); bool DSPHost_OnThread(); bool DSPHost_Wii(); void DSPHost_InterruptRequest(); diff --git a/Source/Core/Core/Src/FifoPlayer/FifoDataFile.cpp b/Source/Core/Core/Src/FifoPlayer/FifoDataFile.cpp index 118511af92..5e7e864ad0 100644 --- a/Source/Core/Core/Src/FifoPlayer/FifoDataFile.cpp +++ b/Source/Core/Core/Src/FifoPlayer/FifoDataFile.cpp @@ -86,7 +86,7 @@ bool FifoDataFile::Save(const char *filename) header.xfRegsSize = XF_REGS_SIZE; header.frameListOffset = frameListOffset; - header.frameCount = m_Frames.size(); + header.frameCount = (u32)m_Frames.size(); header.flags = m_Flags; @@ -111,7 +111,7 @@ bool FifoDataFile::Save(const char *filename) dstFrame.fifoStart = srcFrame.fifoStart; dstFrame.fifoEnd = srcFrame.fifoEnd; dstFrame.memoryUpdatesOffset = memoryUpdatesOffset; - dstFrame.numMemoryUpdates = srcFrame.memoryUpdates.size(); + dstFrame.numMemoryUpdates = (u32)srcFrame.memoryUpdates.size(); // Write frame info u64 frameOffset = frameListOffset + (i * sizeof(FileFrameInfo)); diff --git a/Source/Core/Core/Src/FifoPlayer/FifoPlaybackAnalyzer.cpp b/Source/Core/Core/Src/FifoPlayer/FifoPlaybackAnalyzer.cpp index 1e606e52e4..e6adc14130 100644 --- a/Source/Core/Core/Src/FifoPlayer/FifoPlaybackAnalyzer.cpp +++ b/Source/Core/Core/Src/FifoPlayer/FifoPlaybackAnalyzer.cpp @@ -234,7 +234,7 @@ u32 FifoPlaybackAnalyzer::DecodeCommand(u8 *data) break; } - return data - dataStart; + return (u32)(data - dataStart); } void FifoPlaybackAnalyzer::StoreEfbCopyRegion() diff --git a/Source/Core/Core/Src/FifoPlayer/FifoPlayer.cpp b/Source/Core/Core/Src/FifoPlayer/FifoPlayer.cpp index 0f65c6a966..8aaf962999 100644 --- a/Source/Core/Core/Src/FifoPlayer/FifoPlayer.cpp +++ b/Source/Core/Core/Src/FifoPlayer/FifoPlayer.cpp @@ -105,7 +105,9 @@ bool FifoPlayer::Play() u32 FifoPlayer::GetFrameObjectCount() { if (m_CurrentFrame < m_FrameInfo.size()) - return m_FrameInfo[m_CurrentFrame].objectStarts.size(); + { + return (u32)(m_FrameInfo[m_CurrentFrame].objectStarts.size()); + } return 0; } @@ -172,7 +174,7 @@ void FifoPlayer::WriteFrame(const FifoFrameInfo &frame, const AnalyzedFrameInfo m_FrameFifoSize = frame.fifoDataSize; // Determine start and end objects - u32 numObjects = info.objectStarts.size(); + u32 numObjects = (u32)(info.objectStarts.size()); u32 drawStart = std::min(numObjects, m_ObjectRangeStart); u32 drawEnd = std::min(numObjects - 1, m_ObjectRangeEnd); @@ -181,7 +183,9 @@ void FifoPlayer::WriteFrame(const FifoFrameInfo &frame, const AnalyzedFrameInfo // Skip memory updates during frame if true if (m_EarlyMemoryUpdates) - memoryUpdate = frame.memoryUpdates.size(); + { + memoryUpdate = (u32)(frame.memoryUpdates.size()); + } if (numObjects > 0) { diff --git a/Source/Core/Core/Src/FifoPlayer/FifoRecorder.cpp b/Source/Core/Core/Src/FifoPlayer/FifoRecorder.cpp index fb98205d27..e58b34658a 100644 --- a/Source/Core/Core/Src/FifoPlayer/FifoRecorder.cpp +++ b/Source/Core/Core/Src/FifoPlayer/FifoRecorder.cpp @@ -83,9 +83,9 @@ void FifoRecorder::WriteGPCommand(u8 *data, u32 size) if (m_FrameEnded && m_FifoData.size() > 0) { size_t dataSize = m_FifoData.size(); - m_CurrentFrame.fifoDataSize = dataSize; + m_CurrentFrame.fifoDataSize = (u32)dataSize; m_CurrentFrame.fifoData = new u8[dataSize]; - memcpy(m_CurrentFrame.fifoData, &m_FifoData[0], dataSize); + memcpy(m_CurrentFrame.fifoData, m_FifoData.data(), dataSize); sMutex.lock(); @@ -129,7 +129,7 @@ void FifoRecorder::WriteMemory(u32 address, u32 size, MemoryUpdate::Type type) // Record memory update MemoryUpdate memUpdate; memUpdate.address = address; - memUpdate.fifoPosition = m_FifoData.size(); + memUpdate.fifoPosition = (u32)(m_FifoData.size()); memUpdate.size = size; memUpdate.type = type; memUpdate.data = new u8[size]; diff --git a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AX_Voice.h b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AX_Voice.h index 6819b05818..fce6cdf6a2 100644 --- a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AX_Voice.h +++ b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AX_Voice.h @@ -469,36 +469,42 @@ void ProcessVoice(PB_TYPE& pb, const AXBuffers& buffers, u16 count, AXMixControl // Mix LRS, AUXA and AUXB depending on mixer_control // TODO: Handle DPL2 on AUXB. - if (mctrl & MIX_L) - MixAdd(buffers.left, samples, count, &pb.mixer.left, &pb.dpop.left, mctrl & MIX_L_RAMP); - if (mctrl & MIX_R) - MixAdd(buffers.right, samples, count, &pb.mixer.right, &pb.dpop.right, mctrl & MIX_R_RAMP); - if (mctrl & MIX_S) - MixAdd(buffers.surround, samples, count, &pb.mixer.surround, &pb.dpop.surround, mctrl & MIX_S_RAMP); +#define MIX_ON(C) (0 != (mctrl & MIX_##C)) +#define RAMP_ON(C) (0 != (mctrl & MIX_##C##_RAMP)) - if (mctrl & MIX_AUXA_L) - MixAdd(buffers.auxA_left, samples, count, &pb.mixer.auxA_left, &pb.dpop.auxA_left, mctrl & MIX_AUXA_L_RAMP); - if (mctrl & MIX_AUXA_R) - MixAdd(buffers.auxA_right, samples, count, &pb.mixer.auxA_right, &pb.dpop.auxA_right, mctrl & MIX_AUXA_R_RAMP); - if (mctrl & MIX_AUXA_S) - MixAdd(buffers.auxA_surround, samples, count, &pb.mixer.auxA_surround, &pb.dpop.auxA_surround, mctrl & MIX_AUXA_S_RAMP); + if (MIX_ON(L)) + MixAdd(buffers.left, samples, count, &pb.mixer.left, &pb.dpop.left, RAMP_ON(L)); + if (MIX_ON(R)) + MixAdd(buffers.right, samples, count, &pb.mixer.right, &pb.dpop.right, RAMP_ON(R)); + if (MIX_ON(S)) + MixAdd(buffers.surround, samples, count, &pb.mixer.surround, &pb.dpop.surround, RAMP_ON(S)); - if (mctrl & MIX_AUXB_L) - MixAdd(buffers.auxB_left, samples, count, &pb.mixer.auxB_left, &pb.dpop.auxB_left, mctrl & MIX_AUXB_L_RAMP); - if (mctrl & MIX_AUXB_R) - MixAdd(buffers.auxB_right, samples, count, &pb.mixer.auxB_right, &pb.dpop.auxB_right, mctrl & MIX_AUXB_R_RAMP); - if (mctrl & MIX_AUXB_S) - MixAdd(buffers.auxB_surround, samples, count, &pb.mixer.auxB_surround, &pb.dpop.auxB_surround, mctrl & MIX_AUXB_S_RAMP); + if (MIX_ON(AUXA_L)) + MixAdd(buffers.auxA_left, samples, count, &pb.mixer.auxA_left, &pb.dpop.auxA_left, RAMP_ON(AUXA_L)); + if (MIX_ON(AUXA_R)) + MixAdd(buffers.auxA_right, samples, count, &pb.mixer.auxA_right, &pb.dpop.auxA_right, RAMP_ON(AUXA_R)); + if (MIX_ON(AUXA_S)) + MixAdd(buffers.auxA_surround, samples, count, &pb.mixer.auxA_surround, &pb.dpop.auxA_surround, RAMP_ON(AUXA_S)); + + if (MIX_ON(AUXB_L)) + MixAdd(buffers.auxB_left, samples, count, &pb.mixer.auxB_left, &pb.dpop.auxB_left, RAMP_ON(AUXB_L)); + if (MIX_ON(AUXB_R)) + MixAdd(buffers.auxB_right, samples, count, &pb.mixer.auxB_right, &pb.dpop.auxB_right, RAMP_ON(AUXB_R)); + if (MIX_ON(AUXB_S)) + MixAdd(buffers.auxB_surround, samples, count, &pb.mixer.auxB_surround, &pb.dpop.auxB_surround, RAMP_ON(AUXB_S)); #ifdef AX_WII - if (mctrl & MIX_AUXC_L) - MixAdd(buffers.auxC_left, samples, count, &pb.mixer.auxC_left, &pb.dpop.auxC_left, mctrl & MIX_AUXC_L_RAMP); - if (mctrl & MIX_AUXC_R) - MixAdd(buffers.auxC_right, samples, count, &pb.mixer.auxC_right, &pb.dpop.auxC_right, mctrl & MIX_AUXC_R_RAMP); - if (mctrl & MIX_AUXC_S) - MixAdd(buffers.auxC_surround, samples, count, &pb.mixer.auxC_surround, &pb.dpop.auxC_surround, mctrl & MIX_AUXC_S_RAMP); + if (MIX_ON(AUXC_L)) + MixAdd(buffers.auxC_left, samples, count, &pb.mixer.auxC_left, &pb.dpop.auxC_left, RAMP_ON(AUXC_L)); + if (MIX_ON(AUXC_R)) + MixAdd(buffers.auxC_right, samples, count, &pb.mixer.auxC_right, &pb.dpop.auxC_right, RAMP_ON(AUXC_R)); + if (MIX_ON(AUXC_S)) + MixAdd(buffers.auxC_surround, samples, count, &pb.mixer.auxC_surround, &pb.dpop.auxC_surround, RAMP_ON(AUXC_S)); #endif +#undef MIX_ON +#undef RAMP_ON + // Optionally, phase shift left or right channel to simulate 3D sound. if (pb.initial_time_delay.on) { @@ -524,8 +530,8 @@ void ProcessVoice(PB_TYPE& pb, const AXBuffers& buffers, u16 count, AXMixControl pb.remote_src.cur_addr_frac = curr_pos & 0xFFFF; // Mix to main[0-3] and aux[0-3] -#define WMCHAN_MIX_ON(n) ((pb.remote_mixer_control >> (2 * n)) & 3) -#define WMCHAN_MIX_RAMP(n) ((pb.remote_mixer_control >> (2 * n)) & 2) +#define WMCHAN_MIX_ON(n) (0 != ((pb.remote_mixer_control >> (2 * n)) & 3)) +#define WMCHAN_MIX_RAMP(n) (0 != ((pb.remote_mixer_control >> (2 * n)) & 2)) if (WMCHAN_MIX_ON(0)) MixAdd(buffers.wm_main0, wm_samples, wm_count, &pb.remote_mixer.main0, &pb.remote_dpop.main0, WMCHAN_MIX_RAMP(0)); @@ -544,6 +550,8 @@ void ProcessVoice(PB_TYPE& pb, const AXBuffers& buffers, u16 count, AXMixControl if (WMCHAN_MIX_ON(7)) MixAdd(buffers.wm_aux3, wm_samples, wm_count, &pb.remote_mixer.aux3, &pb.remote_dpop.aux3, WMCHAN_MIX_RAMP(7)); } +#undef WMCHAN_MIX_RAMP +#undef WMCHAN_MIX_ON #endif } diff --git a/Source/Core/Core/Src/HW/DSPLLE/DSPHost.cpp b/Source/Core/Core/Src/HW/DSPLLE/DSPHost.cpp index 4b25f4ba20..5b2dc1f56e 100644 --- a/Source/Core/Core/Src/HW/DSPLLE/DSPHost.cpp +++ b/Source/Core/Core/Src/HW/DSPLLE/DSPHost.cpp @@ -13,6 +13,7 @@ #include "../../ConfigManager.h" #include "../../PowerPC/PowerPC.h" #include "Host.h" +#include "OnScreenDisplay.h" // The user of the DSPCore library must supply a few functions so that the // emulation core can access the environment it runs in. If the emulation @@ -29,6 +30,11 @@ void DSPHost_WriteHostMemory(u8 value, u32 addr) DSP::WriteARAM(value, addr); } +void DSPHost_OSD_AddMessage(const std::string& str, u32 ms) +{ + OSD::AddMessage(str, ms); +} + bool DSPHost_OnThread() { const SCoreStartupParameter& _CoreParameter = SConfig::GetInstance().m_LocalCoreStartupParameter; diff --git a/Source/Core/Core/Src/HW/DVDInterface.cpp b/Source/Core/Core/Src/HW/DVDInterface.cpp index fc326fec90..d77fa4877f 100644 --- a/Source/Core/Core/Src/HW/DVDInterface.cpp +++ b/Source/Core/Core/Src/HW/DVDInterface.cpp @@ -325,7 +325,7 @@ void ChangeDisc(const char* _newFileName) { Movie::g_bDiscChange = true; std::string fileName = _newFileName; - int sizeofpath = fileName.find_last_of("/\\") + 1; + auto sizeofpath = fileName.find_last_of("/\\") + 1; if (fileName.substr(sizeofpath).length() > 40) { PanicAlert("Saving iso filename to .dtm failed; max file name length is 40 characters."); diff --git a/Source/Core/Core/Src/HW/EXI_DeviceMemoryCard.cpp b/Source/Core/Core/Src/HW/EXI_DeviceMemoryCard.cpp index 1cdeb1fbcf..2d1fb56c2a 100644 --- a/Source/Core/Core/Src/HW/EXI_DeviceMemoryCard.cpp +++ b/Source/Core/Core/Src/HW/EXI_DeviceMemoryCard.cpp @@ -191,7 +191,7 @@ void CEXIMemoryCard::CmdDone() void CEXIMemoryCard::CmdDoneLater(u64 cycles) { CoreTiming::RemoveEvent(et_cmd_done); - CoreTiming::ScheduleEvent(cycles, et_cmd_done, (u64)card_index); + CoreTiming::ScheduleEvent((int)cycles, et_cmd_done, (u64)card_index); } void CEXIMemoryCard::SetCS(int cs) diff --git a/Source/Core/Core/Src/HW/GCMemcard.cpp b/Source/Core/Core/Src/HW/GCMemcard.cpp index adaa7a1858..d320f0177a 100644 --- a/Source/Core/Core/Src/HW/GCMemcard.cpp +++ b/Source/Core/Core/Src/HW/GCMemcard.cpp @@ -40,19 +40,19 @@ GCMemcard::GCMemcard(const char *filename, bool forceCreation, bool sjis) PanicAlertT("File has the extension \"%s\"\nvalid extensions are (.raw/.gcp)", fileType.c_str()); return; } - u32 size = mcdFile.GetSize(); + auto size = mcdFile.GetSize(); if (size < MC_FST_BLOCKS*BLOCK_SIZE) { - PanicAlertT("%s failed to load as a memorycard \nfile is not large enough to be a valid memory card file (0x%x bytes)", filename, size); + PanicAlertT("%s failed to load as a memorycard \nfile is not large enough to be a valid memory card file (0x%x bytes)", filename, (unsigned) size); return; } if (size % BLOCK_SIZE) { - PanicAlertT("%s failed to load as a memorycard \n Card file size is invalid (0x%x bytes)", filename, size); + PanicAlertT("%s failed to load as a memorycard \n Card file size is invalid (0x%x bytes)", filename, (unsigned) size); return; } - m_sizeMb = (size/BLOCK_SIZE) / MBIT_TO_BLOCKS; + m_sizeMb = (u16)((size/BLOCK_SIZE) / MBIT_TO_BLOCKS); switch (m_sizeMb) { case MemCard59Mb: @@ -63,7 +63,7 @@ GCMemcard::GCMemcard(const char *filename, bool forceCreation, bool sjis) case MemCard2043Mb: break; default: - PanicAlertT("%s failed to load as a memorycard \n Card size is invalid (0x%x bytes)", filename, size); + PanicAlertT("%s failed to load as a memorycard \n Card size is invalid (0x%x bytes)", filename, (unsigned) size); return; } } diff --git a/Source/Core/Core/Src/HW/GCPadEmu.cpp b/Source/Core/Core/Src/HW/GCPadEmu.cpp index 28c33ae926..fa219c369a 100644 --- a/Source/Core/Core/Src/HW/GCPadEmu.cpp +++ b/Source/Core/Core/Src/HW/GCPadEmu.cpp @@ -209,5 +209,5 @@ void GCPad::LoadDefaults(const ControllerInterface& ciface) bool GCPad::GetMicButton() const { - return m_buttons->controls.back()->control_ref->State(); + return (0.0f != m_buttons->controls.back()->control_ref->State()); } diff --git a/Source/Core/Core/Src/HW/WiimoteEmu/EmuSubroutines.cpp b/Source/Core/Core/Src/HW/WiimoteEmu/EmuSubroutines.cpp index 235d5cb7f1..2014f0b1f4 100644 --- a/Source/Core/Core/Src/HW/WiimoteEmu/EmuSubroutines.cpp +++ b/Source/Core/Core/Src/HW/WiimoteEmu/EmuSubroutines.cpp @@ -32,7 +32,7 @@ namespace WiimoteEmu { -void Spy(Wiimote* wm_, const void* data_, int size_) +void Spy(Wiimote* wm_, const void* data_, size_t size_) { #if 0 // enable log @@ -1275,7 +1275,7 @@ void Wiimote::DoState(PointerWrap& p) else { std::queue tmp_queue(m_read_requests); - size = m_read_requests.size(); + size = (u32)(m_read_requests.size()); p.Do(size); while (!tmp_queue.empty()) { diff --git a/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.cpp b/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.cpp index 28f60940c4..4c80b1adda 100644 --- a/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.cpp +++ b/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.cpp @@ -765,7 +765,7 @@ void Wiimote::Update() if (-1 == rptf_size) { std::copy(rpt.begin(), rpt.end(), data); - rptf_size = rpt.size(); + rptf_size = (s8)(rpt.size()); } } } diff --git a/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.h b/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.h index 9ed58f8b48..f2afda4aa3 100644 --- a/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.h +++ b/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.h @@ -96,7 +96,7 @@ inline double trim(double a) class Wiimote : public ControllerEmu { friend class WiimoteReal::Wiimote; -friend void Spy(Wiimote* wm_, const void* data_, int size_); +friend void Spy(Wiimote* wm_, const void* data_, size_t size_); public: enum @@ -245,7 +245,7 @@ private: } m_reg_speaker; }; -void Spy(Wiimote* wm_, const void* data_, int size_); +void Spy(Wiimote* wm_, const void* data_, size_t size_); } diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IODummy.cpp b/Source/Core/Core/Src/HW/WiimoteReal/IODummy.cpp index ada6237756..57034ff09a 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/IODummy.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/IODummy.cpp @@ -72,7 +72,7 @@ int Wiimote::IORead(u8* buf) return 0; } -int Wiimote::IOWrite(const u8* buf, int len) +int Wiimote::IOWrite(const u8* buf, size_t len) { return 0; } diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IONix.cpp b/Source/Core/Core/Src/HW/WiimoteReal/IONix.cpp index 860a9a3d57..0f4fe5e730 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/IONix.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/IONix.cpp @@ -263,9 +263,9 @@ int Wiimote::IORead(u8* buf) return r; } -int Wiimote::IOWrite(u8 const* buf, int len) +int Wiimote::IOWrite(u8 const* buf, size_t len) { - return write(int_sock, buf, len); + return write(int_sock, buf, (int)len); } }; // WiimoteReal diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp b/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp index 2f1efd0228..13728a9d72 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp @@ -140,7 +140,7 @@ namespace WiimoteReal { -int _IOWrite(HANDLE &dev_handle, OVERLAPPED &hid_overlap_write, enum win_bt_stack_t &stack, const u8* buf, int len); +int _IOWrite(HANDLE &dev_handle, OVERLAPPED &hid_overlap_write, enum win_bt_stack_t &stack, const u8* buf, size_t len); int _IORead(HANDLE &dev_handle, OVERLAPPED &hid_overlap_read, u8* buf, int index); void _IOWakeup(HANDLE &dev_handle, OVERLAPPED &hid_overlap_read); @@ -247,7 +247,7 @@ void WiimoteScanner::FindWiimotes(std::vector & found_wiimotes, Wiimot // SLEEP(2000); } -int CheckDeviceType_Write(HANDLE &dev_handle, const u8* buf, int size, int attempts) +int CheckDeviceType_Write(HANDLE &dev_handle, const u8* buf, size_t size, int attempts) { OVERLAPPED hid_overlap_write = OVERLAPPED(); hid_overlap_write.hEvent = CreateEvent(NULL, true, false, NULL); @@ -641,7 +641,7 @@ int Wiimote::IORead(u8* buf) } -int _IOWrite(HANDLE &dev_handle, OVERLAPPED &hid_overlap_write, enum win_bt_stack_t &stack, const u8* buf, int len) +int _IOWrite(HANDLE &dev_handle, OVERLAPPED &hid_overlap_write, enum win_bt_stack_t &stack, const u8* buf, size_t len) { WiimoteEmu::Spy(NULL, buf, len); @@ -663,7 +663,7 @@ int _IOWrite(HANDLE &dev_handle, OVERLAPPED &hid_overlap_write, enum win_bt_stac } case MSBT_STACK_MS: { - auto result = HidD_SetOutputReport(dev_handle, const_cast(buf) + 1, len - 1); + auto result = HidD_SetOutputReport(dev_handle, const_cast(buf) + 1, (ULONG)(len - 1)); //FlushFileBuffers(dev_handle); if (!result) @@ -715,7 +715,7 @@ int _IOWrite(HANDLE &dev_handle, OVERLAPPED &hid_overlap_write, enum win_bt_stac return 0; } -int Wiimote::IOWrite(const u8* buf, int len) +int Wiimote::IOWrite(const u8* buf, size_t len) { return _IOWrite(dev_handle, hid_overlap_write, stack, buf, len); } diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm b/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm index f59cffee2c..c094c97c13 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm +++ b/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm @@ -310,14 +310,14 @@ int Wiimote::IORead(unsigned char *buf) return inputlen; } -int Wiimote::IOWrite(const unsigned char *buf, int len) +int Wiimote::IOWrite(const unsigned char *buf, size_t len) { IOReturn ret; if (!IsConnected()) return 0; - ret = [ichan writeAsync: const_cast((void *)buf) length: len refcon: nil]; + ret = [ichan writeAsync: const_cast((void *)buf) length: (int)len refcon: nil]; if (ret == kIOReturnSuccess) return len; diff --git a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp index e5fff5b3f1..dea6f7fce6 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp @@ -239,7 +239,9 @@ bool Wiimote::Write() IOWrite(rpt.data(), rpt.size()); if (is_speaker_data) + { m_last_audio_report.Update(); + } m_write_reports.Pop(); return true; @@ -293,8 +295,10 @@ void Wiimote::Update() // Send the report if (!rpt.empty() && m_channel > 0) - Core::Callback_WiimoteInterruptChannel(index, m_channel, - rpt.data(), rpt.size()); + { + Core::Callback_WiimoteInterruptChannel(index, m_channel, + rpt.data(), (u32)rpt.size()); + } } void Wiimote::Prepare(int _index) diff --git a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h index c4807ed95f..bc953102a9 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h +++ b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h @@ -106,7 +106,7 @@ private: void WriteReport(Report rpt); int IORead(u8* buf); - int IOWrite(u8 const* buf, int len); + int IOWrite(u8 const* buf, size_t len); void IOWakeup(); void ThreadFunc(); diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE.cpp index 22115e4900..3bd37ba373 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE.cpp +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE.cpp @@ -83,7 +83,7 @@ static u64 last_reply_time; void EnqueReplyCallback(u64 userdata, int) { std::lock_guard lk(s_reply_queue); - reply_queue.push_back(userdata); + reply_queue.push_back((u32)userdata); } void Init() @@ -546,7 +546,9 @@ void ExecuteCommand(u32 _Address) const s64 ticks_til_last_reply = last_reply_time - CoreTiming::GetTicks(); if (ticks_til_last_reply > 0) - reply_delay = ticks_til_last_reply; + { + reply_delay = (int)ticks_til_last_reply; + } last_reply_time = CoreTiming::GetTicks() + reply_delay; diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_es.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_es.cpp index 58ff0917ed..ea4230f485 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_es.cpp +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_es.cpp @@ -133,7 +133,7 @@ void CWII_IPC_HLE_Device_es::DoState(PointerWrap& p) p.Do(m_AccessIdentID); p.Do(m_TitleIDs); - u32 Count = m_ContentAccessMap.size(); + u32 Count = (u32)(m_ContentAccessMap.size()); p.Do(Count); u32 CFD, Position; diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp index edbcc0967a..4de7af8e06 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp @@ -571,7 +571,7 @@ void CWII_IPC_HLE_Device_fs::DoState(PointerWrap& p) } else { - u32 size = entry.size; + u32 size = (u32)entry.size; p.Do(size); File::IOFile handle(entry.physicalName, "rb"); diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.cpp index 00415a526f..c1b82e4d55 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.cpp +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.cpp @@ -385,12 +385,12 @@ void CWII_IPC_HLE_Device_hid::FillOutDevices(u32 BufferOut, u32 BufferOutSize) Memory::WriteBigEData((const u8*)&wii_device, OffsetBuffer, Align(wii_device.bLength, 4)); OffsetBuffer += Align(wii_device.bLength, 4); bool deviceValid = true; + bool isHID = false; for (c = 0; deviceValid && c < desc.bNumConfigurations; c++) { struct libusb_config_descriptor *config = NULL; int cRet = libusb_get_config_descriptor(device, c, &config); - // do not try to use usb devices with more than one interface, games can crash if(cRet == 0 && config->bNumInterfaces <= MAX_HID_INTERFACES) { @@ -402,10 +402,14 @@ void CWII_IPC_HLE_Device_hid::FillOutDevices(u32 BufferOut, u32 BufferOutSize) for (ic = 0; ic < config->bNumInterfaces; ic++) { const struct libusb_interface *interfaceContainer = &config->interface[ic]; + for (i = 0; i < interfaceContainer->num_altsetting; i++) { const struct libusb_interface_descriptor *interface = &interfaceContainer->altsetting[i]; + if (interface->bInterfaceClass == LIBUSB_CLASS_HID) + isHID = true; + WiiHIDInterfaceDescriptor wii_interface; ConvertInterfaceToWii(&wii_interface, interface); Memory::WriteBigEData((const u8*)&wii_interface, OffsetBuffer, Align(wii_interface.bLength, 4)); @@ -435,6 +439,12 @@ void CWII_IPC_HLE_Device_hid::FillOutDevices(u32 BufferOut, u32 BufferOutSize) } } // configs + if (!isHID) + { + deviceValid = false; + OffsetBuffer = OffsetStart; + } + if (deviceValid) { Memory::Write_U32(OffsetBuffer-OffsetStart, OffsetStart); // fill in length diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.cpp index 990a9e6a7d..aa7d84d661 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.cpp +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.cpp @@ -866,7 +866,7 @@ bool CWII_IPC_HLE_Device_usb_oh1_57e_305::SendEventRoleChange(bdaddr_t _bd, bool bool CWII_IPC_HLE_Device_usb_oh1_57e_305::SendEventNumberOfCompletedPackets() { - SQueuedEvent Event(sizeof(hci_event_hdr_t) + sizeof(hci_num_compl_pkts_ep) + sizeof(hci_num_compl_pkts_info) * m_WiiMotes.size(), 0); + SQueuedEvent Event((u32)(sizeof(hci_event_hdr_t) + sizeof(hci_num_compl_pkts_ep) + (sizeof(hci_num_compl_pkts_info) * m_WiiMotes.size())), 0); INFO_LOG(WII_IPC_WIIMOTE, "Event: SendEventNumberOfCompletedPackets"); diff --git a/Source/Core/Core/Src/NetPlayClient.cpp b/Source/Core/Core/Src/NetPlayClient.cpp index 7e71584c35..6ca13b4836 100644 --- a/Source/Core/Core/Src/NetPlayClient.cpp +++ b/Source/Core/Core/Src/NetPlayClient.cpp @@ -445,10 +445,11 @@ void NetPlayClient::SendWiimoteState(const PadMapping in_game_pad, const NetWiim sf::Packet spac; spac << (MessageId)NP_MSG_WIIMOTE_DATA; spac << in_game_pad; - u8 size = nw.size(); - spac << size; - for (unsigned int i = 0; i < size; ++i) - spac << nw.data()[i]; + spac << (u8)nw.size(); + for (auto it : nw) + { + spac << it; + } std::lock_guard lks(m_crit.send); m_socket.Send(spac); diff --git a/Source/Core/Core/Src/NetPlayServer.cpp b/Source/Core/Core/Src/NetPlayServer.cpp index 0049719a05..296fcd29a4 100644 --- a/Source/Core/Core/Src/NetPlayServer.cpp +++ b/Source/Core/Core/Src/NetPlayServer.cpp @@ -153,7 +153,7 @@ unsigned int NetPlayServer::OnConnect(sf::SocketTCP& socket) rpac >> player.name; // give new client first available id - player.pid = m_players.size() + 1; + player.pid = (PlayerId)(m_players.size() + 1); // try to automatically assign new user a pad for (unsigned int m = 0; m < 4; ++m) @@ -435,12 +435,14 @@ unsigned int NetPlayServer::OnData(sf::Packet& packet, sf::SocketTCP& socket) case NP_MSG_PONG : { - const u32 ping = m_ping_timer.GetTimeElapsed(); + const u32 ping = (u32)m_ping_timer.GetTimeElapsed(); u32 ping_key = 0; packet >> ping_key; if (m_ping_key == ping_key) + { player.ping = ping; + } sf::Packet spac; spac << (MessageId)NP_MSG_PLAYER_PING_DATA; diff --git a/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_FPUtils.h b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_FPUtils.h index d379bf7049..9190a18ed7 100644 --- a/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_FPUtils.h +++ b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_FPUtils.h @@ -5,6 +5,7 @@ #ifndef _INTERPRETER_FPUTILS_H #define _INTERPRETER_FPUTILS_H +#include "CPUDetect.h" #include "Interpreter.h" #include "MathUtil.h" @@ -69,28 +70,22 @@ inline void UpdateFPSCR() inline double ForceSingle(double _x) { - //if (FPSCR.RN != 0) - // PanicAlert("RN = %d at %x", (int)FPSCR.RN, PC); - if (FPSCR.NI) - _x = FlushToZeroAsFloat(_x); - - double x = static_cast(_x); - + // convert to float... + float x = _x; + if (!cpu_info.bFlushToZero && FPSCR.NI) + { + x = FlushToZero(x); + } + // ...and back to double: return x; } inline double ForceDouble(double d) { - //if (FPSCR.RN != 0) - // PanicAlert("RN = %d at %x", (int)FPSCR.RN, PC); - - //if (FPSCR.NI) - //{ - // IntDouble x; x.d = d; - //if ((x.i & DOUBLE_EXP) == 0) - // x.i &= DOUBLE_SIGN; // turn into signed zero - // return x.d; - //} + if (!cpu_info.bFlushToZero && FPSCR.NI) + { + d = FlushToZero(d); + } return d; } diff --git a/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp index 688d166608..475f7591ce 100644 --- a/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp +++ b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp @@ -48,15 +48,8 @@ static void FPSCRtoFPUSettings(UReg_FPSCR fp) // Pokemon Colosseum does this. Gah. } - // Also corresponding SSE rounding mode setting - if (FPSCR.NI) - { - // Either one of these two breaks Beyond Good & Evil. - // if (cpu_info.bSSSE3) - // csr |= DAZ; - // csr |= FTZ; - } - FPURoundMode::SetSIMDMode(FPSCR.RN); + // Set SSE rounding mode and denormal handling + FPURoundMode::SetSIMDMode(FPSCR.RN, FPSCR.NI); } void Interpreter::mtfsb0x(UGeckoInstruction _inst) diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp index 394c7bc86a..87fb248c1f 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp @@ -276,7 +276,7 @@ void Jit64::Cleanup() ABI_CallFunctionCCC((void *)&PowerPC::UpdatePerformanceMonitor, js.downcountAmount, jit->js.numLoadStoreInst, jit->js.numFloatingPointInst); } -void Jit64::WriteExit(u32 destination, int exit_num) +void Jit64::WriteExit(u32 destination) { Cleanup(); @@ -284,8 +284,9 @@ void Jit64::WriteExit(u32 destination, int exit_num) //If nobody has taken care of this yet (this can be removed when all branches are done) JitBlock *b = js.curBlock; - b->exitAddress[exit_num] = destination; - b->exitPtrs[exit_num] = GetWritableCodePtr(); + JitBlock::LinkData linkData; + linkData.exitAddress = destination; + linkData.exitPtrs = GetWritableCodePtr(); // Link opportunity! if (jo.enableBlocklink) @@ -295,12 +296,14 @@ void Jit64::WriteExit(u32 destination, int exit_num) { // It exists! Joy of joy! JMP(blocks.GetBlock(block)->checkedEntry, true); - b->linkStatus[exit_num] = true; + linkData.linkStatus = true; return; } } MOV(32, M(&PC), Imm32(destination)); JMP(asm_routines.dispatcher, true); + + b->linkData.push_back(linkData); } void Jit64::WriteExitDestInEAX() @@ -625,7 +628,7 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc TEST(32, M((void*)PowerPC::GetStatePtr()), Imm32(0xFFFFFFFF)); FixupBranch noBreakpoint = J_CC(CC_Z); - WriteExit(ops[i].address, 0); + WriteExit(ops[i].address); SetJumpTarget(noBreakpoint); } @@ -707,7 +710,7 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc { gpr.Flush(FLUSH_ALL); fpr.Flush(FLUSH_ALL); - WriteExit(nextPC, 0); + WriteExit(nextPC); } b->flags = js.block_flags; diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit.h b/Source/Core/Core/Src/PowerPC/Jit64/Jit.h index 71a556cb5f..1adbdfaac4 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit.h +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit.h @@ -99,7 +99,7 @@ public: // Utilities for use by opcodes - void WriteExit(u32 destination, int exit_num); + void WriteExit(u32 destination); void WriteExitDestInEAX(); void WriteExceptionExit(); void WriteExternalExceptionExit(); @@ -182,7 +182,7 @@ public: void ps_sum(UGeckoInstruction inst); void ps_muls(UGeckoInstruction inst); - void fp_arith_s(UGeckoInstruction inst); + void fp_arith(UGeckoInstruction inst); void frsqrtex(UGeckoInstruction inst); void fcmpx(UGeckoInstruction inst); diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit64_Tables.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit64_Tables.cpp index 0ff2bf5d7f..dc81015573 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit64_Tables.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit64_Tables.cpp @@ -320,12 +320,12 @@ static GekkoOPTemplate table31_2[] = static GekkoOPTemplate table59[] = { - {18, &Jit64::Default}, //{"fdivsx", OPTYPE_FPU, FL_RC_BIT_F, 16}}, - {20, &Jit64::fp_arith_s}, //"fsubsx", OPTYPE_FPU, FL_RC_BIT_F}}, - {21, &Jit64::fp_arith_s}, //"faddsx", OPTYPE_FPU, FL_RC_BIT_F}}, + {18, &Jit64::fp_arith}, //{"fdivsx", OPTYPE_FPU, FL_RC_BIT_F, 16}}, + {20, &Jit64::fp_arith}, //"fsubsx", OPTYPE_FPU, FL_RC_BIT_F}}, + {21, &Jit64::fp_arith}, //"faddsx", OPTYPE_FPU, FL_RC_BIT_F}}, // {22, &Jit64::Default}, //"fsqrtsx", OPTYPE_FPU, FL_RC_BIT_F}}, // Not implemented on gekko {24, &Jit64::Default}, //"fresx", OPTYPE_FPU, FL_RC_BIT_F}}, - {25, &Jit64::fp_arith_s}, //"fmulsx", OPTYPE_FPU, FL_RC_BIT_F}}, + {25, &Jit64::fp_arith}, //"fmulsx", OPTYPE_FPU, FL_RC_BIT_F}}, {28, &Jit64::fmaddXX}, //"fmsubsx", OPTYPE_FPU, FL_RC_BIT_F}}, {29, &Jit64::fmaddXX}, //"fmaddsx", OPTYPE_FPU, FL_RC_BIT_F}}, {30, &Jit64::fmaddXX}, //"fnmsubsx", OPTYPE_FPU, FL_RC_BIT_F}}, @@ -354,12 +354,12 @@ static GekkoOPTemplate table63[] = static GekkoOPTemplate table63_2[] = { - {18, &Jit64::Default}, //"fdivx", OPTYPE_FPU, FL_RC_BIT_F, 30}}, - {20, &Jit64::Default}, //"fsubx", OPTYPE_FPU, FL_RC_BIT_F}}, - {21, &Jit64::Default}, //"faddx", OPTYPE_FPU, FL_RC_BIT_F}}, + {18, &Jit64::fp_arith}, //"fdivx", OPTYPE_FPU, FL_RC_BIT_F, 30}}, + {20, &Jit64::fp_arith}, //"fsubx", OPTYPE_FPU, FL_RC_BIT_F}}, + {21, &Jit64::fp_arith}, //"faddx", OPTYPE_FPU, FL_RC_BIT_F}}, {22, &Jit64::Default}, //"fsqrtx", OPTYPE_FPU, FL_RC_BIT_F}}, {23, &Jit64::Default}, //"fselx", OPTYPE_FPU, FL_RC_BIT_F}}, - {25, &Jit64::fp_arith_s}, //"fmulx", OPTYPE_FPU, FL_RC_BIT_F}}, + {25, &Jit64::fp_arith}, //"fmulx", OPTYPE_FPU, FL_RC_BIT_F}}, {26, &Jit64::frsqrtex}, //"frsqrtex", OPTYPE_FPU, FL_RC_BIT_F}}, {28, &Jit64::fmaddXX}, //"fmsubx", OPTYPE_FPU, FL_RC_BIT_F}}, {29, &Jit64::fmaddXX}, //"fmaddx", OPTYPE_FPU, FL_RC_BIT_F}}, diff --git a/Source/Core/Core/Src/PowerPC/Jit64/JitRegCache.cpp b/Source/Core/Core/Src/PowerPC/Jit64/JitRegCache.cpp index b2317c9394..1be04a0d5d 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/JitRegCache.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/JitRegCache.cpp @@ -166,7 +166,7 @@ int RegCache::SanityCheck() const void RegCache::DiscardRegContentsIfCached(int preg) { - if (regs[preg].away && regs[preg].location.IsSimpleReg()) + if (IsBound(preg)) { X64Reg xr = regs[preg].location.GetSimpleReg(); xregs[xr].free = true; diff --git a/Source/Core/Core/Src/PowerPC/Jit64/JitRegCache.h b/Source/Core/Core/Src/PowerPC/Jit64/JitRegCache.h index cacd1e0e4e..f27dcae91c 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/JitRegCache.h +++ b/Source/Core/Core/Src/PowerPC/Jit64/JitRegCache.h @@ -93,7 +93,7 @@ public: const OpArg &R(int preg) const {return regs[preg].location;} X64Reg RX(int preg) const { - if (regs[preg].away && regs[preg].location.IsSimpleReg()) + if (IsBound(preg)) return regs[preg].location.GetSimpleReg(); PanicAlert("Not so simple - %i", preg); return (X64Reg)-1; @@ -111,6 +111,11 @@ public: return xregs[xreg].free && !xlocks[xreg]; } + bool IsBound(int preg) const + { + return regs[preg].away && regs[preg].location.IsSimpleReg(); + } + X64Reg GetFreeXReg(); diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit_Branch.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit_Branch.cpp index b0f3f1cd18..a1e28ac6ea 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit_Branch.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit_Branch.cpp @@ -91,7 +91,7 @@ void Jit64::bx(UGeckoInstruction inst) // make idle loops go faster js.downcountAmount += 8; } - WriteExit(destination, 0); + WriteExit(destination); } // TODO - optimize to hell and beyond @@ -136,13 +136,13 @@ void Jit64::bcx(UGeckoInstruction inst) destination = SignExt16(inst.BD << 2); else destination = js.compilerPC + SignExt16(inst.BD << 2); - WriteExit(destination, 0); + WriteExit(destination); if ((inst.BO & BO_DONT_CHECK_CONDITION) == 0) SetJumpTarget( pConditionDontBranch ); if ((inst.BO & BO_DONT_DECREMENT_FLAG) == 0) SetJumpTarget( pCTRDontBranch ); - WriteExit(js.compilerPC + 4, 1); + WriteExit(js.compilerPC + 4); } void Jit64::bcctrx(UGeckoInstruction inst) @@ -190,7 +190,7 @@ void Jit64::bcctrx(UGeckoInstruction inst) WriteExitDestInEAX(); // Would really like to continue the block here, but it ends. TODO. SetJumpTarget(b); - WriteExit(js.compilerPC + 4, 1); + WriteExit(js.compilerPC + 4); } } @@ -245,5 +245,5 @@ void Jit64::bclrx(UGeckoInstruction inst) SetJumpTarget( pConditionDontBranch ); if ((inst.BO & BO_DONT_DECREMENT_FLAG) == 0) SetJumpTarget( pCTRDontBranch ); - WriteExit(js.compilerPC + 4, 1); + WriteExit(js.compilerPC + 4); } diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit_FloatingPoint.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit_FloatingPoint.cpp index c4699ecc62..7f77112ae9 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit_FloatingPoint.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit_FloatingPoint.cpp @@ -85,7 +85,7 @@ void Jit64::fp_tri_op(int d, int a, int b, bool reversible, bool single, fpr.UnlockAll(); } -void Jit64::fp_arith_s(UGeckoInstruction inst) +void Jit64::fp_arith(UGeckoInstruction inst) { INSTRUCTION_START JITDISABLE(bJITFloatingPointOff) @@ -106,7 +106,7 @@ void Jit64::fp_arith_s(UGeckoInstruction inst) case 21: fp_tri_op(inst.FD, inst.FA, inst.FB, true, single, &XEmitter::ADDSD, &XEmitter::VADDSD); break; //add case 25: fp_tri_op(inst.FD, inst.FA, inst.FC, true, single, &XEmitter::MULSD, &XEmitter::VMULSD); break; //mul default: - _assert_msg_(DYNA_REC, 0, "fp_arith_s WTF!!!"); + _assert_msg_(DYNA_REC, 0, "fp_arith WTF!!!"); } } @@ -224,16 +224,28 @@ void Jit64::fmrx(UGeckoInstruction inst) { INSTRUCTION_START JITDISABLE(bJITFloatingPointOff) - if (inst.Rc) { + if (inst.Rc) + { Default(inst); return; } int d = inst.FD; int b = inst.FB; - fpr.Lock(b, d); - fpr.BindToRegister(d, d == b, true); - MOVSD(XMM0, fpr.R(b)); - MOVSD(fpr.R(d), XMM0); - fpr.UnlockAll(); + if (d != b) + { + fpr.Lock(b, d); + + // we don't need to load d, but if it already is, it must be marked as dirty + if (fpr.IsBound(d)) + { + fpr.BindToRegister(d); + } + fpr.BindToRegister(b, true, false); + + // caveat: the order of ModRM:r/m, ModRM:reg is deliberate! + // "MOVSD reg, mem" zeros out the upper half of the destination register + MOVSD(fpr.R(d), fpr.RX(b)); + fpr.UnlockAll(); + } } void Jit64::fcmpx(UGeckoInstruction inst) diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit_Integer.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit_Integer.cpp index 244a051aaa..8299f2b044 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit_Integer.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit_Integer.cpp @@ -400,7 +400,7 @@ void Jit64::cmpXX(UGeckoInstruction inst) destination = SignExt16(js.next_inst.BD << 2); else destination = js.next_compilerPC + SignExt16(js.next_inst.BD << 2); - WriteExit(destination, 0); + WriteExit(destination); } else if ((js.next_inst.OPCD == 19) && (js.next_inst.SUBOP10 == 528)) // bcctrx { @@ -424,7 +424,7 @@ void Jit64::cmpXX(UGeckoInstruction inst) } else { - WriteExit(js.next_compilerPC + 4, 0); + WriteExit(js.next_compilerPC + 4); } js.cancel = true; @@ -507,7 +507,7 @@ void Jit64::cmpXX(UGeckoInstruction inst) destination = SignExt16(js.next_inst.BD << 2); else destination = js.next_compilerPC + SignExt16(js.next_inst.BD << 2); - WriteExit(destination, 0); + WriteExit(destination); } else if ((js.next_inst.OPCD == 19) && (js.next_inst.SUBOP10 == 528)) // bcctrx { @@ -534,7 +534,7 @@ void Jit64::cmpXX(UGeckoInstruction inst) if (!!(4 & test_bit) == condition) SetJumpTarget(continue2); if (!!(2 & test_bit) == condition) SetJumpTarget(continue1); - WriteExit(js.next_compilerPC + 4, 1); + WriteExit(js.next_compilerPC + 4); js.cancel = true; } @@ -2221,5 +2221,5 @@ void Jit64::twx(UGeckoInstruction inst) SetJumpTarget(exit3); SetJumpTarget(exit4); SetJumpTarget(exit5); - WriteExit(js.compilerPC + 4, 1); + WriteExit(js.compilerPC + 4); } diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStore.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStore.cpp index a1c3bd971c..1b41c2f1e9 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStore.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStore.cpp @@ -480,5 +480,5 @@ void Jit64::stmw(UGeckoInstruction inst) void Jit64::icbi(UGeckoInstruction inst) { Default(inst); - WriteExit(js.compilerPC + 4, 0); + WriteExit(js.compilerPC + 4); } diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit_SystemRegisters.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit_SystemRegisters.cpp index 573feb3756..8282758a74 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit_SystemRegisters.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit_SystemRegisters.cpp @@ -137,7 +137,7 @@ void Jit64::mtmsr(UGeckoInstruction inst) SetJumpTarget(noExceptionsPending); SetJumpTarget(eeDisabled); - WriteExit(js.compilerPC + 4, 0); + WriteExit(js.compilerPC + 4); js.firstFPInstructionFound = false; } diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/IR_X86.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/IR_X86.cpp index 7a37a1cb43..ef1db98de1 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/IR_X86.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/IR_X86.cpp @@ -552,7 +552,8 @@ static void regEmitICmpInst(RegInfo& RI, InstLoc I, CCFlags flag) { static void regWriteExit(RegInfo& RI, InstLoc dest) { if (isImm(*dest)) { - RI.Jit->WriteExit(RI.Build->GetImmValue(dest), RI.exitNumber++); + RI.exitNumber++; + RI.Jit->WriteExit(RI.Build->GetImmValue(dest)); } else { RI.Jit->WriteExitDestInOpArg(regLocForInst(RI, dest)); } @@ -564,7 +565,7 @@ static bool checkIsSNAN() { return MathUtil::IsSNAN(isSNANTemp[0][0]) || MathUtil::IsSNAN(isSNANTemp[1][0]); } -static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit) { +static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, u32 exitAddress) { //printf("Writing block: %x\n", js.blockStart); RegInfo RI(Jit, ibuild->getFirstInst(), ibuild->getNumInsts()); RI.Build = ibuild; @@ -1791,7 +1792,7 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit) { Jit->ABI_CallFunction(reinterpret_cast(&PowerPC::CheckBreakPoints)); Jit->TEST(32, M((void*)PowerPC::GetStatePtr()), Imm32(0xFFFFFFFF)); FixupBranch noBreakpoint = Jit->J_CC(CC_Z); - Jit->WriteExit(InstLoc, 0); + Jit->WriteExit(InstLoc); Jit->SetJumpTarget(noBreakpoint); break; } @@ -1819,10 +1820,10 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit) { } } - Jit->WriteExit(jit->js.curBlock->exitAddress[0], 0); + Jit->WriteExit(exitAddress); Jit->UD2(); } -void JitIL::WriteCode() { - DoWriteCode(&ibuild, this); +void JitIL::WriteCode(u32 exitAddress) { + DoWriteCode(&ibuild, this, exitAddress); } diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp index b15ffbacca..1518bc57bb 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp @@ -381,7 +381,7 @@ void JitIL::Cleanup() ABI_CallFunctionCCC((void *)&PowerPC::UpdatePerformanceMonitor, js.downcountAmount, jit->js.numLoadStoreInst, jit->js.numFloatingPointInst); } -void JitIL::WriteExit(u32 destination, int exit_num) +void JitIL::WriteExit(u32 destination) { Cleanup(); if (SConfig::GetInstance().m_LocalCoreStartupParameter.bJITILTimeProfiling) { @@ -391,8 +391,9 @@ void JitIL::WriteExit(u32 destination, int exit_num) //If nobody has taken care of this yet (this can be removed when all branches are done) JitBlock *b = js.curBlock; - b->exitAddress[exit_num] = destination; - b->exitPtrs[exit_num] = GetWritableCodePtr(); + JitBlock::LinkData linkData; + linkData.exitAddress = destination; + linkData.exitPtrs = GetWritableCodePtr(); // Link opportunity! int block = blocks.GetBlockNumberFromStartAddress(destination); @@ -400,13 +401,14 @@ void JitIL::WriteExit(u32 destination, int exit_num) { // It exists! Joy of joy! JMP(blocks.GetBlock(block)->checkedEntry, true); - b->linkStatus[exit_num] = true; + linkData.linkStatus = true; } else { MOV(32, M(&PC), Imm32(destination)); JMP(asm_routines.dispatcher, true); } + b->linkData.push_back(linkData); } void JitIL::WriteExitDestInOpArg(const Gen::OpArg& arg) @@ -541,14 +543,16 @@ const u8* JitIL::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc // Analyze the block, collect all instructions it is made of (including inlining, // if that is enabled), reorder instructions for optimal performance, and join joinable instructions. - b->exitAddress[0] = em_address; + u32 exitAddress = em_address; + u32 merged_addresses[32]; const int capacity_of_merged_addresses = sizeof(merged_addresses) / sizeof(merged_addresses[0]); int size_of_merged_addresses = 0; if (!memory_exception) { // If there is a memory exception inside a block (broken_block==true), compile up to that instruction. - b->exitAddress[0] = PPCAnalyst::Flatten(em_address, &size, &js.st, &js.gpa, &js.fpa, broken_block, code_buf, blockSize, merged_addresses, capacity_of_merged_addresses, size_of_merged_addresses); + // TODO + exitAddress = PPCAnalyst::Flatten(em_address, &size, &js.st, &js.gpa, &js.fpa, broken_block, code_buf, blockSize, merged_addresses, capacity_of_merged_addresses, size_of_merged_addresses); } PPCAnalyst::CodeOp *ops = code_buf->codebuffer; @@ -707,7 +711,7 @@ const u8* JitIL::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc } // Perform actual code generation - WriteCode(); + WriteCode(exitAddress); b->codeSize = (u32)(GetCodePtr() - normalEntry); b->originalSize = size; diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.h b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.h index e56a56c815..305a96015f 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.h +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.h @@ -105,7 +105,7 @@ public: // Utilities for use by opcodes - void WriteExit(u32 destination, int exit_num); + void WriteExit(u32 destination); void WriteExitDestInOpArg(const Gen::OpArg& arg); void WriteExceptionExit(); void WriteRfiExitDestInOpArg(const Gen::OpArg& arg); @@ -121,7 +121,7 @@ public: void regimmop(int d, int a, bool binary, u32 value, Operation doop, void (Gen::XEmitter::*op)(int, const Gen::OpArg&, const Gen::OpArg&), bool Rc = false, bool carry = false); void fp_tri_op(int d, int a, int b, bool reversible, bool dupe, void (Gen::XEmitter::*op)(Gen::X64Reg, Gen::OpArg)); - void WriteCode(); + void WriteCode(u32 exitAddress); // OPCODES void unknown_instruction(UGeckoInstruction _inst) override; diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/Jit.cpp b/Source/Core/Core/Src/PowerPC/JitArm32/Jit.cpp index 4083a383e9..eab7f3711a 100644 --- a/Source/Core/Core/Src/PowerPC/JitArm32/Jit.cpp +++ b/Source/Core/Core/Src/PowerPC/JitArm32/Jit.cpp @@ -186,15 +186,16 @@ void JitArm::WriteExceptionExit() MOVI2R(A, (u32)asm_routines.testExceptions); B(A); } -void JitArm::WriteExit(u32 destination, int exit_num) +void JitArm::WriteExit(u32 destination) { Cleanup(); DoDownCount(); //If nobody has taken care of this yet (this can be removed when all branches are done) JitBlock *b = js.curBlock; - b->exitAddress[exit_num] = destination; - b->exitPtrs[exit_num] = GetWritableCodePtr(); + JitBlock::LinkData linkData; + linkData.exitAddress = destination; + linkData.exitPtrs = GetWritableCodePtr(); // Link opportunity! int block = blocks.GetBlockNumberFromStartAddress(destination); @@ -202,7 +203,7 @@ void JitArm::WriteExit(u32 destination, int exit_num) { // It exists! Joy of joy! B(blocks.GetBlock(block)->checkedEntry); - b->linkStatus[exit_num] = true; + linkData.linkStatus = true; } else { @@ -212,6 +213,8 @@ void JitArm::WriteExit(u32 destination, int exit_num) MOVI2R(A, (u32)asm_routines.dispatcher); B(A); } + + b->linkData.push_back(linkData); } void STACKALIGN JitArm::Run() @@ -496,7 +499,7 @@ const u8* JitArm::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBlo if (broken_block) { printf("Broken Block going to 0x%08x\n", nextPC); - WriteExit(nextPC, 0); + WriteExit(nextPC); } b->flags = js.block_flags; diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/Jit.h b/Source/Core/Core/Src/PowerPC/JitArm32/Jit.h index fc1911c5bf..4d1d2d8a4e 100644 --- a/Source/Core/Core/Src/PowerPC/JitArm32/Jit.h +++ b/Source/Core/Core/Src/PowerPC/JitArm32/Jit.h @@ -109,7 +109,7 @@ public: // Utilities for use by opcodes - void WriteExit(u32 destination, int exit_num); + void WriteExit(u32 destination); void WriteExitDestInR(ARMReg Reg); void WriteRfiExitDestInR(ARMReg Reg); void WriteExceptionExit(); diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Branch.cpp b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Branch.cpp index 1879e4af85..eac488a5b0 100644 --- a/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Branch.cpp +++ b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Branch.cpp @@ -135,9 +135,11 @@ void JitArm::bx(UGeckoInstruction inst) else destination = js.compilerPC + SignExt26(inst.LI << 2); #ifdef ACID_TEST - // TODO: Not implemented yet. - //if (inst.LK) - //AND(32, M(&PowerPC::ppcState.cr), Imm32(~(0xFF000000))); + if (inst.LK) + { + MOV(R14, 0); + STRB(R14, R9, PPCSTATE_OFF(cr_fast[0])); + } #endif if (destination == js.compilerPC) { @@ -152,7 +154,7 @@ void JitArm::bx(UGeckoInstruction inst) MOVI2R(R14, (u32)asm_routines.testExceptions); B(R14); } - WriteExit(destination, 0); + WriteExit(destination); } void JitArm::bcx(UGeckoInstruction inst) @@ -207,14 +209,14 @@ void JitArm::bcx(UGeckoInstruction inst) destination = SignExt16(inst.BD << 2); else destination = js.compilerPC + SignExt16(inst.BD << 2); - WriteExit(destination, 0); + WriteExit(destination); if ((inst.BO & BO_DONT_CHECK_CONDITION) == 0) SetJumpTarget( pConditionDontBranch ); if ((inst.BO & BO_DONT_DECREMENT_FLAG) == 0) SetJumpTarget( pCTRDontBranch ); - WriteExit(js.compilerPC + 4, 1); + WriteExit(js.compilerPC + 4); } void JitArm::bcctrx(UGeckoInstruction inst) { @@ -276,7 +278,7 @@ void JitArm::bcctrx(UGeckoInstruction inst) WriteExitDestInR(rA); SetJumpTarget(b); - WriteExit(js.compilerPC + 4, 1); + WriteExit(js.compilerPC + 4); } } void JitArm::bclrx(UGeckoInstruction inst) @@ -329,8 +331,11 @@ void JitArm::bclrx(UGeckoInstruction inst) // This below line can be used to prove that blr "eats flags" in practice. // This observation will let us do a lot of fun observations. #ifdef ACID_TEST - // TODO: Not yet implemented - // AND(32, M(&PowerPC::ppcState.cr), Imm32(~(0xFF000000))); + if (inst.LK) + { + MOV(R14, 0); + STRB(R14, R9, PPCSTATE_OFF(cr_fast[0])); + } #endif //MOV(32, R(EAX), M(&LR)); @@ -350,5 +355,5 @@ void JitArm::bclrx(UGeckoInstruction inst) SetJumpTarget( pConditionDontBranch ); if ((inst.BO & BO_DONT_DECREMENT_FLAG) == 0) SetJumpTarget( pCTRDontBranch ); - WriteExit(js.compilerPC + 4, 1); + WriteExit(js.compilerPC + 4); } diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_LoadStore.cpp b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_LoadStore.cpp index f04c88d6c3..3983772aa6 100644 --- a/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_LoadStore.cpp +++ b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_LoadStore.cpp @@ -531,6 +531,6 @@ void JitArm::dcbst(UGeckoInstruction inst) void JitArm::icbi(UGeckoInstruction inst) { Default(inst); - WriteExit(js.compilerPC + 4, 0); + WriteExit(js.compilerPC + 4); } diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_SystemRegisters.cpp b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_SystemRegisters.cpp index e4ab630fce..62b15e1d5e 100644 --- a/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_SystemRegisters.cpp +++ b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_SystemRegisters.cpp @@ -205,7 +205,7 @@ void JitArm::mtmsr(UGeckoInstruction inst) gpr.Flush(); fpr.Flush(); - WriteExit(js.compilerPC + 4, 0); + WriteExit(js.compilerPC + 4); } void JitArm::mfmsr(UGeckoInstruction inst) diff --git a/Source/Core/Core/Src/PowerPC/JitArmIL/IR_Arm.cpp b/Source/Core/Core/Src/PowerPC/JitArmIL/IR_Arm.cpp index 10620d9183..c1bee507fc 100644 --- a/Source/Core/Core/Src/PowerPC/JitArmIL/IR_Arm.cpp +++ b/Source/Core/Core/Src/PowerPC/JitArmIL/IR_Arm.cpp @@ -156,7 +156,8 @@ static ARMReg regEnsureInReg(RegInfo& RI, InstLoc I) { static void regWriteExit(RegInfo& RI, InstLoc dest) { if (isImm(*dest)) { - RI.Jit->WriteExit(RI.Build->GetImmValue(dest), RI.exitNumber++); + RI.exitNumber++; + RI.Jit->WriteExit(RI.Build->GetImmValue(dest)); } else { RI.Jit->WriteExitDestInReg(regLocForInst(RI, dest)); } @@ -281,7 +282,7 @@ static void regEmitCmp(RegInfo& RI, InstLoc I) { } } -static void DoWriteCode(IRBuilder* ibuild, JitArmIL* Jit) { +static void DoWriteCode(IRBuilder* ibuild, JitArmIL* Jit, u32 exitAddress) { RegInfo RI(Jit, ibuild->getFirstInst(), ibuild->getNumInsts()); RI.Build = ibuild; @@ -733,10 +734,10 @@ static void DoWriteCode(IRBuilder* ibuild, JitArmIL* Jit) { } } - Jit->WriteExit(jit->js.curBlock->exitAddress[0], 0); + Jit->WriteExit(exitAddress); Jit->BKPT(0x111); } -void JitArmIL::WriteCode() { - DoWriteCode(&ibuild, this); +void JitArmIL::WriteCode(u32 exitAddress) { + DoWriteCode(&ibuild, this, exitAddress); } diff --git a/Source/Core/Core/Src/PowerPC/JitArmIL/JitIL.cpp b/Source/Core/Core/Src/PowerPC/JitArmIL/JitIL.cpp index 0aac4d6722..44ebc8b6eb 100644 --- a/Source/Core/Core/Src/PowerPC/JitArmIL/JitIL.cpp +++ b/Source/Core/Core/Src/PowerPC/JitArmIL/JitIL.cpp @@ -117,13 +117,14 @@ void JitArmIL::WriteExceptionExit() MOVI2R(R14, (u32)asm_routines.testExceptions); B(R14); } -void JitArmIL::WriteExit(u32 destination, int exit_num) +void JitArmIL::WriteExit(u32 destination) { DoDownCount(); //If nobody has taken care of this yet (this can be removed when all branches are done) JitBlock *b = js.curBlock; - b->exitAddress[exit_num] = destination; - b->exitPtrs[exit_num] = GetWritableCodePtr(); + JitBlock::LinkData linkData; + linkData.exitAddress = destination; + linkData.exitPtrs = GetWritableCodePtr(); // Link opportunity! int block = blocks.GetBlockNumberFromStartAddress(destination); @@ -131,7 +132,7 @@ void JitArmIL::WriteExit(u32 destination, int exit_num) { // It exists! Joy of joy! B(blocks.GetBlock(block)->checkedEntry); - b->linkStatus[exit_num] = true; + linkData.linkStatus = true; } else { @@ -140,6 +141,8 @@ void JitArmIL::WriteExit(u32 destination, int exit_num) MOVI2R(R14, (u32)asm_routines.dispatcher); B(R14); } + + b->linkData.push_back(linkData); } void JitArmIL::PrintDebug(UGeckoInstruction inst, u32 level) { @@ -347,12 +350,12 @@ const u8* JitArmIL::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitB if (broken_block) { printf("Broken Block going to 0x%08x\n", nextPC); - WriteExit(nextPC, 0); + WriteExit(nextPC); } // Perform actual code generation - WriteCode(); + WriteCode(nextPC); b->flags = js.block_flags; b->codeSize = (u32)(GetCodePtr() - normalEntry); b->originalSize = size; diff --git a/Source/Core/Core/Src/PowerPC/JitArmIL/JitIL.h b/Source/Core/Core/Src/PowerPC/JitArmIL/JitIL.h index 4dec87ddeb..71b09a3251 100644 --- a/Source/Core/Core/Src/PowerPC/JitArmIL/JitIL.h +++ b/Source/Core/Core/Src/PowerPC/JitArmIL/JitIL.h @@ -64,8 +64,8 @@ public: void Run(); void SingleStep(); // - void WriteCode(); - void WriteExit(u32 destination, int exit_num); + void WriteCode(u32 exitAddress); + void WriteExit(u32 destination); void WriteExitDestInReg(ARMReg Reg); void WriteRfiExitDestInR(ARMReg Reg); void WriteExceptionExit(); diff --git a/Source/Core/Core/Src/PowerPC/JitCommon/JitBackpatch.cpp b/Source/Core/Core/Src/PowerPC/JitCommon/JitBackpatch.cpp index dd481da9bc..b7cc031c99 100644 --- a/Source/Core/Core/Src/PowerPC/JitCommon/JitBackpatch.cpp +++ b/Source/Core/Core/Src/PowerPC/JitCommon/JitBackpatch.cpp @@ -234,7 +234,7 @@ const u8 *Jitx86Base::BackPatch(u8 *codePtr, u32 emAddress, void *ctx_void) XEmitter emitter(start); const u8 *trampoline = trampolines.GetWriteTrampoline(info, registersInUse); emitter.CALL((void *)trampoline); - emitter.NOP(codePtr + info.instructionSize - emitter.GetCodePtr()); + emitter.NOP((int)(codePtr + info.instructionSize - emitter.GetCodePtr())); return start; } #else diff --git a/Source/Core/Core/Src/PowerPC/JitCommon/JitCache.cpp b/Source/Core/Core/Src/PowerPC/JitCommon/JitCache.cpp index d7c78d9d17..b81dadd394 100644 --- a/Source/Core/Core/Src/PowerPC/JitCommon/JitCache.cpp +++ b/Source/Core/Core/Src/PowerPC/JitCommon/JitCache.cpp @@ -35,8 +35,6 @@ op_agent_t agent; using namespace Gen; -#define INVALID_EXIT 0xFFFFFFFF - bool JitBaseBlockCache::IsFull() const { return GetNumBlocks() >= MAX_NUM_BLOCKS - 1; @@ -167,12 +165,6 @@ using namespace Gen; JitBlock &b = blocks[num_blocks]; b.invalid = false; b.originalAddress = em_address; - b.exitAddress[0] = INVALID_EXIT; - b.exitAddress[1] = INVALID_EXIT; - b.exitPtrs[0] = 0; - b.exitPtrs[1] = 0; - b.linkStatus[0] = false; - b.linkStatus[1] = false; num_blocks++; //commit the current block return num_blocks - 1; } @@ -193,10 +185,9 @@ using namespace Gen; block_map[std::make_pair(pAddr + 4 * b.originalSize - 1, pAddr)] = block_num; if (block_link) { - for (int i = 0; i < 2; i++) + for (const auto& e : b.linkData) { - if (b.exitAddress[i] != INVALID_EXIT) - links_to.insert(std::pair(b.exitAddress[i], block_num)); + links_to.insert(std::pair(e.exitAddress, block_num)); } LinkBlock(block_num); @@ -275,15 +266,15 @@ using namespace Gen; // This block is dead. Don't relink it. return; } - for (int e = 0; e < 2; e++) + for (auto& e : b.linkData) { - if (b.exitAddress[e] != INVALID_EXIT && !b.linkStatus[e]) + if (!e.linkStatus) { - int destinationBlock = GetBlockNumberFromStartAddress(b.exitAddress[e]); + int destinationBlock = GetBlockNumberFromStartAddress(e.exitAddress); if (destinationBlock != -1) { - WriteLinkBlock(b.exitPtrs[e], blocks[destinationBlock].checkedEntry); - b.linkStatus[e] = true; + WriteLinkBlock(e.exitPtrs, blocks[destinationBlock].checkedEntry); + e.linkStatus = true; } } } @@ -316,10 +307,10 @@ using namespace Gen; return; for (multimap::iterator iter = ppp.first; iter != ppp.second; ++iter) { JitBlock &sourceBlock = blocks[iter->second]; - for (int e = 0; e < 2; e++) + for (auto& e : sourceBlock.linkData) { - if (sourceBlock.exitAddress[e] == b.originalAddress) - sourceBlock.linkStatus[e] = false; + if (e.exitAddress == b.originalAddress) + e.linkStatus = false; } } } diff --git a/Source/Core/Core/Src/PowerPC/JitCommon/JitCache.h b/Source/Core/Core/Src/PowerPC/JitCommon/JitCache.h index b81c5d837a..ffbffaadb5 100644 --- a/Source/Core/Core/Src/PowerPC/JitCommon/JitCache.h +++ b/Source/Core/Core/Src/PowerPC/JitCommon/JitCache.h @@ -35,9 +35,6 @@ struct JitBlock const u8 *checkedEntry; const u8 *normalEntry; - u8 *exitPtrs[2]; // to be able to rewrite the exit jum - u32 exitAddress[2]; // 0xFFFFFFFF == unknown - u32 originalAddress; u32 codeSize; u32 originalSize; @@ -45,7 +42,13 @@ struct JitBlock int flags; bool invalid; - bool linkStatus[2]; + + struct LinkData { + u8 *exitPtrs; // to be able to rewrite the exit jum + u32 exitAddress; + bool linkStatus; // is it already linked? + }; + std::vector linkData; #ifdef _WIN32 // we don't really need to save start and stop diff --git a/Source/Core/Core/Src/PowerPC/JitCommon/Jit_Util.cpp b/Source/Core/Core/Src/PowerPC/JitCommon/Jit_Util.cpp index 00e24e7a20..5c4a712024 100644 --- a/Source/Core/Core/Src/PowerPC/JitCommon/Jit_Util.cpp +++ b/Source/Core/Core/Src/PowerPC/JitCommon/Jit_Util.cpp @@ -323,7 +323,7 @@ void EmuCodeBlock::SafeWriteRegToReg(X64Reg reg_value, X64Reg reg_addr, int acce MOV(32, M(&PC), Imm32(jit->js.compilerPC)); // Helps external systems know which instruction triggered the write TEST(32, R(reg_addr), Imm32(mem_mask)); FixupBranch fast = J_CC(CC_Z, true); - bool noProlog = flags & SAFE_LOADSTORE_NO_PROLOG; + bool noProlog = (0 != (flags & SAFE_LOADSTORE_NO_PROLOG)); bool swap = !(flags & SAFE_LOADSTORE_NO_SWAP); ABI_PushRegistersAndAdjustStack(registersInUse, noProlog); switch (accessSize) diff --git a/Source/Core/Core/Src/PowerPC/PPCTables.cpp b/Source/Core/Core/Src/PowerPC/PPCTables.cpp index d901f639e5..5854f1f0da 100644 --- a/Source/Core/Core/Src/PowerPC/PPCTables.cpp +++ b/Source/Core/Core/Src/PowerPC/PPCTables.cpp @@ -14,24 +14,15 @@ #include "Interpreter/Interpreter_Tables.h" #include "JitInterface.h" -struct op_inf -{ - const char *name; - int count; - bool operator < (const op_inf &o) const - { - return count > o.count; - } -}; - GekkoOPInfo *m_infoTable[64]; - GekkoOPInfo *m_infoTable4[1024]; - GekkoOPInfo *m_infoTable19[1024]; - GekkoOPInfo *m_infoTable31[1024]; - GekkoOPInfo *m_infoTable59[32]; - GekkoOPInfo *m_infoTable63[1024]; +GekkoOPInfo *m_infoTable[64]; +GekkoOPInfo *m_infoTable4[1024]; +GekkoOPInfo *m_infoTable19[1024]; +GekkoOPInfo *m_infoTable31[1024]; +GekkoOPInfo *m_infoTable59[32]; +GekkoOPInfo *m_infoTable63[1024]; - GekkoOPInfo *m_allInstructions[512]; - int m_numInstructions; +GekkoOPInfo *m_allInstructions[512]; +int m_numInstructions; GekkoOPInfo *GetOpInfo(UGeckoInstruction _inst) { @@ -182,26 +173,34 @@ void CountInstruction(UGeckoInstruction _inst) { GekkoOPInfo *info = GetOpInfo(_inst); if (info) + { info->runCount++; + } } void PrintInstructionRunCounts() { - std::vector temp; - for (int i = 0; i < m_numInstructions; i++) + typedef std::pair OpInfo; + std::vector temp; + temp.reserve(m_numInstructions); + for (int i = 0; i < m_numInstructions; ++i) { - op_inf x; - x.name = m_allInstructions[i]->opname; - x.count = m_allInstructions[i]->runCount; - temp.push_back(x); + GekkoOPInfo *pInst = m_allInstructions[i]; + temp.emplace_back(pInst->opname, pInst->runCount); } - std::sort(temp.begin(), temp.end()); - for (int i = 0; i < m_numInstructions; i++) + std::sort(temp.begin(), temp.end(), + [](const OpInfo &a, const OpInfo &b) + { + return a.second > b.second; + }); + + for (auto &inst : temp) { - if (temp[i].count == 0) + if (inst.second == 0) break; - DEBUG_LOG(POWERPC, "%s : %i", temp[i].name,temp[i].count); - //PanicAlert("%s : %i", temp[i].name,temp[i].count); + + DEBUG_LOG(POWERPC, "%s : %llu", inst.first, inst.second); + //PanicAlert("%s : %llu", inst.first, inst.second); } } @@ -212,20 +211,22 @@ void LogCompiledInstructions() File::IOFile f(StringFromFormat("%sinst_log%i.txt", File::GetUserPath(D_LOGS_IDX).c_str(), time), "w"); for (int i = 0; i < m_numInstructions; i++) { - if (m_allInstructions[i]->compileCount > 0) + GekkoOPInfo *pInst = m_allInstructions[i]; + if (pInst->compileCount > 0) { - fprintf(f.GetHandle(), "%s\t%i\t%" PRId64 "\t%08x\n", m_allInstructions[i]->opname, - m_allInstructions[i]->compileCount, m_allInstructions[i]->runCount, m_allInstructions[i]->lastUse); + fprintf(f.GetHandle(), "%s\t%i\t%" PRId64 "\t%08x\n", pInst->opname, + pInst->compileCount, pInst->runCount, pInst->lastUse); } } f.Open(StringFromFormat("%sinst_not%i.txt", File::GetUserPath(D_LOGS_IDX).c_str(), time), "w"); for (int i = 0; i < m_numInstructions; i++) { - if (m_allInstructions[i]->compileCount == 0) + GekkoOPInfo *pInst = m_allInstructions[i]; + if (pInst->compileCount == 0) { - fprintf(f.GetHandle(), "%s\t%i\t%" PRId64 "\n", m_allInstructions[i]->opname, - m_allInstructions[i]->compileCount, m_allInstructions[i]->runCount); + fprintf(f.GetHandle(), "%s\t%i\t%" PRId64 "\n", pInst->opname, + pInst->compileCount, pInst->runCount); } } diff --git a/Source/Core/Core/Src/State.cpp b/Source/Core/Core/Src/State.cpp index 99a1236123..f33003fdb1 100644 --- a/Source/Core/Core/Src/State.cpp +++ b/Source/Core/Core/Src/State.cpp @@ -247,7 +247,7 @@ void CompressAndDumpState(CompressAndDumpState_args save_args) // Setting up the header StateHeader header; memcpy(header.gameID, SConfig::GetInstance().m_LocalCoreStartupParameter.GetUniqueID().c_str(), 6); - header.size = g_use_compression ? buffer_size : 0; + header.size = g_use_compression ? (u32)buffer_size : 0; header.time = Common::Timer::GetDoubleTime(); f.WriteArray(&header, 1); @@ -261,9 +261,13 @@ void CompressAndDumpState(CompressAndDumpState_args save_args) lzo_uint out_len = 0; if ((i + IN_LEN) >= buffer_size) - cur_len = buffer_size - i; + { + cur_len = (lzo_uint32)(buffer_size - i); + } else + { cur_len = IN_LEN; + } if (lzo1x_1_compress(buffer_data + i, cur_len, out, &out_len, wrkmem) != LZO_E_OK) PanicAlertT("Internal LZO Error - compression failed"); diff --git a/Source/Core/DolphinWX/Src/MainAndroid.cpp b/Source/Core/DolphinWX/Src/MainAndroid.cpp index 7382aba219..949724bcf6 100644 --- a/Source/Core/DolphinWX/Src/MainAndroid.cpp +++ b/Source/Core/DolphinWX/Src/MainAndroid.cpp @@ -282,10 +282,22 @@ JNIEXPORT jstring JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetTitle( env->ReleaseStringUTFChars(jFile, File); return env->NewStringUTF(Name.c_str()); } + JNIEXPORT jstring JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetVersionString(JNIEnv *env, jobject obj) { return env->NewStringUTF(scm_rev_str); } + +JNIEXPORT jboolean JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SupportsNEON(JNIEnv *env, jobject obj) +{ + return cpu_info.bNEON; +} + +JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SaveScreenShot(JNIEnv *env, jobject obj) +{ + Core::SaveScreenShot(); +} + JNIEXPORT jstring JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetConfig(JNIEnv *env, jobject obj, jstring jFile, jstring jKey, jstring jValue, jstring jDefault) { IniFile ini; diff --git a/Source/Core/InputCommon/Src/ControllerInterface/SDL/SDL.cpp b/Source/Core/InputCommon/Src/ControllerInterface/SDL/SDL.cpp index bcd3586dc6..24e0d0de58 100644 --- a/Source/Core/InputCommon/Src/ControllerInterface/SDL/SDL.cpp +++ b/Source/Core/InputCommon/Src/ControllerInterface/SDL/SDL.cpp @@ -154,12 +154,13 @@ Joystick::~Joystick() { // stop/destroy all effects SDL_HapticStopAll(m_haptic); - std::list::iterator - i = m_state_out.begin(), - e = m_state_out.end(); - for ( ; i != e; ++i) - if (i->id != -1) - SDL_HapticDestroyEffect(m_haptic, i->id); + for (auto &i : m_state_out) + { + if (i.id != -1) + { + SDL_HapticDestroyEffect(m_haptic, i.id); + } + } // close haptic first SDL_HapticClose(m_haptic); } @@ -210,7 +211,7 @@ void Joystick::ConstantEffect::SetState(ControlState state) } const Sint16 old = m_effect.effect.constant.level; - m_effect.effect.constant.level = state * 0x7FFF; + m_effect.effect.constant.level = (Sint16)(state * 0x7FFF); if (old != m_effect.effect.constant.level) m_effect.changed = true; } @@ -228,7 +229,7 @@ void Joystick::RampEffect::SetState(ControlState state) } const Sint16 old = m_effect.effect.ramp.start; - m_effect.effect.ramp.start = state * 0x7FFF; + m_effect.effect.ramp.start = (Sint16)(state * 0x7FFF); if (old != m_effect.effect.ramp.start) m_effect.changed = true; } @@ -247,7 +248,7 @@ void Joystick::SineEffect::SetState(ControlState state) const Sint16 old = m_effect.effect.periodic.magnitude; m_effect.effect.periodic.period = 5; - m_effect.effect.periodic.magnitude = state * 0x5000; + m_effect.effect.periodic.magnitude = (Sint16)(state * 0x5000); m_effect.effect.periodic.attack_length = 0; m_effect.effect.periodic.fade_length = 500; @@ -293,7 +294,7 @@ void Joystick::TriangleEffect::SetState(ControlState state) const Sint16 old = m_effect.effect.periodic.magnitude; m_effect.effect.periodic.period = 5; - m_effect.effect.periodic.magnitude = state * 0x5000; + m_effect.effect.periodic.magnitude = (Sint16)(state * 0x5000); m_effect.effect.periodic.attack_length = 0; m_effect.effect.periodic.fade_length = 100; @@ -313,34 +314,35 @@ bool Joystick::UpdateInput() bool Joystick::UpdateOutput() { #ifdef USE_SDL_HAPTIC - std::list::iterator - i = m_state_out.begin(), - e = m_state_out.end(); - for ( ; i != e; ++i) + for (auto &i : m_state_out) { - if (i->changed) // if SetState was called on this output + if (i.changed) // if SetState was called on this output { - if (-1 == i->id) // effect isn't currently uploaded + if (-1 == i.id) // effect isn't currently uploaded { - if (i->effect.type) // if outputstate is >0 this would be true - if ((i->id = SDL_HapticNewEffect( m_haptic, &i->effect )) > -1) // upload the effect - SDL_HapticRunEffect(m_haptic, i->id, 1); // run the effect + if (i.effect.type) // if outputstate is >0 this would be true + { + if ((i.id = SDL_HapticNewEffect(m_haptic, &i.effect)) > -1) // upload the effect + { + SDL_HapticRunEffect(m_haptic, i.id, 1); // run the effect + } + } } else // effect is already uploaded { - if (i->effect.type) // if ouputstate >0 + if (i.effect.type) // if ouputstate >0 { - SDL_HapticUpdateEffect(m_haptic, i->id, &i->effect); // update the effect + SDL_HapticUpdateEffect(m_haptic, i.id, &i.effect); // update the effect } else { - SDL_HapticStopEffect(m_haptic, i->id); // else, stop and remove the effect - SDL_HapticDestroyEffect(m_haptic, i->id); - i->id = -1; // mark it as not uploaded + SDL_HapticStopEffect(m_haptic, i.id); // else, stop and remove the effect + SDL_HapticDestroyEffect(m_haptic, i.id); + i.id = -1; // mark it as not uploaded } } - i->changed = false; + i.changed = false; } } #endif diff --git a/Source/Core/VideoBackends/D3D/Src/D3DTexture.cpp b/Source/Core/VideoBackends/D3D/Src/D3DTexture.cpp index 94d778d17b..abf34b3cca 100644 --- a/Source/Core/VideoBackends/D3D/Src/D3DTexture.cpp +++ b/Source/Core/VideoBackends/D3D/Src/D3DTexture.cpp @@ -5,138 +5,12 @@ #include "D3DBase.h" #include "D3DTexture.h" -#include -#include -#include -#pragma comment(lib, "WindowsCodecs.lib") - namespace DX11 { namespace D3D { -HRESULT TextureToPng(D3D11_MAPPED_SUBRESOURCE &map, LPCWSTR wzFilename, int width, int height, bool saveAlpha) -{ - IWICImagingFactory *piFactory = NULL; - IWICBitmapEncoder *piEncoder = NULL; - IWICBitmapFrameEncode *piBitmapFrame = NULL; - IPropertyBag2 *pPropertybag = NULL; - - IWICStream *piStream = NULL; - - HRESULT hr = CoCreateInstance( - CLSID_WICImagingFactory, - NULL, - CLSCTX_INPROC_SERVER, - IID_IWICImagingFactory, - (LPVOID*)&piFactory); - - if (SUCCEEDED(hr)) - { - hr = piFactory->CreateStream(&piStream); - } - - if (SUCCEEDED(hr)) - { - hr = piStream->InitializeFromFilename(wzFilename, GENERIC_WRITE); - } - - if (SUCCEEDED(hr)) - { - hr = piFactory->CreateEncoder(GUID_ContainerFormatPng, NULL, &piEncoder); - } - - if (SUCCEEDED(hr)) - { - hr = piEncoder->Initialize(piStream, WICBitmapEncoderNoCache); - } - - if (SUCCEEDED(hr)) - { - hr = piEncoder->CreateNewFrame(&piBitmapFrame, &pPropertybag); - } - - if (SUCCEEDED(hr)) - { - if (SUCCEEDED(hr)) - { - hr = piBitmapFrame->Initialize(pPropertybag); - } - } - - if (SUCCEEDED(hr)) - { - hr = piBitmapFrame->SetSize(width, height); - } - - WICPixelFormatGUID formatGUID = GUID_WICPixelFormat32bppBGRA; - if (SUCCEEDED(hr)) - { - hr = piBitmapFrame->SetPixelFormat(&formatGUID); - } - - if (SUCCEEDED(hr)) - { - // We're expecting to write out 32bppBGRA. Fail if the encoder cannot do it. - hr = IsEqualGUID(formatGUID, GUID_WICPixelFormat32bppBGRA) ? S_OK : E_FAIL; - } - - if (SUCCEEDED(hr)) - { - if (map.pData != NULL) - { - for (int y = 0; y < height; ++y) - { - u8* ptr = (u8*)map.pData + y * map.RowPitch; - for (unsigned int x = 0; x < map.RowPitch/4; ++x) - { - u8 r = ptr[0]; - u8 g = ptr[1]; - u8 b = ptr[2]; - ptr[0] = b; - ptr[1] = g; - ptr[2] = r; - if (!saveAlpha) - ptr[3] = 0xff; - - - ptr += 4; - } - } - hr = piBitmapFrame->WritePixels(height, map.RowPitch, height * map.RowPitch, (BYTE*)map.pData); - } - else - { - hr = E_OUTOFMEMORY; - } - } - - if (SUCCEEDED(hr)) - { - hr = piBitmapFrame->Commit(); - } - - if (SUCCEEDED(hr)) - { - hr = piEncoder->Commit(); - } - - if (piFactory) - piFactory->Release(); - - if (piBitmapFrame) - piBitmapFrame->Release(); - - if (piEncoder) - piEncoder->Release(); - - if (piStream) - piStream->Release(); - - return hr; -} - void ReplaceRGBATexture2D(ID3D11Texture2D* pTexture, const u8* buffer, unsigned int width, unsigned int height, unsigned int pitch, unsigned int level, D3D11_USAGE usage) { if (usage == D3D11_USAGE_DYNAMIC || usage == D3D11_USAGE_STAGING) diff --git a/Source/Core/VideoBackends/D3D/Src/D3DTexture.h b/Source/Core/VideoBackends/D3D/Src/D3DTexture.h index d047d3f249..5c2aa57f4a 100644 --- a/Source/Core/VideoBackends/D3D/Src/D3DTexture.h +++ b/Source/Core/VideoBackends/D3D/Src/D3DTexture.h @@ -11,7 +11,6 @@ namespace DX11 namespace D3D { - HRESULT TextureToPng(D3D11_MAPPED_SUBRESOURCE& map, LPCWSTR wzFilename, int width, int height, bool saveAlpha = true); void ReplaceRGBATexture2D(ID3D11Texture2D* pTexture, const u8* buffer, unsigned int width, unsigned int height, unsigned int pitch, unsigned int level, D3D11_USAGE usage); } diff --git a/Source/Core/VideoBackends/D3D/Src/FramebufferManager.cpp b/Source/Core/VideoBackends/D3D/Src/FramebufferManager.cpp index 973cf38181..e010068bce 100644 --- a/Source/Core/VideoBackends/D3D/Src/FramebufferManager.cpp +++ b/Source/Core/VideoBackends/D3D/Src/FramebufferManager.cpp @@ -180,7 +180,7 @@ void FramebufferManager::GetTargetSize(unsigned int *width, unsigned int *height } void XFBSource::Draw(const MathUtil::Rectangle &sourcerc, - const MathUtil::Rectangle &drawrc, int width, int height) const + const MathUtil::Rectangle &drawrc) const { D3D::drawShadedTexSubQuad(tex->GetSRV(), &sourcerc, texWidth, texHeight, &drawrc, PixelShaderCache::GetColorCopyProgram(false), diff --git a/Source/Core/VideoBackends/D3D/Src/FramebufferManager.h b/Source/Core/VideoBackends/D3D/Src/FramebufferManager.h index 2b14ec2b66..abd2b27368 100644 --- a/Source/Core/VideoBackends/D3D/Src/FramebufferManager.h +++ b/Source/Core/VideoBackends/D3D/Src/FramebufferManager.h @@ -51,7 +51,7 @@ struct XFBSource : public XFBSourceBase ~XFBSource() { tex->Release(); } void Draw(const MathUtil::Rectangle &sourcerc, - const MathUtil::Rectangle &drawrc, int width, int height) const; + const MathUtil::Rectangle &drawrc) const; void DecodeToTexture(u32 xfbAddr, u32 fbWidth, u32 fbHeight); void CopyEFB(float Gamma); diff --git a/Source/Core/VideoBackends/D3D/Src/Render.cpp b/Source/Core/VideoBackends/D3D/Src/Render.cpp index 33528359c5..a84010c70f 100644 --- a/Source/Core/VideoBackends/D3D/Src/Render.cpp +++ b/Source/Core/VideoBackends/D3D/Src/Render.cpp @@ -34,6 +34,7 @@ #include "FPSCounter.h" #include "ConfigManager.h" #include +#include "ImageWrite.h" namespace DX11 { @@ -693,11 +694,12 @@ bool Renderer::SaveScreenshot(const std::string &filename, const TargetRectangle D3D11_MAPPED_SUBRESOURCE map; D3D::context->Map(s_screenshot_texture, 0, D3D11_MAP_READ_WRITE, 0, &map); - // ready to be saved - HRESULT hr = D3D::TextureToPng(map, UTF8ToUTF16(filename.c_str()).c_str(), rc.GetWidth(), rc.GetHeight(), false); + bool saved_png = TextureToPng((u8*)map.pData, map.RowPitch, filename, rc.GetWidth(), rc.GetHeight(), false); + D3D::context->Unmap(s_screenshot_texture, 0); - if (SUCCEEDED(hr)) + + if (saved_png) { OSD::AddMessage(StringFromFormat("Saved %i x %i %s", rc.GetWidth(), rc.GetHeight(), filename.c_str())); @@ -707,7 +709,7 @@ bool Renderer::SaveScreenshot(const std::string &filename, const TargetRectangle OSD::AddMessage(StringFromFormat("Error saving %s", filename.c_str())); } - return SUCCEEDED(hr); + return saved_png; } void formatBufferDump(const u8* in, u8* out, int w, int h, int p) @@ -830,7 +832,7 @@ void Renderer::Swap(u32 xfbAddr, u32 fbWidth, u32 fbHeight,const EFBRectangle& r //drawRc.right *= hScale; } - xfbSource->Draw(sourceRc, drawRc, 0, 0); + xfbSource->Draw(sourceRc, drawRc); } } else diff --git a/Source/Core/VideoBackends/D3D/Src/TextureCache.cpp b/Source/Core/VideoBackends/D3D/Src/TextureCache.cpp index 9d1e28b9b0..27bee7240e 100644 --- a/Source/Core/VideoBackends/D3D/Src/TextureCache.cpp +++ b/Source/Core/VideoBackends/D3D/Src/TextureCache.cpp @@ -14,12 +14,13 @@ #include "PSTextureEncoder.h" #include "HW/Memmap.h" #include "VideoConfig.h" +#include "ImageWrite.h" namespace DX11 { static TextureEncoder* g_encoder = NULL; -const size_t MAX_COPY_BUFFERS = 25; +const size_t MAX_COPY_BUFFERS = 32; ID3D11Buffer* efbcopycbuf[MAX_COPY_BUFFERS] = { 0 }; TextureCache::TCacheEntry::~TCacheEntry() @@ -32,7 +33,7 @@ void TextureCache::TCacheEntry::Bind(unsigned int stage) D3D::context->PSSetShaderResources(stage, 1, &texture->GetSRV()); } -bool TextureCache::TCacheEntry::Save(const char filename[], unsigned int level) +bool TextureCache::TCacheEntry::Save(const std::string filename, unsigned int level) { // TODO: Somehow implement this (D3DX11 doesn't support dumping individual LODs) static bool warn_once = true; @@ -54,6 +55,8 @@ bool TextureCache::TCacheEntry::Save(const char filename[], unsigned int level) HRESULT hr = D3D::device->CreateTexture2D(&desc, NULL, &pNewTexture); + bool saved_png = false; + if (SUCCEEDED(hr) && pNewTexture) { D3D::context->CopyResource(pNewTexture, pSurface); @@ -62,13 +65,13 @@ bool TextureCache::TCacheEntry::Save(const char filename[], unsigned int level) HRESULT hr = D3D::context->Map(pNewTexture, 0, D3D11_MAP_READ_WRITE, 0, &map); if (SUCCEEDED(hr)) { - hr = D3D::TextureToPng(map, UTF8ToUTF16(filename).c_str(), desc.Width, desc.Height); + saved_png = TextureToPng((u8*)map.pData, map.RowPitch, filename, desc.Width, desc.Height); D3D::context->Unmap(pNewTexture, 0); } SAFE_RELEASE(pNewTexture); } - return SUCCEEDED(hr); + return saved_png; } void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height, diff --git a/Source/Core/VideoBackends/D3D/Src/TextureCache.h b/Source/Core/VideoBackends/D3D/Src/TextureCache.h index 94adfe8cce..91603bc56d 100644 --- a/Source/Core/VideoBackends/D3D/Src/TextureCache.h +++ b/Source/Core/VideoBackends/D3D/Src/TextureCache.h @@ -36,7 +36,7 @@ private: const float *colmat); void Bind(unsigned int stage); - bool Save(const char filename[], unsigned int level); + bool Save(const std::string filename, unsigned int level); }; TCacheEntryBase* CreateTexture(unsigned int width, unsigned int height, diff --git a/Source/Core/VideoBackends/OGL/Src/FramebufferManager.cpp b/Source/Core/VideoBackends/OGL/Src/FramebufferManager.cpp index 081c5e71d0..1530016336 100644 --- a/Source/Core/VideoBackends/OGL/Src/FramebufferManager.cpp +++ b/Source/Core/VideoBackends/OGL/Src/FramebufferManager.cpp @@ -66,15 +66,6 @@ FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int ms // alpha channel should be ignored if the EFB does not have one. // Create EFB target. - u32 depthType; - if (DriverDetails::HasBug(DriverDetails::BUG_ISTEGRA)) - { - depthType = GL_DEPTH_COMPONENT; - } - else - { - depthType = GL_DEPTH_COMPONENT24; - } glGenFramebuffers(1, &m_efbFramebuffer); glActiveTexture(GL_TEXTURE0 + 9); @@ -94,7 +85,7 @@ FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int ms glBindTexture(getFbType(), m_efbDepth); glTexParameteri(getFbType(), GL_TEXTURE_MAX_LEVEL, 0); - glTexImage2D(getFbType(), 0, depthType, m_targetWidth, m_targetHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL); + glTexImage2D(getFbType(), 0, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL); glBindTexture(getFbType(), m_resolvedColorTexture); glTexParameteri(getFbType(), GL_TEXTURE_MAX_LEVEL, 0); @@ -159,7 +150,7 @@ FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int ms glBindTexture(getFbType(), m_resolvedDepthTexture); glTexParameteri(getFbType(), GL_TEXTURE_MAX_LEVEL, 0); - glTexImage2D(getFbType(), 0, depthType, m_targetWidth, m_targetHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL); + glTexImage2D(getFbType(), 0, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL); // Bind resolved textures to resolved framebuffer. @@ -235,13 +226,8 @@ FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int ms " ocol0 = float4(dst6) / 63.f;\n" "}"; - if(g_ogl_config.eSupportedGLSLVersion != GLSLES2) - { - // HACK: This shaders aren't glsles2 compatible as glsles2 don't support bit operations - // it could be workaround by floor + frac + tons off additions, but I think it isn't worth - ProgramShaderCache::CompileShader(m_pixel_format_shaders[0], vs, ps_rgb8_to_rgba6); - ProgramShaderCache::CompileShader(m_pixel_format_shaders[1], vs, ps_rgba6_to_rgb8); - } + ProgramShaderCache::CompileShader(m_pixel_format_shaders[0], vs, ps_rgb8_to_rgba6); + ProgramShaderCache::CompileShader(m_pixel_format_shaders[1], vs, ps_rgba6_to_rgb8); } FramebufferManager::~FramebufferManager() @@ -372,19 +358,6 @@ GLuint FramebufferManager::ResolveAndGetDepthTarget(const EFBRectangle &source_r void FramebufferManager::ReinterpretPixelData(unsigned int convtype) { - if(g_ogl_config.eSupportedGLSLVersion == GLSLES2) { - // This feature isn't supported by glsles2 - - // TODO: move this to InitBackendInfo - // We have to disable both the active and the stored config. Else we - // would either - // show this line per format change in one frame or - // once per frame. - OSD::AddMessage("Format Change Emulation isn't supported by your GPU.", 10000); - g_ActiveConfig.bEFBEmulateFormatChanges = false; - g_Config.bEFBEmulateFormatChanges = false; - return; - } g_renderer->ResetAPIState(); GLuint src_texture = 0; @@ -433,7 +406,7 @@ XFBSource::~XFBSource() void XFBSource::Draw(const MathUtil::Rectangle &sourcerc, - const MathUtil::Rectangle &drawrc, int width, int height) const + const MathUtil::Rectangle &drawrc) const { // Texture map xfbSource->texture onto the main buffer glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); diff --git a/Source/Core/VideoBackends/OGL/Src/FramebufferManager.h b/Source/Core/VideoBackends/OGL/Src/FramebufferManager.h index 47c8b2048d..7b93b239ae 100644 --- a/Source/Core/VideoBackends/OGL/Src/FramebufferManager.h +++ b/Source/Core/VideoBackends/OGL/Src/FramebufferManager.h @@ -52,7 +52,7 @@ struct XFBSource : public XFBSourceBase void CopyEFB(float Gamma) override; void DecodeToTexture(u32 xfbAddr, u32 fbWidth, u32 fbHeight) override; void Draw(const MathUtil::Rectangle &sourcerc, - const MathUtil::Rectangle &drawrc, int width, int height) const override; + const MathUtil::Rectangle &drawrc) const override; const GLuint texture; }; diff --git a/Source/Core/VideoBackends/OGL/Src/GLFunctions.cpp b/Source/Core/VideoBackends/OGL/Src/GLFunctions.cpp index 6ff264aebe..c91908ea11 100644 --- a/Source/Core/VideoBackends/OGL/Src/GLFunctions.cpp +++ b/Source/Core/VideoBackends/OGL/Src/GLFunctions.cpp @@ -72,67 +72,42 @@ namespace GLFunc self = dlopen(NULL, RTLD_LAZY); LoadFunction("glUnmapBuffer", (void**)&glUnmapBuffer); + LoadFunction("glBeginQuery", (void**)&glBeginQuery); + LoadFunction("glEndQuery", (void**)&glEndQuery); + LoadFunction("glGetQueryObjectuiv", (void**)&glGetQueryObjectuiv); + LoadFunction("glDeleteQueries", (void**)&glDeleteQueries); + LoadFunction("glGenQueries", (void**)&glGenQueries); - if (DriverDetails::HasBug(DriverDetails::BUG_ISTEGRA)) - { - LoadFunction("glBeginQueryEXT", (void**)&glBeginQuery); - LoadFunction("glEndQueryEXT", (void**)&glEndQuery); - LoadFunction("glGetQueryObjectuivEXT", (void**)&glGetQueryObjectuiv); - LoadFunction("glDeleteQueriesEXT", (void**)&glDeleteQueries); - LoadFunction("glGenQueriesEXT", (void**)&glGenQueries); + LoadFunction("glMapBufferRange", (void**)&glMapBufferRange); + LoadFunction("glBindBufferRange", (void**)&glBindBufferRange); + LoadFunction("glBlitFramebuffer", (void**)&glBlitFramebuffer); - LoadFunction("glMapBufferRangeNV", (void**)&glMapBufferRange); - LoadFunction("glBindBufferRangeNV", (void**)&glBindBufferRange); - LoadFunction("glBlitFramebufferNV", (void**)&glBlitFramebuffer); + LoadFunction("glGenVertexArrays", (void**)&glGenVertexArrays); + LoadFunction("glDeleteVertexArrays", (void**)&glDeleteVertexArrays); + LoadFunction("glBindVertexArray", (void**)&glBindVertexArray); - LoadFunction("glGenVertexArraysOES", (void**)&glGenVertexArrays); - LoadFunction("glDeleteVertexArraysOES", (void**)&glDeleteVertexArrays); - LoadFunction("glBindVertexArrayOES", (void**)&glBindVertexArray); + LoadFunction("glClientWaitSync", (void**)&glClientWaitSync); + LoadFunction("glDeleteSync", (void**)&glDeleteSync); + LoadFunction("glFenceSync", (void**)&glFenceSync); - LoadFunction("glRenderbufferStorageMultisampleNV", (void**)&glRenderbufferStorageMultisample); + LoadFunction("glSamplerParameterf", (void**)&glSamplerParameterf); + LoadFunction("glSamplerParameteri", (void**)&glSamplerParameteri); + LoadFunction("glSamplerParameterfv", (void**)&glSamplerParameterfv); + LoadFunction("glBindSampler", (void**)&glBindSampler); + LoadFunction("glDeleteSamplers", (void**)&glDeleteSamplers); + LoadFunction("glGenSamplers", (void**)&glGenSamplers); - LoadFunction("glGetUniformBlockIndexNV", (void**)&glGetUniformBlockIndex); - LoadFunction("glUniformBlockBindingNV", (void**)&glUniformBlockBinding); - } - else - { - LoadFunction("glBeginQuery", (void**)&glBeginQuery); - LoadFunction("glEndQuery", (void**)&glEndQuery); - LoadFunction("glGetQueryObjectuiv", (void**)&glGetQueryObjectuiv); - LoadFunction("glDeleteQueries", (void**)&glDeleteQueries); - LoadFunction("glGenQueries", (void**)&glGenQueries); + LoadFunction("glGetProgramBinary", (void**)&glGetProgramBinary); + LoadFunction("glProgramBinary", (void**)&glProgramBinary); + LoadFunction("glProgramParameteri", (void**)&glProgramParameteri); - LoadFunction("glMapBufferRange", (void**)&glMapBufferRange); - LoadFunction("glBindBufferRange", (void**)&glBindBufferRange); - LoadFunction("glBlitFramebuffer", (void**)&glBlitFramebuffer); + LoadFunction("glDrawRangeElements", (void**)&glDrawRangeElements); - LoadFunction("glGenVertexArrays", (void**)&glGenVertexArrays); - LoadFunction("glDeleteVertexArrays", (void**)&glDeleteVertexArrays); - LoadFunction("glBindVertexArray", (void**)&glBindVertexArray); + LoadFunction("glRenderbufferStorageMultisample", (void**)&glRenderbufferStorageMultisample); - LoadFunction("glClientWaitSync", (void**)&glClientWaitSync); - LoadFunction("glDeleteSync", (void**)&glDeleteSync); - LoadFunction("glFenceSync", (void**)&glFenceSync); + LoadFunction("glGetUniformBlockIndex", (void**)&glGetUniformBlockIndex); + LoadFunction("glUniformBlockBinding", (void**)&glUniformBlockBinding); - LoadFunction("glSamplerParameterf", (void**)&glSamplerParameterf); - LoadFunction("glSamplerParameteri", (void**)&glSamplerParameteri); - LoadFunction("glSamplerParameterfv", (void**)&glSamplerParameterfv); - LoadFunction("glBindSampler", (void**)&glBindSampler); - LoadFunction("glDeleteSamplers", (void**)&glDeleteSamplers); - LoadFunction("glGenSamplers", (void**)&glGenSamplers); - - LoadFunction("glGetProgramBinary", (void**)&glGetProgramBinary); - LoadFunction("glProgramBinary", (void**)&glProgramBinary); - LoadFunction("glProgramParameteri", (void**)&glProgramParameteri); - - LoadFunction("glDrawRangeElements", (void**)&glDrawRangeElements); - - LoadFunction("glRenderbufferStorageMultisample", (void**)&glRenderbufferStorageMultisample); - - LoadFunction("glGetUniformBlockIndex", (void**)&glGetUniformBlockIndex); - LoadFunction("glUniformBlockBinding", (void**)&glUniformBlockBinding); - - } dlclose(self); } } diff --git a/Source/Core/VideoBackends/OGL/Src/ProgramShaderCache.cpp b/Source/Core/VideoBackends/OGL/Src/ProgramShaderCache.cpp index cc807b7952..f998c6ced2 100644 --- a/Source/Core/VideoBackends/OGL/Src/ProgramShaderCache.cpp +++ b/Source/Core/VideoBackends/OGL/Src/ProgramShaderCache.cpp @@ -571,12 +571,12 @@ void ProgramShaderCache::CreateHeader ( void ) "%s\n" // ubo "%s\n" // early-z - // Precision defines for GLSLES2/3 + // Precision defines for GLSLES3 "%s\n" "\n"// A few required defines and ones that will make our lives a lot easier - "#define ATTRIN %s\n" - "#define ATTROUT %s\n" + "#define ATTRIN in\n" + "#define ATTROUT out\n" "#define VARYIN %s\n" "#define VARYOUT %s\n" @@ -594,40 +594,18 @@ void ProgramShaderCache::CreateHeader ( void ) "%s\n" "%s\n" - // GLSLES2 hacks - "%s\n" - "%s\n" - "%s\n" - "%s\n" - "%s\n" - "%s\n" - "%s\n" - "#define COLOROUT(name) %s\n" - - - , v==GLSLES2 ? "" : v==GLSLES3 ? "#version 300 es" : v==GLSL_130 ? "#version 130" : v==GLSL_140 ? "#version 140" : "#version 150" + , v==GLSLES3 ? "#version 300 es" : v==GLSL_130 ? "#version 130" : v==GLSL_140 ? "#version 140" : "#version 150" , g_ActiveConfig.backend_info.bSupportsGLSLUBO && v -#endif - // glew1.8 doesn't define KHR_debug #ifndef GL_DEBUG_OUTPUT #define GL_DEBUG_OUTPUT 0x92E0 @@ -78,18 +74,6 @@ void VideoConfig::UpdateProjectionHack() ::UpdateProjectionHack(g_Config.iPhackvalue, g_Config.sPhackvalue); } - -#if defined(HAVE_WX) && HAVE_WX -// Screenshot thread struct -typedef struct -{ - int W, H; - std::string filename; - wxImage *img; -} ScrStrct; -#endif - - int OSDInternalW, OSDInternalH; namespace OGL @@ -387,10 +371,7 @@ Renderer::Renderer() g_ogl_config.bSupportSampleShading = false; g_ogl_config.bSupportOGL31 = false; g_ogl_config.bSupportViewportFloat = false; - if (DriverDetails::HasBug(DriverDetails::BUG_ISTEGRA) || DriverDetails::HasBug(DriverDetails::BUG_ISPOWERVR)) - g_ogl_config.eSupportedGLSLVersion = GLSLES2; - else - g_ogl_config.eSupportedGLSLVersion = GLSLES3; + g_ogl_config.eSupportedGLSLVersion = GLSLES3; #else #ifdef __APPLE__ glewExperimental = 1; @@ -485,19 +466,23 @@ Renderer::Renderer() } - g_Config.backend_info.bSupportsDualSourceBlend = GLEW_ARB_blend_func_extended; - g_Config.backend_info.bSupportsGLSLUBO = GLEW_ARB_uniform_buffer_object; - g_Config.backend_info.bSupportsPrimitiveRestart = GLEW_VERSION_3_1 || GLEW_NV_primitive_restart; - g_Config.backend_info.bSupportsEarlyZ = GLEW_ARB_shader_image_load_store; +#define TO_BOOL(c) (0 != (c)) - g_ogl_config.bSupportsGLSLCache = GLEW_ARB_get_program_binary; - g_ogl_config.bSupportsGLPinnedMemory = GLEW_AMD_pinned_memory; - g_ogl_config.bSupportsGLSync = GLEW_ARB_sync; - g_ogl_config.bSupportsGLBaseVertex = GLEW_ARB_draw_elements_base_vertex; - g_ogl_config.bSupportCoverageMSAA = GLEW_NV_framebuffer_multisample_coverage; - g_ogl_config.bSupportSampleShading = GLEW_ARB_sample_shading; - g_ogl_config.bSupportOGL31 = GLEW_VERSION_3_1; - g_ogl_config.bSupportViewportFloat = GLEW_ARB_viewport_array; + g_Config.backend_info.bSupportsDualSourceBlend = TO_BOOL(GLEW_ARB_blend_func_extended); + g_Config.backend_info.bSupportsGLSLUBO = TO_BOOL(GLEW_ARB_uniform_buffer_object); + g_Config.backend_info.bSupportsPrimitiveRestart = TO_BOOL(GLEW_VERSION_3_1) || TO_BOOL(GLEW_NV_primitive_restart); + g_Config.backend_info.bSupportsEarlyZ = TO_BOOL(GLEW_ARB_shader_image_load_store); + + g_ogl_config.bSupportsGLSLCache = TO_BOOL(GLEW_ARB_get_program_binary); + g_ogl_config.bSupportsGLPinnedMemory = TO_BOOL(GLEW_AMD_pinned_memory); + g_ogl_config.bSupportsGLSync = TO_BOOL(GLEW_ARB_sync); + g_ogl_config.bSupportsGLBaseVertex = TO_BOOL(GLEW_ARB_draw_elements_base_vertex); + g_ogl_config.bSupportCoverageMSAA = TO_BOOL(GLEW_NV_framebuffer_multisample_coverage); + g_ogl_config.bSupportSampleShading = TO_BOOL(GLEW_ARB_sample_shading); + g_ogl_config.bSupportOGL31 = TO_BOOL(GLEW_VERSION_3_1); + g_ogl_config.bSupportViewportFloat = TO_BOOL(GLEW_ARB_viewport_array); + +#undef TO_BOOL if(strstr(g_ogl_config.glsl_version, "1.00") || strstr(g_ogl_config.glsl_version, "1.10") || strstr(g_ogl_config.glsl_version, "1.20")) { @@ -1391,7 +1376,7 @@ void Renderer::Swap(u32 xfbAddr, u32 fbWidth, u32 fbHeight,const EFBRectangle& r sourceRc.top = xfbSource->sourceRc.top; sourceRc.bottom = xfbSource->sourceRc.bottom; - xfbSource->Draw(sourceRc, drawRc, 0, 0); + xfbSource->Draw(sourceRc, drawRc); } } else @@ -1639,7 +1624,7 @@ void Renderer::Swap(u32 xfbAddr, u32 fbWidth, u32 fbHeight,const EFBRectangle& r // For testing zbuffer targets. // Renderer::SetZBufferRender(); - // SaveTexture("tex.tga", GL_TEXTURE_2D, s_FakeZTarget, + // SaveTexture("tex.png", GL_TEXTURE_2D, s_FakeZTarget, // GetTargetWidth(), GetTargetHeight()); Core::Callback_VideoCopiedToXFB(XFBWrited || (g_ActiveConfig.bUseXFB && g_ActiveConfig.bUseRealXFB)); XFBWrited = false; @@ -1800,69 +1785,21 @@ void Renderer::SetInterlacingMode() // TODO } -void Renderer::FlipImageData(u8 *data, int w, int h) +void Renderer::FlipImageData(u8 *data, int w, int h, int pixel_width) { // Flip image upside down. Damn OpenGL. - for (int y = 0; y < h / 2; y++) + for (int y = 0; y < h / 2; ++y) { - for(int x = 0; x < w; x++) + for(int x = 0; x < w; ++x) { - std::swap(data[(y * w + x) * 3], data[((h - 1 - y) * w + x) * 3]); - std::swap(data[(y * w + x) * 3 + 1], data[((h - 1 - y) * w + x) * 3 + 1]); - std::swap(data[(y * w + x) * 3 + 2], data[((h - 1 - y) * w + x) * 3 + 2]); + for (auto delta = 0; delta < pixel_width; ++delta) + std::swap(data[(y * w + x) * pixel_width + delta], data[((h - 1 - y) * w + x) * pixel_width + delta]); } } } } -// TODO: remove -extern bool g_aspect_wide; - -#if defined(HAVE_WX) && HAVE_WX -void TakeScreenshot(ScrStrct* threadStruct) -{ - // These will contain the final image size - float FloatW = (float)threadStruct->W; - float FloatH = (float)threadStruct->H; - - // Handle aspect ratio for the final ScrStrct to look exactly like what's on screen. - if (g_ActiveConfig.iAspectRatio != ASPECT_STRETCH) - { - bool use16_9 = g_aspect_wide; - - // Check for force-settings and override. - if (g_ActiveConfig.iAspectRatio == ASPECT_FORCE_16_9) - use16_9 = true; - else if (g_ActiveConfig.iAspectRatio == ASPECT_FORCE_4_3) - use16_9 = false; - - float Ratio = (FloatW / FloatH) / (!use16_9 ? (4.0f / 3.0f) : (16.0f / 9.0f)); - - // If ratio > 1 the picture is too wide and we have to limit the width. - if (Ratio > 1) - FloatW /= Ratio; - // ratio == 1 or the image is too high, we have to limit the height. - else - FloatH *= Ratio; - - // This is a bit expensive on high resolutions - threadStruct->img->Rescale((int)FloatW, (int)FloatH, wxIMAGE_QUALITY_HIGH); - } - - // Save the screenshot and finally kill the wxImage object - // This is really expensive when saving to PNG, but not at all when using BMP - threadStruct->img->SaveFile(StrToWxStr(threadStruct->filename), - wxBITMAP_TYPE_PNG); - threadStruct->img->Destroy(); - - // Show success messages - OSD::AddMessage(StringFromFormat("Saved %i x %i %s", (int)FloatW, (int)FloatH, - threadStruct->filename.c_str()), 2000); - delete threadStruct; -} -#endif - namespace OGL { @@ -1870,48 +1807,26 @@ bool Renderer::SaveScreenshot(const std::string &filename, const TargetRectangle { u32 W = back_rc.GetWidth(); u32 H = back_rc.GetHeight(); - u8 *data = (u8 *)malloc((sizeof(u8) * 3 * W * H)); + u8 *data = new u8[W * 4 * H]; glPixelStorei(GL_PACK_ALIGNMENT, 1); - glReadPixels(back_rc.left, back_rc.bottom, W, H, GL_RGB, GL_UNSIGNED_BYTE, data); + glReadPixels(back_rc.left, back_rc.bottom, W, H, GL_RGBA, GL_UNSIGNED_BYTE, data); // Show failure message if (GL_REPORT_ERROR() != GL_NO_ERROR) { - free(data); + delete[] data; OSD::AddMessage("Error capturing or saving screenshot.", 2000); return false; } // Turn image upside down - FlipImageData(data, W, H); + FlipImageData(data, W, H, 4); + bool success = TextureToPng(data, W*4, filename, W, H, false); + delete[] data; -#if defined(HAVE_WX) && HAVE_WX - // Create wxImage - wxImage *a = new wxImage(W, H, data); + return success; - if (scrshotThread.joinable()) - scrshotThread.join(); - - ScrStrct *threadStruct = new ScrStrct; - threadStruct->filename = filename; - threadStruct->img = a; - threadStruct->H = H; threadStruct->W = W; - - scrshotThread = std::thread(TakeScreenshot, threadStruct); -#ifdef _WIN32 - SetThreadPriority(scrshotThread.native_handle(), THREAD_PRIORITY_BELOW_NORMAL); -#endif - bool result = true; - - OSD::AddMessage("Saving Screenshot... ", 2000); - -#else - bool result = SaveTGA(filename.c_str(), W, H, data); - free(data); -#endif - - return result; } } diff --git a/Source/Core/VideoBackends/OGL/Src/Render.h b/Source/Core/VideoBackends/OGL/Src/Render.h index 9b4838ee25..9489d5c7ac 100644 --- a/Source/Core/VideoBackends/OGL/Src/Render.h +++ b/Source/Core/VideoBackends/OGL/Src/Render.h @@ -13,7 +13,6 @@ enum GLSL_VERSION { GLSL_130, GLSL_140, GLSL_150, // and above - GLSLES2, GLSLES3 }; @@ -63,7 +62,7 @@ public: void RenderText(const char* pstr, int left, int top, u32 color) override; void DrawDebugInfo(); - void FlipImageData(u8 *data, int w, int h); + void FlipImageData(u8 *data, int w, int h, int pixel_width = 3); u32 AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data) override; diff --git a/Source/Core/VideoBackends/OGL/Src/SamplerCache.cpp b/Source/Core/VideoBackends/OGL/Src/SamplerCache.cpp index 8419777fae..2b50652ade 100644 --- a/Source/Core/VideoBackends/OGL/Src/SamplerCache.cpp +++ b/Source/Core/VideoBackends/OGL/Src/SamplerCache.cpp @@ -16,14 +16,11 @@ SamplerCache::SamplerCache() SamplerCache::~SamplerCache() { - if (!DriverDetails::HasBug(DriverDetails::BUG_ISTEGRA)) - Clear(); + Clear(); } void SamplerCache::SetSamplerState(int stage, const TexMode0& tm0, const TexMode1& tm1) { - if (DriverDetails::HasBug(DriverDetails::BUG_ISTEGRA)) - return; // TODO: can this go somewhere else? if (m_last_max_anisotropy != g_ActiveConfig.iMaxAnisotropy) { diff --git a/Source/Core/VideoBackends/OGL/Src/StreamBuffer.cpp b/Source/Core/VideoBackends/OGL/Src/StreamBuffer.cpp index 9826033098..f6630c0d09 100644 --- a/Source/Core/VideoBackends/OGL/Src/StreamBuffer.cpp +++ b/Source/Core/VideoBackends/OGL/Src/StreamBuffer.cpp @@ -40,7 +40,7 @@ StreamBuffer::StreamBuffer(u32 type, size_t size, StreamType uploadType) m_uploadtype = BUFFERDATA; else if(g_ogl_config.bSupportsGLSync && g_ActiveConfig.bHackedBufferUpload && (m_uploadtype & MAP_AND_RISK)) m_uploadtype = MAP_AND_RISK; - else if(g_ogl_config.bSupportsGLSync && g_ogl_config.bSupportsGLPinnedMemory && (!DriverDetails::HasBug(DriverDetails::BUG_BROKENPINNEDMEMORY) || type != GL_ELEMENT_ARRAY_BUFFER) && (m_uploadtype & PINNED_MEMORY)) + else if(g_ogl_config.bSupportsGLSync && g_ogl_config.bSupportsGLPinnedMemory && !(DriverDetails::HasBug(DriverDetails::BUG_BROKENPINNEDMEMORY) && type == GL_ELEMENT_ARRAY_BUFFER) && (m_uploadtype & PINNED_MEMORY)) m_uploadtype = PINNED_MEMORY; else if(nvidia && (m_uploadtype & BUFFERSUBDATA)) m_uploadtype = BUFFERSUBDATA; @@ -59,7 +59,7 @@ StreamBuffer::~StreamBuffer() glDeleteBuffers(1, &m_buffer); } -#define SLOT(x) (x)*SYNC_POINTS/m_size +#define SLOT(x) ((x)*SYNC_POINTS/m_size) void StreamBuffer::Alloc ( size_t size, u32 stride ) { @@ -81,14 +81,14 @@ void StreamBuffer::Alloc ( size_t size, u32 stride ) case PINNED_MEMORY: // insert waiting slots for used memory - for(u32 i=SLOT(m_used_iterator); i= m_size) { // insert waiting slots in unused space at the end of the buffer - for(u32 i=SLOT(m_used_iterator); i < SYNC_POINTS; i++) + for (size_t i = SLOT(m_used_iterator); i < SYNC_POINTS; i++) + { fences[i] = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); + } // move to the start m_used_iterator = m_iterator_aligned = m_iterator = 0; // offset 0 is always aligned @@ -244,10 +246,14 @@ void StreamBuffer::Shutdown() void StreamBuffer::DeleteFences() { - for(u32 i=SLOT(m_free_iterator)+1; i < SYNC_POINTS; i++) + for (size_t i = SLOT(m_free_iterator) + 1; i < SYNC_POINTS; i++) + { glDeleteSync(fences[i]); - for(u32 i=0; i s_VBO; -bool SaveTexture(const char* filename, u32 textarget, u32 tex, int virtual_width, int virtual_height, unsigned int level) +bool SaveTexture(const std::string filename, u32 textarget, u32 tex, int virtual_width, int virtual_height, unsigned int level) { #ifndef USE_GLES3 int width = std::max(virtual_width >> level, 1); int height = std::max(virtual_height >> level, 1); - std::vector data(width * height); + u8* data = new u8[width * height * 4]; glActiveTexture(GL_TEXTURE0+9); glBindTexture(textarget, tex); - glGetTexImage(textarget, level, GL_BGRA, GL_UNSIGNED_BYTE, &data[0]); + glGetTexImage(textarget, level, GL_RGBA, GL_UNSIGNED_BYTE, data); glBindTexture(textarget, 0); TextureCache::SetStage(); @@ -75,10 +75,12 @@ bool SaveTexture(const char* filename, u32 textarget, u32 tex, int virtual_width if (GL_NO_ERROR != err) { PanicAlert("Can't save texture, GL Error: %s", gluErrorString(err)); + delete[] data; return false; } - - return SaveTGA(filename, width, height, &data[0]); + bool success = TextureToPng(data, width * 4, filename, width, height, true); + delete[] data; + return success; #else return false; #endif @@ -125,13 +127,9 @@ void TextureCache::TCacheEntry::Bind(unsigned int stage) } } -bool TextureCache::TCacheEntry::Save(const char filename[], unsigned int level) +bool TextureCache::TCacheEntry::Save(const std::string filename, unsigned int level) { - // TODO: make ogl dump PNGs - std::string tga_filename(filename); - tga_filename.replace(tga_filename.size() - 3, 3, "tga"); - - return SaveTexture(tga_filename.c_str(), GL_TEXTURE_2D, texture, virtual_width, virtual_height, level); + return SaveTexture(filename, GL_TEXTURE_2D, texture, virtual_width, virtual_height, level); } TextureCache::TCacheEntryBase* TextureCache::CreateTexture(unsigned int width, @@ -395,8 +393,8 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo if (g_ActiveConfig.bDumpEFBTarget) { static int count = 0; - SaveTexture(StringFromFormat("%sefb_frame_%i.tga", File::GetUserPath(D_DUMPTEXTURES_IDX).c_str(), - count++).c_str(), GL_TEXTURE_2D, texture, virtual_width, virtual_height, 0); + SaveTexture(StringFromFormat("%sefb_frame_%i.png", File::GetUserPath(D_DUMPTEXTURES_IDX).c_str(), + count++), GL_TEXTURE_2D, texture, virtual_width, virtual_height, 0); } g_renderer->RestoreAPIState(); diff --git a/Source/Core/VideoBackends/OGL/Src/TextureCache.h b/Source/Core/VideoBackends/OGL/Src/TextureCache.h index 1c95d35f98..af1b60bc06 100644 --- a/Source/Core/VideoBackends/OGL/Src/TextureCache.h +++ b/Source/Core/VideoBackends/OGL/Src/TextureCache.h @@ -53,7 +53,7 @@ private: const float *colmat) override; void Bind(unsigned int stage) override; - bool Save(const char filename[], unsigned int level); + bool Save(const std::string filename, unsigned int level); }; ~TextureCache(); @@ -64,7 +64,7 @@ private: TCacheEntryBase* CreateRenderTargetTexture(unsigned int scaled_tex_w, unsigned int scaled_tex_h) override; }; -bool SaveTexture(const char* filename, u32 textarget, u32 tex, int virtual_width, int virtual_height, unsigned int level); +bool SaveTexture(const std::string filename, u32 textarget, u32 tex, int virtual_width, int virtual_height, unsigned int level); } diff --git a/Source/Core/VideoBackends/OGL/Src/TextureConverter.cpp b/Source/Core/VideoBackends/OGL/Src/TextureConverter.cpp index 0c1800381e..56c1f2e484 100644 --- a/Source/Core/VideoBackends/OGL/Src/TextureConverter.cpp +++ b/Source/Core/VideoBackends/OGL/Src/TextureConverter.cpp @@ -28,8 +28,6 @@ using OGL::TextureCache; static GLuint s_texConvFrameBuffer = 0; static GLuint s_srcTexture = 0; // for decoding from RAM -static GLuint s_srcTextureWidth = 0; -static GLuint s_srcTextureHeight = 0; static GLuint s_dstTexture = 0; // for encoding to RAM const int renderBufferWidth = 1024; @@ -44,11 +42,8 @@ static SHADER s_encodingPrograms[NUM_ENCODING_PROGRAMS]; static GLuint s_encode_VBO = 0; static GLuint s_encode_VAO = 0; -static GLuint s_decode_VBO = 0; static GLuint s_decode_VAO = 0; static TargetRectangle s_cached_sourceRc; -static int s_cached_srcWidth = 0; -static int s_cached_srcHeight = 0; static const char *VProgram = "ATTRIN vec2 rawpos;\n" @@ -62,6 +57,22 @@ static const char *VProgram = void CreatePrograms() { + /* TODO: Accuracy Improvements + * + * This shader doesn't really match what the gamecube does interally in the + * copy pipeline. + * 1. It uses Opengl's built in filtering when yscaling, someone could work + * out how the copypipeline does it's filtering and implement it correctly + * in this shader. + * 2. Deflickering isn't implemented, a futher filtering over 3 lines. + * Isn't really needed on non-interlaced monitors (and would lower quality; + * But hey, accuracy!) + * 3. Flipper's YUYV conversion implements a 3 pixel horozontal blur on the + * UV channels, centering the U channel on the Left pixel and the V channel + * on the Right pixel. + * The current implementation Centers both UV channels at the same place + * inbetween the two Pixels, and only blurs over these two pixels. + */ // Output is BGRA because that is slightly faster than RGBA. const char *FProgramRgbToYuyv = "uniform sampler2DRect samp9;\n" @@ -69,8 +80,8 @@ void CreatePrograms() "COLOROUT(ocol0)\n" "void main()\n" "{\n" - " vec3 c0 = texture2DRect(samp9, uv0).rgb;\n" - " vec3 c1 = texture2DRect(samp9, uv0 + vec2(1.0, 0.0)).rgb;\n" + " vec3 c0 = texture2DRect(samp9, uv0 - dFdx(uv0) * 0.25).rgb;\n" + " vec3 c1 = texture2DRect(samp9, uv0 + dFdx(uv0) * 0.25).rgb;\n" " vec3 c01 = (c0 + c1) * 0.5;\n" " vec3 y_const = vec3(0.257,0.504,0.098);\n" " vec3 u_const = vec3(-0.148,-0.291,0.439);\n" @@ -79,15 +90,35 @@ void CreatePrograms() " ocol0 = vec4(dot(c1,y_const),dot(c01,u_const),dot(c0,y_const),dot(c01, v_const)) + const3;\n" "}\n"; + /* TODO: Accuracy Improvements + * + * The YVYU to RGB conversion here matches the RGB to YUYV done above, but + * if a game modifies or adds images to the XFB then it should be using the + * same algorithm as the flipper, and could result in slight colour inaccuracies + * when run back through this shader. + */ + const char *VProgramYuyvToRgb = + "void main()\n" + "{\n" + " vec2 rawpos = vec2(gl_VertexID&1, gl_VertexID&2);\n" + " gl_Position = vec4(rawpos*2.0-1.0, 0.0, 1.0);\n" + "}\n"; const char *FProgramYuyvToRgb = "uniform sampler2DRect samp9;\n" "VARYIN vec2 uv0;\n" "COLOROUT(ocol0)\n" "void main()\n" "{\n" - " vec4 c0 = texture2DRect(samp9, uv0).rgba;\n" - " float f = step(0.5, fract(uv0.x));\n" - " float y = mix(c0.b, c0.r, f);\n" + " ivec2 uv = ivec2(gl_FragCoord.xy);\n" +#ifdef USE_GLES3 + // We switch top/bottom here. TODO: move this to screen blit. + " ivec2 ts = textureSize(samp9, 0);\n" + " vec4 c0 = texelFetch(samp9, ivec2(uv.x/2, ts.y-uv.y-1), 0);\n" +#else + " ivec2 ts = textureSize(samp9);\n" + " vec4 c0 = texelFetch(samp9, ivec2(uv.x/2, ts.y-uv.y-1));\n" +#endif + " float y = mix(c0.b, c0.r, uv.x & 1);\n" " float yComp = 1.164 * (y - 0.0625);\n" " float uComp = c0.g - 0.5;\n" " float vComp = c0.a - 0.5;\n" @@ -98,7 +129,7 @@ void CreatePrograms() "}\n"; ProgramShaderCache::CompileShader(s_rgbToYuyvProgram, VProgram, FProgramRgbToYuyv); - ProgramShaderCache::CompileShader(s_yuyvToRgbProgram, VProgram, FProgramYuyvToRgb); + ProgramShaderCache::CompileShader(s_yuyvToRgbProgram, VProgramYuyvToRgb, FProgramYuyvToRgb); } SHADER &GetOrCreateEncodingShader(u32 format) @@ -146,19 +177,8 @@ void Init() s_cached_sourceRc.left = -1; s_cached_sourceRc.right = -1; - glGenBuffers(1, &s_decode_VBO ); glGenVertexArrays(1, &s_decode_VAO ); - glBindBuffer(GL_ARRAY_BUFFER, s_decode_VBO ); glBindVertexArray( s_decode_VAO ); - s_cached_srcWidth = -1; - s_cached_srcHeight = -1; - glEnableVertexAttribArray(SHADER_POSITION_ATTRIB); - glVertexAttribPointer(SHADER_POSITION_ATTRIB, 2, GL_FLOAT, 0, sizeof(GLfloat)*4, (GLfloat*)NULL); - glEnableVertexAttribArray(SHADER_TEXTURE0_ATTRIB); - glVertexAttribPointer(SHADER_TEXTURE0_ATTRIB, 2, GL_FLOAT, 0, sizeof(GLfloat)*4, (GLfloat*)NULL+2); - - s_srcTextureWidth = 0; - s_srcTextureHeight = 0; glActiveTexture(GL_TEXTURE0 + 9); glGenTextures(1, &s_srcTexture); @@ -180,7 +200,6 @@ void Shutdown() glDeleteFramebuffers(1, &s_texConvFrameBuffer); glDeleteBuffers(1, &s_encode_VBO ); glDeleteVertexArrays(1, &s_encode_VAO ); - glDeleteBuffers(1, &s_decode_VBO ); glDeleteVertexArrays(1, &s_decode_VAO ); s_rgbToYuyvProgram.Destroy(); @@ -347,7 +366,10 @@ void EncodeToRamYUYV(GLuint srcTexture, const TargetRectangle& sourceRc, u8* des s_rgbToYuyvProgram.Bind(); - EncodeToRamUsingShader(srcTexture, sourceRc, destAddr, dstWidth / 2, dstHeight, 0, false, false); + // We enable linear filtering, because the gamecube does filtering in the vertical direction when + // yscale is enabled. + // Otherwise we get jaggies when a game uses yscaling (most PAL games) + EncodeToRamUsingShader(srcTexture, sourceRc, destAddr, dstWidth / 2, dstHeight, 0, false, true); FramebufferManager::SetFramebuffer(0); TextureCache::DisableStage(0); g_renderer->RestoreAPIState(); @@ -365,8 +387,6 @@ void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, GLuint destTextur return; } - int srcFmtWidth = srcWidth / 2; - g_renderer->ResetAPIState(); // reset any game specific settings // switch to texture converter frame buffer @@ -380,50 +400,14 @@ void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, GLuint destTextur // set srcAddr as data for source texture glActiveTexture(GL_TEXTURE0+9); glBindTexture(getFbType(), s_srcTexture); - - // TODO: make this less slow. (How?) - if ((GLsizei)s_srcTextureWidth == (GLsizei)srcFmtWidth && (GLsizei)s_srcTextureHeight == (GLsizei)srcHeight) - { - glTexSubImage2D(getFbType(), 0,0,0,s_srcTextureWidth, s_srcTextureHeight, - GL_BGRA, GL_UNSIGNED_BYTE, srcAddr); - } - else - { - glTexImage2D(getFbType(), 0, GL_RGBA, (GLsizei)srcFmtWidth, (GLsizei)srcHeight, - 0, GL_BGRA, GL_UNSIGNED_BYTE, srcAddr); - s_srcTextureWidth = (GLsizei)srcFmtWidth; - s_srcTextureHeight = (GLsizei)srcHeight; - } + glTexImage2D(getFbType(), 0, GL_RGBA, srcWidth / 2, srcHeight, 0, GL_BGRA, GL_UNSIGNED_BYTE, srcAddr); glViewport(0, 0, srcWidth, srcHeight); s_yuyvToRgbProgram.Bind(); - GL_REPORT_ERRORD(); - - if(s_cached_srcHeight != srcHeight || s_cached_srcWidth != srcWidth) { - GLfloat vertices[] = { - 1.f, -1.f, - (float)srcFmtWidth, (float)srcHeight, - 1.f, 1.f, - (float)srcFmtWidth, 0.f, - -1.f, -1.f, - 0.f, (float)srcHeight, - -1.f, 1.f, - 0.f, 0.f - }; - - glBindBuffer(GL_ARRAY_BUFFER, s_decode_VBO ); - glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*4*4, vertices, GL_STREAM_DRAW); - - s_cached_srcHeight = srcHeight; - s_cached_srcWidth = srcWidth; - } - glBindVertexArray( s_decode_VAO ); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - GL_REPORT_ERRORD(); - FramebufferManager::SetFramebuffer(0); g_renderer->RestoreAPIState(); diff --git a/Source/Core/VideoBackends/OGL/Src/VertexManager.cpp b/Source/Core/VideoBackends/OGL/Src/VertexManager.cpp index 44d8ddeaa4..64e8f92313 100644 --- a/Source/Core/VideoBackends/OGL/Src/VertexManager.cpp +++ b/Source/Core/VideoBackends/OGL/Src/VertexManager.cpp @@ -43,8 +43,8 @@ const u32 MAX_VBUFFER_SIZE = 16*1024*1024; static StreamBuffer *s_vertexBuffer; static StreamBuffer *s_indexBuffer; -static u32 s_baseVertex; -static u32 s_offset[3]; +static size_t s_baseVertex; +static size_t s_offset[3]; VertexManager::VertexManager() { @@ -89,7 +89,7 @@ void VertexManager::PrepareDrawBuffers(u32 stride) u32 index_size = (triangle_index_size+line_index_size+point_index_size) * sizeof(u16); s_vertexBuffer->Alloc(vertex_data_size, stride); - u32 offset = s_vertexBuffer->Upload(GetVertexBuffer(), vertex_data_size); + size_t offset = s_vertexBuffer->Upload(GetVertexBuffer(), vertex_data_size); s_baseVertex = offset / stride; s_indexBuffer->Alloc(index_size); @@ -121,35 +121,17 @@ void VertexManager::Draw(u32 stride) if(g_ogl_config.bSupportsGLBaseVertex) { if (triangle_index_size > 0) { - glDrawRangeElementsBaseVertex(triangle_mode, 0, max_index, triangle_index_size, GL_UNSIGNED_SHORT, (u8*)NULL+s_offset[0], s_baseVertex); + glDrawRangeElementsBaseVertex(triangle_mode, 0, max_index, triangle_index_size, GL_UNSIGNED_SHORT, (u8*)NULL+s_offset[0], (GLint)s_baseVertex); INCSTAT(stats.thisFrame.numIndexedDrawCalls); } if (line_index_size > 0) { - glDrawRangeElementsBaseVertex(GL_LINES, 0, max_index, line_index_size, GL_UNSIGNED_SHORT, (u8*)NULL+s_offset[1], s_baseVertex); + glDrawRangeElementsBaseVertex(GL_LINES, 0, max_index, line_index_size, GL_UNSIGNED_SHORT, (u8*)NULL+s_offset[1], (GLint)s_baseVertex); INCSTAT(stats.thisFrame.numIndexedDrawCalls); } if (point_index_size > 0) { - glDrawRangeElementsBaseVertex(GL_POINTS, 0, max_index, point_index_size, GL_UNSIGNED_SHORT, (u8*)NULL+s_offset[2], s_baseVertex); - INCSTAT(stats.thisFrame.numIndexedDrawCalls); - } - } - else if (DriverDetails::HasBug(DriverDetails::BUG_ISTEGRA)) - { - if (triangle_index_size > 0) - { - glDrawElements(triangle_mode, triangle_index_size, GL_UNSIGNED_SHORT, (u8*)NULL+s_offset[0]); - INCSTAT(stats.thisFrame.numIndexedDrawCalls); - } - if (line_index_size > 0) - { - glDrawElements(GL_LINES, line_index_size, GL_UNSIGNED_SHORT, (u8*)NULL+s_offset[1]); - INCSTAT(stats.thisFrame.numIndexedDrawCalls); - } - if (point_index_size > 0) - { - glDrawElements(GL_POINTS, point_index_size, GL_UNSIGNED_SHORT, (u8*)NULL+s_offset[2]); + glDrawRangeElementsBaseVertex(GL_POINTS, 0, max_index, point_index_size, GL_UNSIGNED_SHORT, (u8*)NULL+s_offset[2], (GLint)s_baseVertex); INCSTAT(stats.thisFrame.numIndexedDrawCalls); } } else { @@ -236,9 +218,9 @@ void VertexManager::vFlush() 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.texTlut[i&3].tlut_format, - (tex.texMode0[i&3].min_filter & 3), + (0 != (tex.texMode0[i&3].min_filter & 3)), (tex.texMode1[i&3].max_lod + 0xf) / 0x10, - tex.texImage1[i&3].image_type); + (0 != tex.texImage1[i&3].image_type)); if (tentry) { @@ -335,7 +317,7 @@ void VertexManager::vFlush() if (g_ActiveConfig.iLog & CONF_SAVETARGETS) { char str[128]; - sprintf(str, "%starg%.3d.tga", File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), g_ActiveConfig.iSaveTargetId); + sprintf(str, "%starg%.3d.png", File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), g_ActiveConfig.iSaveTargetId); TargetRectangle tr; tr.left = 0; tr.right = Renderer::GetTargetWidth(); diff --git a/Source/Core/VideoBackends/Software/Src/DebugUtil.cpp b/Source/Core/VideoBackends/Software/Src/DebugUtil.cpp index 4472639a20..75c6c08ada 100644 --- a/Source/Core/VideoBackends/Software/Src/DebugUtil.cpp +++ b/Source/Core/VideoBackends/Software/Src/DebugUtil.cpp @@ -42,7 +42,7 @@ void Init() } } -void SaveTexture(const char* filename, u32 texmap, s32 mip) +void SaveTexture(const std::string filename, u32 texmap, s32 mip) { FourTexUnits& texUnit = bpmem.tex[(texmap >> 2) & 1]; u8 subTexmap = texmap & 3; @@ -54,28 +54,21 @@ void SaveTexture(const char* filename, u32 texmap, s32 mip) u8 *data = new u8[width * height * 4]; - GetTextureBGRA(data, texmap, mip, width, height); + GetTextureRGBA(data, texmap, mip, width, height); - (void)SaveTGA(filename, width, height, data); + (void)TextureToPng(data, width*4, filename, width, height, true); + delete[] data; - delete []data; } -void GetTextureBGRA(u8 *dst, u32 texmap, s32 mip, u32 width, u32 height) +void GetTextureRGBA(u8 *dst, u32 texmap, s32 mip, u32 width, u32 height) { - u8 sample[4]; - for (u32 y = 0; y < height; y++) { for (u32 x = 0; x < width; x++) { - TextureSampler::SampleMip(x << 7, y << 7, mip, false, texmap, sample); - - // RGBA to BGRA - *(dst++) = sample[2]; - *(dst++) = sample[1]; - *(dst++) = sample[0]; - *(dst++) = sample[3]; + TextureSampler::SampleMip(x << 7, y << 7, mip, false, texmap, dst); + dst += 4; } } } @@ -104,9 +97,9 @@ void DumpActiveTextures() s32 maxLod = GetMaxTextureLod(texmap); for (s32 mip = 0; mip <= maxLod; ++mip) { - SaveTexture(StringFromFormat("%star%i_ind%i_map%i_mip%i.tga", + SaveTexture(StringFromFormat("%star%i_ind%i_map%i_mip%i.png", File::GetUserPath(D_DUMPTEXTURES_IDX).c_str(), - swstats.thisFrame.numDrawnObjects, stageNum, texmap, mip).c_str(), texmap, mip); + swstats.thisFrame.numDrawnObjects, stageNum, texmap, mip), texmap, mip); } } @@ -121,14 +114,14 @@ void DumpActiveTextures() s32 maxLod = GetMaxTextureLod(texmap); for (s32 mip = 0; mip <= maxLod; ++mip) { - SaveTexture(StringFromFormat("%star%i_stage%i_map%i_mip%i.tga", + SaveTexture(StringFromFormat("%star%i_stage%i_map%i_mip%i.png", File::GetUserPath(D_DUMPTEXTURES_IDX).c_str(), - swstats.thisFrame.numDrawnObjects, stageNum, texmap, mip).c_str(), texmap, mip); + swstats.thisFrame.numDrawnObjects, stageNum, texmap, mip), texmap, mip); } } } -void DumpEfb(const char* filename) +void DumpEfb(const std::string filename) { u8 *data = new u8[EFB_WIDTH * EFB_HEIGHT * 4]; u8 *writePtr = data; @@ -139,20 +132,19 @@ void DumpEfb(const char* filename) for (int x = 0; x < EFB_WIDTH; x++) { EfbInterface::GetColor(x, y, sample); - // ABGR to BGRA - *(writePtr++) = sample[1]; - *(writePtr++) = sample[2]; + // ABGR to RGBA *(writePtr++) = sample[3]; + *(writePtr++) = sample[2]; + *(writePtr++) = sample[1]; *(writePtr++) = sample[0]; } } - (void)SaveTGA(filename, EFB_WIDTH, EFB_HEIGHT, data); - - delete []data; + (void)TextureToPng(data, EFB_WIDTH * 4, filename, EFB_WIDTH, EFB_HEIGHT, true); + delete[] data; } -void DumpDepth(const char* filename) +void DumpDepth(const std::string filename) { u8 *data = new u8[EFB_WIDTH * EFB_HEIGHT * 4]; u8 *writePtr = data; @@ -162,17 +154,16 @@ void DumpDepth(const char* filename) for (int x = 0; x < EFB_WIDTH; x++) { u32 depth = EfbInterface::GetDepth(x, y); - // depth to bgra - *(writePtr++) = (depth >> 16) & 0xff; + // depth to rgba + *(writePtr++) = depth & 0xff; *(writePtr++) = (depth >> 8) & 0xff; - *(writePtr++) = depth & 0xff; + *(writePtr++) = (depth >> 16) & 0xff; *(writePtr++) = 255; } } - (void)SaveTGA(filename, EFB_WIDTH, EFB_HEIGHT, data); - - delete []data; + (void)TextureToPng(data, EFB_WIDTH * 4, filename, EFB_WIDTH, EFB_HEIGHT, true); + delete[] data; } void DrawObjectBuffer(s16 x, s16 y, u8 *color, int bufferBase, int subBuffer, const char *name) @@ -232,9 +223,9 @@ void OnObjectEnd() if (!g_bSkipCurrentFrame) { if (g_SWVideoConfig.bDumpObjects && swstats.thisFrame.numDrawnObjects >= g_SWVideoConfig.drawStart && swstats.thisFrame.numDrawnObjects < g_SWVideoConfig.drawEnd) - DumpEfb(StringFromFormat("%sobject%i.tga", + DumpEfb(StringFromFormat("%sobject%i.png", File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), - swstats.thisFrame.numDrawnObjects).c_str()); + swstats.thisFrame.numDrawnObjects)); if (g_SWVideoConfig.bHwRasterizer || drawingHwTriangles) { @@ -247,11 +238,13 @@ void OnObjectEnd() if (DrawnToBuffer[i]) { DrawnToBuffer[i] = false; - (void)SaveTGA(StringFromFormat("%sobject%i_%s(%i).tga", - File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), - swstats.thisFrame.numDrawnObjects, ObjectBufferName[i], i - BufferBase[i]).c_str(), - EFB_WIDTH, EFB_HEIGHT, ObjectBuffer[i]); + std::string filename = StringFromFormat("%sobject%i_%s(%i).png", + File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), + swstats.thisFrame.numDrawnObjects, ObjectBufferName[i], i - BufferBase[i]); + + (void)TextureToPng((u8*)ObjectBuffer[i], EFB_WIDTH * 4, filename, EFB_WIDTH, EFB_HEIGHT, true); memset(ObjectBuffer[i], 0, sizeof(ObjectBuffer[i])); + } } @@ -265,10 +258,10 @@ void OnFrameEnd() { if (g_SWVideoConfig.bDumpFrames) { - DumpEfb(StringFromFormat("%sframe%i_color.tga", - File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), swstats.frameCount).c_str()); - DumpDepth(StringFromFormat("%sframe%i_depth.tga", - File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), swstats.frameCount).c_str()); + DumpEfb(StringFromFormat("%sframe%i_color.png", + File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), swstats.frameCount)); + DumpDepth(StringFromFormat("%sframe%i_depth.png", + File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), swstats.frameCount)); } } } diff --git a/Source/Core/VideoBackends/Software/Src/DebugUtil.h b/Source/Core/VideoBackends/Software/Src/DebugUtil.h index 3cbb318ffb..7d5ac4beea 100644 --- a/Source/Core/VideoBackends/Software/Src/DebugUtil.h +++ b/Source/Core/VideoBackends/Software/Src/DebugUtil.h @@ -9,7 +9,7 @@ namespace DebugUtil { void Init(); - void GetTextureBGRA(u8 *dst, u32 texmap, s32 mip, u32 width, u32 height); + void GetTextureRGBA(u8 *dst, u32 texmap, s32 mip, u32 width, u32 height); void DumpActiveTextures(); diff --git a/Source/Core/VideoBackends/Software/Src/HwRasterizer.cpp b/Source/Core/VideoBackends/Software/Src/HwRasterizer.cpp index 996b440dc4..88b3e15ebd 100644 --- a/Source/Core/VideoBackends/Software/Src/HwRasterizer.cpp +++ b/Source/Core/VideoBackends/Software/Src/HwRasterizer.cpp @@ -329,15 +329,12 @@ namespace HwRasterizer int image_width = texImage0.width; int image_height = texImage0.height; - DebugUtil::GetTextureBGRA(temp, 0, 0, image_width, image_height); + DebugUtil::GetTextureRGBA(temp, 0, 0, image_width, image_height); glGenTextures(1, (GLuint *)&texture); glBindTexture(TEX2D, texture); -#ifdef USE_GLES glTexImage2D(TEX2D, 0, GL_RGBA, (GLsizei)image_width, (GLsizei)image_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, temp); -#else - glTexImage2D(TEX2D, 0, GL_RGBA8, (GLsizei)image_width, (GLsizei)image_height, 0, GL_BGRA, GL_UNSIGNED_BYTE, temp); -#endif + GL_REPORT_ERRORD(); } diff --git a/Source/Core/VideoBackends/Software/Src/SWRenderer.cpp b/Source/Core/VideoBackends/Software/Src/SWRenderer.cpp index 1d894b18da..069ca5eebc 100644 --- a/Source/Core/VideoBackends/Software/Src/SWRenderer.cpp +++ b/Source/Core/VideoBackends/Software/Src/SWRenderer.cpp @@ -5,6 +5,7 @@ #include "Common.h" #include "../../OGL/Src/GLUtil.h" +#include "ImageWrite.h" #include "RasterFont.h" #include "SWRenderer.h" #include "SWStatistics.h" @@ -17,6 +18,11 @@ static GLint attr_pos = -1, attr_tex = -1; static GLint uni_tex = -1; static GLuint program; +static volatile bool s_bScreenshot; +static std::mutex s_criticalScreenshot; +static std::string s_sScreenshotName; + + // Rasterfont isn't compatible with GLES // degasus: I think it does, but I can't test it #ifndef USE_GLES @@ -25,6 +31,7 @@ RasterFont* s_pfont = NULL; void SWRenderer::Init() { + s_bScreenshot = false; } void SWRenderer::Shutdown() @@ -80,6 +87,13 @@ void SWRenderer::Prepare() GL_REPORT_ERRORD(); } +void SWRenderer::SetScreenshot(const char *_szFilename) +{ + std::lock_guard lk(s_criticalScreenshot); + s_sScreenshotName = _szFilename; + s_bScreenshot = true; +} + void SWRenderer::RenderText(const char* pstr, int left, int top, u32 color) { #ifndef USE_GLES @@ -124,6 +138,15 @@ void SWRenderer::DrawDebugText() void SWRenderer::DrawTexture(u8 *texture, int width, int height) { + // Save screenshot + if (s_bScreenshot) + { + std::lock_guard lk(s_criticalScreenshot); + TextureToPng(texture, width*4, s_sScreenshotName, width, height, false); + // Reset settings + s_sScreenshotName.clear(); + s_bScreenshot = false; + } GLsizei glWidth = (GLsizei)GLInterface->GetBackBufferWidth(); GLsizei glHeight = (GLsizei)GLInterface->GetBackBufferHeight(); diff --git a/Source/Core/VideoBackends/Software/Src/SWRenderer.h b/Source/Core/VideoBackends/Software/Src/SWRenderer.h index ba856936cb..80a93ea203 100644 --- a/Source/Core/VideoBackends/Software/Src/SWRenderer.h +++ b/Source/Core/VideoBackends/Software/Src/SWRenderer.h @@ -6,13 +6,15 @@ #define _RENDERER_H_ #include "CommonTypes.h" +#include "Thread.h" namespace SWRenderer -{ +{ void Init(); void Prepare(); void Shutdown(); - + + void SetScreenshot(const char *_szFilename); void RenderText(const char* pstr, int left, int top, u32 color); void DrawDebugText(); diff --git a/Source/Core/VideoBackends/Software/Src/SWVideoConfig.cpp b/Source/Core/VideoBackends/Software/Src/SWVideoConfig.cpp index 43b6a96ef7..eb7cb79d40 100644 --- a/Source/Core/VideoBackends/Software/Src/SWVideoConfig.cpp +++ b/Source/Core/VideoBackends/Software/Src/SWVideoConfig.cpp @@ -65,8 +65,8 @@ void SWVideoConfig::Save(const char* ini_file) iniFile.Set("Hardware", "RenderToMainframe", renderToMainframe); iniFile.Set("Rendering", "HwRasterizer", bHwRasterizer); - iniFile.Set("Rendering", "ZComploc", &bZComploc); - iniFile.Set("Rendering", "ZFreeze", &bZFreeze); + iniFile.Set("Rendering", "ZComploc", bZComploc); + iniFile.Set("Rendering", "ZFreeze", bZFreeze); iniFile.Set("Info", "ShowStats", bShowStats); diff --git a/Source/Core/VideoBackends/Software/Src/SWmain.cpp b/Source/Core/VideoBackends/Software/Src/SWmain.cpp index 939dd4553a..074b6bc38b 100644 --- a/Source/Core/VideoBackends/Software/Src/SWmain.cpp +++ b/Source/Core/VideoBackends/Software/Src/SWmain.cpp @@ -236,7 +236,8 @@ u32 VideoSoftware::Video_GetQueryResult(PerfQueryType type) bool VideoSoftware::Video_Screenshot(const char *_szFilename) { - return false; + SWRenderer::SetScreenshot(_szFilename); + return true; } // ------------------------------- diff --git a/Source/Core/VideoCommon/CMakeLists.txt b/Source/Core/VideoCommon/CMakeLists.txt index 594624592c..9566712191 100644 --- a/Source/Core/VideoCommon/CMakeLists.txt +++ b/Source/Core/VideoCommon/CMakeLists.txt @@ -39,8 +39,7 @@ set(SRCS Src/BPFunctions.cpp Src/XFMemory.cpp Src/XFStructs.cpp Src/memcpy_amd.cpp) - -set(LIBS core) +set(LIBS core png) if(NOT _M_GENERIC) set(SRCS ${SRCS} Src/x64TextureDecoder.cpp diff --git a/Source/Core/VideoCommon/Src/BPMemory.cpp b/Source/Core/VideoCommon/Src/BPMemory.cpp index 7bc976a943..7272ed0993 100644 --- a/Source/Core/VideoCommon/Src/BPMemory.cpp +++ b/Source/Core/VideoCommon/Src/BPMemory.cpp @@ -19,18 +19,15 @@ void LoadBPReg(u32 value0) int opcode = value0 >> 24; int oldval = ((u32*)&bpmem)[opcode]; int newval = (oldval & ~bpmem.bpMask) | (value0 & bpmem.bpMask); + int changes = (oldval ^ newval) & 0xFFFFFF; + BPCmd bp = {opcode, changes, newval}; + + //reset the mask register if (opcode != 0xFE) - { - //reset the mask register bpmem.bpMask = 0xFFFFFF; - int changes = (oldval ^ newval) & 0xFFFFFF; - BPCmd bp = {opcode, changes, newval}; - BPWritten(bp); - } - else - bpmem.bpMask = newval; + BPWritten(bp); } void GetBPRegInfo(const u8* data, char* name, size_t name_size, char* desc, size_t desc_size) diff --git a/Source/Core/VideoCommon/Src/DriverDetails.cpp b/Source/Core/VideoCommon/Src/DriverDetails.cpp index 21b2273a49..3e975e0917 100644 --- a/Source/Core/VideoCommon/Src/DriverDetails.cpp +++ b/Source/Core/VideoCommon/Src/DriverDetails.cpp @@ -27,7 +27,7 @@ namespace DriverDetails // This is a list of all known bugs for each vendor // We use this to check if the device and driver has a issue BugInfo m_known_bugs[] = { - {VENDOR_QUALCOMM, DRIVER_QUALCOMM_3XX, BUG_NODYNUBOACCESS, 14.0, -1.0, true}, + {VENDOR_QUALCOMM, DRIVER_QUALCOMM_3XX, BUG_NODYNUBOACCESS, 14.0, 46.0, true}, {VENDOR_QUALCOMM, DRIVER_QUALCOMM_3XX, BUG_BROKENCENTROID, 14.0, -1.0, true}, {VENDOR_QUALCOMM, DRIVER_QUALCOMM_3XX, BUG_BROKENINFOLOG, -1.0, -1.0, true}, {VENDOR_QUALCOMM, DRIVER_QUALCOMM_3XX, BUG_ANNIHILATEDUBOS, 41.0, 46.0, true}, @@ -39,9 +39,6 @@ namespace DriverDetails {VENDOR_MESA, DRIVER_I965, BUG_BROKENUBO, 900, 920, true}, {VENDOR_ATI, DRIVER_ATI, BUG_BROKENHACKEDBUFFER, -1.0, -1.0, true}, {VENDOR_MESA, DRIVER_NOUVEAU, BUG_BROKENHACKEDBUFFER, -1.0, -1.0, true}, - {VENDOR_ATI, DRIVER_ATI, BUG_BROKENPINNEDMEMORY, -1.0, -1.0, true}, - {VENDOR_TEGRA, DRIVER_NVIDIA, BUG_ISTEGRA, -1.0, -1.0, true}, - {VENDOR_IMGTEC, DRIVER_IMGTEC, BUG_ISPOWERVR, -1.0, -1.0, true}, }; std::map m_bugs; diff --git a/Source/Core/VideoCommon/Src/DriverDetails.h b/Source/Core/VideoCommon/Src/DriverDetails.h index b9ace5b4f5..0ddf097ea1 100644 --- a/Source/Core/VideoCommon/Src/DriverDetails.h +++ b/Source/Core/VideoCommon/Src/DriverDetails.h @@ -53,7 +53,7 @@ namespace DriverDetails // Bug: No Dynamic UBO array object access // Affected Devices: Qualcomm/Adreno // Started Version: 14 - // Ended Version: -1 + // Ended Version: 53 // Accessing UBO array members dynamically causes the Adreno shader compiler to crash // Errors out with "Internal Error" BUG_NODYNUBOACCESS = 0, @@ -94,15 +94,16 @@ namespace DriverDetails // Bug: The pinned memory extension isn't working for index buffers // Affected devices: AMD as they are the only vendor providing this extension // Started Version: ? - // Ended Version: -1 + // Ended Version: 13.9 working for me (neobrain). // Pinned memory is disabled for index buffer as the amd driver (the only one with pinned memory support) seems // to be broken. We just get flickering/black rendering when using pinned memory here -- degasus - 2013/08/20 // Please see issue #6105 on google code. Let's hope buffer storage solves this issues. + // TODO: Detect broken drivers. BUG_BROKENPINNEDMEMORY, // Bug: Entirely broken UBOs // Affected devices: Qualcomm/Adreno // Started Version: ? (Noticed on v45) - // Ended Version: -1 + // Ended Version: 53 // Uniform buffers are entirely broken on Qualcomm drivers with v45 // Trying to use the uniform buffers causes a malloc to fail inside the driver // To be safe, blanket drivers from v41 - v45 @@ -115,20 +116,6 @@ namespace DriverDetails // Drawing on screen text causes the whole screen to swizzle in a terrible fashion // Clearing the framebuffer causes one to never see a frame. BUG_BROKENSWAP, - // Bug: Running on a Tegra 4 device - // Affected devices: Nvidia Tegra - // Started Version: 4 - // Ended Version: 5 - // Tegra 4 hardware limitations don't allow it to support OpenGL ES 3 - // This is fixed in Tegra 5 - BUG_ISTEGRA, - // Bug: Running on a PowerVR5 device - // Affected devices: PowerVR54x - // Started Version: 540 - // Ended Version: 6xxx - // PowerVR 5 hardware limitations don't allow it to support OpenGL ES 3 - // This is fixed in PowerVR6 - BUG_ISPOWERVR, // Bug: glBufferSubData/glMapBufferRange stalls + OOM // Affected devices: Adreno a3xx/Mali-t6xx // Started Version: -1 diff --git a/Source/Core/VideoCommon/Src/FramebufferManagerBase.h b/Source/Core/VideoCommon/Src/FramebufferManagerBase.h index e529bb1a39..2680f0ced4 100644 --- a/Source/Core/VideoCommon/Src/FramebufferManagerBase.h +++ b/Source/Core/VideoCommon/Src/FramebufferManagerBase.h @@ -15,9 +15,8 @@ struct XFBSourceBase { virtual ~XFBSourceBase() {} - // TODO: only DX9 uses the width/height params virtual void Draw(const MathUtil::Rectangle &sourcerc, - const MathUtil::Rectangle &drawrc, int width, int height) const = 0; + const MathUtil::Rectangle &drawrc) const = 0; virtual void DecodeToTexture(u32 xfbAddr, u32 fbWidth, u32 fbHeight) = 0; diff --git a/Source/Core/VideoCommon/Src/ImageWrite.cpp b/Source/Core/VideoCommon/Src/ImageWrite.cpp index f53bd1c18f..193f058541 100644 --- a/Source/Core/VideoCommon/Src/ImageWrite.cpp +++ b/Source/Core/VideoCommon/Src/ImageWrite.cpp @@ -5,55 +5,10 @@ #include #include +#include "png.h" #include "ImageWrite.h" #include "FileUtil.h" -#pragma pack(push, 1) - -struct TGA_HEADER -{ - u8 identsize; // size of ID field that follows 18 u8 header (0 usually) - u8 colourmaptype; // type of colour map 0=none, 1=has palette - u8 imagetype; // type of image 0=none,1=indexed,2=rgb,3=grey,+8=rle packed - - s16 colourmapstart; // first colour map entry in palette - s16 colourmaplength; // number of colours in palette - u8 colourmapbits; // number of bits per palette entry 15,16,24,32 - - s16 xstart; // image x origin - s16 ystart; // image y origin - s16 width; // image width in pixels - s16 height; // image height in pixels - u8 bits; // image bits per pixel 8,16,24,32 - u8 descriptor; // image descriptor bits (vh flip bits) - - // pixel data follows header -}; - -#pragma pack(pop) - -bool SaveTGA(const char* filename, int width, int height, void* pdata) -{ - TGA_HEADER hdr; - File::IOFile f(filename, "wb"); - if (!f) - return false; - - _assert_(sizeof(TGA_HEADER) == 18 && sizeof(hdr) == 18); - - memset(&hdr, 0, sizeof(hdr)); - hdr.imagetype = 2; - hdr.bits = 32; - hdr.width = width; - hdr.height = height; - hdr.descriptor |= 8|(1<<5); // 8bit alpha, flip vertical - - f.WriteArray(&hdr, 1); - f.WriteBytes(pdata, width * height * 4); - - return true; -} - bool SaveData(const char* filename, const char* data) { std::ofstream f; @@ -62,3 +17,92 @@ bool SaveData(const char* filename, const char* data) return true; } + + +/* +TextureToPng + +Inputs: +data : This is an array of RGBA with 8 bits per channel. 4 bytes for each pixel. +row_stride: Determines the amount of bytes per row of pixels. +*/ +bool TextureToPng(u8* data, int row_stride, const std::string filename, int width, int height, bool saveAlpha) +{ + bool success = false; + + if (!data) + return false; + + char title[] = "Dolphin Screenshot"; + char title_key[] = "Title"; + png_structp png_ptr = NULL; + png_infop info_ptr = NULL; + + // Open file for writing (binary mode) + File::IOFile fp(filename, "wb"); + if (!fp.IsOpen()) { + PanicAlert("Screenshot failed: Could not open file %s %d\n", filename.c_str(), errno); + goto finalise; + } + + // Initialize write structure + png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (png_ptr == NULL) { + PanicAlert("Screenshot failed: Could not allocate write struct\n"); + goto finalise; + + } + + // Initialize info structure + info_ptr = png_create_info_struct(png_ptr); + if (info_ptr == NULL) { + PanicAlert("Screenshot failed: Could not allocate info struct\n"); + goto finalise; + } + + // Setup Exception handling + if (setjmp(png_jmpbuf(png_ptr))) { + PanicAlert("Screenshot failed: Error during png creation\n"); + goto finalise; + } + + png_init_io(png_ptr, fp.GetHandle()); + + // Write header (8 bit colour depth) + png_set_IHDR(png_ptr, info_ptr, width, height, + 8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + + png_text title_text; + title_text.compression = PNG_TEXT_COMPRESSION_NONE; + title_text.key = title_key; + title_text.text = title; + png_set_text(png_ptr, info_ptr, &title_text, 1); + + png_write_info(png_ptr, info_ptr); + + // Write image data + for (auto y = 0; y < height; ++y) + { + u8* row_ptr = (u8*)data + y * row_stride; + u8* ptr = row_ptr; + for (auto x = 0; x < row_stride / 4; ++x) + { + if (!saveAlpha) + ptr[3] = 0xff; + ptr += 4; + } + png_write_row(png_ptr, row_ptr); + } + + // End write + png_write_end(png_ptr, NULL); + + success = true; + +finalise: + if (info_ptr != NULL) png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1); + if (png_ptr != NULL) png_destroy_write_struct(&png_ptr, (png_infopp)NULL); + + return success; +} diff --git a/Source/Core/VideoCommon/Src/ImageWrite.h b/Source/Core/VideoCommon/Src/ImageWrite.h index 7d1d6fa1e8..04de765d32 100644 --- a/Source/Core/VideoCommon/Src/ImageWrite.h +++ b/Source/Core/VideoCommon/Src/ImageWrite.h @@ -7,8 +7,8 @@ #include "Common.h" -bool SaveTGA(const char* filename, int width, int height, void* pdata); bool SaveData(const char* filename, const char* pdata); +bool TextureToPng(u8* data, int row_stride, const std::string filename, int width, int height, bool saveAlpha = true); #endif // _IMAGEWRITE_H diff --git a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp index 05c2e88aae..8555bd736d 100644 --- a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp @@ -283,7 +283,7 @@ PC_TexFormat TextureCache::LoadCustomTexture(u64 tex_hash, int texformat, unsign void TextureCache::DumpTexture(TCacheEntryBase* entry, unsigned int level) { - char szTemp[MAX_PATH]; + std::string filename; std::string szDir = File::GetUserPath(D_DUMPTEXTURES_IDX) + SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID; @@ -295,19 +295,19 @@ void TextureCache::DumpTexture(TCacheEntryBase* entry, unsigned int level) // TODO: TLUT format should actually be stored in filename? :/ if (level == 0) { - sprintf(szTemp, "%s/%s_%08x_%i.png", szDir.c_str(), - SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str(), - (u32) (entry->hash & 0x00000000FFFFFFFFLL), entry->format & 0xFFFF); + filename = StringFromFormat("%s/%s_%08x_%i.png", szDir.c_str(), + SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str(), + (u32)(entry->hash & 0x00000000FFFFFFFFLL), entry->format & 0xFFFF); } else { - sprintf(szTemp, "%s/%s_%08x_%i_mip%i.png", szDir.c_str(), + filename = StringFromFormat("%s/%s_%08x_%i_mip%i.png", szDir.c_str(), SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str(), (u32) (entry->hash & 0x00000000FFFFFFFFLL), entry->format & 0xFFFF, level); } - if (false == File::Exists(szTemp)) - entry->Save(szTemp, level); + if (!File::Exists(filename)) + entry->Save(filename, level); } static u32 CalculateLevelSize(u32 level_0_size, u32 level) @@ -616,6 +616,7 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat ColorMask[0] = ColorMask[1] = ColorMask[2] = ColorMask[3] = 255.0f; ColorMask[4] = ColorMask[5] = ColorMask[6] = ColorMask[7] = 1.0f / 255.0f; unsigned int cbufid = -1; + bool efbHasAlpha = bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24; if (srcFormat == PIXELFMT_Z24) { @@ -633,40 +634,40 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat case 3: // Z16 colmat[1] = colmat[5] = colmat[9] = colmat[12] = 1.0f; - cbufid = 24; + cbufid = 2; break; case 11: // Z16 (reverse order) colmat[0] = colmat[4] = colmat[8] = colmat[13] = 1.0f; - cbufid = 2; + cbufid = 3; break; case 6: // Z24X8 colmat[0] = colmat[5] = colmat[10] = 1.0f; - cbufid = 3; + cbufid = 4; break; case 9: // Z8M colmat[1] = colmat[5] = colmat[9] = colmat[13] = 1.0f; - cbufid = 4; + cbufid = 5; break; case 10: // Z8L colmat[2] = colmat[6] = colmat[10] = colmat[14] = 1.0f; - cbufid = 5; + cbufid = 6; break; case 12: // Z16L - copy lower 16 depth bits // expected to be used as an IA8 texture (upper 8 bits stored as intensity, lower 8 bits stored as alpha) // Used e.g. in Zelda: Skyward Sword colmat[1] = colmat[5] = colmat[9] = colmat[14] = 1.0f; - cbufid = 6; + cbufid = 7; break; default: ERROR_LOG(VIDEO, "Unknown copy zbuf format: 0x%x", dstFormat); colmat[2] = colmat[5] = colmat[8] = 1.0f; - cbufid = 7; + cbufid = 8; break; } } @@ -693,11 +694,11 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat { ColorMask[0] = ColorMask[1] = ColorMask[2] = 15.0f; ColorMask[4] = ColorMask[5] = ColorMask[6] = 1.0f / 15.0f; - cbufid = 8; + cbufid = 9; } else { - cbufid = 9; + cbufid = 10; } } else// alpha @@ -707,11 +708,11 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat { ColorMask[0] = ColorMask[1] = ColorMask[2] = ColorMask[3] = 15.0f; ColorMask[4] = ColorMask[5] = ColorMask[6] = ColorMask[7] = 1.0f / 15.0f; - cbufid = 10; + cbufid = 11; } else { - cbufid = 11; + cbufid = 12; } } @@ -720,7 +721,7 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat default: ERROR_LOG(VIDEO, "Unknown copy intensity format: 0x%x", dstFormat); colmat[0] = colmat[5] = colmat[10] = colmat[15] = 1.0f; - cbufid = 23; + cbufid = 13; break; } } @@ -732,47 +733,68 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat colmat[0] = colmat[4] = colmat[8] = colmat[12] = 1; ColorMask[0] = 15.0f; ColorMask[4] = 1.0f / 15.0f; - cbufid = 12; + cbufid = 14; break; case 1: // R8 case 8: // R8 colmat[0] = colmat[4] = colmat[8] = colmat[12] = 1; - cbufid = 13; + cbufid = 15; break; case 2: // RA4 colmat[0] = colmat[4] = colmat[8] = colmat[15] = 1.0f; ColorMask[0] = ColorMask[3] = 15.0f; ColorMask[4] = ColorMask[7] = 1.0f / 15.0f; - cbufid = 14; + + cbufid = 16; + if(!efbHasAlpha) { + ColorMask[3] = 0.0f; + fConstAdd[3] = 1.0f; + cbufid = 17; + } break; case 3: // RA8 colmat[0] = colmat[4] = colmat[8] = colmat[15] = 1.0f; - cbufid = 15; + + cbufid = 18; + if(!efbHasAlpha) { + ColorMask[3] = 0.0f; + fConstAdd[3] = 1.0f; + cbufid = 19; + } break; case 7: // A8 colmat[3] = colmat[7] = colmat[11] = colmat[15] = 1.0f; - cbufid = 16; + + cbufid = 20; + if(!efbHasAlpha) { + ColorMask[3] = 0.0f; + fConstAdd[0] = 1.0f; + fConstAdd[1] = 1.0f; + fConstAdd[2] = 1.0f; + fConstAdd[3] = 1.0f; + cbufid = 21; + } break; case 9: // G8 colmat[1] = colmat[5] = colmat[9] = colmat[13] = 1.0f; - cbufid = 17; + cbufid = 22; break; case 10: // B8 colmat[2] = colmat[6] = colmat[10] = colmat[14] = 1.0f; - cbufid = 18; + cbufid = 23; break; case 11: // RG8 colmat[0] = colmat[4] = colmat[8] = colmat[13] = 1.0f; - cbufid = 19; + cbufid = 24; break; case 12: // GB8 colmat[1] = colmat[5] = colmat[9] = colmat[14] = 1.0f; - cbufid = 20; + cbufid = 25; break; case 4: // RGB565 @@ -782,7 +804,7 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat ColorMask[1] = 63.0f; ColorMask[5] = 1.0f / 63.0f; fConstAdd[3] = 1.0f; // set alpha to 1 - cbufid = 21; + cbufid = 26; break; case 5: // RGB5A3 @@ -791,17 +813,29 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat ColorMask[4] = ColorMask[5] = ColorMask[6] = 1.0f / 31.0f; ColorMask[3] = 7.0f; ColorMask[7] = 1.0f / 7.0f; - cbufid = 22; + + cbufid = 27; + if(!efbHasAlpha) { + ColorMask[3] = 0.0f; + fConstAdd[3] = 1.0f; + cbufid = 28; + } break; case 6: // RGBA8 colmat[0] = colmat[5] = colmat[10] = colmat[15] = 1.0f; - cbufid = 23; + + cbufid = 29; + if(!efbHasAlpha) { + ColorMask[3] = 0.0f; + fConstAdd[3] = 1.0f; + cbufid = 30; + } break; default: ERROR_LOG(VIDEO, "Unknown copy color format: 0x%x", dstFormat); colmat[0] = colmat[5] = colmat[10] = colmat[15] = 1.0f; - cbufid = 23; + cbufid = 31; break; } } diff --git a/Source/Core/VideoCommon/Src/TextureCacheBase.h b/Source/Core/VideoCommon/Src/TextureCacheBase.h index 1afcb8cd2d..4db768f5e4 100644 --- a/Source/Core/VideoCommon/Src/TextureCacheBase.h +++ b/Source/Core/VideoCommon/Src/TextureCacheBase.h @@ -73,7 +73,7 @@ public: virtual ~TCacheEntryBase(); virtual void Bind(unsigned int stage) = 0; - virtual bool Save(const char filename[], unsigned int level) = 0; + virtual bool Save(const std::string filename, unsigned int level) = 0; virtual void Load(unsigned int width, unsigned int height, unsigned int expanded_width, unsigned int level) = 0; diff --git a/Source/Core/VideoCommon/Src/x64TextureDecoder.cpp b/Source/Core/VideoCommon/Src/x64TextureDecoder.cpp index 6887a0bdd0..a02738479a 100644 --- a/Source/Core/VideoCommon/Src/x64TextureDecoder.cpp +++ b/Source/Core/VideoCommon/Src/x64TextureDecoder.cpp @@ -1460,7 +1460,7 @@ PC_TexFormat TexDecoder_Decode_RGBA(u32 * dst, const u8 * src, int width, int he for (int iy = 0, xStep = 4 * yStep; iy < 4; iy++, xStep++) { u32 *newdst = dst+(y+iy)*width+x; - const __m128i mask = _mm_set_epi8(128,128,6,7,128,128,4,5,128,128,2,3,128,128,0,1); + const __m128i mask = _mm_set_epi8(-128,-128,6,7,-128,-128,4,5,-128,-128,2,3,-128,-128,0,1); const __m128i valV = _mm_shuffle_epi8(_mm_loadl_epi64((const __m128i*)(src + 8 * xStep)),mask); int cmp = _mm_movemask_epi8(valV); //MSB: 0x2 = val0; 0x20=val1; 0x200 = val2; 0x2000=val3 if ((cmp&0x2222)==0x2222) // SSSE3 case #1: all 4 pixels are in RGB555 and alpha = 0xFF. diff --git a/Source/Core/VideoCommon/VideoCommon.vcxproj b/Source/Core/VideoCommon/VideoCommon.vcxproj index dd8bbc6f6d..fa7ef921ae 100644 --- a/Source/Core/VideoCommon/VideoCommon.vcxproj +++ b/Source/Core/VideoCommon/VideoCommon.vcxproj @@ -152,9 +152,15 @@ {aa862e5e-a993-497a-b6a0-0e8e94b10050} + + {4c9f135b-a85e-430c-bad4-4c67ef5fc12c} + {b441cc62-877e-4b3f-93e0-0de80544f705} + + {ff213b23-2c26-4214-9f88-85271e557e87} + {2e6c348c-c75c-4d94-8d1e-9c1fcbf3efe4} diff --git a/Source/DSPTool/Src/DSPTool.cpp b/Source/DSPTool/Src/DSPTool.cpp index 9f38b1347b..5a776be558 100644 --- a/Source/DSPTool/Src/DSPTool.cpp +++ b/Source/DSPTool/Src/DSPTool.cpp @@ -11,6 +11,7 @@ // Stub out the dsplib host stuff, since this is just a simple cmdline tools. u8 DSPHost_ReadHostMemory(u32 addr) { return 0; } void DSPHost_WriteHostMemory(u8 value, u32 addr) {} +void DSPHost_OSD_AddMessage(const std::string& str, u32 ms) {} bool DSPHost_OnThread() { return false; } bool DSPHost_Wii() { return false; } void DSPHost_CodeLoaded(const u8 *ptr, int size) {} diff --git a/Source/VSProps/Base.props b/Source/VSProps/Base.props index 2ee5bd8e8e..1b40800891 100644 --- a/Source/VSProps/Base.props +++ b/Source/VSProps/Base.props @@ -44,6 +44,7 @@ $(ExternalsDir)Bochs_disasm;%(AdditionalIncludeDirectories) $(ExternalsDir)CLRun\include;%(AdditionalIncludeDirectories) $(ExternalsDir)GLew\include;%(AdditionalIncludeDirectories) + $(ExternalsDir)libpng;%(AdditionalIncludeDirectories) $(ExternalsDir)libusbx\libusb;%(AdditionalIncludeDirectories) $(ExternalsDir)LZO;%(AdditionalIncludeDirectories) $(ExternalsDir)miniupnpc\src;%(AdditionalIncludeDirectories)