diff --git a/CMakeLists.txt b/CMakeLists.txt index 0024daaa22..ea88a762d6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -106,9 +106,22 @@ if(DOLPHIN_IS_STABLE) else() set(DOLPHIN_VERSION_PATCH ${DOLPHIN_WC_REVISION}) endif() +message(${CMAKE_SYSTEM_PROCESSOR}) +if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "^arm") + set(_M_GENERIC 1) + set(_M_ARM 1) + add_definitions(-marm -march=armv7-a) + add_definitions(-D_M_ARM=1) + add_definitions(-D_M_GENERIC=1) +endif() +# Set these next two lines to test generic +#set(_M_GENERIC 1) +#add_definitions(-D_M_GENERIC=1) # Various compile flags -add_definitions(-msse2) +if(NOT _M_GENERIC) + add_definitions(-msse2) +endif() include(CheckCXXCompilerFlag) macro(check_and_add_flag var flag) @@ -258,135 +271,141 @@ if(USE_EGL) endif() add_definitions(-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE) +option(ANDROID "Enables a build for Android" OFF) +if(ANDROID) + message("Building for Android") + add_definitions(-DANDROID) +endif() ######################################## # Dependency checking # # TODO: We should have options for dependencies included in the externals to # override autodetection of system libraries and force the usage of the # externals. +if(NOT ANDROID) + include(CheckLib) -include(CheckLib) - -include(FindOpenGL) -include_directories(${OPENGL_INCLUDE_DIR}) -if(NOT OPENGL_GLU_FOUND) - message(FATAL_ERROR "GLU is required but not found") -endif() - -if(OPENMP) - include(FindOpenMP OPTIONAL) - if(OPENMP_FOUND) - message("OpenMP parallelization enabled") - add_definitions("${OpenMP_CXX_FLAGS}") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_CXX_FLAGS}") + include(FindOpenGL) + include_directories(${OPENGL_INCLUDE_DIR}) + if(NOT OPENGL_GLU_FOUND) + message(FATAL_ERROR "GLU is required but not found") endif() -endif() -if(NOT OPENMP_FOUND) - add_definitions(-Wno-unknown-pragmas) - message("OpenMP parallelization disabled") -endif() -include(FindALSA OPTIONAL) -if(ALSA_FOUND) - add_definitions(-DHAVE_ALSA=1) - message("ALSA found, enabling ALSA sound backend") -else() - add_definitions(-DHAVE_ALSA=0) - message("ALSA NOT found, disabling ALSA sound backend") -endif(ALSA_FOUND) + if(OPENMP) + include(FindOpenMP OPTIONAL) + if(OPENMP_FOUND) + message("OpenMP parallelization enabled") + add_definitions("${OpenMP_CXX_FLAGS}") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_CXX_FLAGS}") + endif() + endif() + if(NOT OPENMP_FOUND) + add_definitions(-Wno-unknown-pragmas) + message("OpenMP parallelization disabled") + endif() -check_lib(AO ao QUIET) -if(AO_FOUND) - add_definitions(-DHAVE_AO=1) - message("ao found, enabling ao sound backend") -else() - add_definitions(-DHAVE_AO=0) - message("ao NOT found, disabling ao sound backend") -endif(AO_FOUND) + include(FindALSA OPTIONAL) + if(ALSA_FOUND) + add_definitions(-DHAVE_ALSA=1) + message("ALSA found, enabling ALSA sound backend") + else() + add_definitions(-DHAVE_ALSA=0) + message("ALSA NOT found, disabling ALSA sound backend") + endif(ALSA_FOUND) -check_lib(BLUEZ bluez QUIET) -if(BLUEZ_FOUND) - add_definitions(-DHAVE_BLUEZ=1) - message("bluez found, enabling bluetooth support") -else() - add_definitions(-DHAVE_BLUEZ=0) - message("bluez NOT found, disabling bluetooth support") -endif(BLUEZ_FOUND) + check_lib(AO ao QUIET) + if(AO_FOUND) + add_definitions(-DHAVE_AO=1) + message("ao found, enabling ao sound backend") + else() + add_definitions(-DHAVE_AO=0) + message("ao NOT found, disabling ao sound backend") + endif(AO_FOUND) -check_lib(PULSEAUDIO libpulse-simple QUIET) -if(PULSEAUDIO_FOUND) - add_definitions(-DHAVE_PULSEAUDIO=1) - message("PulseAudio found, enabling PulseAudio sound backend") -else() - add_definitions(-DHAVE_PULSEAUDIO=0) - message("PulseAudio NOT found, disabling PulseAudio sound backend") -endif(PULSEAUDIO_FOUND) + check_lib(BLUEZ bluez QUIET) + if(BLUEZ_FOUND) + add_definitions(-DHAVE_BLUEZ=1) + message("bluez found, enabling bluetooth support") + else() + add_definitions(-DHAVE_BLUEZ=0) + message("bluez NOT found, disabling bluetooth support") + endif(BLUEZ_FOUND) -include(FindOpenAL OPTIONAL) -if(OPENAL_FOUND) - add_definitions(-DHAVE_OPENAL=1) - include_directories(${OPENAL_INCLUDE_DIR}) - message("OpenAL found, enabling OpenAL sound backend") -else() - add_definitions(-DHAVE_OPENAL=0) - message("OpenAL NOT found, disabling OpenAL sound backend") -endif(OPENAL_FOUND) + check_lib(PULSEAUDIO libpulse-simple QUIET) + if(PULSEAUDIO_FOUND) + add_definitions(-DHAVE_PULSEAUDIO=1) + message("PulseAudio found, enabling PulseAudio sound backend") + else() + add_definitions(-DHAVE_PULSEAUDIO=0) + message("PulseAudio NOT found, disabling PulseAudio sound backend") + endif(PULSEAUDIO_FOUND) + + include(FindOpenAL OPTIONAL) + if(OPENAL_FOUND) + add_definitions(-DHAVE_OPENAL=1) + include_directories(${OPENAL_INCLUDE_DIR}) + message("OpenAL found, enabling OpenAL sound backend") + else() + add_definitions(-DHAVE_OPENAL=0) + message("OpenAL NOT found, disabling OpenAL sound backend") + endif(OPENAL_FOUND) # Note: We do not need to explicitly check for X11 as it is done in the cmake # FindOpenGL module on linux. -if(UNIX AND NOT APPLE) + if(UNIX AND NOT APPLE) + if(X11_FOUND) + add_definitions(-DHAVE_X11=1) + include_directories(${X11_INCLUDE_DIR}) + message("X11 found") + else() + message(FATAL_ERROR "X11 is required but not found") + endif(X11_FOUND) + else() + add_definitions(-DHAVE_X11=0) + endif() + if(X11_FOUND) - add_definitions(-DHAVE_X11=1) - include_directories(${X11_INCLUDE_DIR}) - message("X11 found") + check_lib(XRANDR Xrandr) + endif() + if(XRANDR_FOUND) + add_definitions(-DHAVE_XRANDR=1) else() - message(FATAL_ERROR "X11 is required but not found") - endif(X11_FOUND) -else() - add_definitions(-DHAVE_X11=0) -endif() + add_definitions(-DHAVE_XRANDR=0) + endif(XRANDR_FOUND) -if(X11_FOUND) - check_lib(XRANDR Xrandr) -endif() -if(XRANDR_FOUND) - add_definitions(-DHAVE_XRANDR=1) -else() - add_definitions(-DHAVE_XRANDR=0) -endif(XRANDR_FOUND) + if(ENCODE_FRAMEDUMPS) + check_libav() + endif() -if(ENCODE_FRAMEDUMPS) - check_libav() -endif() - -include(CheckCXXSourceRuns) -set(CMAKE_REQUIRED_LIBRARIES portaudio) -CHECK_CXX_SOURCE_RUNS( - "#include - int main(int argc, char **argv) - { if(Pa_GetVersion() >= 1890) return 0; else return 1; }" - PORTAUDIO) -if(PORTAUDIO) - message("PortAudio found, enabling mic support") - add_definitions(-DHAVE_PORTAUDIO=1) - set(PORTAUDIO_FOUND TRUE) -else() - message("PortAudio not found, disabling mic support") - add_definitions(-DHAVE_PORTAUDIO=0) - set(PORTAUDIO_FOUND FALSE) -endif(PORTAUDIO) - -if(OPROFILING) - check_lib(OPROFILE opagent opagent.h) - check_lib(BFD bfd bfd.h) - if(OPROFILE_FOUND AND BFD_FOUND) - message("oprofile found, enabling profiling support") - add_definitions(-DUSE_OPROFILE=1) + include(CheckCXXSourceRuns) + set(CMAKE_REQUIRED_LIBRARIES portaudio) + CHECK_CXX_SOURCE_RUNS( + "#include + int main(int argc, char **argv) + { if(Pa_GetVersion() >= 1890) return 0; else return 1; }" + PORTAUDIO) + if(PORTAUDIO) + message("PortAudio found, enabling mic support") + add_definitions(-DHAVE_PORTAUDIO=1) + set(PORTAUDIO_FOUND TRUE) else() - message(FATAL_ERROR "oprofile or bfd not found. Can't build profiling support.") + message("PortAudio not found, disabling mic support") + add_definitions(-DHAVE_PORTAUDIO=0) + set(PORTAUDIO_FOUND FALSE) + endif(PORTAUDIO) + + option(OPROFILING "Enable profiling" OFF) + if(OPROFILING) + check_lib(OPROFILE opagent opagent.h) + check_lib(BFD bfd bfd.h) + if(OPROFILE_FOUND AND BFD_FOUND) + message("oprofile found, enabling profiling support") + add_definitions(-DUSE_OPROFILE=1) + else() + message(FATAL_ERROR "oprofile or bfd not found. Can't build profiling support.") + endif() endif() endif() - ######################################## # Setup include directories (and make sure they are preferred over the Externals) # @@ -401,7 +420,6 @@ include_directories(Source/Core/InputCommon/Src) include_directories(Source/Core/VideoCommon/Src) include_directories(Source/Core/VideoUICommon/Src) - ######################################## # Process externals and setup their include directories # @@ -415,7 +433,7 @@ include_directories(Source/Core/VideoUICommon/Src) add_subdirectory(Externals/Bochs_disasm) include_directories(Externals/Bochs_disasm) -if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin") +if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin" AND NOT ANDROID) check_lib(LZO lzo2 lzo/lzo1x.h QUIET) endif() if(LZO_FOUND) @@ -440,15 +458,16 @@ if(OPENAL_FOUND) endif() endif() -if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin") - include(FindSDL2 OPTIONAL) -endif() -if(SDL2_FOUND) - message("Using shared SDL2") - include_directories(${SDL2_INCLUDE_DIR}) -else(SDL2_FOUND) - # SDL2 not found, try SDL +if(NOT ANDROID) if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + include(FindSDL2 OPTIONAL) + endif() + if(SDL2_FOUND) + message("Using shared SDL2") + include_directories(${SDL2_INCLUDE_DIR}) + else(SDL2_FOUND) + # SDL2 not found, try SDL + if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin") include(FindSDL OPTIONAL) endif() if(SDL_FOUND) @@ -460,12 +479,13 @@ else(SDL2_FOUND) include_directories(Externals/SDL/SDL Externals/SDL Externals/SDL/include) add_subdirectory(Externals/SDL) endif(SDL_FOUND) -endif(SDL2_FOUND) + endif(SDL2_FOUND) +endif() set(SFML_FIND_VERSION TRUE) set(SFML_FIND_VERSION_MAJOR 1) set(SFML_FIND_VERSION_MINOR 5) -if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin") +if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin" AND NOT ANDROID) include(FindSFML OPTIONAL) endif() if(SFML_FOUND AND NOT SFML_VERSION_MAJOR) # SFML 1.x doesn't define SFML_VERSION_MAJOR @@ -476,7 +496,7 @@ else() include_directories(Externals/SFML/include) endif() -if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin") +if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin" AND NOT ANDROID) check_lib(SOIL SOIL SOIL/SOIL.h QUIET) endif() if(SOIL_FOUND) @@ -506,17 +526,19 @@ if(WIN32) find_library(GLEW glew32s PATHS Externals/GLew) include_directories(Externals/GLew/include) else() - if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin") - check_lib(GLEW GLEW GL/glew.h) + if(NOT ANDROID) + if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + check_lib(GLEW GLEW GL/glew.h) + endif() + if(NOT GLEW_FOUND) + message("Using static GLEW from Externals") + add_subdirectory(Externals/GLew) + include_directories(Externals/GLew/include) + endif(NOT GLEW_FOUND) endif() - if(NOT GLEW_FOUND) - message("Using static GLEW from Externals") - add_subdirectory(Externals/GLew) - include_directories(Externals/GLew/include) - endif(NOT GLEW_FOUND) endif() -if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") +if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin" AND NOT ANDROID) find_library(CL OpenCL) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-weak_framework,OpenCL") else() @@ -524,10 +546,25 @@ else() add_subdirectory(Externals/CLRun) endif() -if(NOT DISABLE_WX) +if(NOT DISABLE_WX AND NOT ANDROID) include(FindwxWidgets OPTIONAL) FIND_PACKAGE(wxWidgets COMPONENTS core aui adv) + if(wxWidgets_FOUND) + EXECUTE_PROCESS( + COMMAND sh "${wxWidgets_CONFIG_EXECUTABLE}" + ${wxWidgets_CONFIG_OPTIONS} --version + OUTPUT_VARIABLE wxWidgets_VERSION + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET + ) + message("Found wxWidgets version ${wxWidgets_VERSION}") + if(${wxWidgets_VERSION} VERSION_LESS "2.8.9") + message("At least 2.8.9 is required; ignoring found version") + unset(wxWidgets_FOUND) + endif() + endif(wxWidgets_FOUND) + if(wxWidgets_FOUND) EXECUTE_PROCESS( COMMAND sh "${wxWidgets_CONFIG_EXECUTABLE}" @@ -548,26 +585,26 @@ if(NOT DISABLE_WX) endif() endif(wxWidgets_FOUND) - if(UNIX AND NOT APPLE) - # There is a bug in the FindGTK module in cmake version 2.8.2 that - # does not find gdk-pixbuf-2.0. On the other hand some 2.8.3 - # users have complained that pkg-config does not find - # gdk-pixbuf-2.0. On yet another hand, cmake version 2.8.3 in - # Ubuntu Natty does not find the glib libraries correctly. - # Ugly!!! - execute_process(COMMAND lsb_release -c -s - OUTPUT_VARIABLE DIST_NAME - ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) - if(${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION} - VERSION_EQUAL 2.8.2 OR "${DIST_NAME}" STREQUAL "natty") - check_lib(GTK2 gtk+-2.0 gtk.h REQUIRED) - else() - include(FindGTK2) - if(GTK2_FOUND) - include_directories(${GTK2_INCLUDE_DIRS}) + if(UNIX AND NOT APPLE) + # There is a bug in the FindGTK module in cmake version 2.8.2 that + # does not find gdk-pixbuf-2.0. On the other hand some 2.8.3 + # users have complained that pkg-config does not find + # gdk-pixbuf-2.0. On yet another hand, cmake version 2.8.3 in + # Ubuntu Natty does not find the glib libraries correctly. + # Ugly!!! + execute_process(COMMAND lsb_release -c -s + OUTPUT_VARIABLE DIST_NAME + ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) + if(${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION} + VERSION_EQUAL 2.8.2 OR "${DIST_NAME}" STREQUAL "natty") + check_lib(GTK2 gtk+-2.0 gtk.h REQUIRED) + else() + include(FindGTK2) + if(GTK2_FOUND) + include_directories(${GTK2_INCLUDE_DIRS}) + endif() endif() endif() - endif() if(wxWidgets_FOUND) include(${wxWidgets_USE_FILE}) @@ -599,7 +636,7 @@ if(NOT DISABLE_WX) set(wxWidgets_LIBRARIES "wx") endif(wxWidgets_FOUND) add_definitions(-DHAVE_WX=1) -endif(NOT DISABLE_WX) +endif(NOT DISABLE_WX AND NOT ANDROID) ######################################## @@ -674,4 +711,4 @@ list(APPEND CPACK_SOURCE_IGNORE_FILES "${CMAKE_BINARY_DIR}") # CPack must be included after the CPACK_* variables are set in order for those # variables to take effect. -include(CPack) +Include(CPack) diff --git a/Data/User/GameConfig/GF8E69.ini b/Data/User/GameConfig/GF8E69.ini index 858a62d3d8..5fa4328270 100644 --- a/Data/User/GameConfig/GF8E69.ini +++ b/Data/User/GameConfig/GF8E69.ini @@ -3,7 +3,7 @@ TLBHack = 1 [EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set. EmulationStateId = 4 -EmulationIssues = +EmulationIssues = The videos are messed up, skip them. [OnFrame] Add memory patches to be applied every frame here. [ActionReplay] Add action replay cheats here. $Master Code @@ -40,3 +40,9 @@ $Away Team Never Scores 00416F8C 00000000 [Video] ProjectionHack = 0 +PH_SZNear = 0 +PH_SZFar = 0 +PH_ExtraParam = 0 +PH_ZNear = +PH_ZFar = +[Gecko] diff --git a/Data/User/GameConfig/GF8P69.ini b/Data/User/GameConfig/GF8P69.ini new file mode 100644 index 0000000000..3d6f730434 --- /dev/null +++ b/Data/User/GameConfig/GF8P69.ini @@ -0,0 +1,16 @@ +# GF8P69 - FIFA Street +[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 = The videos are messed up, skip them. +[OnFrame] Add memory patches to be applied every frame here. +[ActionReplay] Add action replay cheats here. +[Video] +ProjectionHack = 0 +PH_SZNear = 0 +PH_SZFar = 0 +PH_ExtraParam = 0 +PH_ZNear = +PH_ZFar = +[Gecko] diff --git a/Data/User/GameConfig/GFZE01.ini b/Data/User/GameConfig/GFZE01.ini index 450553aa06..32b1e195c0 100644 --- a/Data/User/GameConfig/GFZE01.ini +++ b/Data/User/GameConfig/GFZE01.ini @@ -43,7 +43,4 @@ $All Vehicles Unlocked 840030C8 FFDC6F00 [Gecko] [Video_Hacks] -EFBCopyEnable = True -EFBToTextureEnable = False -EFBCopyCacheEnable = True [Video_Settings] diff --git a/Data/User/GameConfig/GFZP01.ini b/Data/User/GameConfig/GFZP01.ini index 70c517ef4a..0586d53d3f 100644 --- a/Data/User/GameConfig/GFZP01.ini +++ b/Data/User/GameConfig/GFZP01.ini @@ -24,7 +24,4 @@ $Make Save Copyable 04C3110C 4B400410 [Gecko] [Video_Hacks] -EFBCopyEnable = True -EFBToTextureEnable = False -EFBCopyCacheEnable = True [Video_Settings] diff --git a/Data/User/GameConfig/GOSE41.ini b/Data/User/GameConfig/GOSE41.ini index 4682f2275c..adc124119f 100644 --- a/Data/User/GameConfig/GOSE41.ini +++ b/Data/User/GameConfig/GOSE41.ini @@ -1,9 +1,11 @@ # GOSE41 - Open Season [Core] Values set here will override the main dolphin settings. -TLBHack = 1 +MMU = 1 +FastDiscSpeed = 1 +BlockMerging = 1 [EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set. -EmulationStateId = 2 -EmulationIssues = Severe graphic issues. +EmulationStateId = 4 +EmulationIssues = Needs MMU (Slow). [OnFrame] Add memory patches to be applied every frame here. [ActionReplay] Add action replay cheats here. [Video] diff --git a/Data/User/GameConfig/GOSP41.ini b/Data/User/GameConfig/GOSP41.ini index 40fc6ad1f1..cb12055384 100644 --- a/Data/User/GameConfig/GOSP41.ini +++ b/Data/User/GameConfig/GOSP41.ini @@ -1,9 +1,11 @@ # GOSP41 - Open Season [Core] Values set here will override the main dolphin settings. -TLBHack = 1 +MMU = 1 +FastDiscSpeed = 1 +BlockMerging = 1 [EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set. -EmulationStateId = 2 -EmulationIssues = Severe graphic issues. +EmulationStateId = 4 +EmulationIssues = Needs MMU (Slow). [OnFrame] Add memory patches to be applied every frame here. [ActionReplay] Add action replay cheats here. [Video] diff --git a/Data/User/GameConfig/GOSX41.ini b/Data/User/GameConfig/GOSX41.ini index 92662f0a4c..8790cdfd8c 100644 --- a/Data/User/GameConfig/GOSX41.ini +++ b/Data/User/GameConfig/GOSX41.ini @@ -1,9 +1,11 @@ # GOSX41 - Open Season [Core] Values set here will override the main dolphin settings. -TLBHack = 1 +MMU = 1 +FastDiscSpeed = 1 +BlockMerging = 1 [EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set. -EmulationStateId = 2 -EmulationIssues = Severe graphic issues. +EmulationStateId = 4 +EmulationIssues = Needs MMU (Slow). [OnFrame] Add memory patches to be applied every frame here. [ActionReplay] Add action replay cheats here. [Video] diff --git a/Data/User/GameConfig/PH_PRESETS.ini b/Data/User/GameConfig/PH_PRESETS.ini index 8d82d00790..f5e7a4aacf 100644 --- a/Data/User/GameConfig/PH_PRESETS.ini +++ b/Data/User/GameConfig/PH_PRESETS.ini @@ -33,7 +33,7 @@ PH_ExtraParam = 1 [5] Title = Tales of Symphonia GC -PH_ZNear = 0.0002 +PH_ZNear = 0.00026 # --------------------------------------------------- diff --git a/Data/User/GameConfig/R22E01.ini b/Data/User/GameConfig/R22E01.ini index dfe3542671..c494ee5e12 100644 --- a/Data/User/GameConfig/R22E01.ini +++ b/Data/User/GameConfig/R22E01.ini @@ -17,5 +17,4 @@ PH_ZFar = SafeTextureCacheColorSamples = 512 [Video_Hacks] EFBEmulateFormatChanges = True -[Wii] -DisableWiimoteSpeaker = 1 +[Wii] diff --git a/Data/User/GameConfig/R22J01.ini b/Data/User/GameConfig/R22J01.ini index c38ff20966..94aeac02f3 100644 --- a/Data/User/GameConfig/R22J01.ini +++ b/Data/User/GameConfig/R22J01.ini @@ -17,5 +17,4 @@ PH_ZFar = SafeTextureCacheColorSamples = 512 [Video_Hacks] EFBEmulateFormatChanges = True -[Wii] -DisableWiimoteSpeaker = 1 +[Wii] diff --git a/Data/User/GameConfig/R22P01.ini b/Data/User/GameConfig/R22P01.ini index 6153cb0d06..8fb637216f 100644 --- a/Data/User/GameConfig/R22P01.ini +++ b/Data/User/GameConfig/R22P01.ini @@ -17,5 +17,4 @@ PH_ZFar = SafeTextureCacheColorSamples = 512 [Video_Hacks] EFBEmulateFormatChanges = True -[Wii] -DisableWiimoteSpeaker = 1 +[Wii] diff --git a/Data/User/GameConfig/R3ME01.ini b/Data/User/GameConfig/R3ME01.ini index 312d6a15f1..4c891c14b1 100644 --- a/Data/User/GameConfig/R3ME01.ini +++ b/Data/User/GameConfig/R3ME01.ini @@ -1,20 +1,19 @@ -# R3ME01 - Metroid Prime Trilogy -[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 = Disable EuRGB60(PAL60) to avoid a black bar appearing. -[OnFrame] Add memory patches to be applied every frame here. -[ActionReplay] Add action replay cheats here. -[Video] -ProjectionHack = 0 -PH_SZNear = 0 -PH_SZFar = 0 -PH_ExtraParam = 0 -PH_ZNear = -PH_ZFar = -[Gecko] -[Video_Hacks] -EFBToTextureEnable = False -EFBCopyEnable = True -[Wii] -DisableWiimoteSpeaker = 1 +# R3ME01 - Metroid Prime Trilogy +[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 = Disable EuRGB60(PAL60) to avoid a black bar appearing. +[OnFrame] Add memory patches to be applied every frame here. +[ActionReplay] Add action replay cheats here. +[Video] +ProjectionHack = 0 +PH_SZNear = 0 +PH_SZFar = 0 +PH_ExtraParam = 0 +PH_ZNear = +PH_ZFar = +[Gecko] +[Video_Hacks] +EFBToTextureEnable = False +EFBCopyEnable = True +[Wii] diff --git a/Data/User/GameConfig/R3MP01.ini b/Data/User/GameConfig/R3MP01.ini index 291ac8df38..71938b821a 100644 --- a/Data/User/GameConfig/R3MP01.ini +++ b/Data/User/GameConfig/R3MP01.ini @@ -1,20 +1,19 @@ -# R3MP01 - Metroid Prime Trilogy -[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 = Disable EuRGB60(PAL60) to avoid a black bar appearing. -[OnFrame] Add memory patches to be applied every frame here. -[ActionReplay] Add action replay cheats here. -[Video] -ProjectionHack = 0 -PH_SZNear = 0 -PH_SZFar = 0 -PH_ExtraParam = 0 -PH_ZNear = -PH_ZFar = -[Gecko] -[Video_Hacks] -EFBToTextureEnable = False -EFBCopyEnable = True -[Wii] -DisableWiimoteSpeaker = 1 +# R3MP01 - Metroid Prime Trilogy +[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 = Disable EuRGB60(PAL60) to avoid a black bar appearing. +[OnFrame] Add memory patches to be applied every frame here. +[ActionReplay] Add action replay cheats here. +[Video] +ProjectionHack = 0 +PH_SZNear = 0 +PH_SZFar = 0 +PH_ExtraParam = 0 +PH_ZNear = +PH_ZFar = +[Gecko] +[Video_Hacks] +EFBToTextureEnable = False +EFBCopyEnable = True +[Wii] diff --git a/Data/User/GameConfig/R4QE01.ini b/Data/User/GameConfig/R4QE01.ini index 3ae6cb283a..e822d53161 100644 --- a/Data/User/GameConfig/R4QE01.ini +++ b/Data/User/GameConfig/R4QE01.ini @@ -1,20 +1,19 @@ -# R4QE01 - Mario Strikers Charged -[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 = 5 -EmulationIssues = -[OnFrame] Add memory patches to be applied every frame here. -[ActionReplay] Add action replay cheats here. -[Video] -ProjectionHack = 0 -PH_SZNear = 0 -PH_SZFar = 0 -PH_ExtraParam = 0 -PH_ZNear = -PH_ZFar = -[Gecko] -[Video_Enhancements] -[Video_Hacks] -DlistCachingEnable = False -[Wii] -DisableWiimoteSpeaker = 1 +# R4QE01 - Mario Strikers Charged +[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 = 5 +EmulationIssues = +[OnFrame] Add memory patches to be applied every frame here. +[ActionReplay] Add action replay cheats here. +[Video] +ProjectionHack = 0 +PH_SZNear = 0 +PH_SZFar = 0 +PH_ExtraParam = 0 +PH_ZNear = +PH_ZFar = +[Gecko] +[Video_Enhancements] +[Video_Hacks] +DlistCachingEnable = False +[Wii] diff --git a/Data/User/GameConfig/R4QJ01.ini b/Data/User/GameConfig/R4QJ01.ini index d97cc37c84..14bef2a3e5 100644 --- a/Data/User/GameConfig/R4QJ01.ini +++ b/Data/User/GameConfig/R4QJ01.ini @@ -1,20 +1,19 @@ -# R4QJ01 - Mario Strikers Charged -[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 = 5 -EmulationIssues = -[OnFrame] Add memory patches to be applied every frame here. -[ActionReplay] Add action replay cheats here. -[Video] -ProjectionHack = 0 -PH_SZNear = 0 -PH_SZFar = 0 -PH_ExtraParam = 0 -PH_ZNear = -PH_ZFar = -[Gecko] -[Video_Enhancements] -[Video_Hacks] -DlistCachingEnable = False -[Wii] -DisableWiimoteSpeaker = 1 +# R4QJ01 - Mario Strikers Charged +[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 = 5 +EmulationIssues = +[OnFrame] Add memory patches to be applied every frame here. +[ActionReplay] Add action replay cheats here. +[Video] +ProjectionHack = 0 +PH_SZNear = 0 +PH_SZFar = 0 +PH_ExtraParam = 0 +PH_ZNear = +PH_ZFar = +[Gecko] +[Video_Enhancements] +[Video_Hacks] +DlistCachingEnable = False +[Wii] diff --git a/Data/User/GameConfig/R4QK01.ini b/Data/User/GameConfig/R4QK01.ini index 2c45a961a0..2fb7675fd4 100644 --- a/Data/User/GameConfig/R4QK01.ini +++ b/Data/User/GameConfig/R4QK01.ini @@ -1,20 +1,19 @@ -# R4QK01 - Mario Power Soccer -[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 = 5 -EmulationIssues = -[OnFrame] Add memory patches to be applied every frame here. -[ActionReplay] Add action replay cheats here. -[Video] -ProjectionHack = 0 -PH_SZNear = 0 -PH_SZFar = 0 -PH_ExtraParam = 0 -PH_ZNear = -PH_ZFar = -[Gecko] -[Video_Enhancements] -[Video_Hacks] -DlistCachingEnable = False -[Wii] -DisableWiimoteSpeaker = 1 +# R4QK01 - Mario Power Soccer +[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 = 5 +EmulationIssues = +[OnFrame] Add memory patches to be applied every frame here. +[ActionReplay] Add action replay cheats here. +[Video] +ProjectionHack = 0 +PH_SZNear = 0 +PH_SZFar = 0 +PH_ExtraParam = 0 +PH_ZNear = +PH_ZFar = +[Gecko] +[Video_Enhancements] +[Video_Hacks] +DlistCachingEnable = False +[Wii] diff --git a/Data/User/GameConfig/R4QP01.ini b/Data/User/GameConfig/R4QP01.ini index 8ec96e8cf3..54fa2ec234 100644 --- a/Data/User/GameConfig/R4QP01.ini +++ b/Data/User/GameConfig/R4QP01.ini @@ -1,20 +1,19 @@ -# R4QP01 - Mario Strikers Charged -[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 = 5 -EmulationIssues = -[OnFrame] Add memory patches to be applied every frame here. -[ActionReplay] Add action replay cheats here. -[Video] -ProjectionHack = 0 -PH_SZNear = 0 -PH_SZFar = 0 -PH_ExtraParam = 0 -PH_ZNear = -PH_ZFar = -[Gecko] -[Video_Enhancements] -[Video_Hacks] -DlistCachingEnable = False -[Wii] -DisableWiimoteSpeaker = 1 +# R4QP01 - Mario Strikers Charged +[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 = 5 +EmulationIssues = +[OnFrame] Add memory patches to be applied every frame here. +[ActionReplay] Add action replay cheats here. +[Video] +ProjectionHack = 0 +PH_SZNear = 0 +PH_SZFar = 0 +PH_ExtraParam = 0 +PH_ZNear = +PH_ZFar = +[Gecko] +[Video_Enhancements] +[Video_Hacks] +DlistCachingEnable = False +[Wii] diff --git a/Data/User/GameConfig/R5WEA4.ini b/Data/User/GameConfig/R5WEA4.ini index 315f7f340a..48b1c5cd12 100644 --- a/Data/User/GameConfig/R5WEA4.ini +++ b/Data/User/GameConfig/R5WEA4.ini @@ -15,5 +15,4 @@ PH_ZFar = [Gecko] [Video_Settings] SafeTextureCacheColorSamples = 512 -[Wii] -DisableWiimoteSpeaker = 1 +[Wii] diff --git a/Data/User/GameConfig/R5WJA4.ini b/Data/User/GameConfig/R5WJA4.ini index 30a983b648..25d6076a05 100644 --- a/Data/User/GameConfig/R5WJA4.ini +++ b/Data/User/GameConfig/R5WJA4.ini @@ -15,5 +15,4 @@ PH_ZFar = [Gecko] [Video_Settings] SafeTextureCacheColorSamples = 512 -[Wii] -DisableWiimoteSpeaker = 1 +[Wii] diff --git a/Data/User/GameConfig/R7PE01.ini b/Data/User/GameConfig/R7PE01.ini index 1a052239ae..244ccc1db3 100644 --- a/Data/User/GameConfig/R7PE01.ini +++ b/Data/User/GameConfig/R7PE01.ini @@ -1,19 +1,18 @@ -# R7PE01 - Punch Out -[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 = Disable "Use EuRGB60 (PAL60) mode" in the wii configuration tab for the game to run -[OnFrame] Add memory patches to be applied every frame here. -+$Patch -0x8011E0F8:dword:0x4E800020 -[ActionReplay] Add action replay cheats here. -[Video] -ProjectionHack = 0 -PH_SZNear = 0 -PH_SZFar = 0 -PH_ExtraParam = 0 -PH_ZNear = -PH_ZFar = -[Gecko] -[Wii] -DisableWiimoteSpeaker = 1 +# R7PE01 - Punch Out +[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 = Disable "Use EuRGB60 (PAL60) mode" in the wii configuration tab for the game to run +[OnFrame] Add memory patches to be applied every frame here. ++$Patch +0x8011E0F8:dword:0x4E800020 +[ActionReplay] Add action replay cheats here. +[Video] +ProjectionHack = 0 +PH_SZNear = 0 +PH_SZFar = 0 +PH_ExtraParam = 0 +PH_ZNear = +PH_ZFar = +[Gecko] +[Wii] diff --git a/Data/User/GameConfig/R7PP01.ini b/Data/User/GameConfig/R7PP01.ini index 302bd1e965..a0113b7415 100644 --- a/Data/User/GameConfig/R7PP01.ini +++ b/Data/User/GameConfig/R7PP01.ini @@ -1,13 +1,12 @@ -# R7PP01 - Punch Out -[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 = 5 -[OnFrame] Add memory patches to be applied every frame here. -+$Patch -0x8011F1CC:dword:0x4E800020 -[ActionReplay] Add action replay cheats here. -[Video] -ProjectionHack = 0 -[Wii] -DisableWiimoteSpeaker = 1 +# R7PP01 - Punch Out +[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 = 5 +[OnFrame] Add memory patches to be applied every frame here. ++$Patch +0x8011F1CC:dword:0x4E800020 +[ActionReplay] Add action replay cheats here. +[Video] +ProjectionHack = 0 +[Wii] diff --git a/Data/User/GameConfig/RBWE01.ini b/Data/User/GameConfig/RBWE01.ini index 9e8d586cf4..a2cad6ff7d 100644 --- a/Data/User/GameConfig/RBWE01.ini +++ b/Data/User/GameConfig/RBWE01.ini @@ -1,18 +1,17 @@ -# RBWE01 - Battalion Wars 2 -[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 LLE audio for proper sound. -[OnFrame] Add memory patches to be applied every frame here. -[ActionReplay] Add action replay cheats here. -[Video] -ProjectionHack = 0 -PH_SZNear = 0 -PH_SZFar = 0 -PH_ExtraParam = 0 -PH_ZNear = -PH_ZFar = -[Gecko] -[Video_Enhancements] -[Wii] -DisableWiimoteSpeaker = 1 +# RBWE01 - Battalion Wars 2 +[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 LLE audio for proper sound. +[OnFrame] Add memory patches to be applied every frame here. +[ActionReplay] Add action replay cheats here. +[Video] +ProjectionHack = 0 +PH_SZNear = 0 +PH_SZFar = 0 +PH_ExtraParam = 0 +PH_ZNear = +PH_ZFar = +[Gecko] +[Video_Enhancements] +[Wii] diff --git a/Data/User/GameConfig/RBWJ01.ini b/Data/User/GameConfig/RBWJ01.ini index bf95ff65c8..0d799c74fa 100644 --- a/Data/User/GameConfig/RBWJ01.ini +++ b/Data/User/GameConfig/RBWJ01.ini @@ -1,18 +1,17 @@ -# RBWJ01 - Totsugeki Famicom Wars vs. -[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 LLE audio for proper sound. -[OnFrame] Add memory patches to be applied every frame here. -[ActionReplay] Add action replay cheats here. -[Video] -ProjectionHack = 0 -PH_SZNear = 0 -PH_SZFar = 0 -PH_ExtraParam = 0 -PH_ZNear = -PH_ZFar = -[Gecko] -[Video_Enhancements] -[Wii] -DisableWiimoteSpeaker = 1 +# RBWJ01 - Totsugeki Famicom Wars vs. +[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 LLE audio for proper sound. +[OnFrame] Add memory patches to be applied every frame here. +[ActionReplay] Add action replay cheats here. +[Video] +ProjectionHack = 0 +PH_SZNear = 0 +PH_SZFar = 0 +PH_ExtraParam = 0 +PH_ZNear = +PH_ZFar = +[Gecko] +[Video_Enhancements] +[Wii] diff --git a/Data/User/GameConfig/RBWP01.ini b/Data/User/GameConfig/RBWP01.ini index f6282130a5..5422388866 100644 --- a/Data/User/GameConfig/RBWP01.ini +++ b/Data/User/GameConfig/RBWP01.ini @@ -1,18 +1,17 @@ -# RBWP01 - Battalion Wars 2 -[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 LLE audio for proper sound. -[OnFrame] Add memory patches to be applied every frame here. -[ActionReplay] Add action replay cheats here. -[Video] -ProjectionHack = 0 -PH_SZNear = 0 -PH_SZFar = 0 -PH_ExtraParam = 0 -PH_ZNear = -PH_ZFar = -[Gecko] -[Video_Enhancements] -[Wii] -DisableWiimoteSpeaker = 1 +# RBWP01 - Battalion Wars 2 +[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 LLE audio for proper sound. +[OnFrame] Add memory patches to be applied every frame here. +[ActionReplay] Add action replay cheats here. +[Video] +ProjectionHack = 0 +PH_SZNear = 0 +PH_SZFar = 0 +PH_ExtraParam = 0 +PH_ZNear = +PH_ZFar = +[Gecko] +[Video_Enhancements] +[Wii] diff --git a/Data/User/GameConfig/RCJE8P.ini b/Data/User/GameConfig/RCJE8P.ini index 845f08de77..79280a5609 100644 --- a/Data/User/GameConfig/RCJE8P.ini +++ b/Data/User/GameConfig/RCJE8P.ini @@ -24,6 +24,5 @@ PH_ZFar = [Video_Enhancements] ForceFiltering = False [Wii] -DisableWiimoteSpeaker = 1 [Video_Hacks] DlistCachingEnable = False diff --git a/Data/User/GameConfig/RCJP8P.ini b/Data/User/GameConfig/RCJP8P.ini index 6d82c897e5..5a242b5e4e 100644 --- a/Data/User/GameConfig/RCJP8P.ini +++ b/Data/User/GameConfig/RCJP8P.ini @@ -18,6 +18,5 @@ PH_ZFar = [Video_Enhancements] ForceFiltering = False [Wii] -DisableWiimoteSpeaker = 1 [Video_Hacks] DlistCachingEnable = False diff --git a/Data/User/GameConfig/RD2E41.ini b/Data/User/GameConfig/RD2E41.ini index a93f6359e6..92ca3f53b5 100644 --- a/Data/User/GameConfig/RD2E41.ini +++ b/Data/User/GameConfig/RD2E41.ini @@ -1,17 +1,16 @@ -# RD2E41 - Red Steel 2 -[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 wiimote and motion plus. -[OnFrame] Add memory patches to be applied every frame here. -[ActionReplay] Add action replay cheats here. -[Video] -ProjectionHack = 0 -PH_SZNear = 0 -PH_SZFar = 0 -PH_ExtraParam = 0 -PH_ZNear = -PH_ZFar = -[Gecko] -[Wii] -DisableWiimoteSpeaker = 1 +# RD2E41 - Red Steel 2 +[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 wiimote and motion plus. +[OnFrame] Add memory patches to be applied every frame here. +[ActionReplay] Add action replay cheats here. +[Video] +ProjectionHack = 0 +PH_SZNear = 0 +PH_SZFar = 0 +PH_ExtraParam = 0 +PH_ZNear = +PH_ZFar = +[Gecko] +[Wii] diff --git a/Data/User/GameConfig/RD2J41.ini b/Data/User/GameConfig/RD2J41.ini index 8fccc41c35..2042a71430 100644 --- a/Data/User/GameConfig/RD2J41.ini +++ b/Data/User/GameConfig/RD2J41.ini @@ -1,17 +1,16 @@ -# RD2J41 - Red Steel 2 -[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 wiimote and motion plus. -[OnFrame] Add memory patches to be applied every frame here. -[ActionReplay] Add action replay cheats here. -[Video] -ProjectionHack = 0 -PH_SZNear = 0 -PH_SZFar = 0 -PH_ExtraParam = 0 -PH_ZNear = -PH_ZFar = -[Gecko] -[Wii] -DisableWiimoteSpeaker = 1 +# RD2J41 - Red Steel 2 +[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 wiimote and motion plus. +[OnFrame] Add memory patches to be applied every frame here. +[ActionReplay] Add action replay cheats here. +[Video] +ProjectionHack = 0 +PH_SZNear = 0 +PH_SZFar = 0 +PH_ExtraParam = 0 +PH_ZNear = +PH_ZFar = +[Gecko] +[Wii] diff --git a/Data/User/GameConfig/RD2K41.ini b/Data/User/GameConfig/RD2K41.ini index aa0e90f2b2..93123fa871 100644 --- a/Data/User/GameConfig/RD2K41.ini +++ b/Data/User/GameConfig/RD2K41.ini @@ -1,17 +1,16 @@ -# RD2K41 - Red Steel 2 -[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 wiimote and motion plus. -[OnFrame] Add memory patches to be applied every frame here. -[ActionReplay] Add action replay cheats here. -[Video] -ProjectionHack = 0 -PH_SZNear = 0 -PH_SZFar = 0 -PH_ExtraParam = 0 -PH_ZNear = -PH_ZFar = -[Gecko] -[Wii] -DisableWiimoteSpeaker = 1 +# RD2K41 - Red Steel 2 +[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 wiimote and motion plus. +[OnFrame] Add memory patches to be applied every frame here. +[ActionReplay] Add action replay cheats here. +[Video] +ProjectionHack = 0 +PH_SZNear = 0 +PH_SZFar = 0 +PH_ExtraParam = 0 +PH_ZNear = +PH_ZFar = +[Gecko] +[Wii] diff --git a/Data/User/GameConfig/RD2P41.ini b/Data/User/GameConfig/RD2P41.ini index 7cbf91b22d..8a7e5f7541 100644 --- a/Data/User/GameConfig/RD2P41.ini +++ b/Data/User/GameConfig/RD2P41.ini @@ -1,17 +1,16 @@ -# RD2P41 - Red Steel 2 -[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 wiimote and motion plus. -[OnFrame] Add memory patches to be applied every frame here. -[ActionReplay] Add action replay cheats here. -[Video] -ProjectionHack = 0 -PH_SZNear = 0 -PH_SZFar = 0 -PH_ExtraParam = 0 -PH_ZNear = -PH_ZFar = -[Gecko] -[Wii] -DisableWiimoteSpeaker = 1 +# RD2P41 - Red Steel 2 +[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 wiimote and motion plus. +[OnFrame] Add memory patches to be applied every frame here. +[ActionReplay] Add action replay cheats here. +[Video] +ProjectionHack = 0 +PH_SZNear = 0 +PH_SZFar = 0 +PH_ExtraParam = 0 +PH_ZNear = +PH_ZFar = +[Gecko] +[Wii] diff --git a/Data/User/GameConfig/RD2X41.ini b/Data/User/GameConfig/RD2X41.ini index 6748136cad..53f0716869 100644 --- a/Data/User/GameConfig/RD2X41.ini +++ b/Data/User/GameConfig/RD2X41.ini @@ -1,17 +1,16 @@ -# RD2X41 - Red Steel 2 -[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 wiimote and motion plus. -[OnFrame] Add memory patches to be applied every frame here. -[ActionReplay] Add action replay cheats here. -[Video] -ProjectionHack = 0 -PH_SZNear = 0 -PH_SZFar = 0 -PH_ExtraParam = 0 -PH_ZNear = -PH_ZFar = -[Gecko] -[Wii] -DisableWiimoteSpeaker = 1 +# RD2X41 - Red Steel 2 +[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 wiimote and motion plus. +[OnFrame] Add memory patches to be applied every frame here. +[ActionReplay] Add action replay cheats here. +[Video] +ProjectionHack = 0 +PH_SZNear = 0 +PH_SZFar = 0 +PH_ExtraParam = 0 +PH_ZNear = +PH_ZFar = +[Gecko] +[Wii] diff --git a/Data/User/GameConfig/RHDE8P.ini b/Data/User/GameConfig/RHDE8P.ini index b49ec93cb8..31d7a2f620 100644 --- a/Data/User/GameConfig/RHDE8P.ini +++ b/Data/User/GameConfig/RHDE8P.ini @@ -1,20 +1,19 @@ -# RHDE8P - THE HOUSE OF THE DEAD 2 AND 3 RETURN -[Core] Values set here will override the main dolphin settings. -[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set. -EmulationStateId = 4 -EmulationIssues = -[OnFrame] Add memory patches to be applied every frame here. -[ActionReplay] Add action replay cheats here. -[Video] -ProjectionHack = 0 -PH_SZNear = 0 -PH_SZFar = 0 -PH_ExtraParam = 0 -PH_ZNear = -PH_ZFar = -[Gecko] -[Video_Settings] -UseXFB = True -UseRealXFB = False -[Wii] -DisableWiimoteSpeaker = 1 +# RHDE8P - THE HOUSE OF THE DEAD 2 AND 3 RETURN +[Core] Values set here will override the main dolphin settings. +[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set. +EmulationStateId = 4 +EmulationIssues = +[OnFrame] Add memory patches to be applied every frame here. +[ActionReplay] Add action replay cheats here. +[Video] +ProjectionHack = 0 +PH_SZNear = 0 +PH_SZFar = 0 +PH_ExtraParam = 0 +PH_ZNear = +PH_ZFar = +[Gecko] +[Video_Settings] +UseXFB = True +UseRealXFB = False +[Wii] diff --git a/Data/User/GameConfig/RHDJ8P.ini b/Data/User/GameConfig/RHDJ8P.ini index 63e818f737..014c94aaba 100644 --- a/Data/User/GameConfig/RHDJ8P.ini +++ b/Data/User/GameConfig/RHDJ8P.ini @@ -1,20 +1,19 @@ -# RHDJ8P - THE HOUSE OF THE DEAD 2 AND 3 RETURN -[Core] Values set here will override the main dolphin settings. -[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set. -EmulationStateId = 4 -EmulationIssues = -[OnFrame] Add memory patches to be applied every frame here. -[ActionReplay] Add action replay cheats here. -[Video] -ProjectionHack = 0 -PH_SZNear = 0 -PH_SZFar = 0 -PH_ExtraParam = 0 -PH_ZNear = -PH_ZFar = -[Gecko] -[Video_Settings] -UseXFB = True -UseRealXFB = False -[Wii] -DisableWiimoteSpeaker = 1 +# RHDJ8P - THE HOUSE OF THE DEAD 2 AND 3 RETURN +[Core] Values set here will override the main dolphin settings. +[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set. +EmulationStateId = 4 +EmulationIssues = +[OnFrame] Add memory patches to be applied every frame here. +[ActionReplay] Add action replay cheats here. +[Video] +ProjectionHack = 0 +PH_SZNear = 0 +PH_SZFar = 0 +PH_ExtraParam = 0 +PH_ZNear = +PH_ZFar = +[Gecko] +[Video_Settings] +UseXFB = True +UseRealXFB = False +[Wii] diff --git a/Data/User/GameConfig/RHDP8P.ini b/Data/User/GameConfig/RHDP8P.ini index e932c173fb..6183ad8422 100644 --- a/Data/User/GameConfig/RHDP8P.ini +++ b/Data/User/GameConfig/RHDP8P.ini @@ -1,20 +1,19 @@ -# RHDP8P - THE HOUSE OF THE DEAD 2 AND 3 RETURN -[Core] Values set here will override the main dolphin settings. -[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set. -EmulationStateId = 4 -EmulationIssues = -[OnFrame] Add memory patches to be applied every frame here. -[ActionReplay] Add action replay cheats here. -[Video] -ProjectionHack = 0 -PH_SZNear = 0 -PH_SZFar = 0 -PH_ExtraParam = 0 -PH_ZNear = -PH_ZFar = -[Gecko] -[Video_Settings] -UseXFB = True -UseRealXFB = False -[Wii] -DisableWiimoteSpeaker = 1 +# RHDP8P - THE HOUSE OF THE DEAD 2 AND 3 RETURN +[Core] Values set here will override the main dolphin settings. +[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set. +EmulationStateId = 4 +EmulationIssues = +[OnFrame] Add memory patches to be applied every frame here. +[ActionReplay] Add action replay cheats here. +[Video] +ProjectionHack = 0 +PH_SZNear = 0 +PH_SZFar = 0 +PH_ExtraParam = 0 +PH_ZNear = +PH_ZFar = +[Gecko] +[Video_Settings] +UseXFB = True +UseRealXFB = False +[Wii] diff --git a/Data/User/GameConfig/RHOE8P.ini b/Data/User/GameConfig/RHOE8P.ini index c28f341fb6..55d697ca52 100644 --- a/Data/User/GameConfig/RHOE8P.ini +++ b/Data/User/GameConfig/RHOE8P.ini @@ -1,39 +1,38 @@ -# RHOE8P - House Of The Dead: OVERKILL -[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 = Use dx11 plugin (r6945) -[OnFrame] Add memory patches to be applied every frame here. -[ActionReplay] Add action replay cheats here. -[Video] -ProjectionHack = 0 -PH_SZNear = 0 -PH_SZFar = 0 -PH_ExtraParam = 0 -PH_ZNear = -PH_ZFar = -[Gecko] -$Infinte Bomb Usage after Getting 1 [g6flavor] -04159D1C 60000000 -$If Score Increase, MAX [ZiT] -C2142134 00000002 -3CA03B9B 38A5C9FF -90A60178 00000000 -$Infinite LIFE [ZiT] -04130ED4 60000000 -$Infinite Bullet [ZiT] -04159FAC 907D0720 -$CASH MAX [ZiT] -C214B118 00000002 -3CA03B9B 38A5C9FF -90A300D8 00000000 -$CASH MAX [ZiT] -C214B110 00000002 -3CA03B9B 38A5C9FF -90A300DC 00000000 -$If Score Increase, MAX [ZiT] -C2152674 00000002 -3CA03B9B 38A5C9FF -90B60178 00000000 -[Wii] -DisableWiimoteSpeaker = 1 +# RHOE8P - House Of The Dead: OVERKILL +[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 = Use dx11 plugin (r6945) +[OnFrame] Add memory patches to be applied every frame here. +[ActionReplay] Add action replay cheats here. +[Video] +ProjectionHack = 0 +PH_SZNear = 0 +PH_SZFar = 0 +PH_ExtraParam = 0 +PH_ZNear = +PH_ZFar = +[Gecko] +$Infinte Bomb Usage after Getting 1 [g6flavor] +04159D1C 60000000 +$If Score Increase, MAX [ZiT] +C2142134 00000002 +3CA03B9B 38A5C9FF +90A60178 00000000 +$Infinite LIFE [ZiT] +04130ED4 60000000 +$Infinite Bullet [ZiT] +04159FAC 907D0720 +$CASH MAX [ZiT] +C214B118 00000002 +3CA03B9B 38A5C9FF +90A300D8 00000000 +$CASH MAX [ZiT] +C214B110 00000002 +3CA03B9B 38A5C9FF +90A300DC 00000000 +$If Score Increase, MAX [ZiT] +C2152674 00000002 +3CA03B9B 38A5C9FF +90B60178 00000000 +[Wii] diff --git a/Data/User/GameConfig/RHOJ8P.ini b/Data/User/GameConfig/RHOJ8P.ini index 3e23f6605c..2eb65c9fc9 100644 --- a/Data/User/GameConfig/RHOJ8P.ini +++ b/Data/User/GameConfig/RHOJ8P.ini @@ -1,12 +1,11 @@ -# RHOJ8P - House Of The Dead: OVERKILL -[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 = Use dx11 plugin (r6945) -[OnFrame] Add memory patches to be applied every frame here. -[ActionReplay] Add action replay cheats here. -[Video] -ProjectionHack = 0 -[Gecko] -[Wii] -DisableWiimoteSpeaker = 1 +# RHOJ8P - House Of The Dead: OVERKILL +[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 = Use dx11 plugin (r6945) +[OnFrame] Add memory patches to be applied every frame here. +[ActionReplay] Add action replay cheats here. +[Video] +ProjectionHack = 0 +[Gecko] +[Wii] diff --git a/Data/User/GameConfig/RHOP8P.ini b/Data/User/GameConfig/RHOP8P.ini index 8e9d0e879d..85a8e2770a 100644 --- a/Data/User/GameConfig/RHOP8P.ini +++ b/Data/User/GameConfig/RHOP8P.ini @@ -1,12 +1,11 @@ -# RHOP8P - House Of The Dead: OVERKILL -[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 = Use dx11 plugin (r6945) -[OnFrame] Add memory patches to be applied every frame here. -[ActionReplay] Add action replay cheats here. -[Video] -ProjectionHack = 0 -[Gecko] -[Wii] -DisableWiimoteSpeaker = 1 +# RHOP8P - House Of The Dead: OVERKILL +[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 = Use dx11 plugin (r6945) +[OnFrame] Add memory patches to be applied every frame here. +[ActionReplay] Add action replay cheats here. +[Video] +ProjectionHack = 0 +[Gecko] +[Wii] diff --git a/Data/User/GameConfig/RLGE64.ini b/Data/User/GameConfig/RLGE64.ini index 505df3c17d..5e66cda379 100644 --- a/Data/User/GameConfig/RLGE64.ini +++ b/Data/User/GameConfig/RLGE64.ini @@ -6,7 +6,6 @@ EmulationIssues = [OnFrame] Add memory patches to be applied every frame here. [ActionReplay] Add action replay cheats here. [Wii] -DisableWiimoteSpeaker = 1 [Video] ProjectionHack = 0 PH_SZNear = 0 diff --git a/Data/User/GameConfig/RLGJ52.ini b/Data/User/GameConfig/RLGJ52.ini index 52b8648072..37b4f728d1 100644 --- a/Data/User/GameConfig/RLGJ52.ini +++ b/Data/User/GameConfig/RLGJ52.ini @@ -6,7 +6,6 @@ EmulationIssues = [OnFrame] Add memory patches to be applied every frame here. [ActionReplay] Add action replay cheats here. [Wii] -DisableWiimoteSpeaker = 1 [Video] ProjectionHack = 0 PH_SZNear = 0 diff --git a/Data/User/GameConfig/RLGP64.ini b/Data/User/GameConfig/RLGP64.ini index f82d202584..6404bf0a77 100644 --- a/Data/User/GameConfig/RLGP64.ini +++ b/Data/User/GameConfig/RLGP64.ini @@ -6,7 +6,6 @@ EmulationIssues = [OnFrame] Add memory patches to be applied every frame here. [ActionReplay] Add action replay cheats here. [Wii] -DisableWiimoteSpeaker = 1 [Video] ProjectionHack = 0 PH_SZNear = 0 diff --git a/Data/User/GameConfig/RM3E01.ini b/Data/User/GameConfig/RM3E01.ini index cb87db9070..182660bd97 100644 --- a/Data/User/GameConfig/RM3E01.ini +++ b/Data/User/GameConfig/RM3E01.ini @@ -21,6 +21,5 @@ SafeTextureCacheColorSamples = 512 EFBToTextureEnable = False EFBCopyEnable = True [Wii] -DisableWiimoteSpeaker = 1 [Video_Hacks] EFBEmulateFormatChanges = True diff --git a/Data/User/GameConfig/RM3J01.ini b/Data/User/GameConfig/RM3J01.ini index 97a88c4c69..50c84d87a9 100644 --- a/Data/User/GameConfig/RM3J01.ini +++ b/Data/User/GameConfig/RM3J01.ini @@ -21,6 +21,5 @@ SafeTextureCacheColorSamples = 512 EFBToTextureEnable = False EFBCopyEnable = True [Wii] -DisableWiimoteSpeaker = 1 [Video_Hacks] EFBEmulateFormatChanges = True diff --git a/Data/User/GameConfig/RM3P01.ini b/Data/User/GameConfig/RM3P01.ini index 093afc15db..0832325938 100644 --- a/Data/User/GameConfig/RM3P01.ini +++ b/Data/User/GameConfig/RM3P01.ini @@ -23,6 +23,5 @@ SafeTextureCacheColorSamples = 512 EFBToTextureEnable = False EFBCopyEnable = True [Wii] -DisableWiimoteSpeaker = 1 [Video_Hacks] EFBEmulateFormatChanges = True diff --git a/Data/User/GameConfig/RQREXJ.ini b/Data/User/GameConfig/RQREXJ.ini index 91a35e540d..48d52b4320 100644 --- a/Data/User/GameConfig/RQREXJ.ini +++ b/Data/User/GameConfig/RQREXJ.ini @@ -16,5 +16,4 @@ EmulationIssues = Needs single core to run properly(r7436). [OnFrame] [ActionReplay] [Gecko] -[Wii] -DisableWiimoteSpeaker = 1 +[Wii] diff --git a/Data/User/GameConfig/RQRJAF.ini b/Data/User/GameConfig/RQRJAF.ini index c647c4acee..7ae768c3b4 100644 --- a/Data/User/GameConfig/RQRJAF.ini +++ b/Data/User/GameConfig/RQRJAF.ini @@ -16,5 +16,4 @@ EmulationIssues = Needs single core to run properly(r7436). [OnFrame] [ActionReplay] [Gecko] -[Wii] -DisableWiimoteSpeaker = 1 +[Wii] diff --git a/Data/User/GameConfig/RQRPAF.ini b/Data/User/GameConfig/RQRPAF.ini index 8052e6084b..752c0fa2bd 100644 --- a/Data/User/GameConfig/RQRPAF.ini +++ b/Data/User/GameConfig/RQRPAF.ini @@ -16,5 +16,4 @@ EmulationIssues = Needs single core to run properly(r7436). [OnFrame] [ActionReplay] [Gecko] -[Wii] -DisableWiimoteSpeaker = 1 +[Wii] diff --git a/Data/User/GameConfig/RRKE70.ini b/Data/User/GameConfig/RRKE70.ini index 621b0dfd09..ebb3188d0b 100644 --- a/Data/User/GameConfig/RRKE70.ini +++ b/Data/User/GameConfig/RRKE70.ini @@ -16,5 +16,4 @@ EmulationIssues = [Gecko] [Video_Hacks] EFBEmulateFormatChanges = True -[Wii] -DisableWiimoteSpeaker = 1 +[Wii] diff --git a/Data/User/GameConfig/RRKP70.ini b/Data/User/GameConfig/RRKP70.ini index c5fc07ede3..e69e07f92e 100644 --- a/Data/User/GameConfig/RRKP70.ini +++ b/Data/User/GameConfig/RRKP70.ini @@ -16,5 +16,4 @@ EmulationIssues = [Gecko] [Video_Hacks] EFBEmulateFormatChanges = True -[Wii] -DisableWiimoteSpeaker = 1 +[Wii] diff --git a/Data/User/GameConfig/RTZE08.ini b/Data/User/GameConfig/RTZE08.ini index ff41b71a06..27524e8236 100644 --- a/Data/User/GameConfig/RTZE08.ini +++ b/Data/User/GameConfig/RTZE08.ini @@ -1,20 +1,19 @@ -# RTZE08 - Zack and Wiki: Quest for Barbaros' Treasure -[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 -[OnFrame] Add memory patches to be applied every frame here. -[ActionReplay] Add action replay cheats here. -[Video] -ProjectionHack = 0 -PH_SZNear = 0 -PH_SZFar = 0 -PH_ExtraParam = 0 -PH_ZNear = -PH_ZFar = -[Gecko] -[Video_Settings] -UseXFB = True -UseRealXFB = False -[Wii] -DisableWiimoteSpeaker = 1 +# RTZE08 - Zack and Wiki: Quest for Barbaros' Treasure +[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 +[OnFrame] Add memory patches to be applied every frame here. +[ActionReplay] Add action replay cheats here. +[Video] +ProjectionHack = 0 +PH_SZNear = 0 +PH_SZFar = 0 +PH_ExtraParam = 0 +PH_ZNear = +PH_ZFar = +[Gecko] +[Video_Settings] +UseXFB = True +UseRealXFB = False +[Wii] diff --git a/Data/User/GameConfig/RTZJ08.ini b/Data/User/GameConfig/RTZJ08.ini index 5a62e2c8ca..6a5aa8d6ee 100644 --- a/Data/User/GameConfig/RTZJ08.ini +++ b/Data/User/GameConfig/RTZJ08.ini @@ -1,20 +1,19 @@ -# RTZJ08 - Zack and Wiki: Quest for Barbaros' Treasure -[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 -[OnFrame] Add memory patches to be applied every frame here. -[ActionReplay] Add action replay cheats here. -[Video] -ProjectionHack = 0 -PH_SZNear = 0 -PH_SZFar = 0 -PH_ExtraParam = 0 -PH_ZNear = -PH_ZFar = -[Gecko] -[Video_Settings] -UseXFB = True -UseRealXFB = False -[Wii] -DisableWiimoteSpeaker = 1 +# RTZJ08 - Zack and Wiki: Quest for Barbaros' Treasure +[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 +[OnFrame] Add memory patches to be applied every frame here. +[ActionReplay] Add action replay cheats here. +[Video] +ProjectionHack = 0 +PH_SZNear = 0 +PH_SZFar = 0 +PH_ExtraParam = 0 +PH_ZNear = +PH_ZFar = +[Gecko] +[Video_Settings] +UseXFB = True +UseRealXFB = False +[Wii] diff --git a/Data/User/GameConfig/RTZK08.ini b/Data/User/GameConfig/RTZK08.ini index 6a7d00e753..ec333d6bce 100644 --- a/Data/User/GameConfig/RTZK08.ini +++ b/Data/User/GameConfig/RTZK08.ini @@ -1,20 +1,19 @@ -# RTZK08 - Zack and Wiki: Quest for Barbaros' Treasure -[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 -[OnFrame] Add memory patches to be applied every frame here. -[ActionReplay] Add action replay cheats here. -[Video] -ProjectionHack = 0 -PH_SZNear = 0 -PH_SZFar = 0 -PH_ExtraParam = 0 -PH_ZNear = -PH_ZFar = -[Gecko] -[Video_Settings] -UseXFB = True -UseRealXFB = False -[Wii] -DisableWiimoteSpeaker = 1 +# RTZK08 - Zack and Wiki: Quest for Barbaros' Treasure +[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 +[OnFrame] Add memory patches to be applied every frame here. +[ActionReplay] Add action replay cheats here. +[Video] +ProjectionHack = 0 +PH_SZNear = 0 +PH_SZFar = 0 +PH_ExtraParam = 0 +PH_ZNear = +PH_ZFar = +[Gecko] +[Video_Settings] +UseXFB = True +UseRealXFB = False +[Wii] diff --git a/Data/User/GameConfig/RTZP08.ini b/Data/User/GameConfig/RTZP08.ini index 8add9d2869..f3b0834049 100644 --- a/Data/User/GameConfig/RTZP08.ini +++ b/Data/User/GameConfig/RTZP08.ini @@ -1,20 +1,19 @@ -# RTZP08 - Zack and Wiki: Quest for Barbaros' Treasure -[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 -[OnFrame] Add memory patches to be applied every frame here. -[ActionReplay] Add action replay cheats here. -[Video] -ProjectionHack = 0 -PH_SZNear = 0 -PH_SZFar = 0 -PH_ExtraParam = 0 -PH_ZNear = -PH_ZFar = -[Gecko] -[Video_Settings] -UseXFB = True -UseRealXFB = False -[Wii] -DisableWiimoteSpeaker = 1 +# RTZP08 - Zack and Wiki: Quest for Barbaros' Treasure +[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 +[OnFrame] Add memory patches to be applied every frame here. +[ActionReplay] Add action replay cheats here. +[Video] +ProjectionHack = 0 +PH_SZNear = 0 +PH_SZFar = 0 +PH_ExtraParam = 0 +PH_ZNear = +PH_ZFar = +[Gecko] +[Video_Settings] +UseXFB = True +UseRealXFB = False +[Wii] diff --git a/Data/User/GameConfig/RZJD69.ini b/Data/User/GameConfig/RZJD69.ini index 671318fd38..848dcba860 100644 --- a/Data/User/GameConfig/RZJD69.ini +++ b/Data/User/GameConfig/RZJD69.ini @@ -17,5 +17,4 @@ PH_ZFar = [Video_Settings] SafeTextureCacheColorSamples = 512 [Video_Enhancements] -[Wii] -DisableWiimoteSpeaker = 1 +[Wii] diff --git a/Data/User/GameConfig/RZJE69.ini b/Data/User/GameConfig/RZJE69.ini index a37d3f9223..c48c837a27 100644 --- a/Data/User/GameConfig/RZJE69.ini +++ b/Data/User/GameConfig/RZJE69.ini @@ -17,5 +17,4 @@ PH_ZFar = [Video_Settings] SafeTextureCacheColorSamples = 512 [Video_Enhancements] -[Wii] -DisableWiimoteSpeaker = 1 +[Wii] diff --git a/Data/User/GameConfig/RZJJ13.ini b/Data/User/GameConfig/RZJJ13.ini index d109d22a98..24aa98035b 100644 --- a/Data/User/GameConfig/RZJJ13.ini +++ b/Data/User/GameConfig/RZJJ13.ini @@ -17,5 +17,4 @@ PH_ZFar = [Video_Settings] SafeTextureCacheColorSamples = 512 [Video_Enhancements] -[Wii] -DisableWiimoteSpeaker = 1 +[Wii] diff --git a/Data/User/GameConfig/RZJP69.ini b/Data/User/GameConfig/RZJP69.ini index 63b230b1da..9fa88eb843 100644 --- a/Data/User/GameConfig/RZJP69.ini +++ b/Data/User/GameConfig/RZJP69.ini @@ -31,6 +31,5 @@ $Rapid Fire [TNTkryzt] [Video_Settings] SafeTextureCacheColorSamples = 512 [Video_Enhancements] -[Wii] -DisableWiimoteSpeaker = 1 +[Wii] diff --git a/Data/User/GameConfig/RZZE8P.ini b/Data/User/GameConfig/RZZE8P.ini index 31859ef891..9c74320a0b 100644 --- a/Data/User/GameConfig/RZZE8P.ini +++ b/Data/User/GameConfig/RZZE8P.ini @@ -1,17 +1,16 @@ -# RZZE8P - MADWORLD -[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 = 5 -EmulationIssues = -[OnFrame] Add memory patches to be applied every frame here. -[ActionReplay] Add action replay cheats here. -[Video] -ProjectionHack = 0 -PH_SZNear = 0 -PH_SZFar = 0 -PH_ExtraParam = 0 -PH_ZNear = -PH_ZFar = -[Gecko] -[Wii] -DisableWiimoteSpeaker = 1 +# RZZE8P - MADWORLD +[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 = 5 +EmulationIssues = +[OnFrame] Add memory patches to be applied every frame here. +[ActionReplay] Add action replay cheats here. +[Video] +ProjectionHack = 0 +PH_SZNear = 0 +PH_SZFar = 0 +PH_ExtraParam = 0 +PH_ZNear = +PH_ZFar = +[Gecko] +[Wii] diff --git a/Data/User/GameConfig/RZZJEL.ini b/Data/User/GameConfig/RZZJEL.ini index 0e6a08334a..6ace0cb90c 100644 --- a/Data/User/GameConfig/RZZJEL.ini +++ b/Data/User/GameConfig/RZZJEL.ini @@ -1,17 +1,16 @@ -# RZZJEL - MADWORLD -[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 = 5 -EmulationIssues = -[OnFrame] Add memory patches to be applied every frame here. -[ActionReplay] Add action replay cheats here. -[Video] -ProjectionHack = 0 -PH_SZNear = 0 -PH_SZFar = 0 -PH_ExtraParam = 0 -PH_ZNear = -PH_ZFar = -[Gecko] -[Wii] -DisableWiimoteSpeaker = 1 +# RZZJEL - MADWORLD +[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 = 5 +EmulationIssues = +[OnFrame] Add memory patches to be applied every frame here. +[ActionReplay] Add action replay cheats here. +[Video] +ProjectionHack = 0 +PH_SZNear = 0 +PH_SZFar = 0 +PH_ExtraParam = 0 +PH_ZNear = +PH_ZFar = +[Gecko] +[Wii] diff --git a/Data/User/GameConfig/RZZP8P.ini b/Data/User/GameConfig/RZZP8P.ini index 6dc117c26f..ac5bed9812 100644 --- a/Data/User/GameConfig/RZZP8P.ini +++ b/Data/User/GameConfig/RZZP8P.ini @@ -1,17 +1,16 @@ -# RZZP8P - MADWORLD -[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 = 5 -EmulationIssues = -[OnFrame] Add memory patches to be applied every frame here. -[ActionReplay] Add action replay cheats here. -[Video] -ProjectionHack = 0 -PH_SZNear = 0 -PH_SZFar = 0 -PH_ExtraParam = 0 -PH_ZNear = -PH_ZFar = -[Gecko] -[Wii] -DisableWiimoteSpeaker = 1 +# RZZP8P - MADWORLD +[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 = 5 +EmulationIssues = +[OnFrame] Add memory patches to be applied every frame here. +[ActionReplay] Add action replay cheats here. +[Video] +ProjectionHack = 0 +PH_SZNear = 0 +PH_SZFar = 0 +PH_ExtraParam = 0 +PH_ZNear = +PH_ZFar = +[Gecko] +[Wii] diff --git a/Data/User/GameConfig/SC2E8P.ini b/Data/User/GameConfig/SC2E8P.ini index ff46b91be8..998d51859d 100644 --- a/Data/User/GameConfig/SC2E8P.ini +++ b/Data/User/GameConfig/SC2E8P.ini @@ -1,21 +1,20 @@ -# SC2E8P - Conduit 2 -[Core] -BlockMerging = 1 -[Video] -ProjectionHack = 0 -PH_SZNear = 0 -PH_SZFar = 0 -PH_ExtraParam = 0 -PH_ZNear = -PH_ZFar = -[EmuState] -EmulationStateId = 4 -EmulationIssues = -[OnFrame] -[ActionReplay] -[Gecko] -[Video_Hacks] -DlistCachingEnable = False -[Video_Settings] -[Wii] -DisableWiimoteSpeaker = 1 +# SC2E8P - Conduit 2 +[Core] +BlockMerging = 1 +[Video] +ProjectionHack = 0 +PH_SZNear = 0 +PH_SZFar = 0 +PH_ExtraParam = 0 +PH_ZNear = +PH_ZFar = +[EmuState] +EmulationStateId = 4 +EmulationIssues = +[OnFrame] +[ActionReplay] +[Gecko] +[Video_Hacks] +DlistCachingEnable = False +[Video_Settings] +[Wii] diff --git a/Data/User/GameConfig/SC2P8P.ini b/Data/User/GameConfig/SC2P8P.ini index a065f8a096..b9f5c5989c 100644 --- a/Data/User/GameConfig/SC2P8P.ini +++ b/Data/User/GameConfig/SC2P8P.ini @@ -1,70 +1,69 @@ -# SC2P8P - Conduit 2 -[Core] -BlockMerging = 1 -[Video] -ProjectionHack = 0 -PH_SZNear = 0 -PH_SZFar = 0 -PH_ExtraParam = 0 -PH_ZNear = -PH_ZFar = -[EmuState] -EmulationStateId = 4 -EmulationIssues = -[OnFrame] -[ActionReplay] -[Gecko] -$Undead Invincibility Mode [Bully@Wiiplaza] -F6000001 80008100 -8001002C 90180000 -D200000C 00000006 -2C110035 40820020 -2C0800F4 40820018 -2C0300A0 40820010 -3C007FFF 6000FFFF -90040000 80040000 -60000000 00000000 -E0000000 80008000 -**Offline Only* -**You are completely untouchable* -*Picture -> http://imageshack.us/photo/my-images/684/sc2p8p008.png/ -$Inf. Ammo [Bully@Wiiplaza] -F6000001 80008100 -80640000 80050000 -D2000008 00000003 -2C110021 4082000C -38600000 7C030050 -60000000 00000000 -E0000000 80008000 -**Offline Only* -$No Flashwhite [Bully@Wiiplaza] -F6000001 80008100 -EC210032 93C10008 -14000114 60000000 -E0000000 80008000 -$Inf. Money [Bully@Wiiplaza] -F6000001 80008100 -7C003A14 38E70001 -D2000010 00000004 -2C11002F 40820014 -2C0401A8 4082000C -3D807FFF 7D84012E -7C04002E 00000000 -E0000000 80008000 -$Profile One Name Changer Jedi Hack & [Mitch] -0487E2D4 XXXXXXXX -0487E2D8 XXXXXXXX -0487E2DC XXXXXXXX -$Profile Two Name Changer Jedi Hack & [Mitch] -0487E320 0000XXXX -0487E324 XXXXXXXX -0487E328 XXXXXXXX -0487E32C XXXX0000 -$Profile Three Name Changer Jedi Hack & [Mitch] -0487E370 XXXXXXXX -0487E374 XXXXXXXX -[Video_Hacks] -DlistCachingEnable = False -[Video_Settings] -[Wii] -DisableWiimoteSpeaker = 1 +# SC2P8P - Conduit 2 +[Core] +BlockMerging = 1 +[Video] +ProjectionHack = 0 +PH_SZNear = 0 +PH_SZFar = 0 +PH_ExtraParam = 0 +PH_ZNear = +PH_ZFar = +[EmuState] +EmulationStateId = 4 +EmulationIssues = +[OnFrame] +[ActionReplay] +[Gecko] +$Undead Invincibility Mode [Bully@Wiiplaza] +F6000001 80008100 +8001002C 90180000 +D200000C 00000006 +2C110035 40820020 +2C0800F4 40820018 +2C0300A0 40820010 +3C007FFF 6000FFFF +90040000 80040000 +60000000 00000000 +E0000000 80008000 +**Offline Only* +**You are completely untouchable* +*Picture -> http://imageshack.us/photo/my-images/684/sc2p8p008.png/ +$Inf. Ammo [Bully@Wiiplaza] +F6000001 80008100 +80640000 80050000 +D2000008 00000003 +2C110021 4082000C +38600000 7C030050 +60000000 00000000 +E0000000 80008000 +**Offline Only* +$No Flashwhite [Bully@Wiiplaza] +F6000001 80008100 +EC210032 93C10008 +14000114 60000000 +E0000000 80008000 +$Inf. Money [Bully@Wiiplaza] +F6000001 80008100 +7C003A14 38E70001 +D2000010 00000004 +2C11002F 40820014 +2C0401A8 4082000C +3D807FFF 7D84012E +7C04002E 00000000 +E0000000 80008000 +$Profile One Name Changer Jedi Hack & [Mitch] +0487E2D4 XXXXXXXX +0487E2D8 XXXXXXXX +0487E2DC XXXXXXXX +$Profile Two Name Changer Jedi Hack & [Mitch] +0487E320 0000XXXX +0487E324 XXXXXXXX +0487E328 XXXXXXXX +0487E32C XXXX0000 +$Profile Three Name Changer Jedi Hack & [Mitch] +0487E370 XXXXXXXX +0487E374 XXXXXXXX +[Video_Hacks] +DlistCachingEnable = False +[Video_Settings] +[Wii] diff --git a/Data/User/GameConfig/SD2E41.ini b/Data/User/GameConfig/SD2E41.ini index 179c13afb9..ae90ff5196 100644 --- a/Data/User/GameConfig/SD2E41.ini +++ b/Data/User/GameConfig/SD2E41.ini @@ -16,5 +16,4 @@ EmulationIssues = [OnFrame] [ActionReplay] [Gecko] -[Wii] -DisableWiimoteSpeaker = 1 +[Wii] diff --git a/Data/User/GameConfig/SD2J01.ini b/Data/User/GameConfig/SD2J01.ini index f29168a46c..3285e7c75a 100644 --- a/Data/User/GameConfig/SD2J01.ini +++ b/Data/User/GameConfig/SD2J01.ini @@ -16,5 +16,4 @@ EmulationIssues = [OnFrame] [ActionReplay] [Gecko] -[Wii] -DisableWiimoteSpeaker = 1 +[Wii] diff --git a/Data/User/GameConfig/SD2P41.ini b/Data/User/GameConfig/SD2P41.ini index 744a354aaf..2111a3c298 100644 --- a/Data/User/GameConfig/SD2P41.ini +++ b/Data/User/GameConfig/SD2P41.ini @@ -16,5 +16,4 @@ EmulationIssues = [OnFrame] [ActionReplay] [Gecko] -[Wii] -DisableWiimoteSpeaker = 1 +[Wii] diff --git a/Data/User/GameConfig/SD2Y41.ini b/Data/User/GameConfig/SD2Y41.ini index 9daa079aac..59c9fb666b 100644 --- a/Data/User/GameConfig/SD2Y41.ini +++ b/Data/User/GameConfig/SD2Y41.ini @@ -16,5 +16,4 @@ EmulationIssues = [OnFrame] [ActionReplay] [Gecko] -[Wii] -DisableWiimoteSpeaker = 1 +[Wii] diff --git a/Data/User/GameConfig/SEME4Q.ini b/Data/User/GameConfig/SEME4Q.ini index 7e340985b3..48056894b9 100644 --- a/Data/User/GameConfig/SEME4Q.ini +++ b/Data/User/GameConfig/SEME4Q.ini @@ -20,5 +20,4 @@ SafeTextureCacheColorSamples = 0 ForceFiltering = False [Video_Hacks] DlistCachingEnable = False -[Wii] -DisableWiimoteSpeaker = 1 +[Wii] diff --git a/Data/User/GameConfig/SEMJ01.ini b/Data/User/GameConfig/SEMJ01.ini index 7dc481ea34..f0740ca7a3 100644 --- a/Data/User/GameConfig/SEMJ01.ini +++ b/Data/User/GameConfig/SEMJ01.ini @@ -20,5 +20,4 @@ SafeTextureCacheColorSamples = 0 ForceFiltering = False [Video_Hacks] DlistCachingEnable = False -[Wii] -DisableWiimoteSpeaker = 1 +[Wii] diff --git a/Data/User/GameConfig/SEMP4Q.ini b/Data/User/GameConfig/SEMP4Q.ini index fa1afc01c2..f425547cf4 100644 --- a/Data/User/GameConfig/SEMP4Q.ini +++ b/Data/User/GameConfig/SEMP4Q.ini @@ -20,5 +20,4 @@ SafeTextureCacheColorSamples = 0 ForceFiltering = False [Video_Hacks] DlistCachingEnable = False -[Wii] -DisableWiimoteSpeaker = 1 +[Wii] diff --git a/Data/User/GameConfig/SEMX4Q.ini b/Data/User/GameConfig/SEMX4Q.ini index b4c56197ea..43232806a2 100644 --- a/Data/User/GameConfig/SEMX4Q.ini +++ b/Data/User/GameConfig/SEMX4Q.ini @@ -20,5 +20,4 @@ SafeTextureCacheColorSamples = 0 ForceFiltering = False [Video_Hacks] DlistCachingEnable = False -[Wii] -DisableWiimoteSpeaker = 1 +[Wii] diff --git a/Data/User/GameConfig/SEMY4Q.ini b/Data/User/GameConfig/SEMY4Q.ini index 5d8798227d..817f8387e0 100644 --- a/Data/User/GameConfig/SEMY4Q.ini +++ b/Data/User/GameConfig/SEMY4Q.ini @@ -20,5 +20,4 @@ SafeTextureCacheColorSamples = 0 ForceFiltering = False [Video_Hacks] DlistCachingEnable = False -[Wii] -DisableWiimoteSpeaker = 1 +[Wii] diff --git a/Data/User/GameConfig/SEMZ4Q.ini b/Data/User/GameConfig/SEMZ4Q.ini index eecaa23166..515a1bd029 100644 --- a/Data/User/GameConfig/SEMZ4Q.ini +++ b/Data/User/GameConfig/SEMZ4Q.ini @@ -20,5 +20,4 @@ SafeTextureCacheColorSamples = 0 ForceFiltering = False [Video_Hacks] DlistCachingEnable = False -[Wii] -DisableWiimoteSpeaker = 1 +[Wii] diff --git a/Data/User/GameConfig/SERE4Q.ini b/Data/User/GameConfig/SERE4Q.ini index ef5f4edfb2..fbc9fa9d3c 100644 --- a/Data/User/GameConfig/SERE4Q.ini +++ b/Data/User/GameConfig/SERE4Q.ini @@ -16,5 +16,4 @@ PH_ZFar = [Video_Settings] EFBScale = 1 SafeTextureCacheColorSamples = 0 -[Wii] -DisableWiimoteSpeaker = 1 +[Wii] diff --git a/Data/User/GameConfig/SERF4Q.ini b/Data/User/GameConfig/SERF4Q.ini index b03abcf0e9..cd2fca395e 100644 --- a/Data/User/GameConfig/SERF4Q.ini +++ b/Data/User/GameConfig/SERF4Q.ini @@ -16,5 +16,4 @@ PH_ZFar = [Video_Settings] EFBScale = 1 SafeTextureCacheColorSamples = 0 -[Wii] -DisableWiimoteSpeaker = 1 +[Wii] diff --git a/Data/User/GameConfig/SERP4Q.ini b/Data/User/GameConfig/SERP4Q.ini index e57bb14704..7e332b8bcd 100644 --- a/Data/User/GameConfig/SERP4Q.ini +++ b/Data/User/GameConfig/SERP4Q.ini @@ -16,5 +16,4 @@ PH_ZFar = [Video_Settings] EFBScale = 1 SafeTextureCacheColorSamples = 0 -[Wii] -DisableWiimoteSpeaker = 1 +[Wii] diff --git a/Data/User/GameConfig/SF8E01.ini b/Data/User/GameConfig/SF8E01.ini index e8e185cda9..bb2bce7406 100644 --- a/Data/User/GameConfig/SF8E01.ini +++ b/Data/User/GameConfig/SF8E01.ini @@ -16,5 +16,4 @@ PH_ZFar = [Gecko] [Video_Settings] SafeTextureCacheColorSamples = 512 -[Wii] -DisableWiimoteSpeaker = 1 +[Wii] diff --git a/Data/User/GameConfig/SF8J01.ini b/Data/User/GameConfig/SF8J01.ini index bc0b0c2ba5..1f3ef9bb85 100644 --- a/Data/User/GameConfig/SF8J01.ini +++ b/Data/User/GameConfig/SF8J01.ini @@ -16,5 +16,4 @@ PH_ZFar = [Gecko] [Video_Settings] SafeTextureCacheColorSamples = 512 -[Wii] -DisableWiimoteSpeaker = 1 +[Wii] diff --git a/Data/User/GameConfig/SF8P01.ini b/Data/User/GameConfig/SF8P01.ini index 41a5957888..e17f5f4247 100644 --- a/Data/User/GameConfig/SF8P01.ini +++ b/Data/User/GameConfig/SF8P01.ini @@ -16,5 +16,4 @@ PH_ZFar = [Gecko] [Video_Settings] SafeTextureCacheColorSamples = 512 -[Wii] -DisableWiimoteSpeaker = 1 +[Wii] diff --git a/Data/User/GameConfig/SFIE01.ini b/Data/User/GameConfig/SFIE01.ini index 867859d8c4..7475f94fca 100644 --- a/Data/User/GameConfig/SFIE01.ini +++ b/Data/User/GameConfig/SFIE01.ini @@ -6,7 +6,6 @@ EmulationIssues = Needs real xfb for videos to show up. [OnFrame] Add memory patches to be applied every frame here. [ActionReplay] Add action replay cheats here. [Wii] -DisableWiimoteSpeaker = 1 [Video] ProjectionHack = 0 PH_SZNear = 0 diff --git a/Data/User/GameConfig/SFIP01.ini b/Data/User/GameConfig/SFIP01.ini index 8a198d4fe8..114906aac3 100644 --- a/Data/User/GameConfig/SFIP01.ini +++ b/Data/User/GameConfig/SFIP01.ini @@ -6,7 +6,6 @@ EmulationIssues = Needs real xfb for videos to show up. [OnFrame] Add memory patches to be applied every frame here. [ActionReplay] Add action replay cheats here. [Wii] -DisableWiimoteSpeaker = 1 [Video] ProjectionHack = 0 PH_SZNear = 0 diff --git a/Data/User/GameConfig/SHLPA4.ini b/Data/User/GameConfig/SHLPA4.ini index ce64ff21e1..b9eebf93c5 100644 --- a/Data/User/GameConfig/SHLPA4.ini +++ b/Data/User/GameConfig/SHLPA4.ini @@ -15,5 +15,4 @@ PH_ZFar = [Gecko] [Video_Settings] SafeTextureCacheColorSamples = 512 -[Wii] -DisableWiimoteSpeaker = 1 +[Wii] diff --git a/Data/User/GameConfig/SJDE41.ini b/Data/User/GameConfig/SJDE41.ini index 1e16ddd21f..64b712f81d 100644 --- a/Data/User/GameConfig/SJDE41.ini +++ b/Data/User/GameConfig/SJDE41.ini @@ -6,7 +6,6 @@ EmulationIssues = Suffers from random ingame lock ups. [OnFrame] Add memory patches to be applied every frame here. [ActionReplay] Add action replay cheats here. [Wii] -DisableWiimoteSpeaker = 1 [Video] ProjectionHack = 0 PH_SZNear = 0 diff --git a/Data/User/GameConfig/SJDP41.ini b/Data/User/GameConfig/SJDP41.ini index 53f65d5704..450a81c4f8 100644 --- a/Data/User/GameConfig/SJDP41.ini +++ b/Data/User/GameConfig/SJDP41.ini @@ -6,7 +6,6 @@ EmulationIssues = Suffers from random ingame lock ups. [OnFrame] Add memory patches to be applied every frame here. [ActionReplay] Add action replay cheats here. [Wii] -DisableWiimoteSpeaker = 1 [Video] ProjectionHack = 0 PH_SZNear = 0 diff --git a/Data/User/GameConfig/SJDY41.ini b/Data/User/GameConfig/SJDY41.ini index 107abedfd2..74584766c3 100644 --- a/Data/User/GameConfig/SJDY41.ini +++ b/Data/User/GameConfig/SJDY41.ini @@ -6,7 +6,6 @@ EmulationIssues = Suffers from random ingame lock ups. [OnFrame] Add memory patches to be applied every frame here. [ActionReplay] Add action replay cheats here. [Wii] -DisableWiimoteSpeaker = 1 [Video] ProjectionHack = 0 PH_SZNear = 0 diff --git a/Data/User/GameConfig/SJDZ41.ini b/Data/User/GameConfig/SJDZ41.ini index 53f65d5704..450a81c4f8 100644 --- a/Data/User/GameConfig/SJDZ41.ini +++ b/Data/User/GameConfig/SJDZ41.ini @@ -6,7 +6,6 @@ EmulationIssues = Suffers from random ingame lock ups. [OnFrame] Add memory patches to be applied every frame here. [ActionReplay] Add action replay cheats here. [Wii] -DisableWiimoteSpeaker = 1 [Video] ProjectionHack = 0 PH_SZNear = 0 diff --git a/Data/User/GameConfig/SMOE41.ini b/Data/User/GameConfig/SMOE41.ini index 15dc5a693e..3c61475544 100644 --- a/Data/User/GameConfig/SMOE41.ini +++ b/Data/User/GameConfig/SMOE41.ini @@ -1,21 +1,20 @@ -# SMOE41 - MICHAEL JACKSON THE EXPERIENCE SPECIAL EDITION -[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 = Sound noise eliminated using LLE audio. With hle disable idleskip for normal dance school speed. -[OnFrame] Add memory patches to be applied every frame here. -[ActionReplay] Add action replay cheats here. -[Video] -ProjectionHack = 0 -PH_SZNear = 0 -PH_SZFar = 0 -PH_ExtraParam = 0 -PH_ZNear = -PH_ZFar = -[Gecko] -[Video_Hacks] -EFBEmulateFormatChanges = True -[Video_Enhancements] -MaxAnisotropy = 0 -[Wii] -DisableWiimoteSpeaker = 1 +# SMOE41 - MICHAEL JACKSON THE EXPERIENCE SPECIAL EDITION +[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 = Sound noise eliminated using LLE audio. With hle disable idleskip for normal dance school speed. +[OnFrame] Add memory patches to be applied every frame here. +[ActionReplay] Add action replay cheats here. +[Video] +ProjectionHack = 0 +PH_SZNear = 0 +PH_SZFar = 0 +PH_ExtraParam = 0 +PH_ZNear = +PH_ZFar = +[Gecko] +[Video_Hacks] +EFBEmulateFormatChanges = True +[Video_Enhancements] +MaxAnisotropy = 0 +[Wii] diff --git a/Data/User/GameConfig/SMOP41.ini b/Data/User/GameConfig/SMOP41.ini index 6095cd9174..b9f913a639 100644 --- a/Data/User/GameConfig/SMOP41.ini +++ b/Data/User/GameConfig/SMOP41.ini @@ -1,21 +1,20 @@ -# SMOP41 - MICHAEL JACKSON THE EXPERIENCE SPECIAL EDITION -[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 = Sound noise eliminated using LLE audio. With hle disable idleskip for normal dance school speed. -[OnFrame] Add memory patches to be applied every frame here. -[ActionReplay] Add action replay cheats here. -[Video] -ProjectionHack = 0 -PH_SZNear = 0 -PH_SZFar = 0 -PH_ExtraParam = 0 -PH_ZNear = -PH_ZFar = -[Gecko] -[Video_Hacks] -EFBEmulateFormatChanges = True -[Video_Enhancements] -MaxAnisotropy = 0 -[Wii] -DisableWiimoteSpeaker = 1 +# SMOP41 - MICHAEL JACKSON THE EXPERIENCE SPECIAL EDITION +[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 = Sound noise eliminated using LLE audio. With hle disable idleskip for normal dance school speed. +[OnFrame] Add memory patches to be applied every frame here. +[ActionReplay] Add action replay cheats here. +[Video] +ProjectionHack = 0 +PH_SZNear = 0 +PH_SZFar = 0 +PH_ExtraParam = 0 +PH_ZNear = +PH_ZFar = +[Gecko] +[Video_Hacks] +EFBEmulateFormatChanges = True +[Video_Enhancements] +MaxAnisotropy = 0 +[Wii] diff --git a/Data/User/GameConfig/SMOX41.ini b/Data/User/GameConfig/SMOX41.ini index 88ba03da1c..929a58f076 100644 --- a/Data/User/GameConfig/SMOX41.ini +++ b/Data/User/GameConfig/SMOX41.ini @@ -1,21 +1,20 @@ -# SMOX41 - Michael Jackson The Experience: Walmart Edition -[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 = Sound noise eliminated using LLE audio. With hle disable idleskip for normal dance school speed. -[OnFrame] Add memory patches to be applied every frame here. -[ActionReplay] Add action replay cheats here. -[Video] -ProjectionHack = 0 -PH_SZNear = 0 -PH_SZFar = 0 -PH_ExtraParam = 0 -PH_ZNear = -PH_ZFar = -[Gecko] -[Video_Hacks] -EFBEmulateFormatChanges = True -[Video_Enhancements] -MaxAnisotropy = 0 -[Wii] -DisableWiimoteSpeaker = 1 +# SMOX41 - Michael Jackson The Experience: Walmart Edition +[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 = Sound noise eliminated using LLE audio. With hle disable idleskip for normal dance school speed. +[OnFrame] Add memory patches to be applied every frame here. +[ActionReplay] Add action replay cheats here. +[Video] +ProjectionHack = 0 +PH_SZNear = 0 +PH_SZFar = 0 +PH_ExtraParam = 0 +PH_ZNear = +PH_ZFar = +[Gecko] +[Video_Hacks] +EFBEmulateFormatChanges = True +[Video_Enhancements] +MaxAnisotropy = 0 +[Wii] diff --git a/Data/User/GameConfig/SO3EE9.ini b/Data/User/GameConfig/SO3EE9.ini index f8da896a23..c359fede43 100644 --- a/Data/User/GameConfig/SO3EE9.ini +++ b/Data/User/GameConfig/SO3EE9.ini @@ -6,7 +6,6 @@ EmulationIssues = Direct 3d 11 fixes some texture glitches. [OnFrame] Add memory patches to be applied every frame here. [ActionReplay] Add action replay cheats here. [Wii] -DisableWiimoteSpeaker = 1 [Video] ProjectionHack = 0 PH_SZNear = 0 diff --git a/Data/User/GameConfig/SO3J99.ini b/Data/User/GameConfig/SO3J99.ini index 2ad57e3af2..e29dca5b96 100644 --- a/Data/User/GameConfig/SO3J99.ini +++ b/Data/User/GameConfig/SO3J99.ini @@ -6,7 +6,6 @@ EmulationIssues = Direct 3d 11 fixes some texture glitches. [OnFrame] Add memory patches to be applied every frame here. [ActionReplay] Add action replay cheats here. [Wii] -DisableWiimoteSpeaker = 1 [Video] ProjectionHack = 0 PH_SZNear = 0 diff --git a/Data/User/GameConfig/SOJE41.ini b/Data/User/GameConfig/SOJE41.ini index 183a8823ca..af6d49b785 100644 --- a/Data/User/GameConfig/SOJE41.ini +++ b/Data/User/GameConfig/SOJE41.ini @@ -1,17 +1,16 @@ -# SOJE41 - Rayman Origins -[Core] Values set here will override the main dolphin settings. -[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set. -EmulationStateId = 4 -EmulationIssues = -[OnFrame] Add memory patches to be applied every frame here. -[ActionReplay] Add action replay cheats here. -[Video] -ProjectionHack = 1 -PH_SZNear = 1 -PH_SZFar = 0 -PH_ExtraParam = 0 -PH_ZNear = -PH_ZFar = -[Gecko] -[Wii] -DisableWiimoteSpeaker = 1 +# SOJE41 - Rayman Origins +[Core] Values set here will override the main dolphin settings. +[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set. +EmulationStateId = 4 +EmulationIssues = +[OnFrame] Add memory patches to be applied every frame here. +[ActionReplay] Add action replay cheats here. +[Video] +ProjectionHack = 1 +PH_SZNear = 1 +PH_SZFar = 0 +PH_ExtraParam = 0 +PH_ZNear = +PH_ZFar = +[Gecko] +[Wii] diff --git a/Data/User/GameConfig/SOJP41.ini b/Data/User/GameConfig/SOJP41.ini index 2c835fe6e2..fca55f9117 100644 --- a/Data/User/GameConfig/SOJP41.ini +++ b/Data/User/GameConfig/SOJP41.ini @@ -1,17 +1,16 @@ -# SOJP41 - Rayman Origins -[Core] Values set here will override the main dolphin settings. -[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set. -EmulationStateId = 4 -EmulationIssues = -[OnFrame] Add memory patches to be applied every frame here. -[ActionReplay] Add action replay cheats here. -[Video] -ProjectionHack = 1 -PH_SZNear = 1 -PH_SZFar = 0 -PH_ExtraParam = 0 -PH_ZNear = -PH_ZFar = -[Gecko] -[Wii] -DisableWiimoteSpeaker = 1 +# SOJP41 - Rayman Origins +[Core] Values set here will override the main dolphin settings. +[EmuState] The Emulation State. 1 is worst, 5 is best, 0 is not set. +EmulationStateId = 4 +EmulationIssues = +[OnFrame] Add memory patches to be applied every frame here. +[ActionReplay] Add action replay cheats here. +[Video] +ProjectionHack = 1 +PH_SZNear = 1 +PH_SZFar = 0 +PH_ExtraParam = 0 +PH_ZNear = +PH_ZFar = +[Gecko] +[Wii] diff --git a/Data/User/GameConfig/SOUE01.ini b/Data/User/GameConfig/SOUE01.ini index 8461821933..7e37e04936 100644 --- a/Data/User/GameConfig/SOUE01.ini +++ b/Data/User/GameConfig/SOUE01.ini @@ -17,5 +17,4 @@ PH_ZFar = EFBAccessEnable = True DlistCachingEnable = False [Wii] -DisableWiimoteSpeaker = 1 [Video_Settings] diff --git a/Data/User/GameConfig/SOUJ01.ini b/Data/User/GameConfig/SOUJ01.ini index ede7d81148..b02302e15c 100644 --- a/Data/User/GameConfig/SOUJ01.ini +++ b/Data/User/GameConfig/SOUJ01.ini @@ -17,5 +17,4 @@ PH_ZFar = EFBAccessEnable = True DlistCachingEnable = False [Wii] -DisableWiimoteSpeaker = 1 [Video_Settings] diff --git a/Data/User/GameConfig/SOUK01.ini b/Data/User/GameConfig/SOUK01.ini index 512bd21408..201ec99315 100644 --- a/Data/User/GameConfig/SOUK01.ini +++ b/Data/User/GameConfig/SOUK01.ini @@ -17,5 +17,4 @@ PH_ZFar = EFBAccessEnable = True DlistCachingEnable = False [Wii] -DisableWiimoteSpeaker = 1 [Video_Settings] diff --git a/Data/User/GameConfig/SOUP01.ini b/Data/User/GameConfig/SOUP01.ini index 1b6e47096f..eab4d6b442 100644 --- a/Data/User/GameConfig/SOUP01.ini +++ b/Data/User/GameConfig/SOUP01.ini @@ -17,5 +17,4 @@ PH_ZFar = EFBAccessEnable = True DlistCachingEnable = False [Wii] -DisableWiimoteSpeaker = 1 [Video_Settings] diff --git a/Data/User/GameConfig/SRQE41.ini b/Data/User/GameConfig/SRQE41.ini index 5060189327..e923433ee8 100644 --- a/Data/User/GameConfig/SRQE41.ini +++ b/Data/User/GameConfig/SRQE41.ini @@ -14,6 +14,5 @@ PH_ZNear = PH_ZFar = [Gecko] [Wii] -DisableWiimoteSpeaker = 1 [Video_Hacks] DlistCachingEnable = False diff --git a/Data/User/GameConfig/SRQP41.ini b/Data/User/GameConfig/SRQP41.ini index f360aef050..c1001990b1 100644 --- a/Data/User/GameConfig/SRQP41.ini +++ b/Data/User/GameConfig/SRQP41.ini @@ -14,6 +14,5 @@ PH_ZNear = PH_ZFar = [Gecko] [Wii] -DisableWiimoteSpeaker = 1 [Video_Hacks] DlistCachingEnable = False diff --git a/Data/User/GameConfig/SX3J01.ini b/Data/User/GameConfig/SX3J01.ini index 276118af1a..3aef192f00 100644 --- a/Data/User/GameConfig/SX3J01.ini +++ b/Data/User/GameConfig/SX3J01.ini @@ -15,5 +15,4 @@ PH_ZFar = [Gecko] [Video_Settings] SafeTextureCacheColorSamples = 0 -[Wii] -DisableWiimoteSpeaker = 1 +[Wii] diff --git a/Data/User/GameConfig/SX3P01.ini b/Data/User/GameConfig/SX3P01.ini index 94b5c6ef16..a753975414 100644 --- a/Data/User/GameConfig/SX3P01.ini +++ b/Data/User/GameConfig/SX3P01.ini @@ -15,5 +15,4 @@ PH_ZFar = [Gecko] [Video_Settings] SafeTextureCacheColorSamples = 0 -[Wii] -DisableWiimoteSpeaker = 1 +[Wii] diff --git a/Data/User/Themes/Boomy/nobanner.png b/Data/User/Themes/Boomy/nobanner.png new file mode 100644 index 0000000000..08a3088431 Binary files /dev/null and b/Data/User/Themes/Boomy/nobanner.png differ diff --git a/Externals/CLRun/CMakeLists.txt b/Externals/CLRun/CMakeLists.txt index 7810173a81..3a57ae4563 100644 --- a/Externals/CLRun/CMakeLists.txt +++ b/Externals/CLRun/CMakeLists.txt @@ -1,7 +1,10 @@ set(SRCS clrun/clrun.c clrun/dynamiclib.c clrun/gencl.c - clrun/genclgl.c) + clrun/genclgl.c + clrun/genclext.c + clrun/genclglext.c + ) add_library(clrun STATIC ${SRCS}) target_link_libraries(clrun ${CMAKE_DL_LIBS}) diff --git a/Externals/CLRun/clrun/Makefile b/Externals/CLRun/clrun/Makefile index 9f637269e0..f4186ff741 100644 --- a/Externals/CLRun/clrun/Makefile +++ b/Externals/CLRun/clrun/Makefile @@ -10,6 +10,11 @@ compile: genclrun gencl.c genclgl.c genclrun: ../include/CL/cl.h ../include/CL/cl_gl.h ./generateClRun.pl ../include/CL/cl.h > gencl.c ./generateClRun.pl ../include/CL/cl_gl.h > genclgl.c + ./generateClRun.pl ../include/CL/cl_ext.h > genclext.c + ./generateClRun.pl ../include/CL/cl_gl_ext.h > genclglext.c + ./generateClRun.pl ../include/CL/cl_d3d10.h > gencld3d10.c + ./generateClRun.pl ../include/CL/cl_d3d11.h > gencld3d11.c + ./generateClRun.pl ../include/CL/cl_dx9_media_sharing.h > gencldx9.c clean: diff --git a/Externals/CLRun/clrun/gencl.c b/Externals/CLRun/clrun/gencl.c index 9d55b70232..649e3c67b7 100644 --- a/Externals/CLRun/clrun/gencl.c +++ b/Externals/CLRun/clrun/gencl.c @@ -3,398 +3,543 @@ #include "../include/CL/cl.h" -static cl_int (CL_API_CALL *clGetPlatformIDs_ptr)(cl_uint, cl_platform_id *, cl_uint *) = NULL; +static cl_int (*clGetPlatformIDs_ptr)(cl_uint, cl_platform_id *, cl_uint *) = NULL; cl_int CL_API_CALL clGetPlatformIDs (cl_uint num_entries,cl_platform_id * platforms,cl_uint * num_platforms) { if(!clGetPlatformIDs_ptr) clGetPlatformIDs_ptr = getFunction("clGetPlatformIDs"); return (*clGetPlatformIDs_ptr)(num_entries, platforms, num_platforms); } -static cl_int (CL_API_CALL *clGetPlatformInfo_ptr)(cl_platform_id, cl_platform_info, size_t, void *, size_t *) = NULL; +static cl_int (*clGetPlatformInfo_ptr)(cl_platform_id, cl_platform_info, size_t, void *, size_t *) = NULL; cl_int CL_API_CALL clGetPlatformInfo (cl_platform_id platform,cl_platform_info param_name,size_t param_value_size,void * param_value,size_t * param_value_size_ret) { if(!clGetPlatformInfo_ptr) clGetPlatformInfo_ptr = getFunction("clGetPlatformInfo"); return (*clGetPlatformInfo_ptr)(platform, param_name, param_value_size, param_value, param_value_size_ret); } -static cl_int (CL_API_CALL *clGetDeviceIDs_ptr)(cl_platform_id, cl_device_type, cl_uint, cl_device_id *, cl_uint *) = NULL; +static cl_int (*clGetDeviceIDs_ptr)(cl_platform_id, cl_device_type, cl_uint, cl_device_id *, cl_uint *) = NULL; cl_int CL_API_CALL clGetDeviceIDs (cl_platform_id platform,cl_device_type device_type,cl_uint num_entries,cl_device_id * devices,cl_uint * num_devices) { if(!clGetDeviceIDs_ptr) clGetDeviceIDs_ptr = getFunction("clGetDeviceIDs"); return (*clGetDeviceIDs_ptr)(platform, device_type, num_entries, devices, num_devices); } -static cl_int (CL_API_CALL *clGetDeviceInfo_ptr)(cl_device_id, cl_device_info, size_t, void *, size_t *) = NULL; +static cl_int (*clGetDeviceInfo_ptr)(cl_device_id, cl_device_info, size_t, void *, size_t *) = NULL; cl_int CL_API_CALL clGetDeviceInfo (cl_device_id device,cl_device_info param_name,size_t param_value_size,void * param_value,size_t * param_value_size_ret) { if(!clGetDeviceInfo_ptr) clGetDeviceInfo_ptr = getFunction("clGetDeviceInfo"); return (*clGetDeviceInfo_ptr)(device, param_name, param_value_size, param_value, param_value_size_ret); } -static cl_context (CL_API_CALL *clCreateContext_ptr)(const cl_context_properties *, cl_uint, const cl_device_id *, void (CL_CALLBACK *)(const char *, const void *, size_t, void *), void *, cl_int *) = NULL; -cl_context CL_API_CALL clCreateContext (const cl_context_properties * properties,cl_uint num_devices,const cl_device_id * devices,void (CL_CALLBACK * pfn_notify)(const char *, const void *, size_t, void *),void * user_data,cl_int * errcode_ret) { +static cl_int (*clCreateSubDevices_ptr)(cl_device_id, const cl_device_partition_property *, cl_uint, cl_device_id *, cl_uint *) = NULL; +cl_int CL_API_CALL clCreateSubDevices (cl_device_id in_device,const cl_device_partition_property * properties,cl_uint num_devices,cl_device_id * out_devices,cl_uint * num_devices_ret) { + if(!clCreateSubDevices_ptr) clCreateSubDevices_ptr = getFunction("clCreateSubDevices"); + return (*clCreateSubDevices_ptr)(in_device, properties, num_devices, out_devices, num_devices_ret); +} + +static cl_int (*clRetainDevice_ptr)(cl_device_id) = NULL; +cl_int CL_API_CALL clRetainDevice (cl_device_id device) { + if(!clRetainDevice_ptr) clRetainDevice_ptr = getFunction("clRetainDevice"); + return (*clRetainDevice_ptr)(device); +} + +static cl_int (*clReleaseDevice_ptr)(cl_device_id) = NULL; +cl_int CL_API_CALL clReleaseDevice (cl_device_id device) { + if(!clReleaseDevice_ptr) clReleaseDevice_ptr = getFunction("clReleaseDevice"); + return (*clReleaseDevice_ptr)(device); +} + +static cl_context (*clCreateContext_ptr)(const cl_context_properties *, cl_uint, const cl_device_id *, void (CL_CALLBACK *pfn_notify)(const char *, const void *, size_t, void *), void*, cl_int*) = NULL; +cl_context CL_API_CALL clCreateContext(const cl_context_properties * properties, + cl_uint num_devices, + const cl_device_id * devices, + void (CL_CALLBACK *pfn_notify)(const char *, const void *, size_t, void *), + void * user_data, + cl_int * errcode_ret) { if(!clCreateContext_ptr) clCreateContext_ptr = getFunction("clCreateContext"); return (*clCreateContext_ptr)(properties, num_devices, devices, pfn_notify, user_data, errcode_ret); } -static cl_context (CL_API_CALL *clCreateContextFromType_ptr)(const cl_context_properties *, cl_device_type, void (CL_CALLBACK *)(const char *, const void *, size_t, void *), void *, cl_int *) = NULL; -cl_context CL_API_CALL clCreateContextFromType (const cl_context_properties * properties,cl_device_type device_type,void (CL_CALLBACK * pfn_notify)(const char *, const void *, size_t, void *),void * user_data,cl_int * errcode_ret) { +static cl_context (*clCreateContextFromType_ptr)(const cl_context_properties *, cl_device_type, void (CL_CALLBACK * /* pfn_notify */)(const char *, const void *, size_t, void *), void*, cl_int*) = NULL; +cl_context CL_API_CALL clCreateContextFromType(const cl_context_properties * properties, + cl_device_type device_type, + void (CL_CALLBACK * pfn_notify)(const char *, const void *, size_t, void *), + void * user_data, + cl_int * errcode_ret) { if(!clCreateContextFromType_ptr) clCreateContextFromType_ptr = getFunction("clCreateContextFromType"); return (*clCreateContextFromType_ptr)(properties, device_type, pfn_notify, user_data, errcode_ret); } -static cl_int (CL_API_CALL *clRetainContext_ptr)(cl_context) = NULL; +static cl_int (*clRetainContext_ptr)(cl_context) = NULL; cl_int CL_API_CALL clRetainContext (cl_context context) { if(!clRetainContext_ptr) clRetainContext_ptr = getFunction("clRetainContext"); return (*clRetainContext_ptr)(context); } -static cl_int (CL_API_CALL *clReleaseContext_ptr)(cl_context) = NULL; +static cl_int (*clReleaseContext_ptr)(cl_context) = NULL; cl_int CL_API_CALL clReleaseContext (cl_context context) { if(!clReleaseContext_ptr) clReleaseContext_ptr = getFunction("clReleaseContext"); return (*clReleaseContext_ptr)(context); } -static cl_int (CL_API_CALL *clGetContextInfo_ptr)(cl_context, cl_context_info, size_t, void *, size_t *) = NULL; +static cl_int (*clGetContextInfo_ptr)(cl_context, cl_context_info, size_t, void *, size_t *) = NULL; cl_int CL_API_CALL clGetContextInfo (cl_context context,cl_context_info param_name,size_t param_value_size,void * param_value,size_t * param_value_size_ret) { if(!clGetContextInfo_ptr) clGetContextInfo_ptr = getFunction("clGetContextInfo"); return (*clGetContextInfo_ptr)(context, param_name, param_value_size, param_value, param_value_size_ret); } -static cl_command_queue (CL_API_CALL *clCreateCommandQueue_ptr)(cl_context, cl_device_id, cl_command_queue_properties, cl_int *) = NULL; +static cl_command_queue (*clCreateCommandQueue_ptr)(cl_context, cl_device_id, cl_command_queue_properties, cl_int *) = NULL; cl_command_queue CL_API_CALL clCreateCommandQueue (cl_context context,cl_device_id device,cl_command_queue_properties properties,cl_int * errcode_ret) { if(!clCreateCommandQueue_ptr) clCreateCommandQueue_ptr = getFunction("clCreateCommandQueue"); return (*clCreateCommandQueue_ptr)(context, device, properties, errcode_ret); } -static cl_int (CL_API_CALL *clRetainCommandQueue_ptr)(cl_command_queue) = NULL; +static cl_int (*clRetainCommandQueue_ptr)(cl_command_queue) = NULL; cl_int CL_API_CALL clRetainCommandQueue (cl_command_queue command_queue) { if(!clRetainCommandQueue_ptr) clRetainCommandQueue_ptr = getFunction("clRetainCommandQueue"); return (*clRetainCommandQueue_ptr)(command_queue); } -static cl_int (CL_API_CALL *clReleaseCommandQueue_ptr)(cl_command_queue) = NULL; +static cl_int (*clReleaseCommandQueue_ptr)(cl_command_queue) = NULL; cl_int CL_API_CALL clReleaseCommandQueue (cl_command_queue command_queue) { if(!clReleaseCommandQueue_ptr) clReleaseCommandQueue_ptr = getFunction("clReleaseCommandQueue"); return (*clReleaseCommandQueue_ptr)(command_queue); } -static cl_int (CL_API_CALL *clGetCommandQueueInfo_ptr)(cl_command_queue, cl_command_queue_info, size_t, void *, size_t *) = NULL; +static cl_int (*clGetCommandQueueInfo_ptr)(cl_command_queue, cl_command_queue_info, size_t, void *, size_t *) = NULL; cl_int CL_API_CALL clGetCommandQueueInfo (cl_command_queue command_queue,cl_command_queue_info param_name,size_t param_value_size,void * param_value,size_t * param_value_size_ret) { if(!clGetCommandQueueInfo_ptr) clGetCommandQueueInfo_ptr = getFunction("clGetCommandQueueInfo"); return (*clGetCommandQueueInfo_ptr)(command_queue, param_name, param_value_size, param_value, param_value_size_ret); } -static cl_int (CL_API_CALL *clSetCommandQueueProperty_ptr)(cl_command_queue, cl_command_queue_properties, cl_bool, cl_command_queue_properties *) = NULL; -cl_int CL_API_CALL clSetCommandQueueProperty (cl_command_queue command_queue,cl_command_queue_properties properties,cl_bool enable,cl_command_queue_properties * old_properties) { - if(!clSetCommandQueueProperty_ptr) clSetCommandQueueProperty_ptr = getFunction("clSetCommandQueueProperty"); - return (*clSetCommandQueueProperty_ptr)(command_queue, properties, enable, old_properties); -} - -static cl_mem (CL_API_CALL *clCreateBuffer_ptr)(cl_context, cl_mem_flags, size_t, void *, cl_int *) = NULL; +static cl_mem (*clCreateBuffer_ptr)(cl_context, cl_mem_flags, size_t, void *, cl_int *) = NULL; cl_mem CL_API_CALL clCreateBuffer (cl_context context,cl_mem_flags flags,size_t size,void * host_ptr,cl_int * errcode_ret) { if(!clCreateBuffer_ptr) clCreateBuffer_ptr = getFunction("clCreateBuffer"); return (*clCreateBuffer_ptr)(context, flags, size, host_ptr, errcode_ret); } -static cl_mem (CL_API_CALL *clCreateImage2D_ptr)(cl_context, cl_mem_flags, const cl_image_format *, size_t, size_t, size_t, void *, cl_int *) = NULL; -cl_mem CL_API_CALL clCreateImage2D (cl_context context,cl_mem_flags flags,const cl_image_format * image_format,size_t image_width,size_t image_height,size_t image_row_pitch,void * host_ptr,cl_int * errcode_ret) { - if(!clCreateImage2D_ptr) clCreateImage2D_ptr = getFunction("clCreateImage2D"); - return (*clCreateImage2D_ptr)(context, flags, image_format, image_width, image_height, image_row_pitch, host_ptr, errcode_ret); +static cl_mem (*clCreateSubBuffer_ptr)(cl_mem, cl_mem_flags, cl_buffer_create_type, const void *, cl_int *) = NULL; +cl_mem CL_API_CALL clCreateSubBuffer (cl_mem buffer,cl_mem_flags flags,cl_buffer_create_type buffer_create_type,const void * buffer_create_info,cl_int * errcode_ret) { + if(!clCreateSubBuffer_ptr) clCreateSubBuffer_ptr = getFunction("clCreateSubBuffer"); + return (*clCreateSubBuffer_ptr)(buffer, flags, buffer_create_type, buffer_create_info, errcode_ret); } -static cl_mem (CL_API_CALL *clCreateImage3D_ptr)(cl_context, cl_mem_flags, const cl_image_format *, size_t, size_t, size_t, size_t, size_t, void *, cl_int *) = NULL; -cl_mem CL_API_CALL clCreateImage3D (cl_context context,cl_mem_flags flags,const cl_image_format * image_format,size_t image_width,size_t image_height,size_t image_depth,size_t image_row_pitch,size_t image_slice_pitch,void * host_ptr,cl_int * errcode_ret) { - if(!clCreateImage3D_ptr) clCreateImage3D_ptr = getFunction("clCreateImage3D"); - return (*clCreateImage3D_ptr)(context, flags, image_format, image_width, image_height, image_depth, image_row_pitch, image_slice_pitch, host_ptr, errcode_ret); +static cl_mem (*clCreateImage_ptr)(cl_context, cl_mem_flags, const cl_image_format *, const cl_image_desc *, void *, cl_int *) = NULL; +cl_mem CL_API_CALL clCreateImage (cl_context context,cl_mem_flags flags,const cl_image_format * image_format,const cl_image_desc * image_desc,void * host_ptr,cl_int * errcode_ret) { + if(!clCreateImage_ptr) clCreateImage_ptr = getFunction("clCreateImage"); + return (*clCreateImage_ptr)(context, flags, image_format, image_desc, host_ptr, errcode_ret); } -static cl_int (CL_API_CALL *clRetainMemObject_ptr)(cl_mem) = NULL; +static cl_int (*clRetainMemObject_ptr)(cl_mem) = NULL; cl_int CL_API_CALL clRetainMemObject (cl_mem memobj) { if(!clRetainMemObject_ptr) clRetainMemObject_ptr = getFunction("clRetainMemObject"); return (*clRetainMemObject_ptr)(memobj); } -static cl_int (CL_API_CALL *clReleaseMemObject_ptr)(cl_mem) = NULL; +static cl_int (*clReleaseMemObject_ptr)(cl_mem) = NULL; cl_int CL_API_CALL clReleaseMemObject (cl_mem memobj) { if(!clReleaseMemObject_ptr) clReleaseMemObject_ptr = getFunction("clReleaseMemObject"); return (*clReleaseMemObject_ptr)(memobj); } -static cl_int (CL_API_CALL *clGetSupportedImageFormats_ptr)(cl_context, cl_mem_flags, cl_mem_object_type, cl_uint, cl_image_format *, cl_uint *) = NULL; +static cl_int (*clGetSupportedImageFormats_ptr)(cl_context, cl_mem_flags, cl_mem_object_type, cl_uint, cl_image_format *, cl_uint *) = NULL; cl_int CL_API_CALL clGetSupportedImageFormats (cl_context context,cl_mem_flags flags,cl_mem_object_type image_type,cl_uint num_entries,cl_image_format * image_formats,cl_uint * num_image_formats) { if(!clGetSupportedImageFormats_ptr) clGetSupportedImageFormats_ptr = getFunction("clGetSupportedImageFormats"); return (*clGetSupportedImageFormats_ptr)(context, flags, image_type, num_entries, image_formats, num_image_formats); } -static cl_int (CL_API_CALL *clGetMemObjectInfo_ptr)(cl_mem, cl_mem_info, size_t, void *, size_t *) = NULL; +static cl_int (*clGetMemObjectInfo_ptr)(cl_mem, cl_mem_info, size_t, void *, size_t *) = NULL; cl_int CL_API_CALL clGetMemObjectInfo (cl_mem memobj,cl_mem_info param_name,size_t param_value_size,void * param_value,size_t * param_value_size_ret) { if(!clGetMemObjectInfo_ptr) clGetMemObjectInfo_ptr = getFunction("clGetMemObjectInfo"); return (*clGetMemObjectInfo_ptr)(memobj, param_name, param_value_size, param_value, param_value_size_ret); } -static cl_int (CL_API_CALL *clGetImageInfo_ptr)(cl_mem, cl_image_info, size_t, void *, size_t *) = NULL; +static cl_int (*clGetImageInfo_ptr)(cl_mem, cl_image_info, size_t, void *, size_t *) = NULL; cl_int CL_API_CALL clGetImageInfo (cl_mem image,cl_image_info param_name,size_t param_value_size,void * param_value,size_t * param_value_size_ret) { if(!clGetImageInfo_ptr) clGetImageInfo_ptr = getFunction("clGetImageInfo"); return (*clGetImageInfo_ptr)(image, param_name, param_value_size, param_value, param_value_size_ret); } -static cl_sampler (CL_API_CALL *clCreateSampler_ptr)(cl_context, cl_bool, cl_addressing_mode, cl_filter_mode, cl_int *) = NULL; -cl_sampler CL_API_CALL clCreateSampler (cl_context context,cl_bool normalized_coords,cl_addressing_mode addressing_mode,cl_filter_mode filter_mode,cl_int * errcode_ret) { +/* Sampler APIs */ +static cl_int (*clSetMemObjectDestructorCallback_ptr)(cl_mem memobj,void (CL_CALLBACK *pfn_notify)( cl_mem memobj, void*) ,void *user_data ) = NULL; +cl_int CL_API_CALL clSetMemObjectDestructorCallback (cl_mem memobj,void (CL_CALLBACK *pfn_notify)( cl_mem memobj, void*) ,void *user_data ) +{ + if(!clSetMemObjectDestructorCallback_ptr) clSetMemObjectDestructorCallback_ptr = getFunction("clSetMemObjectDestructorCallback"); + return (*clSetMemObjectDestructorCallback_ptr)(memobj, pfn_notify, user_data); +} + +/* Sampler APIs */ +static cl_sampler (*clCreateSampler_ptr)(cl_context, cl_bool, cl_addressing_mode, cl_filter_mode, cl_int *) = NULL; +cl_sampler CL_API_CALL clCreateSampler(cl_context context,cl_bool normalized_coords,cl_addressing_mode addressing_mode,cl_filter_mode filter_mode,cl_int * errcode_ret) { if(!clCreateSampler_ptr) clCreateSampler_ptr = getFunction("clCreateSampler"); return (*clCreateSampler_ptr)(context, normalized_coords, addressing_mode, filter_mode, errcode_ret); } -static cl_int (CL_API_CALL *clRetainSampler_ptr)(cl_sampler) = NULL; +static cl_int (*clRetainSampler_ptr)(cl_sampler) = NULL; cl_int CL_API_CALL clRetainSampler (cl_sampler sampler) { if(!clRetainSampler_ptr) clRetainSampler_ptr = getFunction("clRetainSampler"); return (*clRetainSampler_ptr)(sampler); } -static cl_int (CL_API_CALL *clReleaseSampler_ptr)(cl_sampler) = NULL; +static cl_int (*clReleaseSampler_ptr)(cl_sampler) = NULL; cl_int CL_API_CALL clReleaseSampler (cl_sampler sampler) { if(!clReleaseSampler_ptr) clReleaseSampler_ptr = getFunction("clReleaseSampler"); return (*clReleaseSampler_ptr)(sampler); } -static cl_int (CL_API_CALL *clGetSamplerInfo_ptr)(cl_sampler, cl_sampler_info, size_t, void *, size_t *) = NULL; +static cl_int (*clGetSamplerInfo_ptr)(cl_sampler, cl_sampler_info, size_t, void *, size_t *) = NULL; cl_int CL_API_CALL clGetSamplerInfo (cl_sampler sampler,cl_sampler_info param_name,size_t param_value_size,void * param_value,size_t * param_value_size_ret) { if(!clGetSamplerInfo_ptr) clGetSamplerInfo_ptr = getFunction("clGetSamplerInfo"); return (*clGetSamplerInfo_ptr)(sampler, param_name, param_value_size, param_value, param_value_size_ret); } -static cl_program (CL_API_CALL *clCreateProgramWithSource_ptr)(cl_context, cl_uint, const char **, const size_t *, cl_int *) = NULL; +static cl_program (*clCreateProgramWithSource_ptr)(cl_context, cl_uint, const char **, const size_t *, cl_int *) = NULL; cl_program CL_API_CALL clCreateProgramWithSource (cl_context context,cl_uint count,const char ** strings,const size_t * lengths,cl_int * errcode_ret) { if(!clCreateProgramWithSource_ptr) clCreateProgramWithSource_ptr = getFunction("clCreateProgramWithSource"); return (*clCreateProgramWithSource_ptr)(context, count, strings, lengths, errcode_ret); } -static cl_program (CL_API_CALL *clCreateProgramWithBinary_ptr)(cl_context, cl_uint, const cl_device_id *, const size_t *, const unsigned char **, cl_int *, cl_int *) = NULL; +static cl_program (*clCreateProgramWithBinary_ptr)(cl_context, cl_uint, const cl_device_id *, const size_t *, const unsigned char **, cl_int *, cl_int *) = NULL; cl_program CL_API_CALL clCreateProgramWithBinary (cl_context context,cl_uint num_devices,const cl_device_id * device_list,const size_t * lengths,const unsigned char ** binaries,cl_int * binary_status,cl_int * errcode_ret) { if(!clCreateProgramWithBinary_ptr) clCreateProgramWithBinary_ptr = getFunction("clCreateProgramWithBinary"); return (*clCreateProgramWithBinary_ptr)(context, num_devices, device_list, lengths, binaries, binary_status, errcode_ret); } -static cl_int (CL_API_CALL *clRetainProgram_ptr)(cl_program) = NULL; +static cl_program (*clCreateProgramWithBuiltInKernels_ptr)(cl_context, cl_uint, const cl_device_id *, const char *, cl_int *) = NULL; +cl_program CL_API_CALL clCreateProgramWithBuiltInKernels (cl_context context,cl_uint num_devices,const cl_device_id * device_list,const char * kernel_names,cl_int * errcode_ret) { + if(!clCreateProgramWithBuiltInKernels_ptr) clCreateProgramWithBuiltInKernels_ptr = getFunction("clCreateProgramWithBuiltInKernels"); + return (*clCreateProgramWithBuiltInKernels_ptr)(context, num_devices, device_list, kernel_names, errcode_ret); +} + +static cl_int (*clRetainProgram_ptr)(cl_program) = NULL; cl_int CL_API_CALL clRetainProgram (cl_program program) { if(!clRetainProgram_ptr) clRetainProgram_ptr = getFunction("clRetainProgram"); return (*clRetainProgram_ptr)(program); } -static cl_int (CL_API_CALL *clReleaseProgram_ptr)(cl_program) = NULL; +static cl_int (*clReleaseProgram_ptr)(cl_program) = NULL; cl_int CL_API_CALL clReleaseProgram (cl_program program) { if(!clReleaseProgram_ptr) clReleaseProgram_ptr = getFunction("clReleaseProgram"); return (*clReleaseProgram_ptr)(program); } -static cl_int (CL_API_CALL *clBuildProgram_ptr)(cl_program, cl_uint, const cl_device_id *, const char *, void (CL_CALLBACK * /* pfn_notify */)(cl_program /* program */, void *), void *) = NULL; -cl_int CL_API_CALL clBuildProgram (cl_program program,cl_uint num_devices,const cl_device_id * device_list,const char * options,void (CL_CALLBACK * pfn_notify)(cl_program /* program */, void *),void * user_data) { +static cl_int (*clBuildProgram_ptr)(cl_program, cl_uint, const cl_device_id *, const char *, void (CL_CALLBACK * /* pfn_notify */)(cl_program /* program */, void * /* user_data */), void *) = NULL; +cl_int CL_API_CALL clBuildProgram (cl_program program,cl_uint num_devices,const cl_device_id * device_list,const char * options, void (CL_CALLBACK * pfn_notify)(cl_program /* program */, void * /* user_data */),void * user_data) { if(!clBuildProgram_ptr) clBuildProgram_ptr = getFunction("clBuildProgram"); - return (*clBuildProgram_ptr)(program, num_devices, device_list, options, pfn_notify, user_data); + return (*clBuildProgram_ptr)(program, num_devices, device_list, options, user_data, user_data); } -static cl_int (CL_API_CALL *clUnloadCompiler_ptr)(void) = NULL; -cl_int CL_API_CALL clUnloadCompiler (void) { - if(!clUnloadCompiler_ptr) clUnloadCompiler_ptr = getFunction("clUnloadCompiler"); - return (*clUnloadCompiler_ptr)(); +static cl_int (*clCompileProgram_ptr)(cl_program, cl_uint, const cl_device_id *, const char *, cl_uint, const cl_program *, const char **, void (CL_CALLBACK * /* pfn_notify */)(cl_program /* program */, void * /* user_data */), void *) = NULL; +cl_int CL_API_CALL clCompileProgram (cl_program program,cl_uint num_devices,const cl_device_id * device_list,const char * options,cl_uint num_input_headers,const cl_program * input_headers,const char ** header_include_names,void (CL_CALLBACK * pfn_notify)(cl_program /* program */, void * /* user_data */),void * user_data) { + if(!clCompileProgram_ptr) clCompileProgram_ptr = getFunction("clCompileProgram"); + return (*clCompileProgram_ptr)(program, num_devices, device_list, options, num_input_headers, input_headers, header_include_names, user_data, user_data); } -static cl_int (CL_API_CALL *clGetProgramInfo_ptr)(cl_program, cl_program_info, size_t, void *, size_t *) = NULL; +static cl_program (*clLinkProgram_ptr)(cl_context, cl_uint, const cl_device_id *, const char *, cl_uint, const cl_program *, void (CL_CALLBACK * /* pfn_notify */)(cl_program /* program */, void * /* user_data */), void *, cl_int *) = NULL; +cl_program CL_API_CALL clLinkProgram (cl_context context,cl_uint num_devices,const cl_device_id * device_list,const char * options,cl_uint num_input_programs,const cl_program * input_programs,void (CL_CALLBACK * pfn_notify)(cl_program /* program */, void * /* user_data */),void * user_data,cl_int * errcode_ret) { + if(!clLinkProgram_ptr) clLinkProgram_ptr = getFunction("clLinkProgram"); + return (*clLinkProgram_ptr)(context, num_devices, device_list, options, num_input_programs, input_programs, user_data, user_data, errcode_ret); +} + +static cl_int (*clUnloadPlatformCompiler_ptr)(cl_platform_id) = NULL; +cl_int CL_API_CALL clUnloadPlatformCompiler (cl_platform_id platform) { + if(!clUnloadPlatformCompiler_ptr) clUnloadPlatformCompiler_ptr = getFunction("clUnloadPlatformCompiler"); + return (*clUnloadPlatformCompiler_ptr)(platform); +} + +static cl_int (*clGetProgramInfo_ptr)(cl_program, cl_program_info, size_t, void *, size_t *) = NULL; cl_int CL_API_CALL clGetProgramInfo (cl_program program,cl_program_info param_name,size_t param_value_size,void * param_value,size_t * param_value_size_ret) { if(!clGetProgramInfo_ptr) clGetProgramInfo_ptr = getFunction("clGetProgramInfo"); return (*clGetProgramInfo_ptr)(program, param_name, param_value_size, param_value, param_value_size_ret); } -static cl_int (CL_API_CALL *clGetProgramBuildInfo_ptr)(cl_program, cl_device_id, cl_program_build_info, size_t, void *, size_t *) = NULL; +static cl_int (*clGetProgramBuildInfo_ptr)(cl_program, cl_device_id, cl_program_build_info, size_t, void *, size_t *) = NULL; cl_int CL_API_CALL clGetProgramBuildInfo (cl_program program,cl_device_id device,cl_program_build_info param_name,size_t param_value_size,void * param_value,size_t * param_value_size_ret) { if(!clGetProgramBuildInfo_ptr) clGetProgramBuildInfo_ptr = getFunction("clGetProgramBuildInfo"); return (*clGetProgramBuildInfo_ptr)(program, device, param_name, param_value_size, param_value, param_value_size_ret); } -static cl_kernel (CL_API_CALL *clCreateKernel_ptr)(cl_program, const char *, cl_int *) = NULL; +static cl_kernel (*clCreateKernel_ptr)(cl_program, const char *, cl_int *) = NULL; cl_kernel CL_API_CALL clCreateKernel (cl_program program,const char * kernel_name,cl_int * errcode_ret) { if(!clCreateKernel_ptr) clCreateKernel_ptr = getFunction("clCreateKernel"); return (*clCreateKernel_ptr)(program, kernel_name, errcode_ret); } -static cl_int (CL_API_CALL *clCreateKernelsInProgram_ptr)(cl_program, cl_uint, cl_kernel *, cl_uint *) = NULL; +static cl_int (*clCreateKernelsInProgram_ptr)(cl_program, cl_uint, cl_kernel *, cl_uint *) = NULL; cl_int CL_API_CALL clCreateKernelsInProgram (cl_program program,cl_uint num_kernels,cl_kernel * kernels,cl_uint * num_kernels_ret) { if(!clCreateKernelsInProgram_ptr) clCreateKernelsInProgram_ptr = getFunction("clCreateKernelsInProgram"); return (*clCreateKernelsInProgram_ptr)(program, num_kernels, kernels, num_kernels_ret); } -static cl_int (CL_API_CALL *clRetainKernel_ptr)(cl_kernel) = NULL; +static cl_int (*clRetainKernel_ptr)(cl_kernel) = NULL; cl_int CL_API_CALL clRetainKernel (cl_kernel kernel) { if(!clRetainKernel_ptr) clRetainKernel_ptr = getFunction("clRetainKernel"); return (*clRetainKernel_ptr)(kernel); } -static cl_int (CL_API_CALL *clReleaseKernel_ptr)(cl_kernel) = NULL; +static cl_int (*clReleaseKernel_ptr)(cl_kernel) = NULL; cl_int CL_API_CALL clReleaseKernel (cl_kernel kernel) { if(!clReleaseKernel_ptr) clReleaseKernel_ptr = getFunction("clReleaseKernel"); return (*clReleaseKernel_ptr)(kernel); } -static cl_int (CL_API_CALL *clSetKernelArg_ptr)(cl_kernel, cl_uint, size_t, const void *) = NULL; +static cl_int (*clSetKernelArg_ptr)(cl_kernel, cl_uint, size_t, const void *) = NULL; cl_int CL_API_CALL clSetKernelArg (cl_kernel kernel,cl_uint arg_index,size_t arg_size,const void * arg_value) { if(!clSetKernelArg_ptr) clSetKernelArg_ptr = getFunction("clSetKernelArg"); return (*clSetKernelArg_ptr)(kernel, arg_index, arg_size, arg_value); } -static cl_int (CL_API_CALL *clGetKernelInfo_ptr)(cl_kernel, cl_kernel_info, size_t, void *, size_t *) = NULL; +static cl_int (*clGetKernelInfo_ptr)(cl_kernel, cl_kernel_info, size_t, void *, size_t *) = NULL; cl_int CL_API_CALL clGetKernelInfo (cl_kernel kernel,cl_kernel_info param_name,size_t param_value_size,void * param_value,size_t * param_value_size_ret) { if(!clGetKernelInfo_ptr) clGetKernelInfo_ptr = getFunction("clGetKernelInfo"); return (*clGetKernelInfo_ptr)(kernel, param_name, param_value_size, param_value, param_value_size_ret); } -static cl_int (CL_API_CALL *clGetKernelWorkGroupInfo_ptr)(cl_kernel, cl_device_id, cl_kernel_work_group_info, size_t, void *, size_t *) = NULL; +static cl_int (*clGetKernelArgInfo_ptr)(cl_kernel, cl_uint, cl_kernel_arg_info, size_t, void *, size_t *) = NULL; +cl_int CL_API_CALL clGetKernelArgInfo (cl_kernel kernel,cl_uint arg_indx,cl_kernel_arg_info param_name,size_t param_value_size,void * param_value,size_t * param_value_size_ret) { + if(!clGetKernelArgInfo_ptr) clGetKernelArgInfo_ptr = getFunction("clGetKernelArgInfo"); + return (*clGetKernelArgInfo_ptr)(kernel, arg_indx, param_name, param_value_size, param_value, param_value_size_ret); +} + +static cl_int (*clGetKernelWorkGroupInfo_ptr)(cl_kernel, cl_device_id, cl_kernel_work_group_info, size_t, void *, size_t *) = NULL; cl_int CL_API_CALL clGetKernelWorkGroupInfo (cl_kernel kernel,cl_device_id device,cl_kernel_work_group_info param_name,size_t param_value_size,void * param_value,size_t * param_value_size_ret) { if(!clGetKernelWorkGroupInfo_ptr) clGetKernelWorkGroupInfo_ptr = getFunction("clGetKernelWorkGroupInfo"); return (*clGetKernelWorkGroupInfo_ptr)(kernel, device, param_name, param_value_size, param_value, param_value_size_ret); } -static cl_int (CL_API_CALL *clWaitForEvents_ptr)(cl_uint, const cl_event *) = NULL; +static cl_int (*clWaitForEvents_ptr)(cl_uint, const cl_event *) = NULL; cl_int CL_API_CALL clWaitForEvents (cl_uint num_events,const cl_event * event_list) { if(!clWaitForEvents_ptr) clWaitForEvents_ptr = getFunction("clWaitForEvents"); return (*clWaitForEvents_ptr)(num_events, event_list); } -static cl_int (CL_API_CALL *clGetEventInfo_ptr)(cl_event, cl_event_info, size_t, void *, size_t *) = NULL; +static cl_int (*clGetEventInfo_ptr)(cl_event, cl_event_info, size_t, void *, size_t *) = NULL; cl_int CL_API_CALL clGetEventInfo (cl_event event,cl_event_info param_name,size_t param_value_size,void * param_value,size_t * param_value_size_ret) { if(!clGetEventInfo_ptr) clGetEventInfo_ptr = getFunction("clGetEventInfo"); return (*clGetEventInfo_ptr)(event, param_name, param_value_size, param_value, param_value_size_ret); } -static cl_int (CL_API_CALL *clRetainEvent_ptr)(cl_event) = NULL; -cl_int CL_API_CALL clRetainEvent (cl_event event) { +static cl_event (*clCreateUserEvent_ptr)(cl_context, cl_int * /* errcode_ret */) = NULL; +cl_event CL_API_CALL clCreateUserEvent (cl_context context,cl_int * errcode_ret) +{ + if(!clCreateUserEvent_ptr) clCreateUserEvent_ptr = getFunction("clCreateUserEvent"); + return (*clCreateUserEvent_ptr)(context,errcode_ret); +} + +static cl_int (*clRetainEvent_ptr)(cl_event) = NULL; +cl_int CL_API_CALL clRetainEvent(cl_event event) { if(!clRetainEvent_ptr) clRetainEvent_ptr = getFunction("clRetainEvent"); return (*clRetainEvent_ptr)(event); } -static cl_int (CL_API_CALL *clReleaseEvent_ptr)(cl_event) = NULL; +static cl_int (*clReleaseEvent_ptr)(cl_event) = NULL; cl_int CL_API_CALL clReleaseEvent (cl_event event) { if(!clReleaseEvent_ptr) clReleaseEvent_ptr = getFunction("clReleaseEvent"); return (*clReleaseEvent_ptr)(event); } -static cl_int (CL_API_CALL *clGetEventProfilingInfo_ptr)(cl_event, cl_profiling_info, size_t, void *, size_t *) = NULL; +static cl_int (*clSetUserEventStatus_ptr)(cl_event, cl_int) = NULL; +cl_int CL_API_CALL clSetUserEventStatus (cl_event event,cl_int execution_status) { + if(!clSetUserEventStatus_ptr) clSetUserEventStatus_ptr = getFunction("clSetUserEventStatus"); + return (*clSetUserEventStatus_ptr)(event, execution_status); +} + +static cl_int (*clSetEventCallback_ptr)(cl_event, cl_int, void (CL_CALLBACK * /* pfn_notify */)(cl_event, cl_int, void *), void*) = NULL; +cl_int CL_API_CALL clSetEventCallback (cl_event event,cl_int command_exec_callback_type, void (CL_CALLBACK * pfn_notify)(cl_event, cl_int, void *), void* user_data) { + if(!clSetEventCallback_ptr) clSetEventCallback_ptr = getFunction("clSetEventCallback"); + return (*clSetEventCallback_ptr)(event, command_exec_callback_type, pfn_notify, user_data); +} + +static cl_int (*clGetEventProfilingInfo_ptr)(cl_event, cl_profiling_info, size_t, void *, size_t *) = NULL; cl_int CL_API_CALL clGetEventProfilingInfo (cl_event event,cl_profiling_info param_name,size_t param_value_size,void * param_value,size_t * param_value_size_ret) { if(!clGetEventProfilingInfo_ptr) clGetEventProfilingInfo_ptr = getFunction("clGetEventProfilingInfo"); return (*clGetEventProfilingInfo_ptr)(event, param_name, param_value_size, param_value, param_value_size_ret); } -static cl_int (CL_API_CALL *clFlush_ptr)(cl_command_queue) = NULL; +static cl_int (*clFlush_ptr)(cl_command_queue) = NULL; cl_int CL_API_CALL clFlush (cl_command_queue command_queue) { if(!clFlush_ptr) clFlush_ptr = getFunction("clFlush"); return (*clFlush_ptr)(command_queue); } -static cl_int (CL_API_CALL *clFinish_ptr)(cl_command_queue) = NULL; +static cl_int (*clFinish_ptr)(cl_command_queue) = NULL; cl_int CL_API_CALL clFinish (cl_command_queue command_queue) { if(!clFinish_ptr) clFinish_ptr = getFunction("clFinish"); return (*clFinish_ptr)(command_queue); } -static cl_int (CL_API_CALL *clEnqueueReadBuffer_ptr)(cl_command_queue, cl_mem, cl_bool, size_t, size_t, void *, cl_uint, const cl_event *, cl_event *) = NULL; -cl_int CL_API_CALL clEnqueueReadBuffer (cl_command_queue command_queue,cl_mem buffer,cl_bool blocking_read,size_t offset,size_t cb,void * ptr,cl_uint num_events_in_wait_list,const cl_event * event_wait_list,cl_event * event) { +static cl_int (*clEnqueueReadBuffer_ptr)(cl_command_queue, cl_mem, cl_bool, size_t, size_t, void *, cl_uint, const cl_event *, cl_event *) = NULL; +cl_int CL_API_CALL clEnqueueReadBuffer (cl_command_queue command_queue,cl_mem buffer,cl_bool blocking_read,size_t offset,size_t size,void * ptr,cl_uint num_events_in_wait_list,const cl_event * event_wait_list,cl_event * event) { if(!clEnqueueReadBuffer_ptr) clEnqueueReadBuffer_ptr = getFunction("clEnqueueReadBuffer"); - return (*clEnqueueReadBuffer_ptr)(command_queue, buffer, blocking_read, offset, cb, ptr, num_events_in_wait_list, event_wait_list, event); + return (*clEnqueueReadBuffer_ptr)(command_queue, buffer, blocking_read, offset, size, ptr, num_events_in_wait_list, event_wait_list, event); } -static cl_int (CL_API_CALL *clEnqueueWriteBuffer_ptr)(cl_command_queue, cl_mem, cl_bool, size_t, size_t, const void *, cl_uint, const cl_event *, cl_event *) = NULL; -cl_int CL_API_CALL clEnqueueWriteBuffer (cl_command_queue command_queue,cl_mem buffer,cl_bool blocking_write,size_t offset,size_t cb,const void * ptr,cl_uint num_events_in_wait_list,const cl_event * event_wait_list,cl_event * event) { +static cl_int (*clEnqueueReadBufferRect_ptr)(cl_command_queue, cl_mem, cl_bool, const size_t *, const size_t *, const size_t *, size_t, size_t, size_t, size_t, void *, cl_uint, const cl_event *, cl_event *) = NULL; +cl_int CL_API_CALL clEnqueueReadBufferRect (cl_command_queue command_queue,cl_mem buffer,cl_bool blocking_read,const size_t * buffer_offset,const size_t * host_offset,const size_t * region,size_t buffer_row_pitch,size_t buffer_slice_pitch,size_t host_row_pitch,size_t host_slice_pitch,void * ptr,cl_uint num_events_in_wait_list,const cl_event * event_wait_list,cl_event * event) { + if(!clEnqueueReadBufferRect_ptr) clEnqueueReadBufferRect_ptr = getFunction("clEnqueueReadBufferRect"); + return (*clEnqueueReadBufferRect_ptr)(command_queue, buffer, blocking_read, buffer_offset, host_offset, region, buffer_row_pitch, buffer_slice_pitch, host_row_pitch, host_slice_pitch, ptr, num_events_in_wait_list, event_wait_list, event); +} + +static cl_int (*clEnqueueWriteBuffer_ptr)(cl_command_queue, cl_mem, cl_bool, size_t, size_t, const void *, cl_uint, const cl_event *, cl_event *) = NULL; +cl_int CL_API_CALL clEnqueueWriteBuffer (cl_command_queue command_queue,cl_mem buffer,cl_bool blocking_write,size_t offset,size_t size,const void * ptr,cl_uint num_events_in_wait_list,const cl_event * event_wait_list,cl_event * event) { if(!clEnqueueWriteBuffer_ptr) clEnqueueWriteBuffer_ptr = getFunction("clEnqueueWriteBuffer"); - return (*clEnqueueWriteBuffer_ptr)(command_queue, buffer, blocking_write, offset, cb, ptr, num_events_in_wait_list, event_wait_list, event); + return (*clEnqueueWriteBuffer_ptr)(command_queue, buffer, blocking_write, offset, size, ptr, num_events_in_wait_list, event_wait_list, event); } -static cl_int (CL_API_CALL *clEnqueueCopyBuffer_ptr)(cl_command_queue, cl_mem, cl_mem, size_t, size_t, size_t, cl_uint, const cl_event *, cl_event *) = NULL; -cl_int CL_API_CALL clEnqueueCopyBuffer (cl_command_queue command_queue,cl_mem src_buffer,cl_mem dst_buffer,size_t src_offset,size_t dst_offset,size_t cb,cl_uint num_events_in_wait_list,const cl_event * event_wait_list,cl_event * event) { +static cl_int (*clEnqueueWriteBufferRect_ptr)(cl_command_queue, cl_mem, cl_bool, const size_t *, const size_t *, const size_t *, size_t, size_t, size_t, size_t, const void *, cl_uint, const cl_event *, cl_event *) = NULL; +cl_int CL_API_CALL clEnqueueWriteBufferRect (cl_command_queue command_queue,cl_mem buffer,cl_bool blocking_write,const size_t * buffer_offset,const size_t * host_offset,const size_t * region,size_t buffer_row_pitch,size_t buffer_slice_pitch,size_t host_row_pitch,size_t host_slice_pitch,const void * ptr,cl_uint num_events_in_wait_list,const cl_event * event_wait_list,cl_event * event) { + if(!clEnqueueWriteBufferRect_ptr) clEnqueueWriteBufferRect_ptr = getFunction("clEnqueueWriteBufferRect"); + return (*clEnqueueWriteBufferRect_ptr)(command_queue, buffer, blocking_write, buffer_offset, host_offset, region, buffer_row_pitch, buffer_slice_pitch, host_row_pitch, host_slice_pitch, ptr, num_events_in_wait_list, event_wait_list, event); +} + +static cl_int (*clEnqueueFillBuffer_ptr)(cl_command_queue, cl_mem, const void *, size_t, size_t, size_t, cl_uint, const cl_event *, cl_event *) = NULL; +cl_int CL_API_CALL clEnqueueFillBuffer (cl_command_queue command_queue,cl_mem buffer,const void * pattern,size_t pattern_size,size_t offset,size_t size,cl_uint num_events_in_wait_list,const cl_event * event_wait_list,cl_event * event) { + if(!clEnqueueFillBuffer_ptr) clEnqueueFillBuffer_ptr = getFunction("clEnqueueFillBuffer"); + return (*clEnqueueFillBuffer_ptr)(command_queue, buffer, pattern, pattern_size, offset, size, num_events_in_wait_list, event_wait_list, event); +} + +static cl_int (*clEnqueueCopyBuffer_ptr)(cl_command_queue, cl_mem, cl_mem, size_t, size_t, size_t, cl_uint, const cl_event *, cl_event *) = NULL; +cl_int CL_API_CALL clEnqueueCopyBuffer (cl_command_queue command_queue,cl_mem src_buffer,cl_mem dst_buffer,size_t src_offset,size_t dst_offset,size_t size,cl_uint num_events_in_wait_list,const cl_event * event_wait_list,cl_event * event) { if(!clEnqueueCopyBuffer_ptr) clEnqueueCopyBuffer_ptr = getFunction("clEnqueueCopyBuffer"); - return (*clEnqueueCopyBuffer_ptr)(command_queue, src_buffer, dst_buffer, src_offset, dst_offset, cb, num_events_in_wait_list, event_wait_list, event); + return (*clEnqueueCopyBuffer_ptr)(command_queue, src_buffer, dst_buffer, src_offset, dst_offset, size, num_events_in_wait_list, event_wait_list, event); } -static cl_int (CL_API_CALL *clEnqueueReadImage_ptr)(cl_command_queue, cl_mem, cl_bool, const size_t *, const size_t *, size_t, size_t, void *, cl_uint, const cl_event *, cl_event *) = NULL; +static cl_int (*clEnqueueCopyBufferRect_ptr)(cl_command_queue, cl_mem, cl_mem, const size_t *, const size_t *, const size_t *, size_t, size_t, size_t, size_t, cl_uint, const cl_event *, cl_event *) = NULL; +cl_int CL_API_CALL clEnqueueCopyBufferRect (cl_command_queue command_queue,cl_mem src_buffer,cl_mem dst_buffer,const size_t * src_origin,const size_t * dst_origin,const size_t * region,size_t src_row_pitch,size_t src_slice_pitch,size_t dst_row_pitch,size_t dst_slice_pitch,cl_uint num_events_in_wait_list,const cl_event * event_wait_list,cl_event * event) { + if(!clEnqueueCopyBufferRect_ptr) clEnqueueCopyBufferRect_ptr = getFunction("clEnqueueCopyBufferRect"); + return (*clEnqueueCopyBufferRect_ptr)(command_queue, src_buffer, dst_buffer, src_origin, dst_origin, region, src_row_pitch, src_slice_pitch, dst_row_pitch, dst_slice_pitch, num_events_in_wait_list, event_wait_list, event); +} + +static cl_int (*clEnqueueReadImage_ptr)(cl_command_queue, cl_mem, cl_bool, const size_t *, const size_t *, size_t, size_t, void *, cl_uint, const cl_event *, cl_event *) = NULL; cl_int CL_API_CALL clEnqueueReadImage (cl_command_queue command_queue,cl_mem image,cl_bool blocking_read,const size_t * origin,const size_t * region,size_t row_pitch,size_t slice_pitch,void * ptr,cl_uint num_events_in_wait_list,const cl_event * event_wait_list,cl_event * event) { if(!clEnqueueReadImage_ptr) clEnqueueReadImage_ptr = getFunction("clEnqueueReadImage"); return (*clEnqueueReadImage_ptr)(command_queue, image, blocking_read, origin, region, row_pitch, slice_pitch, ptr, num_events_in_wait_list, event_wait_list, event); } -static cl_int (CL_API_CALL *clEnqueueWriteImage_ptr)(cl_command_queue, cl_mem, cl_bool, const size_t *, const size_t *, size_t, size_t, const void *, cl_uint, const cl_event *, cl_event *) = NULL; +static cl_int (*clEnqueueWriteImage_ptr)(cl_command_queue, cl_mem, cl_bool, const size_t *, const size_t *, size_t, size_t, const void *, cl_uint, const cl_event *, cl_event *) = NULL; cl_int CL_API_CALL clEnqueueWriteImage (cl_command_queue command_queue,cl_mem image,cl_bool blocking_write,const size_t * origin,const size_t * region,size_t input_row_pitch,size_t input_slice_pitch,const void * ptr,cl_uint num_events_in_wait_list,const cl_event * event_wait_list,cl_event * event) { if(!clEnqueueWriteImage_ptr) clEnqueueWriteImage_ptr = getFunction("clEnqueueWriteImage"); return (*clEnqueueWriteImage_ptr)(command_queue, image, blocking_write, origin, region, input_row_pitch, input_slice_pitch, ptr, num_events_in_wait_list, event_wait_list, event); } -static cl_int (CL_API_CALL *clEnqueueCopyImage_ptr)(cl_command_queue, cl_mem, cl_mem, const size_t *, const size_t *, const size_t *, cl_uint, const cl_event *, cl_event *) = NULL; +static cl_int (*clEnqueueFillImage_ptr)(cl_command_queue, cl_mem, const void *, const size_t *, const size_t *, cl_uint, const cl_event *, cl_event *) = NULL; +cl_int CL_API_CALL clEnqueueFillImage (cl_command_queue command_queue,cl_mem image,const void * fill_color,const size_t * origin,const size_t * region,cl_uint num_events_in_wait_list,const cl_event * event_wait_list,cl_event * event) { + if(!clEnqueueFillImage_ptr) clEnqueueFillImage_ptr = getFunction("clEnqueueFillImage"); + return (*clEnqueueFillImage_ptr)(command_queue, image, fill_color, origin, region, num_events_in_wait_list, event_wait_list, event); +} + +static cl_int (*clEnqueueCopyImage_ptr)(cl_command_queue, cl_mem, cl_mem, const size_t *, const size_t *, const size_t *, cl_uint, const cl_event *, cl_event *) = NULL; cl_int CL_API_CALL clEnqueueCopyImage (cl_command_queue command_queue,cl_mem src_image,cl_mem dst_image,const size_t * src_origin,const size_t * dst_origin,const size_t * region,cl_uint num_events_in_wait_list,const cl_event * event_wait_list,cl_event * event) { if(!clEnqueueCopyImage_ptr) clEnqueueCopyImage_ptr = getFunction("clEnqueueCopyImage"); return (*clEnqueueCopyImage_ptr)(command_queue, src_image, dst_image, src_origin, dst_origin, region, num_events_in_wait_list, event_wait_list, event); } -static cl_int (CL_API_CALL *clEnqueueCopyImageToBuffer_ptr)(cl_command_queue, cl_mem, cl_mem, const size_t *, const size_t *, size_t, cl_uint, const cl_event *, cl_event *) = NULL; +static cl_int (*clEnqueueCopyImageToBuffer_ptr)(cl_command_queue, cl_mem, cl_mem, const size_t *, const size_t *, size_t, cl_uint, const cl_event *, cl_event *) = NULL; cl_int CL_API_CALL clEnqueueCopyImageToBuffer (cl_command_queue command_queue,cl_mem src_image,cl_mem dst_buffer,const size_t * src_origin,const size_t * region,size_t dst_offset,cl_uint num_events_in_wait_list,const cl_event * event_wait_list,cl_event * event) { if(!clEnqueueCopyImageToBuffer_ptr) clEnqueueCopyImageToBuffer_ptr = getFunction("clEnqueueCopyImageToBuffer"); return (*clEnqueueCopyImageToBuffer_ptr)(command_queue, src_image, dst_buffer, src_origin, region, dst_offset, num_events_in_wait_list, event_wait_list, event); } -static cl_int (CL_API_CALL *clEnqueueCopyBufferToImage_ptr)(cl_command_queue, cl_mem, cl_mem, size_t, const size_t *, const size_t *, cl_uint, const cl_event *, cl_event *) = NULL; +static cl_int (*clEnqueueCopyBufferToImage_ptr)(cl_command_queue, cl_mem, cl_mem, size_t, const size_t *, const size_t *, cl_uint, const cl_event *, cl_event *) = NULL; cl_int CL_API_CALL clEnqueueCopyBufferToImage (cl_command_queue command_queue,cl_mem src_buffer,cl_mem dst_image,size_t src_offset,const size_t * dst_origin,const size_t * region,cl_uint num_events_in_wait_list,const cl_event * event_wait_list,cl_event * event) { if(!clEnqueueCopyBufferToImage_ptr) clEnqueueCopyBufferToImage_ptr = getFunction("clEnqueueCopyBufferToImage"); return (*clEnqueueCopyBufferToImage_ptr)(command_queue, src_buffer, dst_image, src_offset, dst_origin, region, num_events_in_wait_list, event_wait_list, event); } -static void * (CL_API_CALL *clEnqueueMapBuffer_ptr)(cl_command_queue, cl_mem, cl_bool, cl_map_flags, size_t, size_t, cl_uint, const cl_event *, cl_event *, cl_int *) = NULL; -void * CL_API_CALL clEnqueueMapBuffer (cl_command_queue command_queue,cl_mem buffer,cl_bool blocking_map,cl_map_flags map_flags,size_t offset,size_t cb,cl_uint num_events_in_wait_list,const cl_event * event_wait_list,cl_event * event,cl_int * errcode_ret) { +static void * (*clEnqueueMapBuffer_ptr)(cl_command_queue, cl_mem, cl_bool, cl_map_flags, size_t, size_t, cl_uint, const cl_event *, cl_event *, cl_int *) = NULL; +void * CL_API_CALL clEnqueueMapBuffer (cl_command_queue command_queue,cl_mem buffer,cl_bool blocking_map,cl_map_flags map_flags,size_t offset,size_t size,cl_uint num_events_in_wait_list,const cl_event * event_wait_list,cl_event * event,cl_int * errcode_ret) { if(!clEnqueueMapBuffer_ptr) clEnqueueMapBuffer_ptr = getFunction("clEnqueueMapBuffer"); - return (*clEnqueueMapBuffer_ptr)(command_queue, buffer, blocking_map, map_flags, offset, cb, num_events_in_wait_list, event_wait_list, event, errcode_ret); + return (*clEnqueueMapBuffer_ptr)(command_queue, buffer, blocking_map, map_flags, offset, size, num_events_in_wait_list, event_wait_list, event, errcode_ret); } -static void * (CL_API_CALL *clEnqueueMapImage_ptr)(cl_command_queue, cl_mem, cl_bool, cl_map_flags, const size_t *, const size_t *, size_t *, size_t *, cl_uint, const cl_event *, cl_event *, cl_int *) = NULL; +static void * (*clEnqueueMapImage_ptr)(cl_command_queue, cl_mem, cl_bool, cl_map_flags, const size_t *, const size_t *, size_t *, size_t *, cl_uint, const cl_event *, cl_event *, cl_int *) = NULL; void * CL_API_CALL clEnqueueMapImage (cl_command_queue command_queue,cl_mem image,cl_bool blocking_map,cl_map_flags map_flags,const size_t * origin,const size_t * region,size_t * image_row_pitch,size_t * image_slice_pitch,cl_uint num_events_in_wait_list,const cl_event * event_wait_list,cl_event * event,cl_int * errcode_ret) { if(!clEnqueueMapImage_ptr) clEnqueueMapImage_ptr = getFunction("clEnqueueMapImage"); return (*clEnqueueMapImage_ptr)(command_queue, image, blocking_map, map_flags, origin, region, image_row_pitch, image_slice_pitch, num_events_in_wait_list, event_wait_list, event, errcode_ret); } -static cl_int (CL_API_CALL *clEnqueueUnmapMemObject_ptr)(cl_command_queue, cl_mem, void *, cl_uint, const cl_event *, cl_event *) = NULL; +static cl_int (*clEnqueueUnmapMemObject_ptr)(cl_command_queue, cl_mem, void *, cl_uint, const cl_event *, cl_event *) = NULL; cl_int CL_API_CALL clEnqueueUnmapMemObject (cl_command_queue command_queue,cl_mem memobj,void * mapped_ptr,cl_uint num_events_in_wait_list,const cl_event * event_wait_list,cl_event * event) { if(!clEnqueueUnmapMemObject_ptr) clEnqueueUnmapMemObject_ptr = getFunction("clEnqueueUnmapMemObject"); return (*clEnqueueUnmapMemObject_ptr)(command_queue, memobj, mapped_ptr, num_events_in_wait_list, event_wait_list, event); } -static cl_int (CL_API_CALL *clEnqueueNDRangeKernel_ptr)(cl_command_queue, cl_kernel, cl_uint, const size_t *, const size_t *, const size_t *, cl_uint, const cl_event *, cl_event *) = NULL; +static cl_int (*clEnqueueMigrateMemObjects_ptr)(cl_command_queue, cl_uint, const cl_mem *, cl_mem_migration_flags, cl_uint, const cl_event *, cl_event *) = NULL; +cl_int CL_API_CALL clEnqueueMigrateMemObjects (cl_command_queue command_queue,cl_uint num_mem_objects,const cl_mem * mem_objects,cl_mem_migration_flags flags,cl_uint num_events_in_wait_list,const cl_event * event_wait_list,cl_event * event) { + if(!clEnqueueMigrateMemObjects_ptr) clEnqueueMigrateMemObjects_ptr = getFunction("clEnqueueMigrateMemObjects"); + return (*clEnqueueMigrateMemObjects_ptr)(command_queue, num_mem_objects, mem_objects, flags, num_events_in_wait_list, event_wait_list, event); +} + +static cl_int (*clEnqueueNDRangeKernel_ptr)(cl_command_queue, cl_kernel, cl_uint, const size_t *, const size_t *, const size_t *, cl_uint, const cl_event *, cl_event *) = NULL; cl_int CL_API_CALL clEnqueueNDRangeKernel (cl_command_queue command_queue,cl_kernel kernel,cl_uint work_dim,const size_t * global_work_offset,const size_t * global_work_size,const size_t * local_work_size,cl_uint num_events_in_wait_list,const cl_event * event_wait_list,cl_event * event) { if(!clEnqueueNDRangeKernel_ptr) clEnqueueNDRangeKernel_ptr = getFunction("clEnqueueNDRangeKernel"); return (*clEnqueueNDRangeKernel_ptr)(command_queue, kernel, work_dim, global_work_offset, global_work_size, local_work_size, num_events_in_wait_list, event_wait_list, event); } -static cl_int (CL_API_CALL *clEnqueueTask_ptr)(cl_command_queue, cl_kernel, cl_uint, const cl_event *, cl_event *) = NULL; +static cl_int (*clEnqueueTask_ptr)(cl_command_queue, cl_kernel, cl_uint, const cl_event *, cl_event *) = NULL; cl_int CL_API_CALL clEnqueueTask (cl_command_queue command_queue,cl_kernel kernel,cl_uint num_events_in_wait_list,const cl_event * event_wait_list,cl_event * event) { if(!clEnqueueTask_ptr) clEnqueueTask_ptr = getFunction("clEnqueueTask"); return (*clEnqueueTask_ptr)(command_queue, kernel, num_events_in_wait_list, event_wait_list, event); } -static cl_int (CL_API_CALL *clEnqueueNativeKernel_ptr)(cl_command_queue, void (*)(void *), void *, size_t, cl_uint, const cl_mem *, const void **, cl_uint, const cl_event *, cl_event *) = NULL; -cl_int CL_API_CALL clEnqueueNativeKernel (cl_command_queue command_queue,void (*user_func)(void *),void * args,size_t cb_args,cl_uint num_mem_objects,const cl_mem * mem_list,const void ** args_mem_loc,cl_uint num_events_in_wait_list,const cl_event * event_wait_list,cl_event * event) { +static cl_int (*clEnqueueNativeKernel_ptr)(cl_command_queue, void (CL_CALLBACK * /*user_func*/)(void *), void *, size_t, cl_uint, const cl_mem *, const void **, cl_uint, const cl_event *, cl_event *) = NULL; +cl_int CL_API_CALL clEnqueueNativeKernel (cl_command_queue command_queue,void (CL_CALLBACK *user_func)(void *) ,void * args,size_t cb_args,cl_uint num_mem_objects,const cl_mem * mem_list,const void ** args_mem_loc,cl_uint num_events_in_wait_list,const cl_event * event_wait_list,cl_event * event) { if(!clEnqueueNativeKernel_ptr) clEnqueueNativeKernel_ptr = getFunction("clEnqueueNativeKernel"); return (*clEnqueueNativeKernel_ptr)(command_queue, user_func, args, cb_args, num_mem_objects, mem_list, args_mem_loc, num_events_in_wait_list, event_wait_list, event); } -static cl_int (CL_API_CALL *clEnqueueMarker_ptr)(cl_command_queue, cl_event *) = NULL; -cl_int CL_API_CALL clEnqueueMarker (cl_command_queue command_queue,cl_event * event) { +static cl_int (*clEnqueueMarkerWithWaitList_ptr)(cl_command_queue, cl_uint, const cl_event *, cl_event *) = NULL; +cl_int CL_API_CALL clEnqueueMarkerWithWaitList (cl_command_queue command_queue,cl_uint num_events_in_wait_list,const cl_event * event_wait_list,cl_event * event) { + if(!clEnqueueMarkerWithWaitList_ptr) clEnqueueMarkerWithWaitList_ptr = getFunction("clEnqueueMarkerWithWaitList"); + return (*clEnqueueMarkerWithWaitList_ptr)(command_queue, num_events_in_wait_list, event_wait_list, event); +} + +static cl_int (*clEnqueueBarrierWithWaitList_ptr)(cl_command_queue, cl_uint, const cl_event *, cl_event *) = NULL; +cl_int CL_API_CALL clEnqueueBarrierWithWaitList (cl_command_queue command_queue,cl_uint num_events_in_wait_list,const cl_event * event_wait_list,cl_event * event) { + if(!clEnqueueBarrierWithWaitList_ptr) clEnqueueBarrierWithWaitList_ptr = getFunction("clEnqueueBarrierWithWaitList"); + return (*clEnqueueBarrierWithWaitList_ptr)(command_queue, num_events_in_wait_list, event_wait_list, event); +} + +static void * (*clGetExtensionFunctionAddressForPlatform_ptr)(cl_platform_id, const char *) = NULL; +void * CL_API_CALL clGetExtensionFunctionAddressForPlatform (cl_platform_id platform,const char * func_name) { + if(!clGetExtensionFunctionAddressForPlatform_ptr) clGetExtensionFunctionAddressForPlatform_ptr = getFunction("clGetExtensionFunctionAddressForPlatform"); + return (*clGetExtensionFunctionAddressForPlatform_ptr)(platform, func_name); +} + +static CL_EXT_PREFIX__VERSION_1_1_DEPRECATED cl_mem (*clCreateImage2D_ptr)(cl_context, cl_mem_flags, const cl_image_format *, size_t, size_t, size_t, void *, cl_int *) = NULL; +CL_EXT_PREFIX__VERSION_1_1_DEPRECATED cl_mem CL_API_CALL clCreateImage2D (cl_context context,cl_mem_flags flags,const cl_image_format * image_format,size_t image_width,size_t image_height,size_t image_row_pitch,void * host_ptr,cl_int * errcode_ret) { + if(!clCreateImage2D_ptr) clCreateImage2D_ptr = getFunction("clCreateImage2D"); + return (*clCreateImage2D_ptr)(context, flags, image_format, image_width, image_height, image_row_pitch, host_ptr, errcode_ret); +} + +static CL_EXT_PREFIX__VERSION_1_1_DEPRECATED cl_mem (*clCreateImage3D_ptr)(cl_context, cl_mem_flags, const cl_image_format *, size_t, size_t, size_t, size_t, size_t, void *, cl_int *) = NULL; +CL_EXT_PREFIX__VERSION_1_1_DEPRECATED cl_mem CL_API_CALL clCreateImage3D (cl_context context,cl_mem_flags flags,const cl_image_format * image_format,size_t image_width,size_t image_height,size_t image_depth,size_t image_row_pitch,size_t image_slice_pitch,void * host_ptr,cl_int * errcode_ret) { + if(!clCreateImage3D_ptr) clCreateImage3D_ptr = getFunction("clCreateImage3D"); + return (*clCreateImage3D_ptr)(context, flags, image_format, image_width, image_height, image_depth, image_row_pitch, image_slice_pitch, host_ptr, errcode_ret); +} + +static CL_EXT_PREFIX__VERSION_1_1_DEPRECATED cl_int (*clEnqueueMarker_ptr)(cl_command_queue, cl_event *) = NULL; +CL_EXT_PREFIX__VERSION_1_1_DEPRECATED cl_int CL_API_CALL clEnqueueMarker (cl_command_queue command_queue,cl_event * event) { if(!clEnqueueMarker_ptr) clEnqueueMarker_ptr = getFunction("clEnqueueMarker"); return (*clEnqueueMarker_ptr)(command_queue, event); } -static cl_int (CL_API_CALL *clEnqueueWaitForEvents_ptr)(cl_command_queue, cl_uint, const cl_event *) = NULL; -cl_int CL_API_CALL clEnqueueWaitForEvents (cl_command_queue command_queue,cl_uint num_events,const cl_event * event_list) { +static CL_EXT_PREFIX__VERSION_1_1_DEPRECATED cl_int (*clEnqueueWaitForEvents_ptr)(cl_command_queue, cl_uint, const cl_event *) = NULL; +CL_EXT_PREFIX__VERSION_1_1_DEPRECATED cl_int CL_API_CALL clEnqueueWaitForEvents (cl_command_queue command_queue,cl_uint num_events,const cl_event * event_list) { if(!clEnqueueWaitForEvents_ptr) clEnqueueWaitForEvents_ptr = getFunction("clEnqueueWaitForEvents"); return (*clEnqueueWaitForEvents_ptr)(command_queue, num_events, event_list); } -static cl_int (CL_API_CALL *clEnqueueBarrier_ptr)(cl_command_queue) = NULL; -cl_int CL_API_CALL clEnqueueBarrier (cl_command_queue command_queue) { +static CL_EXT_PREFIX__VERSION_1_1_DEPRECATED cl_int (*clEnqueueBarrier_ptr)(cl_command_queue) = NULL; +CL_EXT_PREFIX__VERSION_1_1_DEPRECATED cl_int CL_API_CALL clEnqueueBarrier (cl_command_queue command_queue) { if(!clEnqueueBarrier_ptr) clEnqueueBarrier_ptr = getFunction("clEnqueueBarrier"); return (*clEnqueueBarrier_ptr)(command_queue); } -static void * (CL_API_CALL *clGetExtensionFunctionAddress_ptr)(const char *) = NULL; -void * CL_API_CALL clGetExtensionFunctionAddress (const char * func_name) { +static CL_EXT_PREFIX__VERSION_1_1_DEPRECATED cl_int (*clUnloadCompiler_ptr)(void) = NULL; +CL_EXT_PREFIX__VERSION_1_1_DEPRECATED cl_int CL_API_CALL clUnloadCompiler (void) { + if(!clUnloadCompiler_ptr) clUnloadCompiler_ptr = getFunction("clUnloadCompiler"); + return (*clUnloadCompiler_ptr)(); +} + +static CL_EXT_PREFIX__VERSION_1_1_DEPRECATED void * (*clGetExtensionFunctionAddress_ptr)(const char *) = NULL; +CL_EXT_PREFIX__VERSION_1_1_DEPRECATED void * CL_API_CALL clGetExtensionFunctionAddress (const char * func_name) { if(!clGetExtensionFunctionAddress_ptr) clGetExtensionFunctionAddress_ptr = getFunction("clGetExtensionFunctionAddress"); return (*clGetExtensionFunctionAddress_ptr)(func_name); } diff --git a/Externals/CLRun/clrun/genclext.c b/Externals/CLRun/clrun/genclext.c new file mode 100644 index 0000000000..e6a73afabf --- /dev/null +++ b/Externals/CLRun/clrun/genclext.c @@ -0,0 +1,28 @@ +// Automatically generated by generateClRun.pl +#include "dynamiclib.h" +#include "../include/CL/cl_ext.h" + + +static cl_int (*clIcdGetPlatformIDsKHR_ptr)(cl_uint, cl_platform_id *, cl_uint *) = NULL; +cl_int CL_API_CALL clIcdGetPlatformIDsKHR (cl_uint num_entries,cl_platform_id * platforms,cl_uint * num_platforms) { + if(!clIcdGetPlatformIDsKHR_ptr) clIcdGetPlatformIDsKHR_ptr = getFunction("clIcdGetPlatformIDsKHR"); + return (*clIcdGetPlatformIDsKHR_ptr)(num_entries, platforms, num_platforms); +} +static cl_int (* clReleaseDeviceEXT_ptr)(cl_device_id) = NULL; +cl_int CL_API_CALL clReleaseDeviceEXT (cl_device_id device) { + if(! clReleaseDeviceEXT_ptr) clReleaseDeviceEXT_ptr = getFunction(" clReleaseDeviceEXT"); + return (* clReleaseDeviceEXT_ptr)(device); +} + +static cl_int (* clRetainDeviceEXT_ptr)(cl_device_id) = NULL; +cl_int CL_API_CALL clRetainDeviceEXT (cl_device_id device) { + if(! clRetainDeviceEXT_ptr) clRetainDeviceEXT_ptr = getFunction(" clRetainDeviceEXT"); + return (* clRetainDeviceEXT_ptr)(device); +} + +static cl_int (* clCreateSubDevicesEXT_ptr)(cl_device_id, const cl_device_partition_property_ext *, cl_uint, cl_device_id *, cl_uint *) = NULL; +cl_int CL_API_CALL clCreateSubDevicesEXT (cl_device_id in_device,const cl_device_partition_property_ext * properties,cl_uint num_entries,cl_device_id * out_devices,cl_uint * num_devices) { + if(! clCreateSubDevicesEXT_ptr) clCreateSubDevicesEXT_ptr = getFunction(" clCreateSubDevicesEXT"); + return (* clCreateSubDevicesEXT_ptr)(in_device, properties, num_entries, out_devices, num_devices); +} + diff --git a/Externals/CLRun/clrun/genclgl.c b/Externals/CLRun/clrun/genclgl.c index cc83a8a7ff..acb06a1ff7 100644 --- a/Externals/CLRun/clrun/genclgl.c +++ b/Externals/CLRun/clrun/genclgl.c @@ -3,55 +3,61 @@ #include "../include/CL/cl_gl.h" -static cl_mem (CL_API_CALL *clCreateFromGLBuffer_ptr)(cl_context, cl_mem_flags, cl_GLuint, int *) = NULL; +static cl_mem (*clCreateFromGLBuffer_ptr)(cl_context, cl_mem_flags, cl_GLuint, int *) = NULL; cl_mem CL_API_CALL clCreateFromGLBuffer (cl_context context,cl_mem_flags flags,cl_GLuint bufobj,int * errcode_ret) { if(!clCreateFromGLBuffer_ptr) clCreateFromGLBuffer_ptr = getFunction("clCreateFromGLBuffer"); - return (*clCreateFromGLBuffer_ptr)(context, flags, bufobj, errcode_ret ); + return (*clCreateFromGLBuffer_ptr)(context, flags, bufobj, errcode_ret); } -static cl_mem (CL_API_CALL *clCreateFromGLTexture2D_ptr)(cl_context, cl_mem_flags, cl_GLenum, cl_GLint, cl_GLuint, cl_int *) = NULL; -cl_mem CL_API_CALL clCreateFromGLTexture2D (cl_context context,cl_mem_flags flags,cl_GLenum target,cl_GLint miplevel,cl_GLuint texture,cl_int * errcode_ret) { - if(!clCreateFromGLTexture2D_ptr) clCreateFromGLTexture2D_ptr = getFunction("clCreateFromGLTexture2D"); - return (*clCreateFromGLTexture2D_ptr)(context, flags, target, miplevel, texture, errcode_ret); +static cl_mem (*clCreateFromGLTexture_ptr)(cl_context, cl_mem_flags, cl_GLenum, cl_GLint, cl_GLuint, cl_int *) = NULL; +cl_mem CL_API_CALL clCreateFromGLTexture (cl_context context,cl_mem_flags flags,cl_GLenum target,cl_GLint miplevel,cl_GLuint texture,cl_int * errcode_ret) { + if(!clCreateFromGLTexture_ptr) clCreateFromGLTexture_ptr = getFunction("clCreateFromGLTexture"); + return (*clCreateFromGLTexture_ptr)(context, flags, target, miplevel, texture, errcode_ret); } -static cl_mem (CL_API_CALL *clCreateFromGLTexture3D_ptr)(cl_context, cl_mem_flags, cl_GLenum, cl_GLint, cl_GLuint, cl_int *) = NULL; -cl_mem CL_API_CALL clCreateFromGLTexture3D (cl_context context,cl_mem_flags flags,cl_GLenum target,cl_GLint miplevel,cl_GLuint texture,cl_int * errcode_ret) { - if(!clCreateFromGLTexture3D_ptr) clCreateFromGLTexture3D_ptr = getFunction("clCreateFromGLTexture3D"); - return (*clCreateFromGLTexture3D_ptr)(context, flags, target, miplevel, texture, errcode_ret); -} - -static cl_mem (CL_API_CALL *clCreateFromGLRenderbuffer_ptr)(cl_context, cl_mem_flags, cl_GLuint, cl_int *) = NULL; +static cl_mem (*clCreateFromGLRenderbuffer_ptr)(cl_context, cl_mem_flags, cl_GLuint, cl_int *) = NULL; cl_mem CL_API_CALL clCreateFromGLRenderbuffer (cl_context context,cl_mem_flags flags,cl_GLuint renderbuffer,cl_int * errcode_ret) { if(!clCreateFromGLRenderbuffer_ptr) clCreateFromGLRenderbuffer_ptr = getFunction("clCreateFromGLRenderbuffer"); return (*clCreateFromGLRenderbuffer_ptr)(context, flags, renderbuffer, errcode_ret); } -static cl_int (CL_API_CALL *clGetGLObjectInfo_ptr)(cl_mem, cl_gl_object_type *, cl_GLuint *) = NULL; +static cl_int (*clGetGLObjectInfo_ptr)(cl_mem, cl_gl_object_type *, cl_GLuint *) = NULL; cl_int CL_API_CALL clGetGLObjectInfo (cl_mem memobj,cl_gl_object_type * gl_object_type,cl_GLuint * gl_object_name) { if(!clGetGLObjectInfo_ptr) clGetGLObjectInfo_ptr = getFunction("clGetGLObjectInfo"); return (*clGetGLObjectInfo_ptr)(memobj, gl_object_type, gl_object_name); } -static cl_int (CL_API_CALL *clGetGLTextureInfo_ptr)(cl_mem, cl_gl_texture_info, size_t, void *, size_t *) = NULL; +static cl_int (*clGetGLTextureInfo_ptr)(cl_mem, cl_gl_texture_info, size_t, void *, size_t *) = NULL; cl_int CL_API_CALL clGetGLTextureInfo (cl_mem memobj,cl_gl_texture_info param_name,size_t param_value_size,void * param_value,size_t * param_value_size_ret) { if(!clGetGLTextureInfo_ptr) clGetGLTextureInfo_ptr = getFunction("clGetGLTextureInfo"); return (*clGetGLTextureInfo_ptr)(memobj, param_name, param_value_size, param_value, param_value_size_ret); } -static cl_int (CL_API_CALL *clEnqueueAcquireGLObjects_ptr)(cl_command_queue, cl_uint, const cl_mem *, cl_uint, const cl_event *, cl_event *) = NULL; +static cl_int (*clEnqueueAcquireGLObjects_ptr)(cl_command_queue, cl_uint, const cl_mem *, cl_uint, const cl_event *, cl_event *) = NULL; cl_int CL_API_CALL clEnqueueAcquireGLObjects (cl_command_queue command_queue,cl_uint num_objects,const cl_mem * mem_objects,cl_uint num_events_in_wait_list,const cl_event * event_wait_list,cl_event * event) { if(!clEnqueueAcquireGLObjects_ptr) clEnqueueAcquireGLObjects_ptr = getFunction("clEnqueueAcquireGLObjects"); return (*clEnqueueAcquireGLObjects_ptr)(command_queue, num_objects, mem_objects, num_events_in_wait_list, event_wait_list, event); } -static cl_int (CL_API_CALL *clEnqueueReleaseGLObjects_ptr)(cl_command_queue, cl_uint, const cl_mem *, cl_uint, const cl_event *, cl_event *) = NULL; +static cl_int (*clEnqueueReleaseGLObjects_ptr)(cl_command_queue, cl_uint, const cl_mem *, cl_uint, const cl_event *, cl_event *) = NULL; cl_int CL_API_CALL clEnqueueReleaseGLObjects (cl_command_queue command_queue,cl_uint num_objects,const cl_mem * mem_objects,cl_uint num_events_in_wait_list,const cl_event * event_wait_list,cl_event * event) { if(!clEnqueueReleaseGLObjects_ptr) clEnqueueReleaseGLObjects_ptr = getFunction("clEnqueueReleaseGLObjects"); return (*clEnqueueReleaseGLObjects_ptr)(command_queue, num_objects, mem_objects, num_events_in_wait_list, event_wait_list, event); } -static cl_int (CL_API_CALL *clGetGLContextInfoKHR_ptr)(const cl_context_properties *, cl_gl_context_info, size_t, void *, size_t *) = NULL; +static CL_EXT_PREFIX__VERSION_1_1_DEPRECATED cl_mem (*clCreateFromGLTexture2D_ptr)(cl_context, cl_mem_flags, cl_GLenum, cl_GLint, cl_GLuint, cl_int *) = NULL; +CL_EXT_PREFIX__VERSION_1_1_DEPRECATED cl_mem CL_API_CALL clCreateFromGLTexture2D (cl_context context,cl_mem_flags flags,cl_GLenum target,cl_GLint miplevel,cl_GLuint texture,cl_int * errcode_ret) { + if(!clCreateFromGLTexture2D_ptr) clCreateFromGLTexture2D_ptr = getFunction("clCreateFromGLTexture2D"); + return (*clCreateFromGLTexture2D_ptr)(context, flags, target, miplevel, texture, errcode_ret); +} + +static CL_EXT_PREFIX__VERSION_1_1_DEPRECATED cl_mem (*clCreateFromGLTexture3D_ptr)(cl_context, cl_mem_flags, cl_GLenum, cl_GLint, cl_GLuint, cl_int *) = NULL; +CL_EXT_PREFIX__VERSION_1_1_DEPRECATED cl_mem CL_API_CALL clCreateFromGLTexture3D (cl_context context,cl_mem_flags flags,cl_GLenum target,cl_GLint miplevel,cl_GLuint texture,cl_int * errcode_ret) { + if(!clCreateFromGLTexture3D_ptr) clCreateFromGLTexture3D_ptr = getFunction("clCreateFromGLTexture3D"); + return (*clCreateFromGLTexture3D_ptr)(context, flags, target, miplevel, texture, errcode_ret); +} + +static cl_int (*clGetGLContextInfoKHR_ptr)(const cl_context_properties *, cl_gl_context_info, size_t, void *, size_t *) = NULL; cl_int CL_API_CALL clGetGLContextInfoKHR (const cl_context_properties * properties,cl_gl_context_info param_name,size_t param_value_size,void * param_value,size_t * param_value_size_ret) { if(!clGetGLContextInfoKHR_ptr) clGetGLContextInfoKHR_ptr = getFunction("clGetGLContextInfoKHR"); return (*clGetGLContextInfoKHR_ptr)(properties, param_name, param_value_size, param_value, param_value_size_ret); diff --git a/Externals/CLRun/clrun/genclglext.c b/Externals/CLRun/clrun/genclglext.c new file mode 100644 index 0000000000..333103ea85 --- /dev/null +++ b/Externals/CLRun/clrun/genclglext.c @@ -0,0 +1,11 @@ +// Automatically generated by generateClRun.pl +#include "dynamiclib.h" +#include "../include/CL/cl_gl_ext.h" + + +static cl_event (*clCreateEventFromGLsyncKHR_ptr)(cl_context, cl_GLsync, cl_int *) = NULL; +cl_event CL_API_CALL clCreateEventFromGLsyncKHR (cl_context context,cl_GLsync cl_GLsync,cl_int * errcode_ret) { + if(!clCreateEventFromGLsyncKHR_ptr) clCreateEventFromGLsyncKHR_ptr = getFunction("clCreateEventFromGLsyncKHR"); + return (*clCreateEventFromGLsyncKHR_ptr)(context, cl_GLsync, errcode_ret); +} + diff --git a/Externals/CLRun/clrun/generateClRun.pl b/Externals/CLRun/clrun/generateClRun.pl old mode 100644 new mode 100755 diff --git a/Externals/CLRun/include/CL/cl.h b/Externals/CLRun/include/CL/cl.h index 6e9a72c776..203c65974f 100644 --- a/Externals/CLRun/include/CL/cl.h +++ b/Externals/CLRun/include/CL/cl.h @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2008-2010 The Khronos Group Inc. + * Copyright (c) 2008 - 2012 The Khronos Group Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and/or associated documentation files (the @@ -21,8 +21,6 @@ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. ******************************************************************************/ -/* $Revision: 11707 $ on $Date: 2010-06-13 23:30:16 -0700 (Sun, 13 Jun 2010) $ */ - #ifndef __OPENCL_CL_H #define __OPENCL_CL_H @@ -53,14 +51,15 @@ typedef cl_ulong cl_bitfield; typedef cl_bitfield cl_device_type; typedef cl_uint cl_platform_info; typedef cl_uint cl_device_info; -typedef cl_bitfield cl_device_address_info; typedef cl_bitfield cl_device_fp_config; typedef cl_uint cl_device_mem_cache_type; typedef cl_uint cl_device_local_mem_type; typedef cl_bitfield cl_device_exec_capabilities; typedef cl_bitfield cl_command_queue_properties; +typedef intptr_t cl_device_partition_property; +typedef cl_bitfield cl_device_affinity_domain; -typedef intptr_t cl_context_properties; +typedef intptr_t cl_context_properties; typedef cl_uint cl_context_info; typedef cl_uint cl_command_queue_info; typedef cl_uint cl_channel_order; @@ -68,25 +67,50 @@ typedef cl_uint cl_channel_type; typedef cl_bitfield cl_mem_flags; typedef cl_uint cl_mem_object_type; typedef cl_uint cl_mem_info; +typedef cl_bitfield cl_mem_migration_flags; typedef cl_uint cl_image_info; +typedef cl_uint cl_buffer_create_type; typedef cl_uint cl_addressing_mode; typedef cl_uint cl_filter_mode; typedef cl_uint cl_sampler_info; typedef cl_bitfield cl_map_flags; typedef cl_uint cl_program_info; typedef cl_uint cl_program_build_info; +typedef cl_uint cl_program_binary_type; typedef cl_int cl_build_status; typedef cl_uint cl_kernel_info; +typedef cl_uint cl_kernel_arg_info; +typedef cl_uint cl_kernel_arg_address_qualifier; +typedef cl_uint cl_kernel_arg_access_qualifier; +typedef cl_bitfield cl_kernel_arg_type_qualifier; typedef cl_uint cl_kernel_work_group_info; typedef cl_uint cl_event_info; typedef cl_uint cl_command_type; typedef cl_uint cl_profiling_info; + typedef struct _cl_image_format { cl_channel_order image_channel_order; cl_channel_type image_channel_data_type; } cl_image_format; +typedef struct _cl_image_desc { + cl_mem_object_type image_type; + size_t image_width; + size_t image_height; + size_t image_depth; + size_t image_array_size; + size_t image_row_pitch; + size_t image_slice_pitch; + cl_uint num_mip_levels; + cl_uint num_samples; + cl_mem buffer; +} cl_image_desc; + +typedef struct _cl_buffer_region { + size_t origin; + size_t size; +} cl_buffer_region; /******************************************************************************/ @@ -105,6 +129,13 @@ typedef struct _cl_image_format { #define CL_IMAGE_FORMAT_NOT_SUPPORTED -10 #define CL_BUILD_PROGRAM_FAILURE -11 #define CL_MAP_FAILURE -12 +#define CL_MISALIGNED_SUB_BUFFER_OFFSET -13 +#define CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST -14 +#define CL_COMPILE_PROGRAM_FAILURE -15 +#define CL_LINKER_NOT_AVAILABLE -16 +#define CL_LINK_PROGRAM_FAILURE -17 +#define CL_DEVICE_PARTITION_FAILED -18 +#define CL_KERNEL_ARG_INFO_NOT_AVAILABLE -19 #define CL_INVALID_VALUE -30 #define CL_INVALID_DEVICE_TYPE -31 @@ -140,13 +171,22 @@ typedef struct _cl_image_format { #define CL_INVALID_BUFFER_SIZE -61 #define CL_INVALID_MIP_LEVEL -62 #define CL_INVALID_GLOBAL_WORK_SIZE -63 +#define CL_INVALID_PROPERTY -64 +#define CL_INVALID_IMAGE_DESCRIPTOR -65 +#define CL_INVALID_COMPILER_OPTIONS -66 +#define CL_INVALID_LINKER_OPTIONS -67 +#define CL_INVALID_DEVICE_PARTITION_COUNT -68 /* OpenCL Version */ #define CL_VERSION_1_0 1 +#define CL_VERSION_1_1 1 +#define CL_VERSION_1_2 1 /* cl_bool */ #define CL_FALSE 0 #define CL_TRUE 1 +#define CL_BLOCKING CL_TRUE +#define CL_NON_BLOCKING CL_FALSE /* cl_platform_info */ #define CL_PLATFORM_PROFILE 0x0900 @@ -160,6 +200,7 @@ typedef struct _cl_image_format { #define CL_DEVICE_TYPE_CPU (1 << 1) #define CL_DEVICE_TYPE_GPU (1 << 2) #define CL_DEVICE_TYPE_ACCELERATOR (1 << 3) +#define CL_DEVICE_TYPE_CUSTOM (1 << 4) #define CL_DEVICE_TYPE_ALL 0xFFFFFFFF /* cl_device_info */ @@ -213,8 +254,32 @@ typedef struct _cl_image_format { #define CL_DEVICE_VERSION 0x102F #define CL_DEVICE_EXTENSIONS 0x1030 #define CL_DEVICE_PLATFORM 0x1031 -/* 0x1032 reserved for CL_DEVICE_DOUBLE_FP_CONFIG */ +#define CL_DEVICE_DOUBLE_FP_CONFIG 0x1032 /* 0x1033 reserved for CL_DEVICE_HALF_FP_CONFIG */ +#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF 0x1034 +#define CL_DEVICE_HOST_UNIFIED_MEMORY 0x1035 +#define CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR 0x1036 +#define CL_DEVICE_NATIVE_VECTOR_WIDTH_SHORT 0x1037 +#define CL_DEVICE_NATIVE_VECTOR_WIDTH_INT 0x1038 +#define CL_DEVICE_NATIVE_VECTOR_WIDTH_LONG 0x1039 +#define CL_DEVICE_NATIVE_VECTOR_WIDTH_FLOAT 0x103A +#define CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE 0x103B +#define CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF 0x103C +#define CL_DEVICE_OPENCL_C_VERSION 0x103D +#define CL_DEVICE_LINKER_AVAILABLE 0x103E +#define CL_DEVICE_BUILT_IN_KERNELS 0x103F +#define CL_DEVICE_IMAGE_MAX_BUFFER_SIZE 0x1040 +#define CL_DEVICE_IMAGE_MAX_ARRAY_SIZE 0x1041 +#define CL_DEVICE_PARENT_DEVICE 0x1042 +#define CL_DEVICE_PARTITION_MAX_SUB_DEVICES 0x1043 +#define CL_DEVICE_PARTITION_PROPERTIES 0x1044 +#define CL_DEVICE_PARTITION_AFFINITY_DOMAIN 0x1045 +#define CL_DEVICE_PARTITION_TYPE 0x1046 +#define CL_DEVICE_REFERENCE_COUNT 0x1047 +#define CL_DEVICE_PREFERRED_INTEROP_USER_SYNC 0x1048 +#define CL_DEVICE_PRINTF_BUFFER_SIZE 0x1049 +#define CL_DEVICE_IMAGE_PITCH_ALIGNMENT 0x104A +#define CL_DEVICE_IMAGE_BASE_ADDRESS_ALIGNMENT 0x104B /* cl_device_fp_config - bitfield */ #define CL_FP_DENORM (1 << 0) @@ -223,6 +288,8 @@ typedef struct _cl_image_format { #define CL_FP_ROUND_TO_ZERO (1 << 3) #define CL_FP_ROUND_TO_INF (1 << 4) #define CL_FP_FMA (1 << 5) +#define CL_FP_SOFT_FLOAT (1 << 6) +#define CL_FP_CORRECTLY_ROUNDED_DIVIDE_SQRT (1 << 7) /* cl_device_mem_cache_type */ #define CL_NONE 0x0 @@ -245,9 +312,25 @@ typedef struct _cl_image_format { #define CL_CONTEXT_REFERENCE_COUNT 0x1080 #define CL_CONTEXT_DEVICES 0x1081 #define CL_CONTEXT_PROPERTIES 0x1082 +#define CL_CONTEXT_NUM_DEVICES 0x1083 -/* cl_context_info + cl_context_properties */ +/* cl_context_properties */ #define CL_CONTEXT_PLATFORM 0x1084 +#define CL_CONTEXT_INTEROP_USER_SYNC 0x1085 + +/* cl_device_partition_property */ +#define CL_DEVICE_PARTITION_EQUALLY 0x1086 +#define CL_DEVICE_PARTITION_BY_COUNTS 0x1087 +#define CL_DEVICE_PARTITION_BY_COUNTS_LIST_END 0x0 +#define CL_DEVICE_PARTITION_BY_AFFINITY_DOMAIN 0x1088 + +/* cl_device_affinity_domain */ +#define CL_DEVICE_AFFINITY_DOMAIN_NUMA (1 << 0) +#define CL_DEVICE_AFFINITY_DOMAIN_L4_CACHE (1 << 1) +#define CL_DEVICE_AFFINITY_DOMAIN_L3_CACHE (1 << 2) +#define CL_DEVICE_AFFINITY_DOMAIN_L2_CACHE (1 << 3) +#define CL_DEVICE_AFFINITY_DOMAIN_L1_CACHE (1 << 4) +#define CL_DEVICE_AFFINITY_DOMAIN_NEXT_PARTITIONABLE (1 << 5) /* cl_command_queue_info */ #define CL_QUEUE_CONTEXT 0x1090 @@ -262,6 +345,14 @@ typedef struct _cl_image_format { #define CL_MEM_USE_HOST_PTR (1 << 3) #define CL_MEM_ALLOC_HOST_PTR (1 << 4) #define CL_MEM_COPY_HOST_PTR (1 << 5) +// reserved (1 << 6) +#define CL_MEM_HOST_WRITE_ONLY (1 << 7) +#define CL_MEM_HOST_READ_ONLY (1 << 8) +#define CL_MEM_HOST_NO_ACCESS (1 << 9) + +/* cl_mem_migration_flags - bitfield */ +#define CL_MIGRATE_MEM_OBJECT_HOST (1 << 0) +#define CL_MIGRATE_MEM_OBJECT_CONTENT_UNDEFINED (1 << 1) /* cl_channel_order */ #define CL_R 0x10B0 @@ -274,6 +365,11 @@ typedef struct _cl_image_format { #define CL_ARGB 0x10B7 #define CL_INTENSITY 0x10B8 #define CL_LUMINANCE 0x10B9 +#define CL_Rx 0x10BA +#define CL_RGx 0x10BB +#define CL_RGBx 0x10BC +#define CL_DEPTH 0x10BD +#define CL_DEPTH_STENCIL 0x10BE /* cl_channel_type */ #define CL_SNORM_INT8 0x10D0 @@ -291,11 +387,16 @@ typedef struct _cl_image_format { #define CL_UNSIGNED_INT32 0x10DC #define CL_HALF_FLOAT 0x10DD #define CL_FLOAT 0x10DE +#define CL_UNORM_INT24 0x10DF /* cl_mem_object_type */ #define CL_MEM_OBJECT_BUFFER 0x10F0 #define CL_MEM_OBJECT_IMAGE2D 0x10F1 #define CL_MEM_OBJECT_IMAGE3D 0x10F2 +#define CL_MEM_OBJECT_IMAGE2D_ARRAY 0x10F3 +#define CL_MEM_OBJECT_IMAGE1D 0x10F4 +#define CL_MEM_OBJECT_IMAGE1D_ARRAY 0x10F5 +#define CL_MEM_OBJECT_IMAGE1D_BUFFER 0x10F6 /* cl_mem_info */ #define CL_MEM_TYPE 0x1100 @@ -305,6 +406,8 @@ typedef struct _cl_image_format { #define CL_MEM_MAP_COUNT 0x1104 #define CL_MEM_REFERENCE_COUNT 0x1105 #define CL_MEM_CONTEXT 0x1106 +#define CL_MEM_ASSOCIATED_MEMOBJECT 0x1107 +#define CL_MEM_OFFSET 0x1108 /* cl_image_info */ #define CL_IMAGE_FORMAT 0x1110 @@ -314,12 +417,17 @@ typedef struct _cl_image_format { #define CL_IMAGE_WIDTH 0x1114 #define CL_IMAGE_HEIGHT 0x1115 #define CL_IMAGE_DEPTH 0x1116 +#define CL_IMAGE_ARRAY_SIZE 0x1117 +#define CL_IMAGE_BUFFER 0x1118 +#define CL_IMAGE_NUM_MIP_LEVELS 0x1119 +#define CL_IMAGE_NUM_SAMPLES 0x111A /* cl_addressing_mode */ #define CL_ADDRESS_NONE 0x1130 #define CL_ADDRESS_CLAMP_TO_EDGE 0x1131 #define CL_ADDRESS_CLAMP 0x1132 #define CL_ADDRESS_REPEAT 0x1133 +#define CL_ADDRESS_MIRRORED_REPEAT 0x1134 /* cl_filter_mode */ #define CL_FILTER_NEAREST 0x1140 @@ -335,6 +443,7 @@ typedef struct _cl_image_format { /* cl_map_flags - bitfield */ #define CL_MAP_READ (1 << 0) #define CL_MAP_WRITE (1 << 1) +#define CL_MAP_WRITE_INVALIDATE_REGION (1 << 2) /* cl_program_info */ #define CL_PROGRAM_REFERENCE_COUNT 0x1160 @@ -344,11 +453,20 @@ typedef struct _cl_image_format { #define CL_PROGRAM_SOURCE 0x1164 #define CL_PROGRAM_BINARY_SIZES 0x1165 #define CL_PROGRAM_BINARIES 0x1166 +#define CL_PROGRAM_NUM_KERNELS 0x1167 +#define CL_PROGRAM_KERNEL_NAMES 0x1168 /* cl_program_build_info */ #define CL_PROGRAM_BUILD_STATUS 0x1181 #define CL_PROGRAM_BUILD_OPTIONS 0x1182 #define CL_PROGRAM_BUILD_LOG 0x1183 +#define CL_PROGRAM_BINARY_TYPE 0x1184 + +/* cl_program_binary_type */ +#define CL_PROGRAM_BINARY_TYPE_NONE 0x0 +#define CL_PROGRAM_BINARY_TYPE_COMPILED_OBJECT 0x1 +#define CL_PROGRAM_BINARY_TYPE_LIBRARY 0x2 +#define CL_PROGRAM_BINARY_TYPE_EXECUTABLE 0x4 /* cl_build_status */ #define CL_BUILD_SUCCESS 0 @@ -362,17 +480,47 @@ typedef struct _cl_image_format { #define CL_KERNEL_REFERENCE_COUNT 0x1192 #define CL_KERNEL_CONTEXT 0x1193 #define CL_KERNEL_PROGRAM 0x1194 +#define CL_KERNEL_ATTRIBUTES 0x1195 + +/* cl_kernel_arg_info */ +#define CL_KERNEL_ARG_ADDRESS_QUALIFIER 0x1196 +#define CL_KERNEL_ARG_ACCESS_QUALIFIER 0x1197 +#define CL_KERNEL_ARG_TYPE_NAME 0x1198 +#define CL_KERNEL_ARG_TYPE_QUALIFIER 0x1199 +#define CL_KERNEL_ARG_NAME 0x119A + +/* cl_kernel_arg_address_qualifier */ +#define CL_KERNEL_ARG_ADDRESS_GLOBAL 0x119B +#define CL_KERNEL_ARG_ADDRESS_LOCAL 0x119C +#define CL_KERNEL_ARG_ADDRESS_CONSTANT 0x119D +#define CL_KERNEL_ARG_ADDRESS_PRIVATE 0x119E + +/* cl_kernel_arg_access_qualifier */ +#define CL_KERNEL_ARG_ACCESS_READ_ONLY 0x11A0 +#define CL_KERNEL_ARG_ACCESS_WRITE_ONLY 0x11A1 +#define CL_KERNEL_ARG_ACCESS_READ_WRITE 0x11A2 +#define CL_KERNEL_ARG_ACCESS_NONE 0x11A3 + +/* cl_kernel_arg_type_qualifer */ +#define CL_KERNEL_ARG_TYPE_NONE 0 +#define CL_KERNEL_ARG_TYPE_CONST (1 << 0) +#define CL_KERNEL_ARG_TYPE_RESTRICT (1 << 1) +#define CL_KERNEL_ARG_TYPE_VOLATILE (1 << 2) /* cl_kernel_work_group_info */ #define CL_KERNEL_WORK_GROUP_SIZE 0x11B0 #define CL_KERNEL_COMPILE_WORK_GROUP_SIZE 0x11B1 #define CL_KERNEL_LOCAL_MEM_SIZE 0x11B2 +#define CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE 0x11B3 +#define CL_KERNEL_PRIVATE_MEM_SIZE 0x11B4 +#define CL_KERNEL_GLOBAL_WORK_SIZE 0x11B5 /* cl_event_info */ #define CL_EVENT_COMMAND_QUEUE 0x11D0 #define CL_EVENT_COMMAND_TYPE 0x11D1 #define CL_EVENT_REFERENCE_COUNT 0x11D2 #define CL_EVENT_COMMAND_EXECUTION_STATUS 0x11D3 +#define CL_EVENT_CONTEXT 0x11D4 /* cl_command_type */ #define CL_COMMAND_NDRANGE_KERNEL 0x11F0 @@ -392,13 +540,24 @@ typedef struct _cl_image_format { #define CL_COMMAND_MARKER 0x11FE #define CL_COMMAND_ACQUIRE_GL_OBJECTS 0x11FF #define CL_COMMAND_RELEASE_GL_OBJECTS 0x1200 +#define CL_COMMAND_READ_BUFFER_RECT 0x1201 +#define CL_COMMAND_WRITE_BUFFER_RECT 0x1202 +#define CL_COMMAND_COPY_BUFFER_RECT 0x1203 +#define CL_COMMAND_USER 0x1204 +#define CL_COMMAND_BARRIER 0x1205 +#define CL_COMMAND_MIGRATE_MEM_OBJECTS 0x1206 +#define CL_COMMAND_FILL_BUFFER 0x1207 +#define CL_COMMAND_FILL_IMAGE 0x1208 /* command execution status */ #define CL_COMPLETE 0x0 #define CL_RUNNING 0x1 #define CL_SUBMITTED 0x2 #define CL_QUEUED 0x3 - + +/* cl_buffer_create_type */ +#define CL_BUFFER_CREATE_TYPE_REGION 0x1220 + /* cl_profiling_info */ #define CL_PROFILING_COMMAND_QUEUED 0x1280 #define CL_PROFILING_COMMAND_SUBMIT 0x1281 @@ -434,22 +593,35 @@ clGetDeviceInfo(cl_device_id /* device */, size_t /* param_value_size */, void * /* param_value */, size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; + +extern CL_API_ENTRY cl_int CL_API_CALL +clCreateSubDevices(cl_device_id /* in_device */, + const cl_device_partition_property * /* properties */, + cl_uint /* num_devices */, + cl_device_id * /* out_devices */, + cl_uint * /* num_devices_ret */) CL_API_SUFFIX__VERSION_1_2; +extern CL_API_ENTRY cl_int CL_API_CALL +clRetainDevice(cl_device_id /* device */) CL_API_SUFFIX__VERSION_1_2; + +extern CL_API_ENTRY cl_int CL_API_CALL +clReleaseDevice(cl_device_id /* device */) CL_API_SUFFIX__VERSION_1_2; + /* Context APIs */ extern CL_API_ENTRY cl_context CL_API_CALL clCreateContext(const cl_context_properties * /* properties */, - cl_uint /* num_devices */, - const cl_device_id * /* devices */, + cl_uint /* num_devices */, + const cl_device_id * /* devices */, void (CL_CALLBACK * /* pfn_notify */)(const char *, const void *, size_t, void *), - void * /* user_data */, - cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; + void * /* user_data */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; extern CL_API_ENTRY cl_context CL_API_CALL clCreateContextFromType(const cl_context_properties * /* properties */, - cl_device_type /* device_type */, + cl_device_type /* device_type */, void (CL_CALLBACK * /* pfn_notify*/ )(const char *, const void *, size_t, void *), - void * /* user_data */, - cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; + void * /* user_data */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; extern CL_API_ENTRY cl_int CL_API_CALL clRetainContext(cl_context /* context */) CL_API_SUFFIX__VERSION_1_0; @@ -484,13 +656,7 @@ clGetCommandQueueInfo(cl_command_queue /* command_queue */, void * /* param_value */, size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; -extern CL_API_ENTRY cl_int CL_API_CALL -clSetCommandQueueProperty(cl_command_queue /* command_queue */, - cl_command_queue_properties /* properties */, - cl_bool /* enable */, - cl_command_queue_properties * /* old_properties */) CL_API_SUFFIX__VERSION_1_0; - -/* Memory Object APIs */ +/* Memory Object APIs */ extern CL_API_ENTRY cl_mem CL_API_CALL clCreateBuffer(cl_context /* context */, cl_mem_flags /* flags */, @@ -499,26 +665,19 @@ clCreateBuffer(cl_context /* context */, cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; extern CL_API_ENTRY cl_mem CL_API_CALL -clCreateImage2D(cl_context /* context */, - cl_mem_flags /* flags */, - const cl_image_format * /* image_format */, - size_t /* image_width */, - size_t /* image_height */, - size_t /* image_row_pitch */, - void * /* host_ptr */, - cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; - +clCreateSubBuffer(cl_mem /* buffer */, + cl_mem_flags /* flags */, + cl_buffer_create_type /* buffer_create_type */, + const void * /* buffer_create_info */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_1; + extern CL_API_ENTRY cl_mem CL_API_CALL -clCreateImage3D(cl_context /* context */, - cl_mem_flags /* flags */, - const cl_image_format * /* image_format */, - size_t /* image_width */, - size_t /* image_height */, - size_t /* image_depth */, - size_t /* image_row_pitch */, - size_t /* image_slice_pitch */, - void * /* host_ptr */, - cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; +clCreateImage(cl_context /* context */, + cl_mem_flags /* flags */, + const cl_image_format * /* image_format */, + const cl_image_desc * /* image_desc */, + void * /* host_ptr */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_2; extern CL_API_ENTRY cl_int CL_API_CALL clRetainMemObject(cl_mem /* memobj */) CL_API_SUFFIX__VERSION_1_0; @@ -548,7 +707,12 @@ clGetImageInfo(cl_mem /* image */, void * /* param_value */, size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; -/* Sampler APIs */ +extern CL_API_ENTRY cl_int CL_API_CALL +clSetMemObjectDestructorCallback( cl_mem /* memobj */, + void (CL_CALLBACK * /*pfn_notify*/)( cl_mem /* memobj */, void* /*user_data*/), + void * /*user_data */ ) CL_API_SUFFIX__VERSION_1_1; + +/* Sampler APIs */ extern CL_API_ENTRY cl_sampler CL_API_CALL clCreateSampler(cl_context /* context */, cl_bool /* normalized_coords */, @@ -586,6 +750,13 @@ clCreateProgramWithBinary(cl_context /* context */, cl_int * /* binary_status */, cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; +extern CL_API_ENTRY cl_program CL_API_CALL +clCreateProgramWithBuiltInKernels(cl_context /* context */, + cl_uint /* num_devices */, + const cl_device_id * /* device_list */, + const char * /* kernel_names */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_2; + extern CL_API_ENTRY cl_int CL_API_CALL clRetainProgram(cl_program /* program */) CL_API_SUFFIX__VERSION_1_0; @@ -601,7 +772,30 @@ clBuildProgram(cl_program /* program */, void * /* user_data */) CL_API_SUFFIX__VERSION_1_0; extern CL_API_ENTRY cl_int CL_API_CALL -clUnloadCompiler(void) CL_API_SUFFIX__VERSION_1_0; +clCompileProgram(cl_program /* program */, + cl_uint /* num_devices */, + const cl_device_id * /* device_list */, + const char * /* options */, + cl_uint /* num_input_headers */, + const cl_program * /* input_headers */, + const char ** /* header_include_names */, + void (CL_CALLBACK * /* pfn_notify */)(cl_program /* program */, void * /* user_data */), + void * /* user_data */) CL_API_SUFFIX__VERSION_1_2; + +extern CL_API_ENTRY cl_program CL_API_CALL +clLinkProgram(cl_context /* context */, + cl_uint /* num_devices */, + const cl_device_id * /* device_list */, + const char * /* options */, + cl_uint /* num_input_programs */, + const cl_program * /* input_programs */, + void (CL_CALLBACK * /* pfn_notify */)(cl_program /* program */, void * /* user_data */), + void * /* user_data */, + cl_int * /* errcode_ret */ ) CL_API_SUFFIX__VERSION_1_2; + + +extern CL_API_ENTRY cl_int CL_API_CALL +clUnloadPlatformCompiler(cl_platform_id /* platform */) CL_API_SUFFIX__VERSION_1_2; extern CL_API_ENTRY cl_int CL_API_CALL clGetProgramInfo(cl_program /* program */, @@ -649,6 +843,14 @@ clGetKernelInfo(cl_kernel /* kernel */, void * /* param_value */, size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; +extern CL_API_ENTRY cl_int CL_API_CALL +clGetKernelArgInfo(cl_kernel /* kernel */, + cl_uint /* arg_indx */, + cl_kernel_arg_info /* param_name */, + size_t /* param_value_size */, + void * /* param_value */, + size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_2; + extern CL_API_ENTRY cl_int CL_API_CALL clGetKernelWorkGroupInfo(cl_kernel /* kernel */, cl_device_id /* device */, @@ -657,7 +859,7 @@ clGetKernelWorkGroupInfo(cl_kernel /* kernel */, void * /* param_value */, size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; -/* Event Object APIs */ +/* Event Object APIs */ extern CL_API_ENTRY cl_int CL_API_CALL clWaitForEvents(cl_uint /* num_events */, const cl_event * /* event_list */) CL_API_SUFFIX__VERSION_1_0; @@ -669,13 +871,27 @@ clGetEventInfo(cl_event /* event */, void * /* param_value */, size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; +extern CL_API_ENTRY cl_event CL_API_CALL +clCreateUserEvent(cl_context /* context */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_1; + extern CL_API_ENTRY cl_int CL_API_CALL clRetainEvent(cl_event /* event */) CL_API_SUFFIX__VERSION_1_0; extern CL_API_ENTRY cl_int CL_API_CALL clReleaseEvent(cl_event /* event */) CL_API_SUFFIX__VERSION_1_0; -/* Profiling APIs */ +extern CL_API_ENTRY cl_int CL_API_CALL +clSetUserEventStatus(cl_event /* event */, + cl_int /* execution_status */) CL_API_SUFFIX__VERSION_1_1; + +extern CL_API_ENTRY cl_int CL_API_CALL +clSetEventCallback( cl_event /* event */, + cl_int /* command_exec_callback_type */, + void (CL_CALLBACK * /* pfn_notify */)(cl_event, cl_int, void *), + void * /* user_data */) CL_API_SUFFIX__VERSION_1_1; + +/* Profiling APIs */ extern CL_API_ENTRY cl_int CL_API_CALL clGetEventProfilingInfo(cl_event /* event */, cl_profiling_info /* param_name */, @@ -696,34 +912,92 @@ clEnqueueReadBuffer(cl_command_queue /* command_queue */, cl_mem /* buffer */, cl_bool /* blocking_read */, size_t /* offset */, - size_t /* cb */, + size_t /* size */, void * /* ptr */, cl_uint /* num_events_in_wait_list */, const cl_event * /* event_wait_list */, cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; +extern CL_API_ENTRY cl_int CL_API_CALL +clEnqueueReadBufferRect(cl_command_queue /* command_queue */, + cl_mem /* buffer */, + cl_bool /* blocking_read */, + const size_t * /* buffer_offset */, + const size_t * /* host_offset */, + const size_t * /* region */, + size_t /* buffer_row_pitch */, + size_t /* buffer_slice_pitch */, + size_t /* host_row_pitch */, + size_t /* host_slice_pitch */, + void * /* ptr */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_1; + extern CL_API_ENTRY cl_int CL_API_CALL clEnqueueWriteBuffer(cl_command_queue /* command_queue */, cl_mem /* buffer */, cl_bool /* blocking_write */, size_t /* offset */, - size_t /* cb */, + size_t /* size */, const void * /* ptr */, cl_uint /* num_events_in_wait_list */, const cl_event * /* event_wait_list */, cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; +extern CL_API_ENTRY cl_int CL_API_CALL +clEnqueueWriteBufferRect(cl_command_queue /* command_queue */, + cl_mem /* buffer */, + cl_bool /* blocking_write */, + const size_t * /* buffer_offset */, + const size_t * /* host_offset */, + const size_t * /* region */, + size_t /* buffer_row_pitch */, + size_t /* buffer_slice_pitch */, + size_t /* host_row_pitch */, + size_t /* host_slice_pitch */, + const void * /* ptr */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_1; + +extern CL_API_ENTRY cl_int CL_API_CALL +clEnqueueFillBuffer(cl_command_queue /* command_queue */, + cl_mem /* buffer */, + const void * /* pattern */, + size_t /* pattern_size */, + size_t /* offset */, + size_t /* size */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_2; + extern CL_API_ENTRY cl_int CL_API_CALL clEnqueueCopyBuffer(cl_command_queue /* command_queue */, cl_mem /* src_buffer */, cl_mem /* dst_buffer */, size_t /* src_offset */, size_t /* dst_offset */, - size_t /* cb */, + size_t /* size */, cl_uint /* num_events_in_wait_list */, const cl_event * /* event_wait_list */, cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; +extern CL_API_ENTRY cl_int CL_API_CALL +clEnqueueCopyBufferRect(cl_command_queue /* command_queue */, + cl_mem /* src_buffer */, + cl_mem /* dst_buffer */, + const size_t * /* src_origin */, + const size_t * /* dst_origin */, + const size_t * /* region */, + size_t /* src_row_pitch */, + size_t /* src_slice_pitch */, + size_t /* dst_row_pitch */, + size_t /* dst_slice_pitch */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_1; + extern CL_API_ENTRY cl_int CL_API_CALL clEnqueueReadImage(cl_command_queue /* command_queue */, cl_mem /* image */, @@ -750,6 +1024,16 @@ clEnqueueWriteImage(cl_command_queue /* command_queue */, const cl_event * /* event_wait_list */, cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; +extern CL_API_ENTRY cl_int CL_API_CALL +clEnqueueFillImage(cl_command_queue /* command_queue */, + cl_mem /* image */, + const void * /* fill_color */, + const size_t * /* origin[3] */, + const size_t * /* region[3] */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_2; + extern CL_API_ENTRY cl_int CL_API_CALL clEnqueueCopyImage(cl_command_queue /* command_queue */, cl_mem /* src_image */, @@ -789,7 +1073,7 @@ clEnqueueMapBuffer(cl_command_queue /* command_queue */, cl_bool /* blocking_map */, cl_map_flags /* map_flags */, size_t /* offset */, - size_t /* cb */, + size_t /* size */, cl_uint /* num_events_in_wait_list */, const cl_event * /* event_wait_list */, cl_event * /* event */, @@ -817,6 +1101,15 @@ clEnqueueUnmapMemObject(cl_command_queue /* command_queue */, const cl_event * /* event_wait_list */, cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; +extern CL_API_ENTRY cl_int CL_API_CALL +clEnqueueMigrateMemObjects(cl_command_queue /* command_queue */, + cl_uint /* num_mem_objects */, + const cl_mem * /* mem_objects */, + cl_mem_migration_flags /* flags */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_2; + extern CL_API_ENTRY cl_int CL_API_CALL clEnqueueNDRangeKernel(cl_command_queue /* command_queue */, cl_kernel /* kernel */, @@ -837,7 +1130,7 @@ clEnqueueTask(cl_command_queue /* command_queue */, extern CL_API_ENTRY cl_int CL_API_CALL clEnqueueNativeKernel(cl_command_queue /* command_queue */, - void (*user_func)(void *), + void (CL_CALLBACK * /*user_func*/)(void *), void * /* args */, size_t /* cb_args */, cl_uint /* num_mem_objects */, @@ -848,16 +1141,17 @@ clEnqueueNativeKernel(cl_command_queue /* command_queue */, cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; extern CL_API_ENTRY cl_int CL_API_CALL -clEnqueueMarker(cl_command_queue /* command_queue */, - cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; +clEnqueueMarkerWithWaitList(cl_command_queue /* command_queue */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_2; extern CL_API_ENTRY cl_int CL_API_CALL -clEnqueueWaitForEvents(cl_command_queue /* command_queue */, - cl_uint /* num_events */, - const cl_event * /* event_list */) CL_API_SUFFIX__VERSION_1_0; +clEnqueueBarrierWithWaitList(cl_command_queue /* command_queue */, + cl_uint /* num_events_in_wait_list */, + const cl_event * /* event_wait_list */, + cl_event * /* event */) CL_API_SUFFIX__VERSION_1_2; -extern CL_API_ENTRY cl_int CL_API_CALL -clEnqueueBarrier(cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0; /* Extension function access * @@ -866,7 +1160,51 @@ clEnqueueBarrier(cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_ * check to make sure the address is not NULL, before using or * calling the returned function address. */ -extern CL_API_ENTRY void * CL_API_CALL clGetExtensionFunctionAddress(const char * /* func_name */) CL_API_SUFFIX__VERSION_1_0; +extern CL_API_ENTRY void * CL_API_CALL +clGetExtensionFunctionAddressForPlatform(cl_platform_id /* platform */, + const char * /* func_name */) CL_API_SUFFIX__VERSION_1_2; + + +// Deprecated OpenCL 1.1 APIs +extern CL_API_ENTRY CL_EXT_PREFIX__VERSION_1_1_DEPRECATED cl_mem CL_API_CALL +clCreateImage2D(cl_context /* context */, + cl_mem_flags /* flags */, + const cl_image_format * /* image_format */, + size_t /* image_width */, + size_t /* image_height */, + size_t /* image_row_pitch */, + void * /* host_ptr */, + cl_int * /* errcode_ret */) CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED; + +extern CL_API_ENTRY CL_EXT_PREFIX__VERSION_1_1_DEPRECATED cl_mem CL_API_CALL +clCreateImage3D(cl_context /* context */, + cl_mem_flags /* flags */, + const cl_image_format * /* image_format */, + size_t /* image_width */, + size_t /* image_height */, + size_t /* image_depth */, + size_t /* image_row_pitch */, + size_t /* image_slice_pitch */, + void * /* host_ptr */, + cl_int * /* errcode_ret */) CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED; + +extern CL_API_ENTRY CL_EXT_PREFIX__VERSION_1_1_DEPRECATED cl_int CL_API_CALL +clEnqueueMarker(cl_command_queue /* command_queue */, + cl_event * /* event */) CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED; + +extern CL_API_ENTRY CL_EXT_PREFIX__VERSION_1_1_DEPRECATED cl_int CL_API_CALL +clEnqueueWaitForEvents(cl_command_queue /* command_queue */, + cl_uint /* num_events */, + const cl_event * /* event_list */) CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED; + +extern CL_API_ENTRY CL_EXT_PREFIX__VERSION_1_1_DEPRECATED cl_int CL_API_CALL +clEnqueueBarrier(cl_command_queue /* command_queue */) CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED; + +extern CL_API_ENTRY CL_EXT_PREFIX__VERSION_1_1_DEPRECATED cl_int CL_API_CALL +clUnloadCompiler(void) CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED; + +extern CL_API_ENTRY CL_EXT_PREFIX__VERSION_1_1_DEPRECATED void * CL_API_CALL +clGetExtensionFunctionAddress(const char * /* func_name */) CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED; #ifdef __cplusplus } diff --git a/Externals/CLRun/include/CL/cl_d3d10.h b/Externals/CLRun/include/CL/cl_d3d10.h new file mode 100644 index 0000000000..81b0d37214 --- /dev/null +++ b/Externals/CLRun/include/CL/cl_d3d10.h @@ -0,0 +1,126 @@ +/********************************************************************************** + * Copyright (c) 2008-2012 The Khronos Group Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and/or associated documentation files (the + * "Materials"), to deal in the Materials without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Materials, and to + * permit persons to whom the Materials are furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Materials. + * + * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. + **********************************************************************************/ + +/* $Revision: 11708 $ on $Date: 2010-06-13 23:36:24 -0700 (Sun, 13 Jun 2010) $ */ + +#ifndef __OPENCL_CL_D3D10_H +#define __OPENCL_CL_D3D10_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/****************************************************************************** + * cl_khr_d3d10_sharing */ +#define cl_khr_d3d10_sharing 1 + +typedef cl_uint cl_d3d10_device_source_khr; +typedef cl_uint cl_d3d10_device_set_khr; + +/******************************************************************************/ + +// Error Codes +#define CL_INVALID_D3D10_DEVICE_KHR -1002 +#define CL_INVALID_D3D10_RESOURCE_KHR -1003 +#define CL_D3D10_RESOURCE_ALREADY_ACQUIRED_KHR -1004 +#define CL_D3D10_RESOURCE_NOT_ACQUIRED_KHR -1005 + +// cl_d3d10_device_source_nv +#define CL_D3D10_DEVICE_KHR 0x4010 +#define CL_D3D10_DXGI_ADAPTER_KHR 0x4011 + +// cl_d3d10_device_set_nv +#define CL_PREFERRED_DEVICES_FOR_D3D10_KHR 0x4012 +#define CL_ALL_DEVICES_FOR_D3D10_KHR 0x4013 + +// cl_context_info +#define CL_CONTEXT_D3D10_DEVICE_KHR 0x4014 +#define CL_CONTEXT_D3D10_PREFER_SHARED_RESOURCES_KHR 0x402C + +// cl_mem_info +#define CL_MEM_D3D10_RESOURCE_KHR 0x4015 + +// cl_image_info +#define CL_IMAGE_D3D10_SUBRESOURCE_KHR 0x4016 + +// cl_command_type +#define CL_COMMAND_ACQUIRE_D3D10_OBJECTS_KHR 0x4017 +#define CL_COMMAND_RELEASE_D3D10_OBJECTS_KHR 0x4018 + +/******************************************************************************/ + +typedef CL_API_ENTRY cl_int (CL_API_CALL *clGetDeviceIDsFromD3D10KHR_fn)( + cl_platform_id platform, + cl_d3d10_device_source_khr d3d_device_source, + void * d3d_object, + cl_d3d10_device_set_khr d3d_device_set, + cl_uint num_entries, + cl_device_id * devices, + cl_uint * num_devices) CL_API_SUFFIX__VERSION_1_0; + +typedef CL_API_ENTRY cl_mem (CL_API_CALL *clCreateFromD3D10BufferKHR_fn)( + cl_context context, + cl_mem_flags flags, + ID3D10Buffer * resource, + cl_int * errcode_ret) CL_API_SUFFIX__VERSION_1_0; + +typedef CL_API_ENTRY cl_mem (CL_API_CALL *clCreateFromD3D10Texture2DKHR_fn)( + cl_context context, + cl_mem_flags flags, + ID3D10Texture2D * resource, + UINT subresource, + cl_int * errcode_ret) CL_API_SUFFIX__VERSION_1_0; + +typedef CL_API_ENTRY cl_mem (CL_API_CALL *clCreateFromD3D10Texture3DKHR_fn)( + cl_context context, + cl_mem_flags flags, + ID3D10Texture3D * resource, + UINT subresource, + cl_int * errcode_ret) CL_API_SUFFIX__VERSION_1_0; + +typedef CL_API_ENTRY cl_int (CL_API_CALL *clEnqueueAcquireD3D10ObjectsKHR_fn)( + cl_command_queue command_queue, + cl_uint num_objects, + const cl_mem * mem_objects, + cl_uint num_events_in_wait_list, + const cl_event * event_wait_list, + cl_event * event) CL_API_SUFFIX__VERSION_1_0; + +typedef CL_API_ENTRY cl_int (CL_API_CALL *clEnqueueReleaseD3D10ObjectsKHR_fn)( + cl_command_queue command_queue, + cl_uint num_objects, + const cl_mem * mem_objects, + cl_uint num_events_in_wait_list, + const cl_event * event_wait_list, + cl_event * event) CL_API_SUFFIX__VERSION_1_0; + +#ifdef __cplusplus +} +#endif + +#endif // __OPENCL_CL_D3D10_H + diff --git a/Externals/CLRun/include/CL/cl_d3d11.h b/Externals/CLRun/include/CL/cl_d3d11.h new file mode 100644 index 0000000000..d3c8bdc2b1 --- /dev/null +++ b/Externals/CLRun/include/CL/cl_d3d11.h @@ -0,0 +1,126 @@ +/********************************************************************************** + * Copyright (c) 2008-2012 The Khronos Group Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and/or associated documentation files (the + * "Materials"), to deal in the Materials without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Materials, and to + * permit persons to whom the Materials are furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Materials. + * + * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. + **********************************************************************************/ + +/* $Revision: 11708 $ on $Date: 2010-06-13 23:36:24 -0700 (Sun, 13 Jun 2010) $ */ + +#ifndef __OPENCL_CL_D3D11_H +#define __OPENCL_CL_D3D11_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/****************************************************************************** + * cl_khr_d3d11_sharing */ +#define cl_khr_d3d11_sharing 1 + +typedef cl_uint cl_d3d11_device_source_khr; +typedef cl_uint cl_d3d11_device_set_khr; + +/******************************************************************************/ + +// Error Codes +#define CL_INVALID_D3D11_DEVICE_KHR -1006 +#define CL_INVALID_D3D11_RESOURCE_KHR -1007 +#define CL_D3D11_RESOURCE_ALREADY_ACQUIRED_KHR -1008 +#define CL_D3D11_RESOURCE_NOT_ACQUIRED_KHR -1009 + +// cl_d3d11_device_source +#define CL_D3D11_DEVICE_KHR 0x4019 +#define CL_D3D11_DXGI_ADAPTER_KHR 0x401A + +// cl_d3d11_device_set +#define CL_PREFERRED_DEVICES_FOR_D3D11_KHR 0x401B +#define CL_ALL_DEVICES_FOR_D3D11_KHR 0x401C + +// cl_context_info +#define CL_CONTEXT_D3D11_DEVICE_KHR 0x401D +#define CL_CONTEXT_D3D11_PREFER_SHARED_RESOURCES_KHR 0x402D + +// cl_mem_info +#define CL_MEM_D3D11_RESOURCE_KHR 0x401E + +// cl_image_info +#define CL_IMAGE_D3D11_SUBRESOURCE_KHR 0x401F + +// cl_command_type +#define CL_COMMAND_ACQUIRE_D3D11_OBJECTS_KHR 0x4020 +#define CL_COMMAND_RELEASE_D3D11_OBJECTS_KHR 0x4021 + +/******************************************************************************/ + +typedef CL_API_ENTRY cl_int (CL_API_CALL *clGetDeviceIDsFromD3D11KHR_fn)( + cl_platform_id platform, + cl_d3d11_device_source_khr d3d_device_source, + void * d3d_object, + cl_d3d11_device_set_khr d3d_device_set, + cl_uint num_entries, + cl_device_id * devices, + cl_uint * num_devices) CL_API_SUFFIX__VERSION_1_2; + +typedef CL_API_ENTRY cl_mem (CL_API_CALL *clCreateFromD3D11BufferKHR_fn)( + cl_context context, + cl_mem_flags flags, + ID3D11Buffer * resource, + cl_int * errcode_ret) CL_API_SUFFIX__VERSION_1_2; + +typedef CL_API_ENTRY cl_mem (CL_API_CALL *clCreateFromD3D11Texture2DKHR_fn)( + cl_context context, + cl_mem_flags flags, + ID3D11Texture2D * resource, + UINT subresource, + cl_int * errcode_ret) CL_API_SUFFIX__VERSION_1_2; + +typedef CL_API_ENTRY cl_mem (CL_API_CALL *clCreateFromD3D11Texture3DKHR_fn)( + cl_context context, + cl_mem_flags flags, + ID3D11Texture3D * resource, + UINT subresource, + cl_int * errcode_ret) CL_API_SUFFIX__VERSION_1_2; + +typedef CL_API_ENTRY cl_int (CL_API_CALL *clEnqueueAcquireD3D11ObjectsKHR_fn)( + cl_command_queue command_queue, + cl_uint num_objects, + const cl_mem * mem_objects, + cl_uint num_events_in_wait_list, + const cl_event * event_wait_list, + cl_event * event) CL_API_SUFFIX__VERSION_1_2; + +typedef CL_API_ENTRY cl_int (CL_API_CALL *clEnqueueReleaseD3D11ObjectsKHR_fn)( + cl_command_queue command_queue, + cl_uint num_objects, + const cl_mem * mem_objects, + cl_uint num_events_in_wait_list, + const cl_event * event_wait_list, + cl_event * event) CL_API_SUFFIX__VERSION_1_2; + +#ifdef __cplusplus +} +#endif + +#endif // __OPENCL_CL_D3D11_H + diff --git a/Externals/CLRun/include/CL/cl_dx9_media_sharing.h b/Externals/CLRun/include/CL/cl_dx9_media_sharing.h new file mode 100644 index 0000000000..1ef543a5af --- /dev/null +++ b/Externals/CLRun/include/CL/cl_dx9_media_sharing.h @@ -0,0 +1,127 @@ +/********************************************************************************** + * Copyright (c) 2008-2012 The Khronos Group Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and/or associated documentation files (the + * "Materials"), to deal in the Materials without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Materials, and to + * permit persons to whom the Materials are furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Materials. + * + * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. + **********************************************************************************/ + +/* $Revision: 11708 $ on $Date: 2010-06-13 23:36:24 -0700 (Sun, 13 Jun 2010) $ */ + +#ifndef __OPENCL_CL_DX9_MEDIA_SHARING_H +#define __OPENCL_CL_DX9_MEDIA_SHARING_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/****************************************************************************** +/* cl_khr_dx9_media_sharing */ +#define cl_khr_dx9_media_sharing 1 + +typedef cl_uint cl_dx9_media_adapter_type_khr; +typedef cl_uint cl_dx9_media_adapter_set_khr; + +#if defined(_WIN32) +#include +typedef struct _cl_dx9_surface_info_khr +{ + IDirect3DSurface9 *resource; + HANDLE shared_handle; +} cl_dx9_surface_info_khr; +#endif + + +/******************************************************************************/ + +// Error Codes +#define CL_INVALID_DX9_MEDIA_ADAPTER_KHR -1010 +#define CL_INVALID_DX9_MEDIA_SURFACE_KHR -1011 +#define CL_DX9_MEDIA_SURFACE_ALREADY_ACQUIRED_KHR -1012 +#define CL_DX9_MEDIA_SURFACE_NOT_ACQUIRED_KHR -1013 + +// cl_media_adapter_type_khr +#define CL_ADAPTER_D3D9_KHR 0x2020 +#define CL_ADAPTER_D3D9EX_KHR 0x2021 +#define CL_ADAPTER_DXVA_KHR 0x2022 + +// cl_media_adapter_set_khr +#define CL_PREFERRED_DEVICES_FOR_DX9_MEDIA_ADAPTER_KHR 0x2023 +#define CL_ALL_DEVICES_FOR_DX9_MEDIA_ADAPTER_KHR 0x2024 + +// cl_context_info +#define CL_CONTEXT_ADAPTER_D3D9_KHR 0x2025 +#define CL_CONTEXT_ADAPTER_D3D9EX_KHR 0x2026 +#define CL_CONTEXT_ADAPTER_DXVA_KHR 0x2027 + +// cl_mem_info +#define CL_MEM_DX9_MEDIA_ADAPTER_TYPE_KHR 0x2028 +#define CL_MEM_DX9_MEDIA_SURFACE_INFO_KHR 0x2029 + +// cl_image_info +#define CL_IMAGE_DX9_MEDIA_PLANE_KHR 0x202A + +// cl_command_type +#define CL_COMMAND_ACQUIRE_DX9_MEDIA_SURFACES_KHR 0x202B +#define CL_COMMAND_RELEASE_DX9_MEDIA_SURFACES_KHR 0x202C + +/******************************************************************************/ + +typedef CL_API_ENTRY cl_int (CL_API_CALL *clGetDeviceIDsFromDX9MediaAdapterKHR_fn)( + cl_platform_id platform, + cl_uint num_media_adapters, + cl_dx9_media_adapter_type_khr * media_adapter_type, + void * media_adapters, + cl_dx9_media_adapter_set_khr media_adapter_set, + cl_uint num_entries, + cl_device_id * devices, + cl_uint * num_devices) CL_API_SUFFIX__VERSION_1_2; + +typedef CL_API_ENTRY cl_mem (CL_API_CALL *clCreateFromDX9MediaSurfaceKHR_fn)( + cl_context context, + cl_mem_flags flags, + cl_dx9_media_adapter_type_khr adapter_type, + void * surface_info, + cl_uint plane, + cl_int * errcode_ret) CL_API_SUFFIX__VERSION_1_2; + +typedef CL_API_ENTRY cl_int (CL_API_CALL *clEnqueueAcquireDX9MediaSurfacesKHR_fn)( + cl_command_queue command_queue, + cl_uint num_objects, + const cl_mem * mem_objects, + cl_uint num_events_in_wait_list, + const cl_event * event_wait_list, + cl_event * event) CL_API_SUFFIX__VERSION_1_2; + +typedef CL_API_ENTRY cl_int (CL_API_CALL *clEnqueueReleaseDX9MediaSurfacesKHR_fn)( + cl_command_queue command_queue, + cl_uint num_objects, + const cl_mem * mem_objects, + cl_uint num_events_in_wait_list, + const cl_event * event_wait_list, + cl_event * event) CL_API_SUFFIX__VERSION_1_2; + +#ifdef __cplusplus +} +#endif + +#endif // __OPENCL_CL_DX9_MEDIA_SHARING_H + diff --git a/Externals/CLRun/include/CL/cl_ext.h b/Externals/CLRun/include/CL/cl_ext.h new file mode 100644 index 0000000000..632cb216b3 --- /dev/null +++ b/Externals/CLRun/include/CL/cl_ext.h @@ -0,0 +1,251 @@ +/******************************************************************************* + * Copyright (c) 2008 - 2012 The Khronos Group Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and/or associated documentation files (the + * "Materials"), to deal in the Materials without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Materials, and to + * permit persons to whom the Materials are furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Materials. + * + * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. + ******************************************************************************/ + +/* $Revision: 11928 $ on $Date: 2010-07-13 09:04:56 -0700 (Tue, 13 Jul 2010) $ */ + +/* cl_ext.h contains OpenCL extensions which don't have external */ +/* (OpenGL, D3D) dependencies. */ + +#ifndef __CL_EXT_H +#define __CL_EXT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __APPLE__ + #include + #include +#else + #include +#endif + +/* cl_khr_fp16 extension - no extension #define since it has no functions */ +#define CL_DEVICE_HALF_FP_CONFIG 0x1033 + +/* Memory object destruction + * + * Apple extension for use to manage externally allocated buffers used with cl_mem objects with CL_MEM_USE_HOST_PTR + * + * Registers a user callback function that will be called when the memory object is deleted and its resources + * freed. Each call to clSetMemObjectCallbackFn registers the specified user callback function on a callback + * stack associated with memobj. The registered user callback functions are called in the reverse order in + * which they were registered. The user callback functions are called and then the memory object is deleted + * and its resources freed. This provides a mechanism for the application (and libraries) using memobj to be + * notified when the memory referenced by host_ptr, specified when the memory object is created and used as + * the storage bits for the memory object, can be reused or freed. + * + * The application may not call CL api's with the cl_mem object passed to the pfn_notify. + * + * Please check for the "cl_APPLE_SetMemObjectDestructor" extension using clGetDeviceInfo(CL_DEVICE_EXTENSIONS) + * before using. + */ +#define cl_APPLE_SetMemObjectDestructor 1 +cl_int CL_API_ENTRY clSetMemObjectDestructorAPPLE( cl_mem /* memobj */, + void (* /*pfn_notify*/)( cl_mem /* memobj */, void* /*user_data*/), + void * /*user_data */ ) CL_EXT_SUFFIX__VERSION_1_0; + + +/* Context Logging Functions + * + * The next three convenience functions are intended to be used as the pfn_notify parameter to clCreateContext(). + * Please check for the "cl_APPLE_ContextLoggingFunctions" extension using clGetDeviceInfo(CL_DEVICE_EXTENSIONS) + * before using. + * + * clLogMessagesToSystemLog fowards on all log messages to the Apple System Logger + */ +#define cl_APPLE_ContextLoggingFunctions 1 +extern void CL_API_ENTRY clLogMessagesToSystemLogAPPLE( const char * /* errstr */, + const void * /* private_info */, + size_t /* cb */, + void * /* user_data */ ) CL_EXT_SUFFIX__VERSION_1_0; + +/* clLogMessagesToStdout sends all log messages to the file descriptor stdout */ +extern void CL_API_ENTRY clLogMessagesToStdoutAPPLE( const char * /* errstr */, + const void * /* private_info */, + size_t /* cb */, + void * /* user_data */ ) CL_EXT_SUFFIX__VERSION_1_0; + +/* clLogMessagesToStderr sends all log messages to the file descriptor stderr */ +extern void CL_API_ENTRY clLogMessagesToStderrAPPLE( const char * /* errstr */, + const void * /* private_info */, + size_t /* cb */, + void * /* user_data */ ) CL_EXT_SUFFIX__VERSION_1_0; + + +/************************ +* cl_khr_icd extension * +************************/ +#define cl_khr_icd 1 + +/* cl_platform_info */ +#define CL_PLATFORM_ICD_SUFFIX_KHR 0x0920 + +/* Additional Error Codes */ +#define CL_PLATFORM_NOT_FOUND_KHR -1001 + +extern CL_API_ENTRY cl_int CL_API_CALL +clIcdGetPlatformIDsKHR(cl_uint /* num_entries */, + cl_platform_id * /* platforms */, + cl_uint * /* num_platforms */); + +typedef CL_API_ENTRY cl_int (CL_API_CALL *clIcdGetPlatformIDsKHR_fn)( + cl_uint /* num_entries */, + cl_platform_id * /* platforms */, + cl_uint * /* num_platforms */); + + +/* Extension: cl_khr_image2D_buffer + * + * This extension allows a 2D image to be created from a cl_mem buffer without a copy. + * The type associated with a 2D image created from a buffer in an OpenCL program is image2d_t. + * Both the sampler and sampler-less read_image built-in functions are supported for 2D images + * and 2D images created from a buffer. Similarly, the write_image built-ins are also supported + * for 2D images created from a buffer. + * + * When the 2D image from buffer is created, the client must specify the width, + * height, image format (i.e. channel order and channel data type) and optionally the row pitch + * + * The pitch specified must be a multiple of CL_DEVICE_IMAGE_PITCH_ALIGNMENT pixels. + * The base address of the buffer must be aligned to CL_DEVICE_IMAGE_BASE_ADDRESS_ALIGNMENT pixels. + */ + +/************************************* + * cl_khr_initalize_memory extension * + *************************************/ + +#define CL_CONTEXT_MEMORY_INITIALIZE_KHR 0x200E + + +/************************************** + * cl_khr_terminate_context extension * + **************************************/ + +#define CL_DEVICE_TERMINATE_CAPABILITY_KHR 0x200F +#define CL_CONTEXT_TERMINATE_KHR 0x2010 + +#define cl_khr_terminate_context 1 +extern CL_API_ENTRY cl_int CL_API_CALL clTerminateContextKHR(cl_context /* context */) CL_EXT_SUFFIX__VERSION_1_2; + +typedef CL_API_ENTRY cl_int (CL_API_CALL *clTerminateContextKHR_fn)(cl_context /* context */) CL_EXT_SUFFIX__VERSION_1_2; + + +/* + * Extension: cl_khr_spir + * + * This extension adds support to create an OpenCL program object from a + * Standard Portable Intermediate Representation (SPIR) instance + */ + +/****************************************** +* cl_nv_device_attribute_query extension * +******************************************/ +/* cl_nv_device_attribute_query extension - no extension #define since it has no functions */ +#define CL_DEVICE_COMPUTE_CAPABILITY_MAJOR_NV 0x4000 +#define CL_DEVICE_COMPUTE_CAPABILITY_MINOR_NV 0x4001 +#define CL_DEVICE_REGISTERS_PER_BLOCK_NV 0x4002 +#define CL_DEVICE_WARP_SIZE_NV 0x4003 +#define CL_DEVICE_GPU_OVERLAP_NV 0x4004 +#define CL_DEVICE_KERNEL_EXEC_TIMEOUT_NV 0x4005 +#define CL_DEVICE_INTEGRATED_MEMORY_NV 0x4006 + + +/********************************* +* cl_amd_device_attribute_query * +*********************************/ +#define CL_DEVICE_PROFILING_TIMER_OFFSET_AMD 0x4036 + +#ifdef CL_VERSION_1_1 + /*********************************** + * cl_ext_device_fission extension * + ***********************************/ + #define cl_ext_device_fission 1 + + extern CL_API_ENTRY cl_int CL_API_CALL + clReleaseDeviceEXT( cl_device_id /*device*/ ) CL_EXT_SUFFIX__VERSION_1_1; + + typedef CL_API_ENTRY cl_int + (CL_API_CALL *clReleaseDeviceEXT_fn)( cl_device_id /*device*/ ) CL_EXT_SUFFIX__VERSION_1_1; + + extern CL_API_ENTRY cl_int CL_API_CALL + clRetainDeviceEXT( cl_device_id /*device*/ ) CL_EXT_SUFFIX__VERSION_1_1; + + typedef CL_API_ENTRY cl_int + (CL_API_CALL *clRetainDeviceEXT_fn)( cl_device_id /*device*/ ) CL_EXT_SUFFIX__VERSION_1_1; + + typedef cl_ulong cl_device_partition_property_ext; + extern CL_API_ENTRY cl_int CL_API_CALL + clCreateSubDevicesEXT( cl_device_id /*in_device*/, + const cl_device_partition_property_ext * /* properties */, + cl_uint /*num_entries*/, + cl_device_id * /*out_devices*/, + cl_uint * /*num_devices*/ ) CL_EXT_SUFFIX__VERSION_1_1; + + typedef CL_API_ENTRY cl_int + ( CL_API_CALL * clCreateSubDevicesEXT_fn)( cl_device_id /*in_device*/, + const cl_device_partition_property_ext * /* properties */, + cl_uint /*num_entries*/, + cl_device_id * /*out_devices*/, + cl_uint * /*num_devices*/ ) CL_EXT_SUFFIX__VERSION_1_1; + + /* cl_device_partition_property_ext */ + #define CL_DEVICE_PARTITION_EQUALLY_EXT 0x4050 + #define CL_DEVICE_PARTITION_BY_COUNTS_EXT 0x4051 + #define CL_DEVICE_PARTITION_BY_NAMES_EXT 0x4052 + #define CL_DEVICE_PARTITION_BY_AFFINITY_DOMAIN_EXT 0x4053 + + /* clDeviceGetInfo selectors */ + #define CL_DEVICE_PARENT_DEVICE_EXT 0x4054 + #define CL_DEVICE_PARTITION_TYPES_EXT 0x4055 + #define CL_DEVICE_AFFINITY_DOMAINS_EXT 0x4056 + #define CL_DEVICE_REFERENCE_COUNT_EXT 0x4057 + #define CL_DEVICE_PARTITION_STYLE_EXT 0x4058 + + /* error codes */ + #define CL_DEVICE_PARTITION_FAILED_EXT -1057 + #define CL_INVALID_PARTITION_COUNT_EXT -1058 + #define CL_INVALID_PARTITION_NAME_EXT -1059 + + /* CL_AFFINITY_DOMAINs */ + #define CL_AFFINITY_DOMAIN_L1_CACHE_EXT 0x1 + #define CL_AFFINITY_DOMAIN_L2_CACHE_EXT 0x2 + #define CL_AFFINITY_DOMAIN_L3_CACHE_EXT 0x3 + #define CL_AFFINITY_DOMAIN_L4_CACHE_EXT 0x4 + #define CL_AFFINITY_DOMAIN_NUMA_EXT 0x10 + #define CL_AFFINITY_DOMAIN_NEXT_FISSIONABLE_EXT 0x100 + + /* cl_device_partition_property_ext list terminators */ + #define CL_PROPERTIES_LIST_END_EXT ((cl_device_partition_property_ext) 0) + #define CL_PARTITION_BY_COUNTS_LIST_END_EXT ((cl_device_partition_property_ext) 0) + #define CL_PARTITION_BY_NAMES_LIST_END_EXT ((cl_device_partition_property_ext) 0 - 1) + + + +#endif /* CL_VERSION_1_1 */ + +#ifdef __cplusplus +} +#endif + + +#endif /* __CL_EXT_H */ diff --git a/Externals/CLRun/include/CL/cl_gl.h b/Externals/CLRun/include/CL/cl_gl.h index fcaa5bd392..af2036cc99 100644 --- a/Externals/CLRun/include/CL/cl_gl.h +++ b/Externals/CLRun/include/CL/cl_gl.h @@ -1,5 +1,5 @@ /********************************************************************************** - * Copyright (c) 2008-2010 The Khronos Group Inc. + * Copyright (c) 2008 - 2012 The Khronos Group Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and/or associated documentation files (the @@ -21,14 +21,6 @@ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. **********************************************************************************/ -/* $Revision: 11707 $ on $Date: 2010-06-13 23:30:16 -0700 (Sun, 13 Jun 2010) $ */ - -/* - * cl_gl.h contains Khronos-approved (KHR) OpenCL extensions which have - * OpenGL dependencies. The application is responsible for #including - * OpenGL or OpenGL ES headers before #including cl_gl.h. - */ - #ifndef __OPENCL_CL_GL_H #define __OPENCL_CL_GL_H @@ -36,7 +28,7 @@ #include #else #include -#endif +#endif #ifdef __cplusplus extern "C" { @@ -45,16 +37,23 @@ extern "C" { typedef cl_uint cl_gl_object_type; typedef cl_uint cl_gl_texture_info; typedef cl_uint cl_gl_platform_info; +typedef struct __GLsync *cl_GLsync; -/* cl_gl_object_type */ -#define CL_GL_OBJECT_BUFFER 0x2000 -#define CL_GL_OBJECT_TEXTURE2D 0x2001 -#define CL_GL_OBJECT_TEXTURE3D 0x2002 -#define CL_GL_OBJECT_RENDERBUFFER 0x2003 +/* cl_gl_object_type = 0x2000 - 0x200F enum values are currently taken */ +#define CL_GL_OBJECT_BUFFER 0x2000 +#define CL_GL_OBJECT_TEXTURE2D 0x2001 +#define CL_GL_OBJECT_TEXTURE3D 0x2002 +#define CL_GL_OBJECT_RENDERBUFFER 0x2003 +#define CL_GL_OBJECT_TEXTURE2D_ARRAY 0x200E +#define CL_GL_OBJECT_TEXTURE1D 0x200F +#define CL_GL_OBJECT_TEXTURE1D_ARRAY 0x2010 +#define CL_GL_OBJECT_TEXTURE_BUFFER 0x2011 + +/* cl_gl_texture_info */ +#define CL_GL_TEXTURE_TARGET 0x2004 +#define CL_GL_MIPMAP_LEVEL 0x2005 +#define CL_GL_NUM_SAMPLES 0x2012 -/* cl_gl_texture_info */ -#define CL_GL_TEXTURE_TARGET 0x2004 -#define CL_GL_MIPMAP_LEVEL 0x2005 extern CL_API_ENTRY cl_mem CL_API_CALL clCreateFromGLBuffer(cl_context /* context */, @@ -63,21 +62,13 @@ clCreateFromGLBuffer(cl_context /* context */, int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; extern CL_API_ENTRY cl_mem CL_API_CALL -clCreateFromGLTexture2D(cl_context /* context */, - cl_mem_flags /* flags */, - cl_GLenum /* target */, - cl_GLint /* miplevel */, - cl_GLuint /* texture */, - cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; - -extern CL_API_ENTRY cl_mem CL_API_CALL -clCreateFromGLTexture3D(cl_context /* context */, - cl_mem_flags /* flags */, - cl_GLenum /* target */, - cl_GLint /* miplevel */, - cl_GLuint /* texture */, - cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; - +clCreateFromGLTexture(cl_context /* context */, + cl_mem_flags /* flags */, + cl_GLenum /* target */, + cl_GLint /* miplevel */, + cl_GLuint /* texture */, + cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_2; + extern CL_API_ENTRY cl_mem CL_API_CALL clCreateFromGLRenderbuffer(cl_context /* context */, cl_mem_flags /* flags */, @@ -87,8 +78,8 @@ clCreateFromGLRenderbuffer(cl_context /* context */, extern CL_API_ENTRY cl_int CL_API_CALL clGetGLObjectInfo(cl_mem /* memobj */, cl_gl_object_type * /* gl_object_type */, - cl_GLuint * /* gl_object_name */) CL_API_SUFFIX__VERSION_1_0; - + cl_GLuint * /* gl_object_name */) CL_API_SUFFIX__VERSION_1_0; + extern CL_API_ENTRY cl_int CL_API_CALL clGetGLTextureInfo(cl_mem /* memobj */, cl_gl_texture_info /* param_name */, @@ -112,33 +103,51 @@ clEnqueueReleaseGLObjects(cl_command_queue /* command_queue */, const cl_event * /* event_wait_list */, cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; + +// Deprecated OpenCL 1.1 APIs +extern CL_API_ENTRY CL_EXT_PREFIX__VERSION_1_1_DEPRECATED cl_mem CL_API_CALL +clCreateFromGLTexture2D(cl_context /* context */, + cl_mem_flags /* flags */, + cl_GLenum /* target */, + cl_GLint /* miplevel */, + cl_GLuint /* texture */, + cl_int * /* errcode_ret */) CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED; + +extern CL_API_ENTRY CL_EXT_PREFIX__VERSION_1_1_DEPRECATED cl_mem CL_API_CALL +clCreateFromGLTexture3D(cl_context /* context */, + cl_mem_flags /* flags */, + cl_GLenum /* target */, + cl_GLint /* miplevel */, + cl_GLuint /* texture */, + cl_int * /* errcode_ret */) CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED; + /* cl_khr_gl_sharing extension */ - + #define cl_khr_gl_sharing 1 - + typedef cl_uint cl_gl_context_info; - + /* Additional Error Codes */ #define CL_INVALID_GL_SHAREGROUP_REFERENCE_KHR -1000 - + /* cl_gl_context_info */ #define CL_CURRENT_DEVICE_FOR_GL_CONTEXT_KHR 0x2006 #define CL_DEVICES_FOR_GL_CONTEXT_KHR 0x2007 - + /* Additional cl_context_properties */ #define CL_GL_CONTEXT_KHR 0x2008 #define CL_EGL_DISPLAY_KHR 0x2009 #define CL_GLX_DISPLAY_KHR 0x200A #define CL_WGL_HDC_KHR 0x200B #define CL_CGL_SHAREGROUP_KHR 0x200C - + extern CL_API_ENTRY cl_int CL_API_CALL clGetGLContextInfoKHR(const cl_context_properties * /* properties */, cl_gl_context_info /* param_name */, size_t /* param_value_size */, void * /* param_value */, size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; - + typedef CL_API_ENTRY cl_int (CL_API_CALL *clGetGLContextInfoKHR_fn)( const cl_context_properties * properties, cl_gl_context_info param_name, @@ -150,4 +159,4 @@ typedef CL_API_ENTRY cl_int (CL_API_CALL *clGetGLContextInfoKHR_fn)( } #endif -#endif /* __OPENCL_CL_GL_H */ +#endif /* __OPENCL_CL_GL_H */ diff --git a/Externals/CLRun/include/CL/cl_gl_ext.h b/Externals/CLRun/include/CL/cl_gl_ext.h new file mode 100644 index 0000000000..77d53536f6 --- /dev/null +++ b/Externals/CLRun/include/CL/cl_gl_ext.h @@ -0,0 +1,69 @@ +/********************************************************************************** + * Copyright (c) 2008-2012 The Khronos Group Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and/or associated documentation files (the + * "Materials"), to deal in the Materials without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Materials, and to + * permit persons to whom the Materials are furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Materials. + * + * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. + **********************************************************************************/ + +/* $Revision: 11708 $ on $Date: 2010-06-13 23:36:24 -0700 (Sun, 13 Jun 2010) $ */ + +/* cl_gl_ext.h contains vendor (non-KHR) OpenCL extensions which have */ +/* OpenGL dependencies. */ + +#ifndef __OPENCL_CL_GL_EXT_H +#define __OPENCL_CL_GL_EXT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __APPLE__ + #include +#else + #include +#endif + +/* + * For each extension, follow this template + * cl_VEN_extname extension */ +/* #define cl_VEN_extname 1 + * ... define new types, if any + * ... define new tokens, if any + * ... define new APIs, if any + * + * If you need GLtypes here, mirror them with a cl_GLtype, rather than including a GL header + * This allows us to avoid having to decide whether to include GL headers or GLES here. + */ + +/* + * cl_khr_gl_event extension + * See section 9.9 in the OpenCL 1.1 spec for more information + */ +#define CL_COMMAND_GL_FENCE_SYNC_OBJECT_KHR 0x200D + +extern CL_API_ENTRY cl_event CL_API_CALL +clCreateEventFromGLsyncKHR(cl_context /* context */, + cl_GLsync /* cl_GLsync */, + cl_int * /* errcode_ret */) CL_EXT_SUFFIX__VERSION_1_1; + +#ifdef __cplusplus +} +#endif + +#endif /* __OPENCL_CL_GL_EXT_H */ diff --git a/Externals/CLRun/include/CL/cl_platform.h b/Externals/CLRun/include/CL/cl_platform.h index 8fdcb17341..cf2b7210ac 100644 --- a/Externals/CLRun/include/CL/cl_platform.h +++ b/Externals/CLRun/include/CL/cl_platform.h @@ -1,5 +1,5 @@ /********************************************************************************** - * Copyright (c) 2008-2010 The Khronos Group Inc. + * Copyright (c) 2008-2012 The Khronos Group Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and/or associated documentation files (the @@ -21,7 +21,7 @@ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. **********************************************************************************/ -/* $Revision: 11707 $ on $Date: 2010-06-13 23:30:16 -0700 (Sun, 13 Jun 2010) $ */ +/* $Revision: 11803 $ on $Date: 2010-06-25 10:02:12 -0700 (Fri, 25 Jun 2010) $ */ #ifndef __CL_PLATFORM_H #define __CL_PLATFORM_H @@ -36,21 +36,85 @@ extern "C" { #endif #if defined(_WIN32) -#define CL_API_ENTRY -#define CL_API_CALL __stdcall + #define CL_API_ENTRY + #define CL_API_CALL __stdcall + #define CL_CALLBACK __stdcall #else -#define CL_API_ENTRY -#define CL_API_CALL + #define CL_API_ENTRY + #define CL_API_CALL + #define CL_CALLBACK #endif #ifdef __APPLE__ -#define CL_API_SUFFIX__VERSION_1_0 AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER -#define CL_API_SUFFIX__VERSION_1_1 -#define CL_EXTENSION_WEAK_LINK __attribute__((weak_import)) + #define CL_EXTENSION_WEAK_LINK __attribute__((weak_import)) + #define CL_API_SUFFIX__VERSION_1_0 AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER + #define CL_EXT_SUFFIX__VERSION_1_0 CL_EXTENSION_WEAK_LINK AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER + #define CL_API_SUFFIX__VERSION_1_1 AVAILABLE_MAC_OS_X_VERSION_10_7_AND_LATER + #define GCL_API_SUFFIX__VERSION_1_1 AVAILABLE_MAC_OS_X_VERSION_10_7_AND_LATER + #define CL_EXT_SUFFIX__VERSION_1_1 CL_EXTENSION_WEAK_LINK AVAILABLE_MAC_OS_X_VERSION_10_7_AND_LATER + #define CL_EXT_SUFFIX__VERSION_1_0_DEPRECATED CL_EXTENSION_WEAK_LINK AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_7 + + #ifdef AVAILABLE_MAC_OS_X_VERSION_10_8_AND_LATER + #define CL_API_SUFFIX__VERSION_1_2 AVAILABLE_MAC_OS_X_VERSION_10_8_AND_LATER + #define GCL_API_SUFFIX__VERSION_1_2 AVAILABLE_MAC_OS_X_VERSION_10_8_AND_LATER + #define CL_EXT_SUFFIX__VERSION_1_2 CL_EXTENSION_WEAK_LINK AVAILABLE_MAC_OS_X_VERSION_10_8_AND_LATER + #define CL_EXT_PREFIX__VERSION_1_1_DEPRECATED + #define CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED CL_EXTENSION_WEAK_LINK AVAILABLE_MAC_OS_X_VERSION_10_7_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_8 + #else + #warning This path should never happen outside of internal operating system development. AvailabilityMacros do not function correctly here! + #define CL_API_SUFFIX__VERSION_1_2 AVAILABLE_MAC_OS_X_VERSION_10_7_AND_LATER + #define GCL_API_SUFFIX__VERSION_1_2 AVAILABLE_MAC_OS_X_VERSION_10_7_AND_LATER + #define CL_EXT_SUFFIX__VERSION_1_2 CL_EXTENSION_WEAK_LINK AVAILABLE_MAC_OS_X_VERSION_10_7_AND_LATER + #define CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED CL_EXTENSION_WEAK_LINK AVAILABLE_MAC_OS_X_VERSION_10_7_AND_LATER + #endif #else -#define CL_API_SUFFIX__VERSION_1_0 -#define CL_API_SUFFIX__VERSION_1_1 -#define CL_EXTENSION_WEAK_LINK + #define CL_EXTENSION_WEAK_LINK + #define CL_API_SUFFIX__VERSION_1_0 + #define CL_EXT_SUFFIX__VERSION_1_0 + #define CL_API_SUFFIX__VERSION_1_1 + #define CL_EXT_SUFFIX__VERSION_1_1 + #define CL_API_SUFFIX__VERSION_1_2 + #define CL_EXT_SUFFIX__VERSION_1_2 + + #ifdef __GNUC__ + #ifdef CL_USE_DEPRECATED_OPENCL_1_0_APIS + #define CL_EXT_SUFFIX__VERSION_1_0_DEPRECATED + #define CL_EXT_PREFIX__VERSION_1_0_DEPRECATED + #else + #define CL_EXT_SUFFIX__VERSION_1_0_DEPRECATED __attribute__((deprecated)) + #define CL_EXT_PREFIX__VERSION_1_0_DEPRECATED + #endif + + #ifdef CL_USE_DEPRECATED_OPENCL_1_1_APIS + #define CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED + #define CL_EXT_PREFIX__VERSION_1_1_DEPRECATED + #else + #define CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED __attribute__((deprecated)) + #define CL_EXT_PREFIX__VERSION_1_1_DEPRECATED + #endif + #elif _WIN32 + #ifdef CL_USE_DEPRECATED_OPENCL_1_0_APIS + #define CL_EXT_SUFFIX__VERSION_1_0_DEPRECATED + #define CL_EXT_PREFIX__VERSION_1_0_DEPRECATED + #else + #define CL_EXT_SUFFIX__VERSION_1_0_DEPRECATED + #define CL_EXT_PREFIX__VERSION_1_0_DEPRECATED __declspec(deprecated) + #endif + + #ifdef CL_USE_DEPRECATED_OPENCL_1_1_APIS + #define CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED + #define CL_EXT_PREFIX__VERSION_1_1_DEPRECATED + #else + #define CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED + #define CL_EXT_PREFIX__VERSION_1_1_DEPRECATED __declspec(deprecated) + #endif + #else + #define CL_EXT_SUFFIX__VERSION_1_0_DEPRECATED + #define CL_EXT_PREFIX__VERSION_1_0_DEPRECATED + + #define CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED + #define CL_EXT_PREFIX__VERSION_1_1_DEPRECATED + #endif #endif #if (defined (_WIN32) && defined(_MSC_VER)) @@ -108,14 +172,40 @@ typedef double cl_double; #define CL_DBL_MIN 2.225073858507201383090e-308 #define CL_DBL_EPSILON 2.220446049250313080847e-16 +#define CL_M_E 2.718281828459045090796 +#define CL_M_LOG2E 1.442695040888963387005 +#define CL_M_LOG10E 0.434294481903251816668 +#define CL_M_LN2 0.693147180559945286227 +#define CL_M_LN10 2.302585092994045901094 +#define CL_M_PI 3.141592653589793115998 +#define CL_M_PI_2 1.570796326794896557999 +#define CL_M_PI_4 0.785398163397448278999 +#define CL_M_1_PI 0.318309886183790691216 +#define CL_M_2_PI 0.636619772367581382433 +#define CL_M_2_SQRTPI 1.128379167095512558561 +#define CL_M_SQRT2 1.414213562373095145475 +#define CL_M_SQRT1_2 0.707106781186547572737 + +#define CL_M_E_F 2.71828174591064f +#define CL_M_LOG2E_F 1.44269502162933f +#define CL_M_LOG10E_F 0.43429449200630f +#define CL_M_LN2_F 0.69314718246460f +#define CL_M_LN10_F 2.30258512496948f +#define CL_M_PI_F 3.14159274101257f +#define CL_M_PI_2_F 1.57079637050629f +#define CL_M_PI_4_F 0.78539818525314f +#define CL_M_1_PI_F 0.31830987334251f +#define CL_M_2_PI_F 0.63661974668503f +#define CL_M_2_SQRTPI_F 1.12837922573090f +#define CL_M_SQRT2_F 1.41421353816986f +#define CL_M_SQRT1_2_F 0.70710676908493f + #define CL_NAN (CL_INFINITY - CL_INFINITY) #define CL_HUGE_VALF ((cl_float) 1e50) #define CL_HUGE_VAL ((cl_double) 1e500) #define CL_MAXFLOAT CL_FLT_MAX #define CL_INFINITY CL_HUGE_VALF -#define CL_CALLBACK __stdcall - #else #include @@ -173,6 +263,34 @@ typedef double cl_double __attribute__((aligned(8))); #define CL_DBL_MIN 0x1.0p-1022 #define CL_DBL_EPSILON 0x1.0p-52 +#define CL_M_E 2.718281828459045090796 +#define CL_M_LOG2E 1.442695040888963387005 +#define CL_M_LOG10E 0.434294481903251816668 +#define CL_M_LN2 0.693147180559945286227 +#define CL_M_LN10 2.302585092994045901094 +#define CL_M_PI 3.141592653589793115998 +#define CL_M_PI_2 1.570796326794896557999 +#define CL_M_PI_4 0.785398163397448278999 +#define CL_M_1_PI 0.318309886183790691216 +#define CL_M_2_PI 0.636619772367581382433 +#define CL_M_2_SQRTPI 1.128379167095512558561 +#define CL_M_SQRT2 1.414213562373095145475 +#define CL_M_SQRT1_2 0.707106781186547572737 + +#define CL_M_E_F 2.71828174591064f +#define CL_M_LOG2E_F 1.44269502162933f +#define CL_M_LOG10E_F 0.43429449200630f +#define CL_M_LN2_F 0.69314718246460f +#define CL_M_LN10_F 2.30258512496948f +#define CL_M_PI_F 3.14159274101257f +#define CL_M_PI_2_F 1.57079637050629f +#define CL_M_PI_4_F 0.78539818525314f +#define CL_M_1_PI_F 0.31830987334251f +#define CL_M_2_PI_F 0.63661974668503f +#define CL_M_2_SQRTPI_F 1.12837922573090f +#define CL_M_SQRT2_F 1.41421353816986f +#define CL_M_SQRT1_2_F 0.70710676908493f + #if defined( __GNUC__ ) #define CL_HUGE_VALF __builtin_huge_valf() #define CL_HUGE_VAL __builtin_huge_val() @@ -186,13 +304,11 @@ typedef double cl_double __attribute__((aligned(8))); #define CL_MAXFLOAT CL_FLT_MAX #define CL_INFINITY CL_HUGE_VALF -#define CL_CALLBACK - #endif #include -/* Mirror types to GL types. Mirror types allow us to avoid deciding which headers to load based on whether we are using GL or GLES here. */ +/* Mirror types to GL types. Mirror types allow us to avoid deciding which 87s to load based on whether we are using GL or GLES here. */ typedef unsigned int cl_GLuint; typedef int cl_GLint; typedef unsigned int cl_GLenum; @@ -389,6 +505,9 @@ typedef union #endif }cl_char4; +/* cl_char3 is identical in size, alignment and behavior to cl_char4. See section 6.1.5. */ +typedef cl_char4 cl_char3; + typedef union { cl_char CL_ALIGNED(8) s[8]; @@ -461,6 +580,9 @@ typedef union #endif }cl_uchar4; +/* cl_uchar3 is identical in size, alignment and behavior to cl_uchar4. See section 6.1.5. */ +typedef cl_uchar4 cl_uchar3; + typedef union { cl_uchar CL_ALIGNED(8) s[8]; @@ -533,6 +655,9 @@ typedef union #endif }cl_short4; +/* cl_short3 is identical in size, alignment and behavior to cl_short4. See section 6.1.5. */ +typedef cl_short4 cl_short3; + typedef union { cl_short CL_ALIGNED(16) s[8]; @@ -605,6 +730,9 @@ typedef union #endif }cl_ushort4; +/* cl_ushort3 is identical in size, alignment and behavior to cl_ushort4. See section 6.1.5. */ +typedef cl_ushort4 cl_ushort3; + typedef union { cl_ushort CL_ALIGNED(16) s[8]; @@ -676,6 +804,9 @@ typedef union #endif }cl_int4; +/* cl_int3 is identical in size, alignment and behavior to cl_int4. See section 6.1.5. */ +typedef cl_int4 cl_int3; + typedef union { cl_int CL_ALIGNED(32) s[8]; @@ -748,6 +879,9 @@ typedef union #endif }cl_uint4; +/* cl_uint3 is identical in size, alignment and behavior to cl_uint4. See section 6.1.5. */ +typedef cl_uint4 cl_uint3; + typedef union { cl_uint CL_ALIGNED(32) s[8]; @@ -819,6 +953,9 @@ typedef union #endif }cl_long4; +/* cl_long3 is identical in size, alignment and behavior to cl_long4. See section 6.1.5. */ +typedef cl_long4 cl_long3; + typedef union { cl_long CL_ALIGNED(64) s[8]; @@ -891,6 +1028,9 @@ typedef union #endif }cl_ulong4; +/* cl_ulong3 is identical in size, alignment and behavior to cl_ulong4. See section 6.1.5. */ +typedef cl_ulong4 cl_ulong3; + typedef union { cl_ulong CL_ALIGNED(64) s[8]; @@ -964,6 +1104,9 @@ typedef union #endif }cl_float4; +/* cl_float3 is identical in size, alignment and behavior to cl_float4. See section 6.1.5. */ +typedef cl_float4 cl_float3; + typedef union { cl_float CL_ALIGNED(32) s[8]; @@ -1036,6 +1179,9 @@ typedef union #endif }cl_double4; +/* cl_double3 is identical in size, alignment and behavior to cl_double4. See section 6.1.5. */ +typedef cl_double4 cl_double3; + typedef union { cl_double CL_ALIGNED(64) s[8]; @@ -1077,6 +1223,29 @@ typedef union #endif }cl_double16; +/* Macro to facilitate debugging + * Usage: + * Place CL_PROGRAM_STRING_DEBUG_INFO on the line before the first line of your source. + * The first line ends with: CL_PROGRAM_STRING_DEBUG_INFO \" + * Each line thereafter of OpenCL C source must end with: \n\ + * The last line ends in "; + * + * Example: + * + * const char *my_program = CL_PROGRAM_STRING_DEBUG_INFO "\ + * kernel void foo( int a, float * b ) \n\ + * { \n\ + * // my comment \n\ + * *b[ get_global_id(0)] = a; \n\ + * } \n\ + * "; + * + * This should correctly set up the line, (column) and file information for your source + * string so you can do source level debugging. + */ +#define __CL_STRINGIFY( _x ) # _x +#define _CL_STRINGIFY( _x ) __CL_STRINGIFY( _x ) +#define CL_PROGRAM_STRING_DEBUG_INFO "#line " _CL_STRINGIFY(__LINE__) " \"" __FILE__ "\" \n\n" #ifdef __cplusplus } diff --git a/Source/Core/AudioCommon/CMakeLists.txt b/Source/Core/AudioCommon/CMakeLists.txt index 3b6d0cea4d..939956460d 100644 --- a/Source/Core/AudioCommon/CMakeLists.txt +++ b/Source/Core/AudioCommon/CMakeLists.txt @@ -6,6 +6,11 @@ set(SRCS Src/AudioCommon.cpp set(LIBS "") +if(ANDROID) + set(SRCS ${SRCS} Src/OpenSLESStream.cpp) + set(LIBS ${LIBS} OpenSLES) +endif(ANDROID) + if(ALSA_FOUND) set(SRCS ${SRCS} Src/AlsaSoundStream.cpp) set(LIBS ${LIBS} ${ALSA_LIBRARIES}) diff --git a/Source/Core/AudioCommon/Src/AudioCommon.cpp b/Source/Core/AudioCommon/Src/AudioCommon.cpp index e14b9ac45e..2f299d0edb 100644 --- a/Source/Core/AudioCommon/Src/AudioCommon.cpp +++ b/Source/Core/AudioCommon/Src/AudioCommon.cpp @@ -26,6 +26,7 @@ #include "CoreAudioSoundStream.h" #include "OpenALStream.h" #include "PulseAudioStream.h" +#include "OpenSLESStream.h" #include "../../Core/Src/Movie.h" #include "../../Core/Src/ConfigManager.h" @@ -55,7 +56,8 @@ namespace AudioCommon soundStream = new CoreAudioSound(mixer); else if (backend == BACKEND_PULSEAUDIO && PulseAudio::isValid()) soundStream = new PulseAudio(mixer); - + else if (backend == BACKEND_OPENSLES && OpenSLESStream::isValid()) + soundStream = new OpenSLESStream(mixer); if (soundStream != NULL) { UpdateSoundStream(); @@ -116,7 +118,8 @@ namespace AudioCommon backends.push_back(BACKEND_PULSEAUDIO); if (OpenALStream::isValid()) backends.push_back(BACKEND_OPENAL); - + if (OpenSLESStream::isValid()) + backends.push_back(BACKEND_OPENSLES); return backends; } diff --git a/Source/Core/AudioCommon/Src/OpenALStream.cpp b/Source/Core/AudioCommon/Src/OpenALStream.cpp index 6b239a584c..7d1c45175b 100644 --- a/Source/Core/AudioCommon/Src/OpenALStream.cpp +++ b/Source/Core/AudioCommon/Src/OpenALStream.cpp @@ -200,6 +200,7 @@ void OpenALStream::SoundLoop() u64 num_samples_to_render = (audio_dma_period * ais_samples_per_second) / SystemTimers::GetTicksPerSecond(); unsigned int numSamples = (unsigned int)num_samples_to_render; + unsigned int minSamples = surround_capable ? 240 : 0; // DPL2 accepts 240 samples minimum (FWRDURATION) numSamples = (numSamples > OAL_MAX_SAMPLES) ? OAL_MAX_SAMPLES : numSamples; numSamples = m_mixer->Mix(realtimeBuffer, numSamples); @@ -236,9 +237,15 @@ void OpenALStream::SoundLoop() // Adjust SETTING_SEQUENCE_MS to balance between lag vs hollow audio soundTouch.setSetting(SETTING_SEQUENCE_MS, (int)(1 / (rate * rate))); soundTouch.setTempo(rate); + if (rate > 10) + { + soundTouch.clear(); + } } - unsigned int nSamples = soundTouch.receiveSamples(sampleBuffer, OAL_MAX_SAMPLES * SIZE_FLOAT * SURROUND_CHANNELS * OAL_MAX_BUFFERS); - if (nSamples > 0) + + unsigned int nSamples = soundTouch.receiveSamples(sampleBuffer, OAL_MAX_SAMPLES * SIZE_FLOAT * OAL_MAX_BUFFERS); + + if (nSamples > minSamples) { // Remove the Buffer from the Queue. (uiBuffer contains the Buffer ID for the unqueued Buffer) if (iBuffersFilled == 0) diff --git a/Source/Core/AudioCommon/Src/OpenSLESStream.cpp b/Source/Core/AudioCommon/Src/OpenSLESStream.cpp new file mode 100644 index 0000000000..b0913a1895 --- /dev/null +++ b/Source/Core/AudioCommon/Src/OpenSLESStream.cpp @@ -0,0 +1,145 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#ifdef ANDROID +#include "Common.h" +#include +#include "OpenSLESStream.h" + +#include +#include + +// engine interfaces +static SLObjectItf engineObject; +static SLEngineItf engineEngine; +static SLObjectItf outputMixObject; + +// buffer queue player interfaces +static SLObjectItf bqPlayerObject = NULL; +static SLPlayItf bqPlayerPlay; +static SLAndroidSimpleBufferQueueItf bqPlayerBufferQueue; +static SLMuteSoloItf bqPlayerMuteSolo; +static SLVolumeItf bqPlayerVolume; +static CMixer *g_mixer; +#define BUFFER_SIZE 512 +#define BUFFER_SIZE_IN_SAMPLES (BUFFER_SIZE / 2) + +// Double buffering. +static short buffer[2][BUFFER_SIZE]; +static int curBuffer = 0; + +static void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void *context) { + assert(bq == bqPlayerBufferQueue); + assert(NULL == context); + + short *nextBuffer = buffer[curBuffer]; + int nextSize = sizeof(buffer[0]); + + SLresult result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, nextBuffer, nextSize); + + // Comment from sample code: + // the most likely other result is SL_RESULT_BUFFER_INSUFFICIENT, + // which for this code example would indicate a programming error + assert(SL_RESULT_SUCCESS == result); + + curBuffer ^= 1; // Switch buffer + // Render to the fresh buffer + g_mixer->Mix(reinterpret_cast(buffer[curBuffer]), BUFFER_SIZE_IN_SAMPLES); +} +bool OpenSLESStream::Start() +{ + SLresult result; + // create engine + result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL); + assert(SL_RESULT_SUCCESS == result); + result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE); + assert(SL_RESULT_SUCCESS == result); + result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine); + assert(SL_RESULT_SUCCESS == result); + result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 0, 0, 0); + assert(SL_RESULT_SUCCESS == result); + result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE); + assert(SL_RESULT_SUCCESS == result); + + SLDataLocator_AndroidSimpleBufferQueue loc_bufq = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2}; + SLDataFormat_PCM format_pcm = { + SL_DATAFORMAT_PCM, + 2, + SL_SAMPLINGRATE_44_1, + SL_PCMSAMPLEFORMAT_FIXED_16, + SL_PCMSAMPLEFORMAT_FIXED_16, + SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT, + SL_BYTEORDER_LITTLEENDIAN + }; + + SLDataSource audioSrc = {&loc_bufq, &format_pcm}; + + // configure audio sink + SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, outputMixObject}; + SLDataSink audioSnk = {&loc_outmix, NULL}; + + // create audio player + const SLInterfaceID ids[2] = {SL_IID_BUFFERQUEUE, SL_IID_VOLUME}; + const SLboolean req[2] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE}; + result = (*engineEngine)->CreateAudioPlayer(engineEngine, &bqPlayerObject, &audioSrc, &audioSnk, 2, ids, req); + assert(SL_RESULT_SUCCESS == result); + + result = (*bqPlayerObject)->Realize(bqPlayerObject, SL_BOOLEAN_FALSE); + assert(SL_RESULT_SUCCESS == result); + result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_PLAY, &bqPlayerPlay); + assert(SL_RESULT_SUCCESS == result); + result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_BUFFERQUEUE, + &bqPlayerBufferQueue); + assert(SL_RESULT_SUCCESS == result); + result = (*bqPlayerBufferQueue)->RegisterCallback(bqPlayerBufferQueue, bqPlayerCallback, NULL); + assert(SL_RESULT_SUCCESS == result); + result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_PLAYING); + assert(SL_RESULT_SUCCESS == result); + + // Render and enqueue a first buffer. (or should we just play the buffer empty?) + curBuffer = 0; + + result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, buffer[curBuffer], sizeof(buffer[curBuffer])); + if (SL_RESULT_SUCCESS != result) { + return false; + } + curBuffer ^= 1; + g_mixer = m_mixer; + return true; +} + +void OpenSLESStream::Stop() +{ + if (bqPlayerObject != NULL) { + (*bqPlayerObject)->Destroy(bqPlayerObject); + bqPlayerObject = NULL; + bqPlayerPlay = NULL; + bqPlayerBufferQueue = NULL; + bqPlayerMuteSolo = NULL; + bqPlayerVolume = NULL; + } + if (outputMixObject != NULL) { + (*outputMixObject)->Destroy(outputMixObject); + outputMixObject = NULL; + } + if (engineObject != NULL) { + (*engineObject)->Destroy(engineObject); + engineObject = NULL; + engineEngine = NULL; + } +} +#endif diff --git a/Source/Core/AudioCommon/Src/OpenSLESStream.h b/Source/Core/AudioCommon/Src/OpenSLESStream.h new file mode 100644 index 0000000000..f49160c4bc --- /dev/null +++ b/Source/Core/AudioCommon/Src/OpenSLESStream.h @@ -0,0 +1,48 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#ifndef _OPENSLSTREAM_H_ +#define _OPENSLSTREAM_H_ + +#include "Thread.h" +#include "SoundStream.h" + +class OpenSLESStream : public SoundStream +{ +#ifdef ANDROID +public: + OpenSLESStream(CMixer *mixer, void *hWnd = NULL) + : SoundStream(mixer) + {}; + + virtual ~OpenSLESStream() {}; + + virtual bool Start(); + virtual void Stop(); + static bool isValid() { return true; } + virtual bool usesMixer() const { return true; } + +private: + std::thread thread; + Common::Event soundSyncEvent; +#else +public: + OpenSLESStream(CMixer *mixer, void *hWnd = NULL): SoundStream(mixer) {} +#endif // HAVE_OPENSL +}; + +#endif diff --git a/Source/Core/Common/CMakeLists.txt b/Source/Core/Common/CMakeLists.txt index 92d2bec668..480a08a0fc 100644 --- a/Source/Core/Common/CMakeLists.txt +++ b/Source/Core/Common/CMakeLists.txt @@ -1,9 +1,7 @@ -set(SRCS Src/ABI.cpp - Src/BreakPoints.cpp +set(SRCS Src/BreakPoints.cpp Src/CDUtils.cpp Src/ColorUtil.cpp Src/ConsoleListener.cpp - Src/CPUDetect.cpp Src/FileSearch.cpp Src/FileUtil.cpp Src/Hash.cpp @@ -20,10 +18,10 @@ set(SRCS Src/ABI.cpp Src/SymbolDB.cpp Src/SysConf.cpp Src/Thread.cpp - Src/Thunk.cpp Src/Timer.cpp Src/Version.cpp Src/VideoBackendBase.cpp + Src/x64ABI.cpp Src/x64Analyzer.cpp Src/x64Emitter.cpp Src/Crypto/aes_cbc.cpp @@ -33,6 +31,23 @@ set(SRCS Src/ABI.cpp Src/Crypto/md5.cpp Src/Crypto/sha1.cpp) +if(_M_ARM) #ARM + set(SRCS ${SRCS} + Src/ArmCPUDetect.cpp + Src/ArmEmitter.cpp) +else() + if(NOT _M_GENERIC) #X86 + set(SRCS ${SRCS} + Src/x64FPURoundMode.cpp + Src/x64Thunk.cpp + ) + endif() + set(SRCS ${SRCS} Src/x64CPUDetect.cpp) +endif() +if(_M_GENERIC) #Generic + set(SRCS ${SRCS} + Src/GenericFPURoundMode.cpp) +endif() if(WIN32) set(SRCS ${SRCS} Src/ExtendedTrace.cpp) endif(WIN32) diff --git a/Source/Core/Common/Common.vcxproj b/Source/Core/Common/Common.vcxproj index 0128a75a09..822fafe74b 100644 --- a/Source/Core/Common/Common.vcxproj +++ b/Source/Core/Common/Common.vcxproj @@ -44,7 +44,7 @@ false StaticLibrary - MultiByte + Unicode StaticLibrary @@ -54,7 +54,7 @@ false StaticLibrary - MultiByte + Unicode StaticLibrary @@ -158,12 +158,10 @@ - - @@ -195,15 +193,17 @@ - + + + + - @@ -251,6 +251,7 @@ + diff --git a/Source/Core/Common/Common.vcxproj.filters b/Source/Core/Common/Common.vcxproj.filters index 8b05ecbba4..d427b70cdd 100644 --- a/Source/Core/Common/Common.vcxproj.filters +++ b/Source/Core/Common/Common.vcxproj.filters @@ -1,11 +1,9 @@  - - @@ -23,7 +21,6 @@ - @@ -53,9 +50,12 @@ Crypto + + + + - @@ -121,6 +121,7 @@ + diff --git a/Source/Core/Common/Src/ArmCPUDetect.cpp b/Source/Core/Common/Src/ArmCPUDetect.cpp new file mode 100644 index 0000000000..8b5cbf9b79 --- /dev/null +++ b/Source/Core/Common/Src/ArmCPUDetect.cpp @@ -0,0 +1,161 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "Common.h" +#include "CPUDetect.h" +#include "StringUtil.h" +#include "FileUtil.h" + +const char procfile[] = "/proc/cpuinfo"; + +char *GetCPUString() +{ + const char marker[] = "Hardware\t: "; + char *cpu_string = 0; + // Count the number of processor lines in /proc/cpuinfo + char buf[1024]; + + File::IOFile file(procfile, "r"); + auto const fp = file.GetHandle(); + if (!fp) + return 0; + + while (fgets(buf, sizeof(buf), fp)) + { + if (strncmp(buf, marker, sizeof(marker) - 1)) + continue; + cpu_string = buf + sizeof(marker) - 1; + cpu_string = strndup(cpu_string, strlen(cpu_string) - 1); // Strip the newline + break; + } + return cpu_string; +} +bool CheckCPUFeature(const char *feature) +{ + const char marker[] = "Features\t: "; + char buf[1024]; + + File::IOFile file(procfile, "r"); + auto const fp = file.GetHandle(); + if (!fp) + return 0; + + while (fgets(buf, sizeof(buf), fp)) + { + if (strncmp(buf, marker, sizeof(marker) - 1)) + continue; + char *featurestring = buf + sizeof(marker) - 1; + char *token = strtok(featurestring, " "); + while (token != NULL) + { + if (strstr(token, feature)) + return true; + token = strtok(NULL, " "); + } + } + return false; +} +int GetCoreCount() +{ + const char marker[] = "processor\t: "; + int cores = 0; + char buf[1024]; + + File::IOFile file(procfile, "r"); + auto const fp = file.GetHandle(); + if (!fp) + return 0; + + while (fgets(buf, sizeof(buf), fp)) + { + if (strncmp(buf, marker, sizeof(marker) - 1)) + continue; + ++cores; + } + return cores; +} + +CPUInfo cpu_info; + +CPUInfo::CPUInfo() { + Detect(); +} + +// Detects the various cpu features +void CPUInfo::Detect() +{ + // Set some defaults here + // When ARMv8 cpus come out, these need to be updated. + HTT = false; + OS64bit = false; + CPU64bit = false; + Mode64bit = false; + vendor = VENDOR_ARM; + + // Get the information about the CPU + strncpy(cpu_string, GetCPUString(), sizeof(cpu_string)); + num_cores = GetCoreCount(); + bSwp = CheckCPUFeature("swp"); + bHalf = CheckCPUFeature("half"); + bThumb = CheckCPUFeature("thumb"); + bFastMult = CheckCPUFeature("fastmult"); + bVFP = CheckCPUFeature("vfp"); + bEDSP = CheckCPUFeature("edsp"); + bThumbEE = CheckCPUFeature("thumbee"); + bNEON = CheckCPUFeature("neon"); + bVFPv3 = CheckCPUFeature("vfpv3"); + bTLS = CheckCPUFeature("tls"); + bVFPv4 = CheckCPUFeature("vfpv4"); + bIDIVa = CheckCPUFeature("idiva"); + bIDIVt = CheckCPUFeature("idivt"); + // These two are ARMv8 specific. + bFP = CheckCPUFeature("fp"); + bASIMD = CheckCPUFeature("asimd"); + + +#if defined(__ARM_ARCH_7A__) + bArmV7 = true; +#else + bArmV7 = false; +#endif +} + +// Turn the cpu info into a string we can show +std::string CPUInfo::Summarize() +{ + std::string sum; + if (num_cores == 1) + sum = StringFromFormat("%s, %i core", cpu_string, num_cores); + else + sum = StringFromFormat("%s, %i cores", cpu_string, num_cores); + + if (bSwp) sum += ", SWP"; + if (bHalf) sum += ", Half"; + if (bThumb) sum += ", Thumb"; + if (bFastMult) sum += ", FastMult"; + if (bVFP) sum += ", VFP"; + if (bEDSP) sum += ", EDSP"; + if (bThumbEE) sum += ", ThumbEE"; + if (bNEON) sum += ", NEON"; + if (bVFPv3) sum += ", VFPv3"; + if (bTLS) sum += ", TLS"; + if (bVFPv4) sum += ", VFPv4"; + if (bIDIVa) sum += ", IDIVa"; + if (bIDIVt) sum += ", IDIVt"; + + return sum; +} diff --git a/Source/Core/Common/Src/ArmEmitter.cpp b/Source/Core/Common/Src/ArmEmitter.cpp new file mode 100644 index 0000000000..a56724b78b --- /dev/null +++ b/Source/Core/Common/Src/ArmEmitter.cpp @@ -0,0 +1,1066 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "Common.h" +#include "ArmEmitter.h" +#include "CPUDetect.h" + +#include +#include + +// For cache flushing on Symbian/iOS/Blackberry +#ifdef __SYMBIAN32__ +#include +#endif + +#ifdef IOS +#include +#include +#endif + +#ifdef BLACKBERRY +#include +#endif + +namespace ArmGen +{ + +inline u32 RotR(u32 a, int amount) { + if (!amount) return a; + return (a >> amount) | (a << (32 - amount)); +} + +inline u32 RotL(u32 a, int amount) { + if (!amount) return a; + return (a << amount) | (a >> (32 - amount)); +} + +bool TryMakeOperand2(u32 imm, Operand2 &op2) { + // Just brute force it. + for (int i = 0; i < 16; i++) { + int mask = RotR(0xFF, i * 2); + if ((imm & mask) == imm) { + op2 = Operand2((u8)(RotL(imm, i * 2)), (u8)i); + return true; + } + } + return false; +} + +bool TryMakeOperand2_AllowInverse(u32 imm, Operand2 &op2, bool *inverse) +{ + if (!TryMakeOperand2(imm, op2)) { + *inverse = true; + return TryMakeOperand2(~imm, op2); + } else { + *inverse = false; + return true; + } +} + +bool TryMakeOperand2_AllowNegation(s32 imm, Operand2 &op2, bool *negated) +{ + if (!TryMakeOperand2(imm, op2)) { + *negated = true; + return TryMakeOperand2(-imm, op2); + } else { + *negated = false; + return true; + } +} + +void ARMXEmitter::MOVI2R(ARMReg reg, u32 val, bool optimize) +{ + Operand2 op2; + bool inverse; + if (!optimize) + { + // Only used in backpatch atm + // Only support ARMv7 right now + if (cpu_info.bArmV7) { + MOVW(reg, val & 0xFFFF); + MOVT(reg, val, true); + } + else + { + // ARMv6 version won't use backpatch for now + // Run again with optimizations + MOVI2R(reg, val); + } + } else if (TryMakeOperand2_AllowInverse(val, op2, &inverse)) { + if (!inverse) + MOV(reg, op2); + else + MVN(reg, op2); + } else { + if (cpu_info.bArmV7) { + // ARMv7 - can use MOVT/MOVW, best choice + MOVW(reg, val & 0xFFFF); + if(val & 0xFFFF0000) + MOVT(reg, val, true); + } else { + // ARMv6 - fallback sequence. + // TODO: Optimize further. Can for example choose negation etc. + // Literal pools is another way to do this but much more complicated + // so I can't really be bothered for an outdated CPU architecture like ARMv6. + bool first = true; + int shift = 16; + for (int i = 0; i < 4; i++) { + if (val & 0xFF) { + if (first) { + MOV(reg, Operand2((u8)val, (u8)(shift & 0xF))); + first = false; + } else { + ORR(reg, reg, Operand2((u8)val, (u8)(shift & 0xF))); + } + } + shift -= 4; + val >>= 8; + } + } + } +} +// Moves IMM to memory location +void ARMXEmitter::ARMABI_MOVI2M(Operand2 op, Operand2 val) +{ + // This moves imm to a memory location + MOVW(R14, val); MOVT(R14, val, true); + MOVW(R12, op); MOVT(R12, op, true); + STR(R12, R14); // R10 is what we want to store +} +void ARMXEmitter::QuickCallFunction(ARMReg reg, void *func) { + MOVI2R(reg, (u32)(func)); + BL(reg); +} + +void ARMXEmitter::SetCodePtr(u8 *ptr) +{ + code = ptr; + startcode = code; +} + +const u8 *ARMXEmitter::GetCodePtr() const +{ + return code; +} + +u8 *ARMXEmitter::GetWritableCodePtr() +{ + return code; +} + +void ARMXEmitter::ReserveCodeSpace(u32 bytes) +{ + for (u32 i = 0; i < bytes/4; i++) + Write32(0xE1200070); //bkpt 0 +} + +const u8 *ARMXEmitter::AlignCode16() +{ + ReserveCodeSpace((-(s32)code) & 15); + return code; +} + +const u8 *ARMXEmitter::AlignCodePage() +{ + ReserveCodeSpace((-(s32)code) & 4095); + return code; +} + +void ARMXEmitter::FlushIcache() +{ + FlushIcacheSection(lastCacheFlushEnd, code); + lastCacheFlushEnd = code; +} + +void ARMXEmitter::FlushIcacheSection(u8 *start, u8 *end) +{ +#ifdef __SYMBIAN32__ + User::IMB_Range(start, end); +#elif defined(BLACKBERRY) + msync(start, end - start, MS_SYNC | MS_INVALIDATE_ICACHE); +#elif defined(IOS) + sys_cache_control(kCacheFunctionPrepareForExecution, start, end - start); +#elif !defined(_WIN32) +#ifndef ANDROID + start = startcode; +#endif + __builtin___clear_cache(start, end); +#endif +} + +void ARMXEmitter::SetCC(CCFlags cond) +{ + condition = cond << 28; +} + +void ARMXEmitter::NOP(int count) +{ + for (int i = 0; i < count; i++) { + Write32(condition | 0x01A00000); + } +} + +void ARMXEmitter::SETEND(bool BE) +{ + //SETEND is non-conditional + Write32( 0xF1010000 | (BE << 9)); +} +void ARMXEmitter::BKPT(u16 arg) +{ + Write32(condition | 0x01200070 | (arg << 4 & 0x000FFF00) | (arg & 0x0000000F)); +} +void ARMXEmitter::YIELD() +{ + Write32(condition | 0x0320F001); +} + +FixupBranch ARMXEmitter::B() +{ + FixupBranch branch; + branch.type = 0; // Zero for B + branch.ptr = code; + branch.condition = condition; + //We'll write NOP here for now. + Write32(condition | 0x01A00000); + return branch; +} +FixupBranch ARMXEmitter::BL() +{ + FixupBranch branch; + branch.type = 1; // Zero for B + branch.ptr = code; + branch.condition = condition; + //We'll write NOP here for now. + Write32(condition | 0x01A00000); + return branch; +} + +FixupBranch ARMXEmitter::B_CC(CCFlags Cond) +{ + FixupBranch branch; + branch.type = 0; // Zero for B + branch.ptr = code; + branch.condition = Cond << 28; + //We'll write NOP here for now. + Write32(condition | 0x01A00000); + return branch; +} +void ARMXEmitter::B_CC(CCFlags Cond, const void *fnptr) +{ + s32 distance = (s32)fnptr - (s32(code) + 8); + _assert_msg_(DYNA_REC, distance > -33554432 + && distance <= 33554432, + "B_CC out of range (%p calls %p)", code, fnptr); + + Write32((Cond << 28) | 0x0A000000 | ((distance >> 2) & 0x00FFFFFF)); +} +FixupBranch ARMXEmitter::BL_CC(CCFlags Cond) +{ + FixupBranch branch; + branch.type = 1; // Zero for B + branch.ptr = code; + branch.condition = Cond << 28; + //We'll write NOP here for now. + Write32(condition | 0x01A00000); + return branch; +} +void ARMXEmitter::SetJumpTarget(FixupBranch const &branch) +{ + s32 distance = (s32(code) - 8) - (s32)branch.ptr; + _assert_msg_(DYNA_REC, distance > -33554432 + && distance <= 33554432, + "SetJumpTarget out of range (%p calls %p)", code, + branch.ptr); + if(branch.type == 0) // B + *(u32*)branch.ptr = (u32)(branch.condition | (10 << 24) | ((distance >> 2) & + 0x00FFFFFF)); + else // BL + *(u32*)branch.ptr = (u32)(branch.condition | 0x0B000000 | ((distance >> 2) + & 0x00FFFFFF)); +} +void ARMXEmitter::B (const void *fnptr) +{ + s32 distance = (s32)fnptr - (s32(code) + 8); + _assert_msg_(DYNA_REC, distance > -33554432 + && distance <= 33554432, + "B out of range (%p calls %p)", code, fnptr); + + Write32(condition | 0x0A000000 | ((distance >> 2) & 0x00FFFFFF)); +} + +void ARMXEmitter::B(ARMReg src) +{ + Write32(condition | 0x12FFF10 | src); +} + +void ARMXEmitter::BL(const void *fnptr) +{ + s32 distance = (s32)fnptr - (s32(code) + 8); + _assert_msg_(DYNA_REC, distance > -33554432 + && distance <= 33554432, + "BL out of range (%p calls %p)", code, fnptr); + Write32(condition | 0x0B000000 | ((distance >> 2) & 0x00FFFFFF)); +} +void ARMXEmitter::BL(ARMReg src) +{ + Write32(condition | 0x12FFF30 | src); +} +void ARMXEmitter::PUSH(const int num, ...) +{ + u16 RegList = 0; + u8 Reg; + int i; + va_list vl; + va_start(vl, num); + for (i=0;i> 16 : Rm); } + +void ARMXEmitter::WriteInstruction (u32 Op, ARMReg Rd, ARMReg Rn, Operand2 Rm, bool SetFlags) // This can get renamed later +{ + s32 op = InstOps[Op][Rm.GetType()]; // Type always decided by last operand + u32 Data = Rm.GetData(); + if (Rm.GetType() == TYPE_IMM) + { + switch (Op) + { + // MOV cases that support IMM16 + case 16: + case 17: + Data = Rm.Imm16(); + break; + default: + break; + } + } + if (op == -1) + _assert_msg_(DYNA_REC, false, "%s not yet support %d", InstNames[Op], Rm.GetType()); + Write32(condition | (op << 21) | (SetFlags ? (1 << 20) : 0) | Rn << 16 | Rd << 12 | Data); +} + +// Data Operations +void ARMXEmitter::WriteSignedMultiply(u32 Op, u32 Op2, u32 Op3, ARMReg dest, ARMReg r1, ARMReg r2) +{ + Write32(condition | (0x7 << 24) | (Op << 20) | (dest << 16) | (Op2 << 12) | (r1 << 8) | (Op3 << 5) | (1 << 4) | r2); +} +void ARMXEmitter::UDIV(ARMReg dest, ARMReg dividend, ARMReg divisor) +{ + if (!cpu_info.bIDIVa) + PanicAlert("Trying to use integer divide on hardware that doesn't support it. Bad programmer."); + WriteSignedMultiply(3, 0xF, 0, dest, divisor, dividend); +} +void ARMXEmitter::SDIV(ARMReg dest, ARMReg dividend, ARMReg divisor) +{ + if (!cpu_info.bIDIVa) + PanicAlert("Trying to use integer divide on hardware that doesn't support it. Bad programmer."); + WriteSignedMultiply(1, 0xF, 0, dest, divisor, dividend); +} +void ARMXEmitter::LSL (ARMReg dest, ARMReg src, Operand2 op2) { WriteShiftedDataOp(0, false, dest, src, op2);} +void ARMXEmitter::LSLS(ARMReg dest, ARMReg src, Operand2 op2) { WriteShiftedDataOp(0, true, dest, src, op2);} +void ARMXEmitter::LSL (ARMReg dest, ARMReg src, ARMReg op2) { WriteShiftedDataOp(1, false, dest, src, op2);} +void ARMXEmitter::LSLS(ARMReg dest, ARMReg src, ARMReg op2) { WriteShiftedDataOp(1, true, dest, src, op2);} +void ARMXEmitter::MUL (ARMReg dest, ARMReg src, ARMReg op2) +{ + Write32(condition | (dest << 16) | (src << 8) | (9 << 4) | op2); +} +void ARMXEmitter::MULS(ARMReg dest, ARMReg src, ARMReg op2) +{ + Write32(condition | (1 << 20) | (dest << 16) | (src << 8) | (9 << 4) | op2); +} + +void ARMXEmitter::Write4OpMultiply(u32 op, ARMReg destLo, ARMReg destHi, ARMReg rm, ARMReg rn) { + Write32(condition | (op << 20) | (destHi << 16) | (destLo << 12) | (rm << 8) | (9 << 4) | rn); +} + +void ARMXEmitter::UMULL(ARMReg destLo, ARMReg destHi, ARMReg rm, ARMReg rn) +{ + Write4OpMultiply(0x8, destLo, destHi, rn, rm); +} + +void ARMXEmitter::SMULL(ARMReg destLo, ARMReg destHi, ARMReg rm, ARMReg rn) +{ + Write4OpMultiply(0xC, destLo, destHi, rn, rm); +} + +void ARMXEmitter::SXTB (ARMReg dest, ARMReg op2) +{ + Write32(condition | (0x6AF << 16) | (dest << 12) | (7 << 4) | op2); +} +void ARMXEmitter::SXTH (ARMReg dest, ARMReg op2, u8 rotation) +{ + SXTAH(dest, (ARMReg)15, op2, rotation); +} +void ARMXEmitter::SXTAH(ARMReg dest, ARMReg src, ARMReg op2, u8 rotation) +{ + // bits ten and 11 are the rotation amount, see 8.8.232 for more + // information + Write32(condition | (0x6B << 20) | (src << 16) | (dest << 12) | (rotation << 10) | (7 << 4) | op2); +} +void ARMXEmitter::REV (ARMReg dest, ARMReg src ) +{ + Write32(condition | (107 << 20) | (15 << 16) | (dest << 12) | (243 << 4) | src); +} +void ARMXEmitter::REV16(ARMReg dest, ARMReg src) +{ + Write32(condition | (0x3DF << 16) | (dest << 12) | (0xFD << 4) | src); +} + +void ARMXEmitter::_MSR (bool write_nzcvq, bool write_g, Operand2 op2) +{ + Write32(condition | (0x320F << 12) | (write_nzcvq << 19) | (write_g << 18) | op2.Imm12Mod()); +} +void ARMXEmitter::_MSR (bool write_nzcvq, bool write_g, ARMReg src) +{ + Write32(condition | (0x120F << 12) | (write_nzcvq << 19) | (write_g << 18) | src); +} +void ARMXEmitter::MRS (ARMReg dest) +{ + Write32(condition | (16 << 20) | (15 << 16) | (dest << 12)); +} + +void ARMXEmitter::WriteStoreOp(u32 op, ARMReg dest, ARMReg src, s16 op2) +{ + bool Index = op2 != 0 ? true : false; + bool Add = op2 >= 0 ? true : false; + u32 imm = abs(op2); + Write32(condition | (op << 20) | (Index << 24) | (Add << 23) | (dest << 16) | (src << 12) | imm); +} +void ARMXEmitter::STR (ARMReg dest, ARMReg src, s16 op) { WriteStoreOp(0x40, dest, src, op);} +void ARMXEmitter::STRB(ARMReg dest, ARMReg src, s16 op) { WriteStoreOp(0x44, dest, src, op);} +void ARMXEmitter::STR (ARMReg dest, ARMReg base, ARMReg offset, bool Index, bool Add) +{ + Write32(condition | (0x60 << 20) | (Index << 24) | (Add << 23) | (dest << 16) | (base << 12) | offset); +} +void ARMXEmitter::LDREX(ARMReg dest, ARMReg base) +{ + Write32(condition | (25 << 20) | (base << 16) | (dest << 12) | 0xF9F); +} +void ARMXEmitter::STREX(ARMReg dest, ARMReg base, ARMReg op) +{ + _assert_msg_(DYNA_REC, (dest != base && dest != op), "STREX dest can't be other two registers"); + Write32(condition | (24 << 20) | (base << 16) | (dest << 12) | (0xF9 << 4) | op); +} +void ARMXEmitter::DMB () +{ + Write32(0xF57FF05E); +} +void ARMXEmitter::SVC(Operand2 op) +{ + Write32(condition | (0x0F << 24) | op.Imm24()); +} + +void ARMXEmitter::LDR (ARMReg dest, ARMReg src, s16 op) { WriteStoreOp(0x41, src, dest, op);} +void ARMXEmitter::LDRH(ARMReg dest, ARMReg src, Operand2 op) +{ + u8 Imm = op.Imm8(); + Write32(condition | (0x05 << 20) | (src << 16) | (dest << 12) | ((Imm >> 4) << 8) | (0xB << 4) | (Imm & 0x0F)); +} +void ARMXEmitter::LDRB(ARMReg dest, ARMReg src, s16 op) { WriteStoreOp(0x45, src, dest, op);} + +void ARMXEmitter::LDR (ARMReg dest, ARMReg base, ARMReg offset, bool Index, bool Add) +{ + Write32(condition | (0x61 << 20) | (Index << 24) | (Add << 23) | (base << 16) | (dest << 12) | offset); +} +void ARMXEmitter::WriteRegStoreOp(u32 op, ARMReg dest, bool WriteBack, u16 RegList) +{ + Write32(condition | (op << 20) | (WriteBack << 21) | (dest << 16) | RegList); +} +void ARMXEmitter::STMFD(ARMReg dest, bool WriteBack, const int Regnum, ...) +{ + u16 RegList = 0; + u8 Reg; + int i; + va_list vl; + va_start(vl, Regnum); + for (i=0;i= S0) + { + if (Reg >= D0) + { + if (Reg >= Q0) + return (ARMReg)((Reg - Q0) * 2); // Always gets encoded as a double register + return (ARMReg)(Reg - D0); + } + return (ARMReg)(Reg - S0); + } + return Reg; +} + +// NEON Specific +void ARMXEmitter::VADD(IntegerSize Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to VADD(integer)"); + _assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use VADD(integer) when CPU doesn't support it"); + + bool register_quad = Vd >= Q0; + + // Gets encoded as a double register + Vd = SubBase(Vd); + Vn = SubBase(Vn); + Vm = SubBase(Vm); + + Write32((0xF2 << 24) | ((Vd & 0x10) << 18) | (Size << 20) | ((Vn & 0xF) << 16) \ + | ((Vd & 0xF) << 12) | (0x8 << 8) | ((Vn & 0x10) << 3) | (register_quad << 6) \ + | ((Vm & 0x10) << 2) | (Vm & 0xF)); + +} +void ARMXEmitter::VSUB(IntegerSize Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _assert_msg_(DYNA_REC, Vd >= Q0, "Pass invalid register to VSUB(integer)"); + _assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use VSUB(integer) when CPU doesn't support it"); + + // Gets encoded as a double register + Vd = SubBase(Vd); + Vn = SubBase(Vn); + Vm = SubBase(Vm); + + Write32((0xF3 << 24) | ((Vd & 0x10) << 18) | (Size << 20) | ((Vn & 0xF) << 16) \ + | ((Vd & 0xF) << 12) | (0x8 << 8) | ((Vn & 0x10) << 3) | (1 << 6) \ + | ((Vm & 0x10) << 2) | (Vm & 0xF)); +} + +// VFP Specific + +void ARMXEmitter::VLDR(ARMReg Dest, ARMReg Base, s16 offset) +{ + _assert_msg_(DYNA_REC, Dest >= S0 && Dest <= D31, "Passed Invalid dest register to VLDR"); + _assert_msg_(DYNA_REC, Base <= R15, "Passed invalid Base register to VLDR"); + + bool Add = offset >= 0 ? true : false; + u32 imm = abs(offset); + + _assert_msg_(DYNA_REC, (imm & 0xC03) == 0, "VLDR: Offset needs to be word aligned and small enough"); + + if (imm & 0xC03) { + ERROR_LOG(DYNA_REC, "VLDR: Bad offset %08x", imm); + } + + bool single_reg = Dest < D0; + + Dest = SubBase(Dest); + + if (single_reg) + { + Write32(NO_COND | (0xD << 24) | (Add << 23) | ((Dest & 0x1) << 22) | (1 << 20) | (Base << 16) \ + | ((Dest & 0x1E) << 11) | (10 << 8) | (imm >> 2)); + + } + else + { + Write32(NO_COND | (0xD << 24) | (Add << 23) | ((Dest & 0x10) << 18) | (1 << 20) | (Base << 16) \ + | ((Dest & 0xF) << 12) | (11 << 8) | (imm >> 2)); + } +} +void ARMXEmitter::VSTR(ARMReg Src, ARMReg Base, s16 offset) +{ + _assert_msg_(DYNA_REC, Src >= S0 && Src <= D31, "Passed invalid src register to VSTR"); + _assert_msg_(DYNA_REC, Base <= R15, "Passed invalid base register to VSTR"); + + bool Add = offset >= 0 ? true : false; + u32 imm = abs(offset); + + _assert_msg_(DYNA_REC, (imm & 0xC03) == 0, "VSTR: Offset needs to be word aligned and small enough"); + + if (imm & 0xC03) { + ERROR_LOG(DYNA_REC, "VSTR: Bad offset %08x", imm); + } + + bool single_reg = Src < D0; + + Src = SubBase(Src); + + if (single_reg) + { + Write32(NO_COND | (0xD << 24) | (Add << 23) | ((Src & 0x1) << 22) | (Base << 16) \ + | ((Src & 0x1E) << 11) | (10 << 8) | (imm >> 2)); + + } + else + { + Write32(NO_COND | (0xD << 24) | (Add << 23) | ((Src & 0x10) << 18) | (Base << 16) \ + | ((Src & 0xF) << 12) | (11 << 8) | (imm >> 2)); + } +} +void ARMXEmitter::VCMP(ARMReg Vd, ARMReg Vm) +{ + _assert_msg_(DYNA_REC, Vd < Q0, "Passed invalid Vd to VCMP"); + bool single_reg = Vd < D0; + + Vd = SubBase(Vd); + Vm = SubBase(Vm); + + if (single_reg) + { + Write32(NO_COND | (0x1D << 23) | ((Vd & 0x1) << 22) | (0x34 << 16) | ((Vd & 0x1E) << 11) \ + | (0x2B << 6) | ((Vm & 0x1) << 5) | (Vm >> 1)); + } + else + { + Write32(NO_COND | (0x1D << 23) | ((Vd & 0x10) << 18) | (0x34 << 16) | ((Vd & 0xF) << 12) \ + | (0x2F << 6) | ((Vm & 0x10) << 1) | (Vm & 0xF)); + } +} +void ARMXEmitter::VCMP(ARMReg Vd) +{ + _assert_msg_(DYNA_REC, Vd < Q0, "Passed invalid Vd to VCMP"); + bool single_reg = Vd < D0; + + Vd = SubBase(Vd); + + if (single_reg) + { + Write32(NO_COND | (0x1D << 23) | ((Vd & 0x1) << 22) | (0x35 << 16) | ((Vd & 0x1E) << 11) \ + | (0x2B << 6)); + } + else + { + Write32(NO_COND | (0x1D << 23) | ((Vd & 0x10) << 18) | (0x35 << 16) | ((Vd & 0xF) << 12) \ + | (0x2F << 6)); + } +} +void ARMXEmitter::VDIV(ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _assert_msg_(DYNA_REC, Vd < Q0, "Pased invalid dest register to VSQRT"); + _assert_msg_(DYNA_REC, Vn < Q0, "Passed invalid Vn to VSQRT"); + _assert_msg_(DYNA_REC, Vm < Q0, "Passed invalid Vm to VSQRT"); + bool single_reg = Vd < D0; + + Vd = SubBase(Vd); + Vn = SubBase(Vn); + Vm = SubBase(Vm); + + if (single_reg) + { + Write32(NO_COND | (0x1D << 23) | ((Vd & 0x1) << 22) | ((Vn & 0x1E) << 15) \ + | ((Vd & 0x1E) << 11) | (0xA << 8) | ((Vn & 0x1) << 7) | ((Vm & 0x1) << 5) \ + | (Vm >> 1)); + } + else + { + Write32(NO_COND | (0x1D << 23) | ((Vd & 0x10) << 18) | ((Vn & 0xF) << 16) \ + | ((Vd & 0xF) << 12) | (0xB << 8) | ((Vn & 0x10) << 3) | ((Vm & 0x10) << 2) \ + | (Vm & 0xF)); + } +} +void ARMXEmitter::VSQRT(ARMReg Vd, ARMReg Vm) +{ + _assert_msg_(DYNA_REC, Vd < Q0, "Pased invalid dest register to VSQRT"); + _assert_msg_(DYNA_REC, Vm < Q0, "Passed invalid Vm to VSQRT"); + bool single_reg = Vd < D0; + + Vd = SubBase(Vd); + Vm = SubBase(Vm); + + if (single_reg) + { + Write32(NO_COND | (0x1D << 23) | ((Vd & 0x1) << 22) | (0x31 << 16) \ + | ((Vd & 0x1E) << 11) | (0x2B << 6) | ((Vm & 0x1) << 5) | (Vm >> 1)); + } + else + { + Write32(NO_COND | (0x1D << 23) | ((Vd & 0x10) << 18) | (0x31 << 16) \ + | ((Vd & 0xF) << 12) | (0x2F << 6) | ((Vm & 0x10) << 2) | (Vm & 0xF)); + } +} + +// VFP and ASIMD +void ARMXEmitter::VABS(ARMReg Vd, ARMReg Vm) +{ + _assert_msg_(DYNA_REC, Vd < Q0, "VABS doesn't currently support Quad reg"); + _assert_msg_(DYNA_REC, Vd >= S0, "VABS doesn't support ARM Regs"); + bool single_reg = Vd < D0; + bool double_reg = Vd < Q0; + + Vd = SubBase(Vd); + Vm = SubBase(Vm); + + if (single_reg) + { + Write32(NO_COND | (0xEB << 20) | ((Vd & 0x1) << 22) | ((Vd & 0x1E) << 11) \ + | (0xAC << 4) | ((Vm & 0x1) << 5) | (Vm >> 1)); + } + else + { + if (double_reg) + { + Write32(NO_COND | (0xEB << 20) | ((Vd & 0x10) << 18) | ((Vd & 0xF) << 12) \ + | (0xBC << 4) | ((Vm & 0x10) << 1) | (Vm & 0xF)); + } + else + { + _assert_msg_(DYNA_REC, cpu_info.bNEON, "Trying to use VADD with Quad Reg without support!"); + // XXX: TODO + } + } +} + +void ARMXEmitter::VADD(ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _assert_msg_(DYNA_REC, Vd >= S0, "Passed invalid dest register to VADD"); + _assert_msg_(DYNA_REC, Vn >= S0, "Passed invalid Vn to VADD"); + _assert_msg_(DYNA_REC, Vm >= S0, "Passed invalid Vm to VADD"); + bool single_reg = Vd < D0; + bool double_reg = Vd < Q0; + + Vd = SubBase(Vd); + Vn = SubBase(Vn); + Vm = SubBase(Vm); + + if (single_reg) + { + Write32(NO_COND | (0x1C << 23) | ((Vd & 0x1) << 22) | (0x3 << 20) \ + | ((Vn & 0x1E) << 15) | ((Vd & 0x1E) << 11) | (0x5 << 9) \ + | ((Vn & 0x1) << 7) | ((Vm & 0x1) << 5) | (Vm >> 1)); + } + else + { + if (double_reg) + { + Write32(NO_COND | (0x1C << 23) | ((Vd & 0x10) << 18) | (0x3 << 20) \ + | ((Vn & 0xF) << 16) | ((Vd & 0xF) << 12) | (0xB << 8) \ + | ((Vn & 0x10) << 3) | ((Vm & 0x10) << 2) | (Vm & 0xF)); + } + else + { + _assert_msg_(DYNA_REC, cpu_info.bNEON, "Trying to use VADD with Quad Reg without support!"); + Write32((0xF2 << 24) | ((Vd & 0x10) << 18) | ((Vn & 0xF) << 16) \ + | ((Vd & 0xF) << 12) | (0xD << 8) | ((Vn & 0x10) << 3) \ + | (1 << 6) | ((Vm & 0x10) << 2) | (Vm & 0xF)); + } + } +} +void ARMXEmitter::VSUB(ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _assert_msg_(DYNA_REC, Vd >= S0, "Passed invalid dest register to VSUB"); + _assert_msg_(DYNA_REC, Vn >= S0, "Passed invalid Vn to VSUB"); + _assert_msg_(DYNA_REC, Vm >= S0, "Passed invalid Vm to VSUB"); + bool single_reg = Vd < D0; + bool double_reg = Vd < Q0; + + Vd = SubBase(Vd); + Vn = SubBase(Vn); + Vm = SubBase(Vm); + + if (single_reg) + { + Write32(NO_COND | (0x1C << 23) | ((Vd & 0x1) << 22) | (0x3 << 20) \ + | ((Vn & 0x1E) << 15) | ((Vd & 0x1E) << 11) | (0x5 << 9) \ + | ((Vn & 0x1) << 7) | (1 << 6) | ((Vm & 0x1) << 5) | (Vm >> 1)); + } + else + { + if (double_reg) + { + Write32(NO_COND | (0x1C << 23) | ((Vd & 0x10) << 18) | (0x3 << 20) \ + | ((Vn & 0xF) << 16) | ((Vd & 0xF) << 12) | (0xB << 8) \ + | ((Vn & 0x10) << 3) | (1 << 6) | ((Vm & 0x10) << 2) | (Vm & 0xF)); + } + else + { + _assert_msg_(DYNA_REC, cpu_info.bNEON, "Trying to use VADD with Quad Reg without support!"); + Write32((0xF2 << 24) | (1 << 21) | ((Vd & 0x10) << 18) | ((Vn & 0xF) << 16) \ + | ((Vd & 0xF) << 12) | (0xD << 8) | ((Vn & 0x10) << 3) \ + | (1 << 6) | ((Vm & 0x10) << 2) | (Vm & 0xF)); + } + } +} +void ARMXEmitter::VMUL(ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _assert_msg_(DYNA_REC, Vd >= S0, "Passed invalid dest register to VADD"); + _assert_msg_(DYNA_REC, Vn >= S0, "Passed invalid Vn to VADD"); + _assert_msg_(DYNA_REC, Vm >= S0, "Passed invalid Vm to VADD"); + bool single_reg = Vd < D0; + bool double_reg = Vd < Q0; + + Vd = SubBase(Vd); + Vn = SubBase(Vn); + Vm = SubBase(Vm); + + if (single_reg) + { + Write32(NO_COND | (0x1C << 23) | ((Vd & 0x1) << 22) | (0x2 << 20) \ + | ((Vn & 0x1E) << 15) | ((Vd & 0x1E) << 11) | (0x5 << 9) \ + | ((Vn & 0x1) << 7) | ((Vm & 0x1) << 5) | (Vm >> 1)); + } + else + { + if (double_reg) + { + Write32(NO_COND | (0x1C << 23) | ((Vd & 0x10) << 18) | (0x2 << 20) \ + | ((Vn & 0xF) << 16) | ((Vd & 0xF) << 12) | (0xB << 8) \ + | ((Vn & 0x10) << 3) | ((Vm & 0x10) << 2) | (Vm & 0xF)); + } + else + { + _assert_msg_(DYNA_REC, cpu_info.bNEON, "Trying to use VMUL with Quad Reg without support!"); + // XXX: TODO + } + } +} + +void ARMXEmitter::VNEG(ARMReg Vd, ARMReg Vm) +{ + _assert_msg_(DYNA_REC, Vd < Q0, "VNEG doesn't currently support Quad reg"); + _assert_msg_(DYNA_REC, Vd >= S0, "VNEG doesn't support ARM Regs"); + bool single_reg = Vd < D0; + bool double_reg = Vd < Q0; + + Vd = SubBase(Vd); + Vm = SubBase(Vm); + + if (single_reg) + { + Write32(NO_COND | (0x1D << 23) | ((Vd & 0x1) << 22) | (0x31 << 16) \ + | ((Vd & 0x1E) << 11) | (0x29 << 6) | ((Vm & 0x1) << 5) | (Vm >> 1)); + } + else + { + if (double_reg) + { + Write32(NO_COND | (0x1D << 23) | ((Vd & 0x10) << 18) | (0x31 << 16) \ + | ((Vd & 0xF) << 12) | (0x2D << 6) | ((Vm & 0x10) << 2) | (Vm & 0xF)); + } + else + { + _assert_msg_(DYNA_REC, cpu_info.bNEON, "Trying to use VNEG with Quad Reg without support!"); + // XXX: TODO + + } + } +} + +void ARMXEmitter::VMOV(ARMReg Dest, ARMReg Src, bool high) +{ + _assert_msg_(DYNA_REC, Src < S0, "This VMOV doesn't support SRC other than ARM Reg"); + _assert_msg_(DYNA_REC, Dest >= D0, "This VMOV doesn't support DEST other than VFP"); + + Dest = SubBase(Dest); + + Write32(NO_COND | (0xE << 24) | (high << 21) | ((Dest & 0xF) << 16) | (Src << 12) \ + | (11 << 8) | ((Dest & 0x10) << 3) | (1 << 4)); +} + +void ARMXEmitter::VMOV(ARMReg Dest, ARMReg Src) +{ + if (Dest > R15) + { + if (Src < S0) + { + if (Dest < D0) + { + // Moving to a Neon register FROM ARM Reg + Dest = (ARMReg)(Dest - S0); + Write32(NO_COND | (0xE0 << 20) | ((Dest & 0x1E) << 15) | (Src << 12) \ + | (0xA << 8) | ((Dest & 0x1) << 7) | (1 << 4)); + return; + } + else + { + // Move 64bit from Arm reg + _assert_msg_(DYNA_REC, false, "This VMOV doesn't support moving 64bit ARM to NEON"); + return; + } + } + } + else + { + if (Src > R15) + { + if (Src < D0) + { + // Moving to ARM Reg from Neon Register + Src = (ARMReg)(Src - S0); + Write32(NO_COND | (0xE1 << 20) | ((Src & 0x1E) << 15) | (Dest << 12) \ + | (0xA << 8) | ((Src & 0x1) << 7) | (1 << 4)); + return; + } + else + { + // Move 64bit To Arm reg + _assert_msg_(DYNA_REC, false, "This VMOV doesn't support moving 64bit ARM From NEON"); + return; + } + } + else + { + // Move Arm reg to Arm reg + _assert_msg_(DYNA_REC, false, "VMOV doesn't support moving ARM registers"); + } + } + // Moving NEON registers + int SrcSize = Src < D0 ? 1 : Src < Q0 ? 2 : 4; + int DestSize = Dest < D0 ? 1 : Dest < Q0 ? 2 : 4; + bool Single = DestSize == 1; + bool Quad = DestSize == 4; + + _assert_msg_(DYNA_REC, SrcSize == DestSize, "VMOV doesn't support moving different register sizes"); + + Dest = SubBase(Dest); + Src = SubBase(Src); + + if (Single) + { + Write32(NO_COND | (0x1D << 23) | ((Dest & 0x1) << 22) | (0x3 << 20) | ((Dest & 0x1E) << 11) \ + | (0x5 << 9) | (1 << 6) | ((Src & 0x1) << 5) | ((Src & 0x1E) >> 1)); + } + else + { + // Double and quad + if (Quad) + { + _assert_msg_(DYNA_REC, cpu_info.bNEON, "Trying to use quad registers when you don't support ASIMD."); + // Gets encoded as a Double register + Write32((0xF2 << 24) | ((Dest & 0x10) << 18) | (2 << 20) | ((Src & 0xF) << 16) \ + | ((Dest & 0xF) << 12) | (1 << 8) | ((Src & 0x10) << 3) | (1 << 6) \ + | ((Src & 0x10) << 1) | (1 << 4) | (Src & 0xF)); + + } + else + { + Write32(NO_COND | (0x1D << 23) | ((Dest & 0x10) << 18) | (0x3 << 20) | ((Dest & 0xF) << 12) \ + | (0x2D << 6) | ((Src & 0x10) << 1) | (Src & 0xF)); + } + } +} + +} diff --git a/Source/Core/Common/Src/ArmEmitter.h b/Source/Core/Common/Src/ArmEmitter.h new file mode 100644 index 0000000000..d3155285f3 --- /dev/null +++ b/Source/Core/Common/Src/ArmEmitter.h @@ -0,0 +1,589 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +// WARNING - THIS LIBRARY IS NOT THREAD SAFE!!! + +#ifndef _DOLPHIN_ARM_CODEGEN_ +#define _DOLPHIN_ARM_CODEGEN_ + +#include "Common.h" +#include "MemoryUtil.h" +#if defined(__SYMBIAN32__) || defined(PANDORA) +#include +#endif + +#undef _IP +#undef R0 +#undef _SP +#undef _LR +#undef _PC + +namespace ArmGen +{ +enum ARMReg +{ + // GPRs + R0 = 0, R1, R2, R3, R4, R5, + R6, R7, R8, R9, R10, R11, + + // SPRs + // R13 - R15 are SP, LR, and PC. + // Almost always referred to by name instead of register number + R12 = 12, R13 = 13, R14 = 14, R15 = 15, + _IP = 12, _SP = 13, _LR = 14, _PC = 15, + + + // VFP single precision registers + S0, S1, S2, S3, S4, S5, S6, + S7, S8, S9, S10, S11, S12, S13, + S14, S15, S16, S17, S18, S19, S20, + S21, S22, S23, S24, S25, S26, S27, + S28, S29, S30, S31, + + // VFP Double Precision registers + D0, D1, D2, D3, D4, D5, D6, D7, + D8, D9, D10, D11, D12, D13, D14, D15, + D16, D17, D18, D19, D20, D21, D22, D23, + D24, D25, D26, D27, D28, D29, D30, D31, + + // ASIMD Quad-Word registers + Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, + Q8, Q9, Q10, Q11, Q12, Q13, Q14, Q15, + INVALID_REG = 0xFFFFFFFF +}; + +enum CCFlags +{ + CC_EQ = 0, // Equal + CC_NEQ, // Not equal + CC_CS, // Carry Set + CC_CC, // Carry Clear + CC_MI, // Minus (Negative) + CC_PL, // Plus + CC_VS, // Overflow + CC_VC, // No Overflow + CC_HI, // Unsigned higher + CC_LS, // Unsigned lower or same + CC_GE, // Signed greater than or equal + CC_LT, // Signed less than + CC_GT, // Signed greater than + CC_LE, // Signed less than or equal + CC_AL, // Always (unconditional) 14 + CC_HS = CC_CS, // Alias of CC_CS Unsigned higher or same + CC_LO = CC_CC, // Alias of CC_CC Unsigned lower +}; +const u32 NO_COND = 0xE0000000; + +enum ShiftType +{ + ST_LSL = 0, + ST_ASL = 0, + ST_LSR = 1, + ST_ASR = 2, + ST_ROR = 3, + ST_RRX = 4 +}; +enum IntegerSize +{ + I_I8 = 0, + I_I16, + I_I32, + I_I64 +}; + +enum +{ + NUMGPRs = 13, +}; + +class ARMXEmitter; + +enum OpType +{ + TYPE_IMM = 0, + TYPE_REG, + TYPE_IMMSREG, + TYPE_RSR, + TYPE_MEM +}; + +// This is no longer a proper operand2 class. Need to split up. +class Operand2 +{ + friend class ARMXEmitter; +protected: + u32 Value; + +private: + OpType Type; + + // IMM types + u8 Rotation; // Only for u8 values + + // Register types + u8 IndexOrShift; + ShiftType Shift; +public: + OpType GetType() + { + return Type; + } + Operand2() {} + Operand2(u32 imm, OpType type = TYPE_IMM) + { + Type = type; + Value = imm; + Rotation = 0; + } + + Operand2(ARMReg Reg) + { + Type = TYPE_REG; + Value = Reg; + Rotation = 0; + } + Operand2(u8 imm, u8 rotation) + { + Type = TYPE_IMM; + Value = imm; + Rotation = rotation; + } + Operand2(ARMReg base, ShiftType type, ARMReg shift) // RSR + { + Type = TYPE_RSR; + _assert_msg_(DYNA_REC, type != ST_RRX, "Invalid Operand2: RRX does not take a register shift amount"); + IndexOrShift = shift; + Shift = type; + Value = base; + } + + Operand2(u8 shift, ShiftType type, ARMReg base)// For IMM shifted register + { + if(shift == 32) shift = 0; + switch (type) + { + case ST_LSL: + _assert_msg_(DYNA_REC, shift < 32, "Invalid Operand2: LSL %u", shift); + break; + case ST_LSR: + _assert_msg_(DYNA_REC, shift <= 32, "Invalid Operand2: LSR %u", shift); + if (!shift) + type = ST_LSL; + if (shift == 32) + shift = 0; + break; + case ST_ASR: + _assert_msg_(DYNA_REC, shift < 32, "Invalid Operand2: LSR %u", shift); + if (!shift) + type = ST_LSL; + if (shift == 32) + shift = 0; + break; + case ST_ROR: + _assert_msg_(DYNA_REC, shift < 32, "Invalid Operand2: ROR %u", shift); + if (!shift) + type = ST_LSL; + break; + case ST_RRX: + _assert_msg_(DYNA_REC, shift == 0, "Invalid Operand2: RRX does not take an immediate shift amount"); + type = ST_ROR; + break; + } + IndexOrShift = shift; + Shift = type; + Value = base; + Type = TYPE_IMMSREG; + } + u32 GetData() + { + switch(Type) + { + case TYPE_IMM: + return Imm12Mod(); // This'll need to be changed later + case TYPE_REG: + return Rm(); + case TYPE_IMMSREG: + return IMMSR(); + case TYPE_RSR: + return RSR(); + default: + _assert_msg_(DYNA_REC, false, "GetData with Invalid Type"); + return 0; + } + } + u32 IMMSR() // IMM shifted register + { + _assert_msg_(DYNA_REC, Type == TYPE_IMMSREG, "IMMSR must be imm shifted register"); + return ((IndexOrShift & 0x1f) << 7 | (Shift << 5) | Value); + } + u32 RSR() // Register shifted register + { + _assert_msg_(DYNA_REC, Type == TYPE_RSR, "RSR must be RSR Of Course"); + return (IndexOrShift << 8) | (Shift << 5) | 0x10 | Value; + } + u32 Rm() + { + _assert_msg_(DYNA_REC, Type == TYPE_REG, "Rm must be with Reg"); + return Value; + } + + u32 Imm5() + { + _assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm5 not IMM value"); + return ((Value & 0x0000001F) << 7); + } + u32 Imm8() + { + _assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm8Rot not IMM value"); + return Value & 0xFF; + } + u32 Imm8Rot() // IMM8 with Rotation + { + _assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm8Rot not IMM value"); + _assert_msg_(DYNA_REC, (Rotation & 0xE1) != 0, "Invalid Operand2: immediate rotation %u", Rotation); + return (1 << 25) | (Rotation << 7) | (Value & 0x000000FF); + } + u32 Imm12() + { + _assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm12 not IMM"); + return (Value & 0x00000FFF); + } + + u32 Imm12Mod() + { + // This is a IMM12 with the top four bits being rotation and the + // bottom eight being a IMM. This is for instructions that need to + // expand a 8bit IMM to a 32bit value and gives you some rotation as + // well. + // Each rotation rotates to the right by 2 bits + _assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm12Mod not IMM"); + return ((Rotation & 0xF) << 8) | (Value & 0xFF); + } + u32 Imm16() + { + _assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm16 not IMM"); + return ( (Value & 0xF000) << 4) | (Value & 0x0FFF); + } + u32 Imm16Low() + { + return Imm16(); + } + u32 Imm16High() // Returns high 16bits + { + _assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm16 not IMM"); + return ( ((Value >> 16) & 0xF000) << 4) | ((Value >> 16) & 0x0FFF); + } + u32 Imm24() + { + _assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm16 not IMM"); + return (Value & 0x0FFFFFFF); + } + // NEON and ASIMD specific + u32 Imm8ASIMD() + { + _assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm8ASIMD not IMM"); + return ((Value & 0x80) << 17) | ((Value & 0x70) << 12) | (Value & 0xF); + } + u32 Imm8VFP() + { + _assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm8VFP not IMM"); + return ((Value & 0xF0) << 12) | (Value & 0xF); + } +}; + +// Use these when you don't know if an imm can be represented as an operand2. +// This lets you generate both an optimal and a fallback solution by checking +// the return value, which will be false if these fail to find a Operand2 that +// represents your 32-bit imm value. +bool TryMakeOperand2(u32 imm, Operand2 &op2); +bool TryMakeOperand2_AllowInverse(u32 imm, Operand2 &op2, bool *inverse); +bool TryMakeOperand2_AllowNegation(s32 imm, Operand2 &op2, bool *negated); + +inline Operand2 R(ARMReg Reg) { return Operand2(Reg, TYPE_REG); } +inline Operand2 IMM(u32 Imm) { return Operand2(Imm, TYPE_IMM); } +inline Operand2 Mem(void *ptr) { return Operand2((u32)ptr, TYPE_IMM); } +//usage: struct {int e;} s; STRUCT_OFFSET(s,e) +#define STRUCT_OFF(str,elem) ((u32)((u32)&(str).elem-(u32)&(str))) + + +struct FixupBranch +{ + u8 *ptr; + u32 condition; // Remembers our codition at the time + int type; //0 = B 1 = BL +}; + +typedef const u8* JumpTarget; + +class ARMXEmitter +{ + friend struct OpArg; // for Write8 etc +private: + u8 *code, *startcode; + u8 *lastCacheFlushEnd; + u32 condition; + + void WriteStoreOp(u32 op, ARMReg dest, ARMReg src, s16 op2); + void WriteRegStoreOp(u32 op, ARMReg dest, bool WriteBack, u16 RegList); + void WriteShiftedDataOp(u32 op, bool SetFlags, ARMReg dest, ARMReg src, ARMReg op2); + void WriteShiftedDataOp(u32 op, bool SetFlags, ARMReg dest, ARMReg src, Operand2 op2); + void WriteSignedMultiply(u32 Op, u32 Op2, u32 Op3, ARMReg dest, ARMReg r1, ARMReg r2); + + + void Write4OpMultiply(u32 op, ARMReg destLo, ARMReg destHi, ARMReg rn, ARMReg rm); + + // New Ops + void WriteInstruction(u32 op, ARMReg Rd, ARMReg Rn, Operand2 Rm, bool SetFlags = false); + +protected: + inline void Write32(u32 value) {*(u32*)code = value; code+=4;} + +public: + ARMXEmitter() : code(0), startcode(0), lastCacheFlushEnd(0) { + condition = CC_AL << 28; + } + ARMXEmitter(u8 *code_ptr) { + code = code_ptr; + lastCacheFlushEnd = code_ptr; + startcode = code_ptr; + condition = CC_AL << 28; + } + virtual ~ARMXEmitter() {} + + void SetCodePtr(u8 *ptr); + void ReserveCodeSpace(u32 bytes); + const u8 *AlignCode16(); + const u8 *AlignCodePage(); + const u8 *GetCodePtr() const; + void FlushIcache(); + void FlushIcacheSection(u8 *start, u8 *end); + u8 *GetWritableCodePtr(); + + void SetCC(CCFlags cond = CC_AL); + + // Special purpose instructions + + // Dynamic Endian Switching + void SETEND(bool BE); + // Debug Breakpoint + void BKPT(u16 arg); + + // Hint instruction + void YIELD(); + + // Do nothing + void NOP(int count = 1); //nop padding - TODO: fast nop slides, for amd and intel (check their manuals) + +#ifdef CALL +#undef CALL +#endif + + // Branching + FixupBranch B(); + FixupBranch B_CC(CCFlags Cond); + void B_CC(CCFlags Cond, const void *fnptr); + FixupBranch BL(); + FixupBranch BL_CC(CCFlags Cond); + void SetJumpTarget(FixupBranch const &branch); + + void B (const void *fnptr); + void B (ARMReg src); + void BL(const void *fnptr); + void BL(ARMReg src); + + void PUSH(const int num, ...); + void POP(const int num, ...); + + // New Data Ops + void AND (ARMReg Rd, ARMReg Rn, Operand2 Rm); + void ANDS(ARMReg Rd, ARMReg Rn, Operand2 Rm); + void EOR (ARMReg dest, ARMReg src, Operand2 op2); + void EORS(ARMReg dest, ARMReg src, Operand2 op2); + void SUB (ARMReg dest, ARMReg src, Operand2 op2); + void SUBS(ARMReg dest, ARMReg src, Operand2 op2); + void RSB (ARMReg dest, ARMReg src, Operand2 op2); + void RSBS(ARMReg dest, ARMReg src, Operand2 op2); + void ADD (ARMReg dest, ARMReg src, Operand2 op2); + void ADDS(ARMReg dest, ARMReg src, Operand2 op2); + void ADC (ARMReg dest, ARMReg src, Operand2 op2); + void ADCS(ARMReg dest, ARMReg src, Operand2 op2); + void LSL (ARMReg dest, ARMReg src, Operand2 op2); + void LSL (ARMReg dest, ARMReg src, ARMReg op2); + void LSLS(ARMReg dest, ARMReg src, Operand2 op2); + void LSLS(ARMReg dest, ARMReg src, ARMReg op2); + void SBC (ARMReg dest, ARMReg src, Operand2 op2); + void SBCS(ARMReg dest, ARMReg src, Operand2 op2); + void REV (ARMReg dest, ARMReg src); + void REV16 (ARMReg dest, ARMReg src); + void RSC (ARMReg dest, ARMReg src, Operand2 op2); + void RSCS(ARMReg dest, ARMReg src, Operand2 op2); + void TST ( ARMReg src, Operand2 op2); + void TEQ ( ARMReg src, Operand2 op2); + void CMP ( ARMReg src, Operand2 op2); + void CMN ( ARMReg src, Operand2 op2); + void ORR (ARMReg dest, ARMReg src, Operand2 op2); + void ORRS(ARMReg dest, ARMReg src, Operand2 op2); + void MOV (ARMReg dest, Operand2 op2); + void MOVS(ARMReg dest, Operand2 op2); + void BIC (ARMReg dest, ARMReg src, Operand2 op2); // BIC = ANDN + void BICS(ARMReg dest, ARMReg src, Operand2 op2); + void MVN (ARMReg dest, Operand2 op2); + void MVNS(ARMReg dest, Operand2 op2); + void MOVW(ARMReg dest, Operand2 op2); + void MOVT(ARMReg dest, Operand2 op2, bool TopBits = false); + + // UDIV and SDIV are only available on CPUs that have + // the idiva hardare capacity + void UDIV(ARMReg dest, ARMReg dividend, ARMReg divisor); + void SDIV(ARMReg dest, ARMReg dividend, ARMReg divisor); + + void MUL (ARMReg dest, ARMReg src, ARMReg op2); + void MULS(ARMReg dest, ARMReg src, ARMReg op2); + + void UMULL(ARMReg destLo, ARMReg destHi, ARMReg rn, ARMReg rm); + void SMULL(ARMReg destLo, ARMReg destHi, ARMReg rn, ARMReg rm); + + void SXTB(ARMReg dest, ARMReg op2); + void SXTH(ARMReg dest, ARMReg op2, u8 rotation = 0); + void SXTAH(ARMReg dest, ARMReg src, ARMReg op2, u8 rotation = 0); + // Using just MSR here messes with our defines on the PPC side of stuff (when this code was in dolphin...) + // Just need to put an underscore here, bit annoying. + void _MSR (bool nzcvq, bool g, Operand2 op2); + void _MSR (bool nzcvq, bool g, ARMReg src ); + void MRS (ARMReg dest); + + // Memory load/store operations + void LDR (ARMReg dest, ARMReg src, s16 op2 = 0); + // Offset adds to the base register in LDR + void LDR (ARMReg dest, ARMReg base, ARMReg offset, bool Index, bool Add); + void LDRH(ARMReg dest, ARMReg src, Operand2 op = 0); + void LDRB(ARMReg dest, ARMReg src, s16 op2 = 0); + void STR (ARMReg dest, ARMReg src, s16 op2 = 0); + // Offset adds on to the destination register in STR + void STR (ARMReg dest, ARMReg base, ARMReg offset, bool Index, bool Add); + + void STRB(ARMReg dest, ARMReg src, s16 op2 = 0); + void STMFD(ARMReg dest, bool WriteBack, const int Regnum, ...); + void LDMFD(ARMReg dest, bool WriteBack, const int Regnum, ...); + + // Exclusive Access operations + void LDREX(ARMReg dest, ARMReg base); + // dest contains the result if the instruction managed to store the value + void STREX(ARMReg dest, ARMReg base, ARMReg op); + void DMB (); + void SVC(Operand2 op); + + // NEON and ASIMD instructions + // None of these will be created with conditional since ARM + // is deprecating conditional execution of ASIMD instructions. + // ASIMD instructions don't even have a conditional encoding. + + // Subtracts the base from the register to give us the real one + ARMReg SubBase(ARMReg Reg); + // NEON Only + void VADD(IntegerSize Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VSUB(IntegerSize Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + + // VFP Only + void VLDR(ARMReg Dest, ARMReg Base, s16 offset); + void VSTR(ARMReg Src, ARMReg Base, s16 offset); + void VCMP(ARMReg Vd, ARMReg Vm); + // Compares against zero + void VCMP(ARMReg Vd); + void VDIV(ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VSQRT(ARMReg Vd, ARMReg Vm); + + // NEON and VFP + void VADD(ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VSUB(ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VABS(ARMReg Vd, ARMReg Vm); + void VNEG(ARMReg Vd, ARMReg Vm); + void VMUL(ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VMOV(ARMReg Dest, ARMReg Src, bool high); + void VMOV(ARMReg Dest, ARMReg Src); + + void QuickCallFunction(ARMReg scratchreg, void *func); + // Utility functions + void MOVI2R(ARMReg reg, u32 val, bool optimize = true); + void ARMABI_MOVI2M(Operand2 op, Operand2 val); +}; // class ARMXEmitter + + +// Everything that needs to generate X86 code should inherit from this. +// You get memory management for free, plus, you can use all the MOV etc functions without +// having to prefix them with gen-> or something similar. +class ARMXCodeBlock : public ARMXEmitter +{ +protected: + u8 *region; + size_t region_size; + +public: + ARMXCodeBlock() : region(NULL), region_size(0) {} + virtual ~ARMXCodeBlock() { if (region) FreeCodeSpace(); } + + // Call this before you generate any code. + void AllocCodeSpace(int size) + { + region_size = size; + region = (u8*)AllocateExecutableMemory(region_size); + SetCodePtr(region); + } + + // Always clear code space with breakpoints, so that if someone accidentally executes + // uninitialized, it just breaks into the debugger. + void ClearCodeSpace() + { + // x86/64: 0xCC = breakpoint + memset(region, 0xCC, region_size); + ResetCodePtr(); + } + + // Call this when shutting down. Don't rely on the destructor, even though it'll do the job. + void FreeCodeSpace() + { + FreeMemoryPages(region, region_size); + region = NULL; + region_size = 0; + } + + bool IsInSpace(u8 *ptr) + { + return ptr >= region && ptr < region + region_size; + } + + // Cannot currently be undone. Will write protect the entire code region. + // Start over if you need to change the code (call FreeCodeSpace(), AllocCodeSpace()). + void WriteProtect() + { + WriteProtectMemory(region, region_size, true); + } + + void ResetCodePtr() + { + SetCodePtr(region); + } + + size_t GetSpaceLeft() const + { + return region_size - (GetCodePtr() - region); + } +}; + +} // namespace + +#endif // _DOLPHIN_INTEL_CODEGEN_ diff --git a/Source/Core/Common/Src/CDUtils.cpp b/Source/Core/Common/Src/CDUtils.cpp index 42aa9bfe34..9a302b9189 100644 --- a/Source/Core/Common/Src/CDUtils.cpp +++ b/Source/Core/Common/Src/CDUtils.cpp @@ -6,6 +6,7 @@ #include // for std::unique_ptr #ifdef _WIN32 #include +#include "StringUtil.h" #elif __APPLE__ #include #include @@ -25,7 +26,7 @@ #ifdef _WIN32 // takes a root drive path, returns true if it is a cdrom drive -bool is_cdrom(const char drive[]) +bool is_cdrom(const TCHAR* drive) { return (DRIVE_CDROM == GetDriveType(drive)); } @@ -36,15 +37,15 @@ std::vector cdio_get_devices() std::vector drives; const DWORD buffsize = GetLogicalDriveStrings(0, NULL); - std::unique_ptr buff(new char[buffsize]); - if (GetLogicalDriveStrings(buffsize, buff.get()) == buffsize - 1) + std::vector buff(buffsize); + if (GetLogicalDriveStrings(buffsize, buff.data()) == buffsize - 1) { - const char* drive = buff.get(); + auto drive = buff.data(); while (*drive) { if (is_cdrom(drive)) { - std::string str(drive); + std::string str(TStrToUTF8(drive)); str.pop_back(); // we don't want the final backslash drives.push_back(std::move(str)); } diff --git a/Source/Core/Common/Src/CPUDetect.h b/Source/Core/Common/Src/CPUDetect.h index 928b34c109..351120e3a2 100644 --- a/Source/Core/Common/Src/CPUDetect.h +++ b/Source/Core/Common/Src/CPUDetect.h @@ -25,7 +25,8 @@ enum CPUVendor { VENDOR_INTEL = 0, VENDOR_AMD = 1, - VENDOR_OTHER = 2, + VENDOR_ARM = 2, + VENDOR_OTHER = 3, }; struct CPUInfo @@ -55,6 +56,26 @@ struct CPUInfo bool bAES; bool bLAHFSAHF64; bool bLongMode; + + // ARM specific CPUInfo + bool bSwp; + bool bHalf; + bool bThumb; + bool bFastMult; + bool bVFP; + bool bEDSP; + bool bThumbEE; + bool bNEON; + bool bVFPv3; + bool bTLS; + bool bVFPv4; + bool bIDIVa; + bool bIDIVt; + bool bArmV7; // enable MOVT, MOVW etc + + // ARMv8 specific + bool bFP; + bool bASIMD; // Call Detect() explicit CPUInfo(); diff --git a/Source/Core/Common/Src/ChunkFile.h b/Source/Core/Common/Src/ChunkFile.h index 38e1b2176c..3c0a58f678 100644 --- a/Source/Core/Common/Src/ChunkFile.h +++ b/Source/Core/Common/Src/ChunkFile.h @@ -29,6 +29,7 @@ #include #include +#include #include #include @@ -45,7 +46,8 @@ struct LinkedListItem : public T class PointerWrap { public: - enum Mode { + enum Mode + { MODE_READ = 1, // load MODE_WRITE, // save MODE_MEASURE, // calculate size @@ -57,124 +59,95 @@ public: public: PointerWrap(u8 **ptr_, Mode mode_) : ptr(ptr_), mode(mode_) {} - PointerWrap(unsigned char **ptr_, int mode_) : ptr((u8**)ptr_), mode((Mode)mode_) {} - void SetMode(Mode mode_) {mode = mode_;} - Mode GetMode() const {return mode;} - u8 **GetPPtr() {return ptr;} + void SetMode(Mode mode_) { mode = mode_; } + Mode GetMode() const { return mode; } + u8** GetPPtr() { return ptr; } - void DoVoid(void *data, int size) + template + void Do(std::map& x) { - switch (mode) { - case MODE_READ: memcpy(data, *ptr, size); break; - case MODE_WRITE: memcpy(*ptr, data, size); break; - case MODE_MEASURE: break; // MODE_MEASURE - don't need to do anything - case MODE_VERIFY: for(int i = 0; i < size; i++) _dbg_assert_msg_(COMMON, ((u8*)data)[i] == (*ptr)[i], "Savestate verification failure: %d (0x%X) (at %p) != %d (0x%X) (at %p).\n", ((u8*)data)[i], ((u8*)data)[i], &((u8*)data)[i], (*ptr)[i], (*ptr)[i], &(*ptr)[i]); break; - default: break; // throw an error? - } - (*ptr) += size; - } - - template - void Do(std::map &x) - { - unsigned int number = (unsigned int)x.size(); - Do(number); - switch (mode) { + u32 count = (u32)x.size(); + Do(count); + + switch (mode) + { case MODE_READ: + for (x.clear(); count != 0; --count) { - x.clear(); - while (number > 0) - { - unsigned int first = 0; - Do(first); - T second; - Do(second); - x[first] = second; - --number; - } + std::pair pair; + Do(pair.first); + Do(pair.second); + x.insert(pair); } break; + case MODE_WRITE: case MODE_MEASURE: case MODE_VERIFY: + for (auto itr = x.begin(); itr != x.end(); ++itr) { - typename std::map::iterator itr = x.begin(); - while (number > 0) - { - Do(itr->first); - Do(itr->second); - --number; - ++itr; - } + Do(itr->first); + Do(itr->second); } break; } } - - // Store vectors. - template - void Do(std::vector &x) - { - u32 vec_size = (u32)x.size(); - Do(vec_size); - x.resize(vec_size); - DoArray(&x[0], vec_size); - } - // Store deques. - template - void Do(std::deque &x) + template + void DoContainer(T& x) { - u32 deq_size = (u32)x.size(); - Do(deq_size); - x.resize(deq_size); - u32 i; - for(i = 0; i < deq_size; i++) - DoVoid(&x[i],sizeof(T)); - } - - // Store strings. - void Do(std::string &x) - { - int stringLen = (int)x.length() + 1; - Do(stringLen); + u32 size = (u32)x.size(); + Do(size); + x.resize(size); - switch (mode) { - case MODE_READ: x = (char*)*ptr; break; - case MODE_WRITE: memcpy(*ptr, x.c_str(), stringLen); break; - case MODE_MEASURE: break; - case MODE_VERIFY: _dbg_assert_msg_(COMMON, !strcmp(x.c_str(), (char*)*ptr), "Savestate verification failure: \"%s\" != \"%s\" (at %p).\n", x.c_str(), (char*)*ptr, ptr); break; - } - (*ptr) += stringLen; + for (auto itr = x.begin(); itr != x.end(); ++itr) + Do(*itr); } - void Do(std::wstring &x) + template + void Do(std::vector& x) { - int stringLen = sizeof(wchar_t)*((int)x.length() + 1); - Do(stringLen); - - switch (mode) { - case MODE_READ: x.assign((wchar_t*)*ptr, (stringLen / sizeof(wchar_t)) - 1); break; - case MODE_WRITE: memcpy(*ptr, x.c_str(), stringLen); break; - case MODE_MEASURE: break; - case MODE_VERIFY: _dbg_assert_msg_(COMMON, x == (wchar_t*)*ptr, "Savestate verification failure: \"%ls\" != \"%ls\" (at %p).\n", x.c_str(), (wchar_t*)*ptr, ptr); break; - } - (*ptr) += stringLen; + DoContainer(x); + } + + template + void Do(std::list& x) + { + DoContainer(x); + } + + template + void Do(std::deque& x) + { + DoContainer(x); + } + + template + void Do(std::basic_string& x) + { + DoContainer(x); } - template - void DoArray(T *x, int count) { - DoVoid((void *)x, sizeof(T) * count); + template + void DoArray(T* x, u32 count) + { + for (u32 i = 0; i != count; ++i) + Do(x[i]); } - template - void Do(T &x) { - DoVoid((void *)&x, sizeof(x)); + template + void Do(T& x) + { + // TODO: Bad, Do(some_non_POD) will compile and fail at runtime + // type_traits are not fully supported everywhere yet + + DoVoid((void*)&x, sizeof(x)); } - template - void DoPointer(T* &x, T*const base) { + template + void DoPointer(T*& x, T* const base) + { // pointers can be more than 2^31 apart, but you're using this function wrong if you need that much range s32 offset = x - base; Do(offset); @@ -182,7 +155,8 @@ public: x = base + offset; } - template* (*TNew)(), void (*TFree)(LinkedListItem*), void (*TDo)(PointerWrap&, T*)> + // Let's pretend std::list doesn't exist! + template * (*TNew)(), void (*TFree)(LinkedListItem*), void (*TDo)(PointerWrap&, T*)> void DoLinkedList(LinkedListItem*& list_start, LinkedListItem** list_end=0) { LinkedListItem* list_cur = list_start; @@ -242,25 +216,61 @@ public: } } - void DoMarker(const char* prevName, u32 arbitraryNumber=0x42) + void DoMarker(const char* prevName, u32 arbitraryNumber = 0x42) { u32 cookie = arbitraryNumber; Do(cookie); - if(mode == PointerWrap::MODE_READ && cookie != arbitraryNumber) + + if (mode == PointerWrap::MODE_READ && cookie != arbitraryNumber) { - PanicAlertT("Error: After \"%s\", found %d (0x%X) instead of save marker %d (0x%X). Aborting savestate load...", prevName, cookie, cookie, arbitraryNumber, arbitraryNumber); + PanicAlertT("Error: After \"%s\", found %d (0x%X) instead of save marker %d (0x%X). Aborting savestate load...", + prevName, cookie, cookie, arbitraryNumber, arbitraryNumber); mode = PointerWrap::MODE_MEASURE; } } + +private: + __forceinline void DoByte(u8& x) + { + switch (mode) + { + case MODE_READ: + x = **ptr; + break; + + case MODE_WRITE: + **ptr = x; + break; + + case MODE_MEASURE: + break; + + case MODE_VERIFY: + _dbg_assert_msg_(COMMON, (x == *ptr), + "Savestate verification failure: %d (0x%X) (at %p) != %d (0x%X) (at %p).\n", + x, x, &x, *ptr, *ptr, &*ptr); + break; + + default: + break; + } + + ++(*ptr); + } + + void DoVoid(void *data, u32 size) + { + for(u32 i = 0; i != size; ++i) + DoByte(reinterpret_cast(data)[i]); + } }; - class CChunkFileReader { public: // Load file template template - static bool Load(const std::string& _rFilename, int _Revision, T& _class) + static bool Load(const std::string& _rFilename, u32 _Revision, T& _class) { INFO_LOG(COMMON, "ChunkReader: Loading %s" , _rFilename.c_str()); @@ -300,7 +310,7 @@ public: } // get size - const int sz = (int)(fileSize - headerSize); + const u32 sz = (u32)(fileSize - headerSize); if (header.ExpectedSize != sz) { ERROR_LOG(COMMON,"ChunkReader: Bad file size, got %d expected %d", @@ -309,17 +319,16 @@ public: } // read the state - u8* buffer = new u8[sz]; - if (!pFile.ReadBytes(buffer, sz)) + std::vector buffer(sz); + if (!pFile.ReadArray(&buffer[0], sz)) { ERROR_LOG(COMMON,"ChunkReader: Error reading file"); return false; } - u8 *ptr = buffer; + u8* ptr = &buffer[0]; PointerWrap p(&ptr, PointerWrap::MODE_READ); _class.DoState(p); - delete[] buffer; INFO_LOG(COMMON, "ChunkReader: Done loading %s" , _rFilename.c_str()); return true; @@ -327,7 +336,7 @@ public: // Save file template template - static bool Save(const std::string& _rFilename, int _Revision, T& _class) + static bool Save(const std::string& _rFilename, u32 _Revision, T& _class) { INFO_LOG(COMMON, "ChunkReader: Writing %s" , _rFilename.c_str()); File::IOFile pFile(_rFilename, "wb"); @@ -349,9 +358,8 @@ public: // Create header SChunkHeader header; - header.Compress = 0; header.Revision = _Revision; - header.ExpectedSize = (int)sz; + header.ExpectedSize = (u32)sz; // Write to file if (!pFile.WriteArray(&header, 1)) @@ -360,23 +368,21 @@ public: return false; } - if (!pFile.WriteBytes(&buffer[0], sz)) + if (!pFile.WriteArray(&buffer[0], sz)) { ERROR_LOG(COMMON,"ChunkReader: Failed writing data"); return false; } - INFO_LOG(COMMON,"ChunkReader: Done writing %s", - _rFilename.c_str()); + INFO_LOG(COMMON,"ChunkReader: Done writing %s", _rFilename.c_str()); return true; } private: struct SChunkHeader { - int Revision; - int Compress; - int ExpectedSize; + u32 Revision; + u32 ExpectedSize; }; }; diff --git a/Source/Core/Common/Src/Common.h b/Source/Core/Common/Src/Common.h index c3cab37dd8..904095e255 100644 --- a/Source/Core/Common/Src/Common.h +++ b/Source/Core/Common/Src/Common.h @@ -133,7 +133,9 @@ private: // wxWidgets does not have a true dummy macro for this. #define _trans(a) a -#if defined __GNUC__ +#if defined _M_GENERIC +# define _M_SSE 0x0 +#elif defined __GNUC__ # if defined __SSE4_2__ # define _M_SSE 0x402 # elif defined __SSE4_1__ @@ -144,7 +146,7 @@ private: # define _M_SSE 0x300 # endif #elif (_MSC_VER >= 1500) || __INTEL_COMPILER // Visual Studio 2008 -# define _M_SSE 0x402 +# define _M_SSE 0x402 #endif // Host communication. @@ -155,7 +157,6 @@ enum HOST_COMM WM_USER_CREATE, WM_USER_SETCURSOR, WM_USER_KEYDOWN, - WIIMOTE_DISCONNECT // Disconnect Wiimote }; // Used for notification on emulation state diff --git a/Source/Core/Common/Src/CommonFuncs.h b/Source/Core/Common/Src/CommonFuncs.h index 585fe0999a..19223a74a7 100644 --- a/Source/Core/Common/Src/CommonFuncs.h +++ b/Source/Core/Common/Src/CommonFuncs.h @@ -35,7 +35,7 @@ template<> struct CompileTimeAssert {}; #define b32(x) (b16(x) | (b16(x) >>16) ) #define ROUND_UP_POW2(x) (b32(x - 1) + 1) -#if defined __GNUC__ && !defined __SSSE3__ +#if defined __GNUC__ && !defined __SSSE3__ && !defined _M_GENERIC #include static __inline __m128i __attribute__((__always_inline__)) _mm_shuffle_epi8(__m128i a, __m128i mask) @@ -60,6 +60,8 @@ _mm_shuffle_epi8(__m128i a, __m128i mask) // go to debugger mode #ifdef GEKKO #define Crash() + #elif defined _M_GENERIC + #define Crash() { exit(1); } #else #define Crash() {asm ("int $3");} #endif @@ -136,6 +138,15 @@ inline u8 swap8(u8 _data) {return _data;} inline u16 swap16(u16 _data) {return _byteswap_ushort(_data);} inline u32 swap32(u32 _data) {return _byteswap_ulong (_data);} inline u64 swap64(u64 _data) {return _byteswap_uint64(_data);} +#elif _M_ARM +#ifdef ANDROID +#undef swap16 +#undef swap32 +#undef swap64 +#endif +inline u16 swap16 (u16 _data) { u32 data = _data; __asm__ ("rev16 %0, %1\n" : "=l" (data) : "l" (data)); return (u16)data;} +inline u32 swap32 (u32 _data) {__asm__ ("rev %0, %1\n" : "=l" (_data) : "l" (_data)); return _data;} +inline u64 swap64(u64 _data) {return ((u64)swap32(_data) << 32) | swap32(_data >> 32);} #elif __linux__ inline u16 swap16(u16 _data) {return bswap_16(_data);} inline u32 swap32(u32 _data) {return bswap_32(_data);} @@ -162,6 +173,40 @@ inline u16 swap16(const u8* _pData) {return swap16(*(const u16*)_pData);} inline u32 swap32(const u8* _pData) {return swap32(*(const u32*)_pData);} inline u64 swap64(const u8* _pData) {return swap64(*(const u64*)_pData);} +template +void swap(u8*); + +template <> +inline void swap<1>(u8* data) +{} + +template <> +inline void swap<2>(u8* data) +{ + *reinterpret_cast(data) = swap16(data); +} + +template <> +inline void swap<4>(u8* data) +{ + *reinterpret_cast(data) = swap32(data); +} + +template <> +inline void swap<8>(u8* data) +{ + *reinterpret_cast(data) = swap64(data); +} + +template +inline T FromBigEndian(T data) +{ + //static_assert(std::is_arithmetic::value, "function only makes sense with arithmetic types"); + + swap(reinterpret_cast(&data)); + return data; +} + } // Namespace Common #endif // _COMMONFUNCS_H_ diff --git a/Source/Core/Common/Src/CommonPaths.h b/Source/Core/Common/Src/CommonPaths.h index 9e14d7cf7e..cab7ce3762 100644 --- a/Source/Core/Common/Src/CommonPaths.h +++ b/Source/Core/Common/Src/CommonPaths.h @@ -36,6 +36,9 @@ // You can use the File::GetUserPath() util for this #define USERDATA_DIR "Contents/Resources/User" #define DOLPHIN_DATA_DIR "Library/Application Support/Dolphin" +#elif defined ANDROID + #define USERDATA_DIR "user" + #define DOLPHIN_DATA_DIR "/sdcard/dolphin-emu" #else #define USERDATA_DIR "user" #ifdef USER_DIR @@ -52,6 +55,8 @@ #define SYSDATA_DIR "Contents/Resources/Sys" #define SHARED_USER_DIR File::GetBundleDirectory() + \ DIR_SEP USERDATA_DIR DIR_SEP +#elif defined ANDROID + #define SYSDATA_DIR "/sdcard/dolphin-emu" #else #ifdef DATA_DIR #define SYSDATA_DIR DATA_DIR "sys" diff --git a/Source/Core/Common/Src/ConsoleListener.cpp b/Source/Core/Common/Src/ConsoleListener.cpp index cf03581431..5a4ff126bf 100644 --- a/Source/Core/Common/Src/ConsoleListener.cpp +++ b/Source/Core/Common/Src/ConsoleListener.cpp @@ -61,7 +61,7 @@ void ConsoleListener::Open(bool Hidden, int Width, int Height, const char *Title // Save the window handle that AllocConsole() created hConsole = GetStdHandle(STD_OUTPUT_HANDLE); // Set the console window title - SetConsoleTitle(Title); + SetConsoleTitle(UTF8ToTStr(Title).c_str()); // Set letter space LetterSpace(80, 4000); //MoveWindow(GetConsoleWindow(), 200,200, 800,800, true); @@ -195,7 +195,7 @@ void ConsoleListener::PixelSpace(int Left, int Top, int Width, int Height, bool static const int MAX_BYTES = 1024 * 16; - std::vector> Str; + std::vector> Str; std::vector> Attr; // ReadConsoleOutputAttribute seems to have a limit at this level diff --git a/Source/Core/Common/Src/Crypto/md5.cpp b/Source/Core/Common/Src/Crypto/md5.cpp index 7fff7713da..7b8dc149f4 100644 --- a/Source/Core/Common/Src/Crypto/md5.cpp +++ b/Source/Core/Common/Src/Crypto/md5.cpp @@ -37,6 +37,8 @@ #include #include +#include "../FileUtil.h" + /* * 32-bit integer manipulation macros (little endian) */ @@ -301,7 +303,10 @@ int md5_file( char *path, unsigned char output[16] ) md5_context ctx; unsigned char buf[1024]; - if( ( f = fopen( path, "rb" ) ) == NULL ) + File::IOFile file(path, "rb"); + f = file.GetHandle(); + + if (f == NULL) return( 1 ); md5_starts( &ctx ); @@ -315,11 +320,9 @@ int md5_file( char *path, unsigned char output[16] ) if( ferror( f ) != 0 ) { - fclose( f ); return( 2 ); } - fclose( f ); return( 0 ); } diff --git a/Source/Core/Common/Src/Crypto/sha1.cpp b/Source/Core/Common/Src/Crypto/sha1.cpp index 17ad930986..45b88b2b6e 100644 --- a/Source/Core/Common/Src/Crypto/sha1.cpp +++ b/Source/Core/Common/Src/Crypto/sha1.cpp @@ -36,6 +36,8 @@ #include #include +#include "../FileUtil.h" + /* * 32-bit integer manipulation macros (big endian) */ @@ -335,7 +337,10 @@ int sha1_file( char *path, unsigned char output[20] ) sha1_context ctx; unsigned char buf[1024]; - if( ( f = fopen( path, "rb" ) ) == NULL ) + File::IOFile file(path, "rb"); + f = file.GetHandle(); + + if (f == NULL) return( 1 ); sha1_starts( &ctx ); @@ -349,11 +354,9 @@ int sha1_file( char *path, unsigned char output[20] ) if( ferror( f ) != 0 ) { - fclose( f ); return( 2 ); } - fclose( f ); return( 0 ); } diff --git a/Source/Core/Common/Src/ExtendedTrace.cpp b/Source/Core/Common/Src/ExtendedTrace.cpp index 3fe661f2e4..85057639a5 100644 --- a/Source/Core/Common/Src/ExtendedTrace.cpp +++ b/Source/Core/Common/Src/ExtendedTrace.cpp @@ -17,6 +17,7 @@ #include #include #include "ExtendedTrace.h" +#include "StringUtil.h" using namespace std; #include @@ -274,13 +275,21 @@ static BOOL GetSourceInfoFromAddress( UINT address, LPTSTR lpszSourceInfo ) return ret; } -void StackTrace( HANDLE hThread, LPCTSTR lpszMessage, FILE *file ) +void PrintFunctionAndSourceInfo(FILE* file, const STACKFRAME& callstack) +{ + TCHAR symInfo[BUFFERSIZE] = _T("?"); + TCHAR srcInfo[BUFFERSIZE] = _T("?"); + + GetFunctionInfoFromAddresses((ULONG)callstack.AddrPC.Offset, (ULONG)callstack.AddrFrame.Offset, symInfo); + GetSourceInfoFromAddress((ULONG)callstack.AddrPC.Offset, srcInfo); + etfprint(file, " " + TStrToUTF8(srcInfo) + " : " + TStrToUTF8(symInfo) + "\n"); +} + +void StackTrace( HANDLE hThread, const char* lpszMessage, FILE *file ) { STACKFRAME callStack; BOOL bResult; CONTEXT context; - TCHAR symInfo[BUFFERSIZE] = _T("?"); - TCHAR srcInfo[BUFFERSIZE] = _T("?"); HANDLE hProcess = GetCurrentProcess(); // If it's not this thread, let's suspend it, and resume it at the end @@ -318,9 +327,7 @@ void StackTrace( HANDLE hThread, LPCTSTR lpszMessage, FILE *file ) etfprint(file, "Call stack info: \n"); etfprint(file, lpszMessage); - GetFunctionInfoFromAddresses( (ULONG)callStack.AddrPC.Offset, (ULONG)callStack.AddrFrame.Offset, symInfo ); - GetSourceInfoFromAddress( (ULONG)callStack.AddrPC.Offset, srcInfo ); - etfprint(file, string(" ") + srcInfo + string(" : ") + symInfo + string("\n")); + PrintFunctionAndSourceInfo(file, callStack); for( ULONG index = 0; ; index++ ) { @@ -341,9 +348,7 @@ void StackTrace( HANDLE hThread, LPCTSTR lpszMessage, FILE *file ) if( !bResult || callStack.AddrFrame.Offset == 0 ) break; - GetFunctionInfoFromAddresses( (ULONG)callStack.AddrPC.Offset, (ULONG)callStack.AddrFrame.Offset, symInfo ); - GetSourceInfoFromAddress( (UINT)callStack.AddrPC.Offset, srcInfo ); - etfprint(file, string(" ") + srcInfo + string(" : ") + symInfo + string("\n")); + PrintFunctionAndSourceInfo(file, callStack); } @@ -351,19 +356,7 @@ void StackTrace( HANDLE hThread, LPCTSTR lpszMessage, FILE *file ) ResumeThread( hThread ); } -void StackTrace( HANDLE hThread, wchar_t const*lpszMessage, FILE *file, DWORD eip, DWORD esp, DWORD ebp ) -{ - // TODO: remove when Common builds as unicode - size_t origsize = wcslen(lpszMessage) + 1; - const size_t newsize = 100; - size_t convertedChars = 0; - char nstring[newsize]; - wcstombs_s(&convertedChars, nstring, origsize, lpszMessage, _TRUNCATE); - - StackTrace(hThread, nstring, file, eip, esp, ebp ); -} - -void StackTrace( HANDLE hThread, LPCTSTR lpszMessage, FILE *file, DWORD eip, DWORD esp, DWORD ebp ) +void StackTrace(HANDLE hThread, const char* lpszMessage, FILE *file, DWORD eip, DWORD esp, DWORD ebp ) { STACKFRAME callStack; BOOL bResult; @@ -391,9 +384,7 @@ void StackTrace( HANDLE hThread, LPCTSTR lpszMessage, FILE *file, DWORD eip, DWO etfprint(file, "Call stack info: \n"); etfprint(file, lpszMessage); - GetFunctionInfoFromAddresses( (ULONG)callStack.AddrPC.Offset, (ULONG)callStack.AddrFrame.Offset, symInfo ); - GetSourceInfoFromAddress( (UINT)callStack.AddrPC.Offset, srcInfo ); - etfprint(file, string(" ") + srcInfo + string(" : ") + symInfo + string("\n")); + PrintFunctionAndSourceInfo(file, callStack); for( ULONG index = 0; ; index++ ) { @@ -414,10 +405,7 @@ void StackTrace( HANDLE hThread, LPCTSTR lpszMessage, FILE *file, DWORD eip, DWO if( !bResult || callStack.AddrFrame.Offset == 0 ) break; - GetFunctionInfoFromAddresses( (ULONG)callStack.AddrPC.Offset, (ULONG)callStack.AddrFrame.Offset, symInfo ); - GetSourceInfoFromAddress( (UINT)callStack.AddrPC.Offset, srcInfo ); - etfprint(file, string(" ") + srcInfo + string(" : ") + symInfo + string("\n")); - + PrintFunctionAndSourceInfo(file, callStack); } if ( hThread != GetCurrentThread() ) @@ -426,7 +414,8 @@ void StackTrace( HANDLE hThread, LPCTSTR lpszMessage, FILE *file, DWORD eip, DWO char g_uefbuf[2048]; -void etfprintf(FILE *file, const char *format, ...) { +void etfprintf(FILE *file, const char *format, ...) +{ va_list ap; va_start(ap, format); int len = vsprintf(g_uefbuf, format, ap); @@ -434,7 +423,8 @@ void etfprintf(FILE *file, const char *format, ...) { va_end(ap); } -void etfprint(FILE *file, const std::string &text) { +void etfprint(FILE *file, const std::string &text) +{ size_t len = text.length(); fwrite(text.data(), 1, len, file); } diff --git a/Source/Core/Common/Src/ExtendedTrace.h b/Source/Core/Common/Src/ExtendedTrace.h index 12e7ed41fa..003c8a68e3 100644 --- a/Source/Core/Common/Src/ExtendedTrace.h +++ b/Source/Core/Common/Src/ExtendedTrace.h @@ -26,15 +26,14 @@ #define EXTENDEDTRACEINITIALIZE( IniSymbolPath ) InitSymInfo( IniSymbolPath ) #define EXTENDEDTRACEUNINITIALIZE() UninitSymInfo() -#define STACKTRACE(file) StackTrace( GetCurrentThread(), _T(""), file) -#define STACKTRACE2(file, eip, esp, ebp) StackTrace(GetCurrentThread(), _T(""), file, eip, esp, ebp) +#define STACKTRACE(file) StackTrace( GetCurrentThread(), "", file) +#define STACKTRACE2(file, eip, esp, ebp) StackTrace(GetCurrentThread(), "", file, eip, esp, ebp) // class File; BOOL InitSymInfo( PCSTR ); BOOL UninitSymInfo(); -void StackTrace( HANDLE, LPCTSTR, FILE *file); -void StackTrace( HANDLE, LPCTSTR, FILE *file, DWORD eip, DWORD esp, DWORD ebp); -void StackTrace( HANDLE hThread, wchar_t const* lpszMessage, FILE *file, DWORD eip, DWORD esp, DWORD ebp); +void StackTrace(HANDLE, char const* msg, FILE *file); +void StackTrace(HANDLE, char const* msg, FILE *file, DWORD eip, DWORD esp, DWORD ebp); // functions by Masken void etfprintf(FILE *file, const char *format, ...); diff --git a/Source/Core/Common/Src/FPURoundMode.h b/Source/Core/Common/Src/FPURoundMode.h new file mode 100644 index 0000000000..acfd89c313 --- /dev/null +++ b/Source/Core/Common/Src/FPURoundMode.h @@ -0,0 +1,51 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ +#ifndef FPU_ROUND_MODE_H_ +#define FPU_ROUND_MODE_H_ +#include "Common.h" + +namespace FPURoundMode +{ + enum RoundModes + { + ROUND_NEAR = 0, + ROUND_CHOP, + ROUND_UP, + ROUND_DOWN + }; + enum PrecisionModes { + PREC_24 = 0, + PREC_53, + PREC_64 + }; + void SetRoundMode(u32 mode); + + void SetPrecisionMode(u32 mode); + + void SetSIMDMode(u32 mode); + + /* + There are two different flavors of float to int conversion: + _mm_cvtps_epi32() and _mm_cvttps_epi32(). The first rounds + according to the MXCSR rounding bits. The second one always + uses round towards zero. + */ + void SaveSIMDState(); + void LoadSIMDState(); + void LoadDefaultSIMDState(); +} +#endif diff --git a/Source/Core/Common/Src/FileSearch.cpp b/Source/Core/Common/Src/FileSearch.cpp index 595dfe7000..674cf0e1d5 100644 --- a/Source/Core/Common/Src/FileSearch.cpp +++ b/Source/Core/Common/Src/FileSearch.cpp @@ -51,7 +51,7 @@ void CFileSearch::FindFiles(const std::string& _searchString, const std::string& BuildCompleteFilename(GCMSearchPath, _strPath, _searchString); #ifdef _WIN32 WIN32_FIND_DATA findData; - HANDLE FindFirst = FindFirstFile(GCMSearchPath.c_str(), &findData); + HANDLE FindFirst = FindFirstFile(UTF8ToTStr(GCMSearchPath).c_str(), &findData); if (FindFirst != INVALID_HANDLE_VALUE) { @@ -62,7 +62,7 @@ void CFileSearch::FindFiles(const std::string& _searchString, const std::string& if (findData.cFileName[0] != '.') { std::string strFilename; - BuildCompleteFilename(strFilename, _strPath, findData.cFileName); + BuildCompleteFilename(strFilename, _strPath, TStrToUTF8(findData.cFileName)); m_FileNames.push_back(strFilename); } @@ -112,7 +112,6 @@ void CFileSearch::FindFiles(const std::string& _searchString, const std::string& #endif } - const CFileSearch::XStringVector& CFileSearch::GetFileNames() const { return m_FileNames; diff --git a/Source/Core/Common/Src/FileUtil.cpp b/Source/Core/Common/Src/FileUtil.cpp index d6ab33962a..7b9ab2e464 100644 --- a/Source/Core/Common/Src/FileUtil.cpp +++ b/Source/Core/Common/Src/FileUtil.cpp @@ -41,10 +41,11 @@ #include #endif -#include #include #include +#include "StringUtil.h" + #ifndef S_ISDIR #define S_ISDIR(m) (((m)&S_IFMT) == S_IFDIR) #endif @@ -81,7 +82,11 @@ bool Exists(const std::string &filename) std::string copy(filename); StripTailDirSlashes(copy); +#ifdef _WIN32 + int result = _tstat64(UTF8ToTStr(copy).c_str(), &file_info); +#else int result = stat64(copy.c_str(), &file_info); +#endif return (result == 0); } @@ -94,7 +99,11 @@ bool IsDirectory(const std::string &filename) std::string copy(filename); StripTailDirSlashes(copy); +#ifdef _WIN32 + int result = _tstat64(UTF8ToTStr(copy).c_str(), &file_info); +#else int result = stat64(copy.c_str(), &file_info); +#endif if (result < 0) { WARN_LOG(COMMON, "IsDirectory: stat failed on %s: %s", @@ -127,7 +136,7 @@ bool Delete(const std::string &filename) } #ifdef _WIN32 - if (!DeleteFile(filename.c_str())) + if (!DeleteFile(UTF8ToTStr(filename).c_str())) { WARN_LOG(COMMON, "Delete: DeleteFile failed on %s: %s", filename.c_str(), GetLastErrorMsg()); @@ -149,7 +158,7 @@ bool CreateDir(const std::string &path) { INFO_LOG(COMMON, "CreateDir: directory %s", path.c_str()); #ifdef _WIN32 - if (::CreateDirectory(path.c_str(), NULL)) + if (::CreateDirectory(UTF8ToTStr(path).c_str(), NULL)) return true; DWORD error = GetLastError(); if (error == ERROR_ALREADY_EXISTS) @@ -228,7 +237,7 @@ bool DeleteDir(const std::string &filename) } #ifdef _WIN32 - if (::RemoveDirectory(filename.c_str())) + if (::RemoveDirectory(UTF8ToTStr(filename).c_str())) return true; #else if (rmdir(filename.c_str()) == 0) @@ -257,7 +266,7 @@ bool Copy(const std::string &srcFilename, const std::string &destFilename) INFO_LOG(COMMON, "Copy: %s --> %s", srcFilename.c_str(), destFilename.c_str()); #ifdef _WIN32 - if (CopyFile(srcFilename.c_str(), destFilename.c_str(), FALSE)) + if (CopyFile(UTF8ToTStr(srcFilename).c_str(), UTF8ToTStr(destFilename).c_str(), FALSE)) return true; ERROR_LOG(COMMON, "Copy: failed %s --> %s: %s", @@ -342,8 +351,13 @@ u64 GetSize(const std::string &filename) WARN_LOG(COMMON, "GetSize: failed %s: is a directory", filename.c_str()); return 0; } + struct stat64 buf; +#ifdef _WIN32 + if (_tstat64(UTF8ToTStr(filename).c_str(), &buf) == 0) +#else if (stat64(filename.c_str(), &buf) == 0) +#endif { DEBUG_LOG(COMMON, "GetSize: %s: %lld", filename.c_str(), (long long)buf.st_size); @@ -391,13 +405,13 @@ bool CreateEmptyFile(const std::string &filename) { INFO_LOG(COMMON, "CreateEmptyFile: %s", filename.c_str()); - FILE *pFile = fopen(filename.c_str(), "wb"); - if (!pFile) { + if (!File::IOFile(filename, "wb")) + { ERROR_LOG(COMMON, "CreateEmptyFile: failed %s: %s", filename.c_str(), GetLastErrorMsg()); return false; } - fclose(pFile); + return true; } @@ -413,7 +427,7 @@ u32 ScanDirectoryTree(const std::string &directory, FSTEntry& parentEntry) // Find the first file in the directory. WIN32_FIND_DATA ffd; - HANDLE hFind = FindFirstFile((directory + "\\*").c_str(), &ffd); + HANDLE hFind = FindFirstFile(UTF8ToTStr(directory + "\\*").c_str(), &ffd); if (hFind == INVALID_HANDLE_VALUE) { FindClose(hFind); @@ -423,7 +437,7 @@ u32 ScanDirectoryTree(const std::string &directory, FSTEntry& parentEntry) do { FSTEntry entry; - const std::string virtualName(ffd.cFileName); + const std::string virtualName(TStrToUTF8(ffd.cFileName)); #else struct dirent dirent, *result = NULL; @@ -480,7 +494,7 @@ bool DeleteDirRecursively(const std::string &directory) #ifdef _WIN32 // Find the first file in the directory. WIN32_FIND_DATA ffd; - HANDLE hFind = FindFirstFile((directory + "\\*").c_str(), &ffd); + HANDLE hFind = FindFirstFile(UTF8ToTStr(directory + "\\*").c_str(), &ffd); if (hFind == INVALID_HANDLE_VALUE) { @@ -491,7 +505,7 @@ bool DeleteDirRecursively(const std::string &directory) // windows loop do { - const std::string virtualName = ffd.cFileName; + const std::string virtualName(TStrToUTF8(ffd.cFileName)); #else struct dirent dirent, *result = NULL; DIR *dirp = opendir(directory.c_str()); @@ -622,14 +636,14 @@ std::string GetBundleDirectory() #endif #ifdef _WIN32 -std::string &GetExeDirectory() +std::string& GetExeDirectory() { static std::string DolphinPath; if (DolphinPath.empty()) { - char Dolphin_exe_Path[2048]; - GetModuleFileNameA(NULL, Dolphin_exe_Path, 2048); - DolphinPath = Dolphin_exe_Path; + TCHAR Dolphin_exe_Path[2048]; + GetModuleFileName(NULL, Dolphin_exe_Path, 2048); + DolphinPath = TStrToUTF8(Dolphin_exe_Path); DolphinPath = DolphinPath.substr(0, DolphinPath.find_last_of('\\')); } return DolphinPath; @@ -668,9 +682,10 @@ std::string &GetUserPath(const unsigned int DirIDX, const std::string &newPath) if (File::Exists(ROOT_DIR DIR_SEP USERDATA_DIR)) paths[D_USER_IDX] = ROOT_DIR DIR_SEP USERDATA_DIR DIR_SEP; else - paths[D_USER_IDX] = std::string(getenv("HOME") ? getenv("HOME") : getenv("PWD")) + DIR_SEP DOLPHIN_DATA_DIR DIR_SEP; + paths[D_USER_IDX] = std::string(getenv("HOME") ? + getenv("HOME") : getenv("PWD") ? + getenv("PWD") : "") + DIR_SEP DOLPHIN_DATA_DIR DIR_SEP; #endif - INFO_LOG(COMMON, "GetUserPath: Setting user directory to %s:", paths[D_USER_IDX].c_str()); paths[D_GCUSER_IDX] = paths[D_USER_IDX] + GC_USER_DIR DIR_SEP; paths[D_WIIROOT_IDX] = paths[D_USER_IDX] + WII_USER_DIR; @@ -729,31 +744,19 @@ std::string &GetUserPath(const unsigned int DirIDX, const std::string &newPath) bool WriteStringToFile(bool text_file, const std::string &str, const char *filename) { - FILE *f = fopen(filename, text_file ? "w" : "wb"); - if (!f) - return false; - size_t len = str.size(); - if (len != fwrite(str.data(), 1, str.size(), f)) // TODO: string::data() may not be contiguous - { - fclose(f); - return false; - } - fclose(f); - return true; + return File::IOFile(filename, text_file ? "w" : "wb").WriteBytes(str.data(), str.size()); } bool ReadFileToString(bool text_file, const char *filename, std::string &str) { - FILE *f = fopen(filename, text_file ? "r" : "rb"); + File::IOFile file(filename, text_file ? "r" : "rb"); + auto const f = file.GetHandle(); + if (!f) return false; - size_t len = (size_t)GetSize(f); - char *buf = new char[len + 1]; - buf[fread(buf, 1, len, f)] = 0; - str = std::string(buf, len); - fclose(f); - delete [] buf; - return true; + + str.resize(GetSize(f)); + return file.ReadArray(&str[0], str.size()); } IOFile::IOFile() @@ -781,9 +784,9 @@ IOFile::IOFile(IOFile&& other) Swap(other); } -IOFile& IOFile::operator=(IOFile other) +IOFile& IOFile::operator=(IOFile&& other) { - Swap(other); + IOFile((IOFile&&)other).Swap(*this); return *this; } @@ -797,7 +800,7 @@ bool IOFile::Open(const std::string& filename, const char openmode[]) { Close(); #ifdef _WIN32 - fopen_s(&m_file, filename.c_str(), openmode); + _tfopen_s(&m_file, UTF8ToTStr(filename).c_str(), UTF8ToTStr(openmode).c_str()); #else m_file = fopen(filename.c_str(), openmode); #endif diff --git a/Source/Core/Common/Src/FileUtil.h b/Source/Core/Common/Src/FileUtil.h index 2c8bf8f64b..2747c50cf4 100644 --- a/Source/Core/Common/Src/FileUtil.h +++ b/Source/Core/Common/Src/FileUtil.h @@ -25,6 +25,7 @@ #include #include "Common.h" +#include "StringUtil.h" // User directory indices for GetUserPath enum { @@ -160,7 +161,7 @@ public: ~IOFile(); IOFile(IOFile&& other); - IOFile& operator=(IOFile other); + IOFile& operator=(IOFile&& other); void Swap(IOFile& other); @@ -226,4 +227,15 @@ private: } // namespace +// To deal with Windows being dumb at unicode: +template +void OpenFStream(T& fstream, const std::string& filename, std::ios_base::openmode openmode) +{ +#ifdef _WIN32 + fstream.open(UTF8ToTStr(filename).c_str(), openmode); +#else + fstream.open(filename.c_str(), openmode); +#endif +} + #endif diff --git a/Source/Core/Common/Src/GenericFPURoundMode.cpp b/Source/Core/Common/Src/GenericFPURoundMode.cpp new file mode 100644 index 0000000000..cc878291a1 --- /dev/null +++ b/Source/Core/Common/Src/GenericFPURoundMode.cpp @@ -0,0 +1,41 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "FPURoundMode.h" + +// Generic, do nothing +namespace FPURoundMode +{ + void SetRoundMode(u32 mode) + { + } + void SetPrecisionMode(u32 mode) + { + } + void SetSIMDMode(u32 mode) + { + } + void SaveSIMDState() + { + } + void LoadSIMDState() + { + } + void LoadDefaultSIMDState() + { + } +} diff --git a/Source/Core/Common/Src/IniFile.cpp b/Source/Core/Common/Src/IniFile.cpp index acad498106..da44855941 100644 --- a/Source/Core/Common/Src/IniFile.cpp +++ b/Source/Core/Common/Src/IniFile.cpp @@ -25,6 +25,7 @@ #include #include +#include "FileUtil.h" #include "StringUtil.h" #include "IniFile.h" @@ -400,7 +401,7 @@ bool IniFile::Load(const char* filename) // Open file std::ifstream in; - in.open(filename, std::ios::in); + OpenFStream(in, filename, std::ios::in); if (in.fail()) return false; @@ -452,7 +453,7 @@ bool IniFile::Load(const char* filename) bool IniFile::Save(const char* filename) { std::ofstream out; - out.open(filename, std::ios::out); + OpenFStream(out, filename, std::ios::out); if (out.fail()) { diff --git a/Source/Core/Common/Src/LinearDiskCache.h b/Source/Core/Common/Src/LinearDiskCache.h index 9a55882a66..b60c849c8e 100644 --- a/Source/Core/Common/Src/LinearDiskCache.h +++ b/Source/Core/Common/Src/LinearDiskCache.h @@ -71,7 +71,7 @@ public: m_num_entries = 0; // try opening for reading/writing - m_file.open(filename, ios_base::in | ios_base::out | ios_base::binary); + OpenFStream(m_file, filename, ios_base::in | ios_base::out | ios_base::binary); m_file.seekg(0, std::ios::end); std::fstream::pos_type end_pos = m_file.tellg(); diff --git a/Source/Core/Common/Src/LogManager.cpp b/Source/Core/Common/Src/LogManager.cpp index a79c413cf8..9b0ed43333 100644 --- a/Source/Core/Common/Src/LogManager.cpp +++ b/Source/Core/Common/Src/LogManager.cpp @@ -17,6 +17,9 @@ #include +#ifdef ANDROID +#include "Host.h" +#endif #include "LogManager.h" #include "ConsoleListener.h" #include "Timer.h" @@ -132,7 +135,9 @@ void LogManager::Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, Common::Timer::GetTimeFormatted().c_str(), file, line, level_to_char[(int)level], log->GetShortName(), temp); - +#ifdef ANDROID + Host_SysMessage(msg); +#endif log->Trigger(level, msg); } @@ -181,7 +186,7 @@ void LogContainer::Trigger(LogTypes::LOG_LEVELS level, const char *msg) FileLogListener::FileLogListener(const char *filename) { - m_logfile.open(filename, std::ios::app); + OpenFStream(m_logfile, filename, std::ios::app); SetEnable(true); } diff --git a/Source/Core/Common/Src/MathUtil.cpp b/Source/Core/Common/Src/MathUtil.cpp index e078db2e9d..b97d55e62c 100644 --- a/Source/Core/Common/Src/MathUtil.cpp +++ b/Source/Core/Common/Src/MathUtil.cpp @@ -21,13 +21,6 @@ #include #include -namespace { - -static u32 saved_sse_state = _mm_getcsr(); -static const u32 default_sse_state = _mm_getcsr(); - -} - namespace MathUtil { @@ -114,23 +107,6 @@ u32 ClassifyFloat(float fvalue) } // namespace -void LoadDefaultSSEState() -{ - _mm_setcsr(default_sse_state); -} - - -void LoadSSEState() -{ - _mm_setcsr(saved_sse_state); -} - - -void SaveSSEState() -{ - saved_sse_state = _mm_getcsr(); -} - inline void MatrixMul(int n, const float *a, const float *b, float *result) { for (int i = 0; i < n; ++i) diff --git a/Source/Core/Common/Src/MathUtil.h b/Source/Core/Common/Src/MathUtil.h index c5f613ada1..d99b9503e8 100644 --- a/Source/Core/Common/Src/MathUtil.h +++ b/Source/Core/Common/Src/MathUtil.h @@ -20,8 +20,8 @@ #include "Common.h" -#include #include +#include "FPURoundMode.h" namespace MathUtil { @@ -149,22 +149,32 @@ struct Rectangle inline float pow2f(float x) {return x * x;} inline double pow2(double x) {return x * x;} - -/* - There are two different flavors of float to int conversion: - _mm_cvtps_epi32() and _mm_cvttps_epi32(). The first rounds - according to the MXCSR rounding bits. The second one always - uses round towards zero. - */ - -void SaveSSEState(); -void LoadSSEState(); -void LoadDefaultSSEState(); float MathFloatVectorSum(const std::vector&); #define ROUND_UP(x, a) (((x) + (a) - 1) & ~((a) - 1)) #define ROUND_DOWN(x, a) ((x) & ~((a) - 1)) +// Rounds down. 0 -> undefined +inline u64 Log2(u64 val) +{ +#if defined(__GNUC__) + return 63 - __builtin_clzll(val); + +#elif defined(_MSC_VER) && defined(_M_X64) + unsigned long result = -1; + _BitScanReverse64(&result, val); + return result; + +#else + u64 result = -1; + while (val != 0) + { + val >>= 1; + ++result; + } + return result; +#endif +} // Tiny matrix/vector library. // Used for things like Free-Look in the gfx backend. diff --git a/Source/Core/Common/Src/MemArena.cpp b/Source/Core/Common/Src/MemArena.cpp index 1dcdef6672..0a2b9e0306 100644 --- a/Source/Core/Common/Src/MemArena.cpp +++ b/Source/Core/Common/Src/MemArena.cpp @@ -27,6 +27,10 @@ #include #include #include +#ifdef ANDROID +#include +#include +#endif #endif #if defined(__APPLE__) @@ -34,11 +38,41 @@ static const char* ram_temp_file = "/tmp/gc_mem.tmp"; #elif !defined(_WIN32) // non OSX unixes static const char* ram_temp_file = "/dev/shm/gc_mem.tmp"; #endif +#ifdef ANDROID +#define ASHMEM_DEVICE "/dev/ashmem" + +int AshmemCreateFileMapping(const char *name, size_t size) +{ + int fd, ret; + fd = open(ASHMEM_DEVICE, O_RDWR); + if (fd < 0) + return fd; + + // We don't really care if we can't set the name, it is optional + ret = ioctl(fd, ASHMEM_SET_NAME, name); + + ret = ioctl(fd, ASHMEM_SET_SIZE, size); + if (ret < 0) + { + close(fd); + NOTICE_LOG(MEMMAP, "Ashmem returned error: 0x%08x", ret); + return ret; + } + return fd; +} +#endif void MemArena::GrabLowMemSpace(size_t size) { #ifdef _WIN32 hMemoryMapping = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, (DWORD)(size), NULL); +#elif defined(ANDROID) + fd = AshmemCreateFileMapping("Dolphin-emu", size); + if (fd < 0) + { + NOTICE_LOG(MEMMAP, "Ashmem allocation failed"); + return; + } #else mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; fd = open(ram_temp_file, O_RDWR | O_CREAT, mode); diff --git a/Source/Core/Common/Src/MemoryUtil.cpp b/Source/Core/Common/Src/MemoryUtil.cpp index 0888746d42..ff50347799 100644 --- a/Source/Core/Common/Src/MemoryUtil.cpp +++ b/Source/Core/Common/Src/MemoryUtil.cpp @@ -117,9 +117,12 @@ void* AllocateAlignedMemory(size_t size,size_t alignment) void* ptr = _aligned_malloc(size,alignment); #else void* ptr = NULL; +#ifdef ANDROID + ptr = memalign(alignment, size); +#else if (posix_memalign(&ptr, alignment, size) != 0) ERROR_LOG(MEMMAP, "Failed to allocate aligned memory"); -; +#endif #endif // printf("Mapped memory at %p (size %ld)\n", ptr, diff --git a/Source/Core/Common/Src/Misc.cpp b/Source/Core/Common/Src/Misc.cpp index aafe37886f..8364bda48d 100644 --- a/Source/Core/Common/Src/Misc.cpp +++ b/Source/Core/Common/Src/Misc.cpp @@ -31,7 +31,7 @@ const char* GetLastErrorMsg() #ifdef _WIN32 static __declspec(thread) char err_str[buff_size] = {}; - FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), + FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), err_str, buff_size, NULL); #else diff --git a/Source/Core/Common/Src/MsgHandler.cpp b/Source/Core/Common/Src/MsgHandler.cpp index 7c666227aa..283dc72ef1 100644 --- a/Source/Core/Common/Src/MsgHandler.cpp +++ b/Source/Core/Common/Src/MsgHandler.cpp @@ -106,7 +106,7 @@ bool DefaultMsgHandler(const char* caption, const char* text, bool yes_no, int S if (Style == QUESTION) STYLE = MB_ICONQUESTION; if (Style == WARNING) STYLE = MB_ICONWARNING; - return IDYES == MessageBox(0, text, caption, STYLE | (yes_no ? MB_YESNO : MB_OK)); + return IDYES == MessageBox(0, UTF8ToTStr(text).c_str(), UTF8ToTStr(caption).c_str(), STYLE | (yes_no ? MB_YESNO : MB_OK)); #else printf("%s\n", text); diff --git a/Source/Core/Common/Src/NandPaths.cpp b/Source/Core/Common/Src/NandPaths.cpp index cec79414a7..eb0673afe0 100644 --- a/Source/Core/Common/Src/NandPaths.cpp +++ b/Source/Core/Common/Src/NandPaths.cpp @@ -86,7 +86,8 @@ bool CheckTitleTIK(u64 _titleID) static void CreateReplacementFile(std::string &filename) { - std::ofstream replace(filename.c_str()); + std::ofstream replace; + OpenFStream(replace, filename, std::ios_base::out); replace <<"\" __22__\n"; replace << "* __2a__\n"; //replace << "/ __2f__\n"; @@ -108,7 +109,8 @@ void ReadReplacements(replace_v& replacements) if (!File::Exists(filename)) CreateReplacementFile(filename); - std::ifstream f(filename.c_str()); + std::ifstream f; + OpenFStream(f, filename, std::ios_base::in); char letter; std::string replacement; diff --git a/Source/Core/Common/Src/SDCardUtil.cpp b/Source/Core/Common/Src/SDCardUtil.cpp index 0f2ad08607..cf37ffff3e 100644 --- a/Source/Core/Common/Src/SDCardUtil.cpp +++ b/Source/Core/Common/Src/SDCardUtil.cpp @@ -29,6 +29,7 @@ // Modified for Dolphin. #include "SDCardUtil.h" +#include "FileUtil.h" #include #include @@ -190,7 +191,6 @@ bool SDCardCreate(u64 disk_size /*in MB*/, const char* filename) { u32 sectors_per_fat; u32 sectors_per_disk; - FILE* f; // Convert MB to bytes disk_size *= 1024 * 1024; @@ -207,7 +207,8 @@ bool SDCardCreate(u64 disk_size /*in MB*/, const char* filename) boot_sector_init(s_boot_sector, s_fsinfo_sector, disk_size, nullptr); fat_init(s_fat_head); - f = fopen(filename, "wb"); + File::IOFile file(filename, "wb"); + FILE* const f = file.GetHandle(); if (!f) { ERROR_LOG(COMMON, "Could not create file '%s', aborting...\n", filename); @@ -247,13 +248,11 @@ bool SDCardCreate(u64 disk_size /*in MB*/, const char* filename) if (write_empty(f, sectors_per_disk - RESERVED_SECTORS - 2*sectors_per_fat)) goto FailWrite; - fclose(f); return true; FailWrite: ERROR_LOG(COMMON, "Could not write to '%s', aborting...\n", filename); if (unlink(filename) < 0) ERROR_LOG(COMMON, "unlink(%s) failed\n%s", filename, GetLastErrorMsg()); - fclose(f); return false; } diff --git a/Source/Core/Common/Src/StdConditionVariable.h b/Source/Core/Common/Src/StdConditionVariable.h index 1b81766ee0..11de6536b4 100644 --- a/Source/Core/Common/Src/StdConditionVariable.h +++ b/Source/Core/Common/Src/StdConditionVariable.h @@ -5,7 +5,7 @@ #define GCC_VER(x,y,z) ((x) * 10000 + (y) * 100 + (z)) #define GCC_VERSION GCC_VER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) -#if GCC_VERSION >= GCC_VER(4,4,0) && __GXX_EXPERIMENTAL_CXX0X__ +#if GCC_VERSION >= GCC_VER(4,4,0) && __GXX_EXPERIMENTAL_CXX0X__ && !ANDROID // GCC 4.4 provides #include #else diff --git a/Source/Core/Common/Src/StdMutex.h b/Source/Core/Common/Src/StdMutex.h index 8949e905ac..8a5d22f928 100644 --- a/Source/Core/Common/Src/StdMutex.h +++ b/Source/Core/Common/Src/StdMutex.h @@ -5,7 +5,7 @@ #define GCC_VER(x,y,z) ((x) * 10000 + (y) * 100 + (z)) #define GCC_VERSION GCC_VER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) -#if GCC_VERSION >= GCC_VER(4,4,0) && __GXX_EXPERIMENTAL_CXX0X__ +#if GCC_VERSION >= GCC_VER(4,4,0) && __GXX_EXPERIMENTAL_CXX0X__ && !ANDROID // GCC 4.4 provides #include #else diff --git a/Source/Core/Common/Src/StdThread.h b/Source/Core/Common/Src/StdThread.h index fea058c874..6897235658 100644 --- a/Source/Core/Common/Src/StdThread.h +++ b/Source/Core/Common/Src/StdThread.h @@ -5,7 +5,7 @@ #define GCC_VER(x,y,z) ((x) * 10000 + (y) * 100 + (z)) #define GCC_VERSION GCC_VER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) -#if GCC_VERSION >= GCC_VER(4,4,0) && __GXX_EXPERIMENTAL_CXX0X__ +#if GCC_VERSION >= GCC_VER(4,4,0) && __GXX_EXPERIMENTAL_CXX0X__ && !ANDROID // GCC 4.4 provides #ifndef _GLIBCXX_USE_SCHED_YIELD #define _GLIBCXX_USE_SCHED_YIELD diff --git a/Source/Core/Common/Src/StringUtil.cpp b/Source/Core/Common/Src/StringUtil.cpp index e5c70b2c6b..c38184776b 100644 --- a/Source/Core/Common/Src/StringUtil.cpp +++ b/Source/Core/Common/Src/StringUtil.cpp @@ -17,11 +17,21 @@ #include #include +#include #include "Common.h" #include "CommonPaths.h" #include "StringUtil.h" +#ifdef _WIN32 + #include +#elif defined(ANDROID) + +#else + #include + #include +#endif + // faster than sscanf bool AsciiToHex(const char* _szValue, u32& result) { @@ -263,25 +273,25 @@ std::string ReplaceAll(std::string result, const std::string& src, const std::st const char HEX2DEC[256] = { /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ - /* 0 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, - /* 1 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, - /* 2 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, - /* 3 */ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1, -1,-1,-1,-1, + /* 0 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16, + /* 1 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16, + /* 2 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16, + /* 3 */ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,16,16, 16,16,16,16, - /* 4 */ -1,10,11,12, 13,14,15,-1, -1,-1,-1,-1, -1,-1,-1,-1, - /* 5 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, - /* 6 */ -1,10,11,12, 13,14,15,-1, -1,-1,-1,-1, -1,-1,-1,-1, - /* 7 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + /* 4 */ 16,10,11,12, 13,14,15,16, 16,16,16,16, 16,16,16,16, + /* 5 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16, + /* 6 */ 16,10,11,12, 13,14,15,16, 16,16,16,16, 16,16,16,16, + /* 7 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16, - /* 8 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, - /* 9 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, - /* A */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, - /* B */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + /* 8 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16, + /* 9 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16, + /* A */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16, + /* B */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16, - /* C */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, - /* D */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, - /* E */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, - /* F */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1 + /* C */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16, + /* D */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16, + /* E */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16, + /* F */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16 }; std::string UriDecode(const std::string & sSrc) @@ -303,8 +313,8 @@ std::string UriDecode(const std::string & sSrc) if (*pSrc == '%') { char dec1, dec2; - if (-1 != (dec1 = HEX2DEC[*(pSrc + 1)]) - && -1 != (dec2 = HEX2DEC[*(pSrc + 2)])) + if (16 != (dec1 = HEX2DEC[*(pSrc + 1)]) + && 16 != (dec2 = HEX2DEC[*(pSrc + 2)])) { *pEnd++ = (dec1 << 4) + dec2; pSrc += 3; @@ -375,3 +385,137 @@ std::string UriEncode(const std::string & sSrc) delete [] pStart; return sResult; } + +#ifdef _WIN32 + +std::string UTF16ToUTF8(const std::wstring& input) +{ + auto const size = WideCharToMultiByte(CP_UTF8, 0, input.data(), input.size(), nullptr, 0, nullptr, nullptr); + + std::string output; + output.resize(size); + + if (size != WideCharToMultiByte(CP_UTF8, 0, input.data(), input.size(), &output[0], output.size(), nullptr, nullptr)) + output.clear(); + + return output; +} + +std::wstring CPToUTF16(u32 code_page, const std::string& input) +{ + auto const size = MultiByteToWideChar(code_page, 0, input.data(), input.size(), nullptr, 0); + + std::wstring output; + output.resize(size); + + if (size != MultiByteToWideChar(code_page, 0, input.data(), input.size(), &output[0], output.size())) + output.clear(); + + return output; +} + +std::wstring UTF8ToUTF16(const std::string& input) +{ + return CPToUTF16(CP_UTF8, input); +} + +std::string SHIFTJISToUTF8(const std::string& input) +{ + return UTF16ToUTF8(CPToUTF16(932, input)); +} + +std::string CP1252ToUTF8(const std::string& input) +{ + return UTF16ToUTF8(CPToUTF16(1252, input)); +} + +#else + +template +std::string CodeToUTF8(const char* fromcode, const std::basic_string& input) +{ + std::string result; + +#if defined(ANDROID) + result = "Not implemented on Android!"; + +#else + iconv_t const conv_desc = iconv_open("UTF-8", fromcode); + if ((iconv_t)-1 == conv_desc) + { + ERROR_LOG(COMMON, "Iconv initialization failure [%s]: %s", fromcode, strerror(errno)); + } + else + { + size_t const in_bytes = sizeof(T) * input.size(); + size_t const out_buffer_size = 4 * in_bytes; + + std::string out_buffer; + out_buffer.resize(out_buffer_size); + + auto src_buffer = &input[0]; + size_t src_bytes = in_bytes; + auto dst_buffer = &out_buffer[0]; + size_t dst_bytes = out_buffer.size(); + + while (src_bytes != 0) + { + size_t const iconv_result = iconv(conv_desc, (char**)(&src_buffer), &src_bytes, + &dst_buffer, &dst_bytes); + + if ((size_t)-1 == iconv_result) + { + if (EILSEQ == errno || EINVAL == errno) + { + // Try to skip the bad character + if (src_bytes != 0) + { + --src_bytes; + ++src_buffer; + } + } + else + { + ERROR_LOG(COMMON, "iconv failure [%s]: %s", fromcode, strerror(errno)); + break; + } + } + } + + out_buffer.resize(out_buffer_size - dst_bytes); + out_buffer.swap(result); + + iconv_close(conv_desc); + } + +#endif + return result; +} + +std::string CP1252ToUTF8(const std::string& input) +{ + //return CodeToUTF8("CP1252//TRANSLIT", input); + //return CodeToUTF8("CP1252//IGNORE", input); + return CodeToUTF8("CP1252", input); +} + +std::string SHIFTJISToUTF8(const std::string& input) +{ + //return CodeToUTF8("CP932", input); + return CodeToUTF8("SJIS", input); +} + +std::string UTF16ToUTF8(const std::wstring& input) +{ + std::string result = + // CodeToUTF8("UCS-2", input); + // CodeToUTF8("UCS-2LE", input); + // CodeToUTF8("UTF-16", input); + CodeToUTF8("UTF-16LE", input); + + // TODO: why is this needed? + result.erase(std::remove(result.begin(), result.end(), 0x00), result.end()); + return result; +} + +#endif diff --git a/Source/Core/Common/Src/StringUtil.h b/Source/Core/Common/Src/StringUtil.h index 102ae2d5fb..9463db5bb1 100644 --- a/Source/Core/Common/Src/StringUtil.h +++ b/Source/Core/Common/Src/StringUtil.h @@ -97,4 +97,28 @@ std::string ReplaceAll(std::string result, const std::string& src, const std::st std::string UriDecode(const std::string & sSrc); std::string UriEncode(const std::string & sSrc); +std::string CP1252ToUTF8(const std::string& str); +std::string SHIFTJISToUTF8(const std::string& str); +std::string UTF16ToUTF8(const std::wstring& str); + +#ifdef _WIN32 + +std::wstring UTF8ToUTF16(const std::string& str); + +#ifdef _UNICODE +inline std::string TStrToUTF8(const std::wstring& str) +{ return UTF16ToUTF8(str); } + +inline std::wstring UTF8ToTStr(const std::string& str) +{ return UTF8ToUTF16(str); } +#else +inline std::string TStrToUTF8(const std::string& str) +{ return str; } + +inline std::string UTF8ToTStr(const std::string& str) +{ return str; } +#endif + +#endif + #endif // _STRINGUTIL_H_ diff --git a/Source/Core/Common/Src/Thread.cpp b/Source/Core/Common/Src/Thread.cpp index 73f83c204f..3e8440b74f 100644 --- a/Source/Core/Common/Src/Thread.cpp +++ b/Source/Core/Common/Src/Thread.cpp @@ -105,7 +105,7 @@ void SetThreadAffinity(std::thread::native_handle_type thread, u32 mask) #ifdef __APPLE__ thread_policy_set(pthread_mach_thread_np(thread), THREAD_AFFINITY_POLICY, (integer_t *)&mask, 1); -#elif defined __linux__ || defined BSD4_4 +#elif (defined __linux__ || defined BSD4_4) && !(defined ANDROID) cpu_set_t cpu_set; CPU_ZERO(&cpu_set); diff --git a/Source/Core/Common/Src/Thread.h b/Source/Core/Common/Src/Thread.h index e711fcab5c..8b38be1de1 100644 --- a/Source/Core/Common/Src/Thread.h +++ b/Source/Core/Common/Src/Thread.h @@ -33,8 +33,6 @@ #define INFINITE 0xffffffff #endif -#include - //for gettimeofday and struct time(spec|val) #include #include diff --git a/Source/Core/Common/Src/VideoBackendBase.h b/Source/Core/Common/Src/VideoBackendBase.h index 4454bde8a7..54c4ff4cc8 100644 --- a/Source/Core/Common/Src/VideoBackendBase.h +++ b/Source/Core/Common/Src/VideoBackendBase.h @@ -22,6 +22,7 @@ #include #include "ChunkFile.h" +#include "../../VideoCommon/Src/PerfQueryBase.h" typedef void (*writeFn16)(const u16,const u32); typedef void (*writeFn32)(const u32,const u32); @@ -108,6 +109,7 @@ public: virtual void Video_EndField() = 0; virtual u32 Video_AccessEFB(EFBAccessType, u32, u32, u32) = 0; + virtual u32 Video_GetQueryResult(PerfQueryType type) = 0; virtual void Video_AddMessage(const char* pstr, unsigned int milliseconds) = 0; virtual void Video_ClearMessages() = 0; @@ -157,8 +159,10 @@ class VideoBackendHardware : public VideoBackend void Video_ExitLoop(); void Video_BeginField(u32, FieldType, u32, u32); void Video_EndField(); - u32 Video_AccessEFB(EFBAccessType, u32, u32, u32); + u32 Video_AccessEFB(EFBAccessType, u32, u32, u32); + u32 Video_GetQueryResult(PerfQueryType type); + void Video_AddMessage(const char* pstr, unsigned int milliseconds); void Video_ClearMessages(); bool Video_Screenshot(const char* filename); diff --git a/Source/Core/Common/Src/ABI.cpp b/Source/Core/Common/Src/x64ABI.cpp similarity index 99% rename from Source/Core/Common/Src/ABI.cpp rename to Source/Core/Common/Src/x64ABI.cpp index 63a8e76934..cd2f410dbf 100644 --- a/Source/Core/Common/Src/ABI.cpp +++ b/Source/Core/Common/Src/x64ABI.cpp @@ -17,7 +17,7 @@ #include "Common.h" #include "x64Emitter.h" -#include "ABI.h" +#include "x64ABI.h" using namespace Gen; diff --git a/Source/Core/Common/Src/ABI.h b/Source/Core/Common/Src/x64ABI.h similarity index 100% rename from Source/Core/Common/Src/ABI.h rename to Source/Core/Common/Src/x64ABI.h diff --git a/Source/Core/Common/Src/CPUDetect.cpp b/Source/Core/Common/Src/x64CPUDetect.cpp similarity index 98% rename from Source/Core/Common/Src/CPUDetect.cpp rename to Source/Core/Common/Src/x64CPUDetect.cpp index 282929e7b2..2898b91bec 100644 --- a/Source/Core/Common/Src/CPUDetect.cpp +++ b/Source/Core/Common/Src/x64CPUDetect.cpp @@ -30,7 +30,9 @@ #else //#include +#ifndef _M_GENERIC #include +#endif #if defined __FreeBSD__ #include @@ -39,7 +41,9 @@ static inline void do_cpuid(unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx) { -#ifdef _LP64 +#if defined _M_GENERIC + (*eax) = (*ebx) = (*ecx) = (*edx) = 0; +#elif defined _LP64 // Note: EBX is reserved on Mac OS X and in PIC on Linux, so it has to // restored at the end of the asm block. __asm__ ( diff --git a/Source/Core/Common/Src/x64Emitter.cpp b/Source/Core/Common/Src/x64Emitter.cpp index 5f8d0a66f1..9f15845875 100644 --- a/Source/Core/Common/Src/x64Emitter.cpp +++ b/Source/Core/Common/Src/x64Emitter.cpp @@ -17,7 +17,7 @@ #include "Common.h" #include "x64Emitter.h" -#include "ABI.h" +#include "x64ABI.h" #include "CPUDetect.h" namespace Gen diff --git a/Source/Core/Common/Src/x64Emitter.h b/Source/Core/Common/Src/x64Emitter.h index 3b699c81a0..6b8c59b5a5 100644 --- a/Source/Core/Common/Src/x64Emitter.h +++ b/Source/Core/Common/Src/x64Emitter.h @@ -757,7 +757,7 @@ public: region_size = 0; } - bool IsInCodeSpace(u8 *ptr) + bool IsInSpace(u8 *ptr) { return ptr >= region && ptr < region + region_size; } diff --git a/Source/Core/Common/Src/x64FPURoundMode.cpp b/Source/Core/Common/Src/x64FPURoundMode.cpp new file mode 100644 index 0000000000..0beefd860a --- /dev/null +++ b/Source/Core/Common/Src/x64FPURoundMode.cpp @@ -0,0 +1,120 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "Common.h" +#include "FPURoundMode.h" + +#ifndef _WIN32 +static const unsigned short FPU_ROUND_NEAR = 0 << 10; +static const unsigned short FPU_ROUND_DOWN = 1 << 10; +static const unsigned short FPU_ROUND_UP = 2 << 10; +static const unsigned short FPU_ROUND_CHOP = 3 << 10; +static const unsigned short FPU_ROUND_MASK = 3 << 10; +#include +#endif + +const u32 MASKS = 0x1F80; // mask away the interrupts. +const u32 DAZ = 0x40; +const u32 FTZ = 0x8000; + +namespace FPURoundMode +{ + // Get the default SSE states here. + static u32 saved_sse_state = _mm_getcsr(); + static const u32 default_sse_state = _mm_getcsr(); + + void SetRoundMode(u32 mode) + { + // Set FPU rounding mode to mimic the PowerPC's + #ifdef _M_IX86 + // This shouldn't really be needed anymore since we use SSE + #ifdef _WIN32 + const int table[4] = + { + _RC_NEAR, + _RC_CHOP, + _RC_UP, + _RC_DOWN + }; + _set_controlfp(_MCW_RC, table[mode]); + #else + const unsigned short table[4] = + { + FPU_ROUND_NEAR, + FPU_ROUND_CHOP, + FPU_ROUND_UP, + FPU_ROUND_DOWN + }; + unsigned short _mode; + asm ("fstcw %0" : "=m" (_mode) : ); + _mode = (_mode & ~FPU_ROUND_MASK) | table[mode]; + asm ("fldcw %0" : : "m" (_mode)); + #endif + #endif + } + + void SetPrecisionMode(u32 mode) + { + #ifdef _M_IX86 + // sets the floating-point lib to 53-bit + // PowerPC has a 53bit floating pipeline only + // eg: sscanf is very sensitive + #ifdef _WIN32 + _control87(_PC_53, MCW_PC); + #else + const unsigned short table[4] = { + 0 << 8, // FPU_PREC_24 + 2 << 8, // FPU_PREC_53 + 3 << 8, // FPU_PREC_64 + 3 << 8, // FPU_PREC_MASK + }; + unsigned short _mode; + asm ("fstcw %0" : : "m" (_mode)); + _mode = (_mode & ~table[4]) | table[mode]; + asm ("fldcw %0" : : "m" (_mode)); + #endif + #else + //x64 doesn't need this - fpu is done with SSE + //but still - set any useful sse options here + #endif + } + void SetSIMDMode(u32 mode) + { + static const u32 ssetable[4] = + { + (0 << 13) | MASKS, + (3 << 13) | MASKS, + (2 << 13) | MASKS, + (1 << 13) | MASKS, + }; + u32 csr = ssetable[mode]; + _mm_setcsr(csr); + } + + void SaveSIMDState() + { + saved_sse_state = _mm_getcsr(); + } + void LoadSIMDState() + { + _mm_setcsr(saved_sse_state); + } + void LoadDefaultSIMDState() + { + _mm_setcsr(default_sse_state); + } +} diff --git a/Source/Core/Common/Src/Thunk.cpp b/Source/Core/Common/Src/x64Thunk.cpp similarity index 98% rename from Source/Core/Common/Src/Thunk.cpp rename to Source/Core/Common/Src/x64Thunk.cpp index 1792df3e77..b9fd54f354 100644 --- a/Source/Core/Common/Src/Thunk.cpp +++ b/Source/Core/Common/Src/x64Thunk.cpp @@ -18,9 +18,8 @@ #include #include "Common.h" -#include "x64Emitter.h" #include "MemoryUtil.h" -#include "ABI.h" +#include "x64ABI.h" #include "Thunk.h" #define THUNK_ARENA_SIZE 1024*1024*1 diff --git a/Source/Core/Core/CMakeLists.txt b/Source/Core/Core/CMakeLists.txt index 6ffeeaec3a..b8976f42ea 100644 --- a/Source/Core/Core/CMakeLists.txt +++ b/Source/Core/Core/CMakeLists.txt @@ -9,7 +9,6 @@ set(SRCS Src/ActionReplay.cpp Src/DSPEmulator.cpp Src/GeckoCodeConfig.cpp Src/GeckoCode.cpp - Src/MemTools.cpp Src/Movie.cpp Src/NetPlay.cpp Src/NetPlayClient.cpp @@ -153,6 +152,7 @@ set(SRCS Src/ActionReplay.cpp Src/PowerPC/PPCTables.cpp Src/PowerPC/Profiler.cpp Src/PowerPC/SignatureDB.cpp + Src/PowerPC/JitInterface.cpp Src/PowerPC/Interpreter/Interpreter_Branch.cpp Src/PowerPC/Interpreter/Interpreter.cpp Src/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp @@ -162,6 +162,15 @@ set(SRCS Src/ActionReplay.cpp Src/PowerPC/Interpreter/Interpreter_Paired.cpp Src/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp Src/PowerPC/Interpreter/Interpreter_Tables.cpp + Src/PowerPC/JitCommon/JitAsmCommon.cpp + Src/PowerPC/JitCommon/JitBackpatch.cpp + Src/PowerPC/JitCommon/JitBase.cpp + Src/PowerPC/JitCommon/JitCache.cpp + Src/PowerPC/JitCommon/Jit_Util.cpp) + +if(NOT _M_GENERIC) + set(SRCS ${SRCS} + Src/x64MemTools.cpp Src/PowerPC/Jit64IL/IR.cpp Src/PowerPC/Jit64IL/IR_X86.cpp Src/PowerPC/Jit64IL/JitILAsm.cpp @@ -186,12 +195,25 @@ set(SRCS Src/ActionReplay.cpp Src/PowerPC/Jit64/Jit_LoadStorePaired.cpp Src/PowerPC/Jit64/Jit_Paired.cpp Src/PowerPC/Jit64/JitRegCache.cpp - Src/PowerPC/Jit64/Jit_SystemRegisters.cpp - Src/PowerPC/JitCommon/JitAsmCommon.cpp - Src/PowerPC/JitCommon/JitBackpatch.cpp - Src/PowerPC/JitCommon/JitBase.cpp - Src/PowerPC/JitCommon/JitCache.cpp - Src/PowerPC/JitCommon/Jit_Util.cpp) + Src/PowerPC/Jit64/Jit_SystemRegisters.cpp) +endif() +if(_M_ARM) + set(SRCS ${SRCS} + Src/ArmMemTools.cpp + Src/PowerPC/JitArm32/Jit.cpp + Src/PowerPC/JitArm32/JitAsm.cpp + Src/PowerPC/JitArm32/JitArm_BackPatch.cpp + Src/PowerPC/JitArm32/JitArm_Tables.cpp + Src/PowerPC/JitArm32/JitArmCache.cpp + Src/PowerPC/JitArm32/JitRegCache.cpp + Src/PowerPC/JitArm32/JitFPRCache.cpp + Src/PowerPC/JitArm32/JitArm_Branch.cpp + Src/PowerPC/JitArm32/JitArm_Integer.cpp + Src/PowerPC/JitArm32/JitArm_LoadStore.cpp + Src/PowerPC/JitArm32/JitArm_FloatingPoint.cpp + Src/PowerPC/JitArm32/JitArm_SystemRegisters.cpp + Src/PowerPC/JitArm32/JitArm_LoadStoreFloating.cpp) +endif() set(LIBS bdisasm inputcommon videosoftware sfml-network) diff --git a/Source/Core/Core/Core.vcxproj b/Source/Core/Core/Core.vcxproj index bd3d97f11b..17495de740 100644 --- a/Source/Core/Core/Core.vcxproj +++ b/Source/Core/Core/Core.vcxproj @@ -44,7 +44,7 @@ false StaticLibrary - MultiByte + Unicode StaticLibrary @@ -54,7 +54,7 @@ false StaticLibrary - MultiByte + Unicode StaticLibrary @@ -332,7 +332,7 @@ - + @@ -378,6 +378,7 @@ + @@ -387,10 +388,10 @@ - false - false - false - + false + false + false + Create Create @@ -563,6 +564,7 @@ + @@ -600,4 +602,4 @@ - + \ No newline at end of file diff --git a/Source/Core/Core/Core.vcxproj.filters b/Source/Core/Core/Core.vcxproj.filters index 246dafd972..b4f3f47be7 100644 --- a/Source/Core/Core/Core.vcxproj.filters +++ b/Source/Core/Core/Core.vcxproj.filters @@ -5,9 +5,8 @@ - - + @@ -562,6 +561,9 @@ HW %28Flipper/Hollywood%29\GCMemcard + + PowerPC + @@ -1048,6 +1050,9 @@ HW %28Flipper/Hollywood%29\GCMemcard + + PowerPC + diff --git a/Source/Core/Core/Src/ArmMemTools.cpp b/Source/Core/Core/Src/ArmMemTools.cpp new file mode 100644 index 0000000000..34a0c34b7d --- /dev/null +++ b/Source/Core/Core/Src/ArmMemTools.cpp @@ -0,0 +1,103 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + + +#include +#include +#ifdef ANDROID +#include +#else +#include // Look in here for the context definition. +#include +#endif + +#include "Common.h" +#include "MemTools.h" +#include "HW/Memmap.h" +#include "PowerPC/PowerPC.h" +#include "PowerPC/JitInterface.h" +#include "PowerPC/JitCommon/JitBase.h" + +namespace EMM +{ +#ifdef ANDROID +typedef struct sigcontext mcontext_t; +typedef struct ucontext { + uint32_t uc_flags; + struct ucontext* uc_link; + stack_t uc_stack; + mcontext_t uc_mcontext; + // Other fields are not used by Google Breakpad. Don't define them. +} ucontext_t; +#endif + +void sigsegv_handler(int signal, siginfo_t *info, void *raw_context) +{ + if (signal != SIGSEGV) + { + // We are not interested in other signals - handle it as usual. + return; + } + ucontext_t *context = (ucontext_t *)raw_context; + int sicode = info->si_code; + if (sicode != SEGV_MAPERR && sicode != SEGV_ACCERR) + { + // Huh? Return. + return; + } + + + // Get all the information we can out of the context. + mcontext_t *ctx = &context->uc_mcontext; + + void *fault_memory_ptr = (void*)ctx->arm_r10; + u8 *fault_instruction_ptr = (u8 *)ctx->arm_pc; + + if (!JitInterface::IsInCodeSpace(fault_instruction_ptr)) { + // Let's not prevent debugging. + return; + } + + u64 bad_address = (u64)fault_memory_ptr; + u64 memspace_bottom = (u64)Memory::base; + if (bad_address < memspace_bottom) { + PanicAlertT("Exception handler - access below memory space. %08llx%08llx", + bad_address >> 32, bad_address); + } + + u32 em_address = (u32)(bad_address - memspace_bottom); + + int access_type = 0; + + CONTEXT fake_ctx; + fake_ctx.reg_pc = ctx->arm_pc; + const u8 *new_rip = jit->BackPatch(fault_instruction_ptr, access_type, em_address, &fake_ctx); + if (new_rip) { + ctx->arm_pc = fake_ctx.reg_pc; + } +} + +void InstallExceptionHandler() +{ + struct sigaction sa; + sa.sa_handler = 0; + sa.sa_sigaction = &sigsegv_handler; + sa.sa_flags = SA_SIGINFO; + sigemptyset(&sa.sa_mask); + sigaction(SIGSEGV, &sa, NULL); +} +} // namespace diff --git a/Source/Core/Core/Src/Boot/Boot_WiiWAD.cpp b/Source/Core/Core/Src/Boot/Boot_WiiWAD.cpp index d3fa172621..a86c38286d 100644 --- a/Source/Core/Core/Src/Boot/Boot_WiiWAD.cpp +++ b/Source/Core/Core/Src/Boot/Boot_WiiWAD.cpp @@ -90,9 +90,7 @@ bool CBoot::Boot_WiiWAD(const char* _pFilename) u64 titleID = ContentLoader.GetTitleID(); // create data directory File::CreateFullPath(Common::GetTitleDataPath(titleID)); - - if (titleID == TITLEID_SYSMENU) - HLE_IPC_CreateVirtualFATFilesystem(); + // setup wii mem if (!SetupWiiMemory(ContentLoader.GetCountry())) return false; diff --git a/Source/Core/Core/Src/ConfigManager.cpp b/Source/Core/Core/Src/ConfigManager.cpp index f6194c1bb7..8b6fec58e2 100644 --- a/Source/Core/Core/Src/ConfigManager.cpp +++ b/Source/Core/Core/Src/ConfigManager.cpp @@ -100,9 +100,6 @@ SConfig::SConfig() { // Make sure we have log manager LoadSettings(); - //Make sure we load any extra settings - LoadSettingsWii(); - } void SConfig::Init() @@ -140,7 +137,7 @@ void SConfig::SaveSettings() ini.Get("General", "GCMPathes", &oldPaths, 0); for (int i = numPaths; i < oldPaths; i++) { - TCHAR tmp[16]; + char tmp[16]; sprintf(tmp, "GCMPath%i", i); ini.DeleteKey("General", tmp); } @@ -149,7 +146,7 @@ void SConfig::SaveSettings() for (int i = 0; i < numPaths; i++) { - TCHAR tmp[16]; + char tmp[16]; sprintf(tmp, "GCMPath%i", i); ini.Set("General", tmp, m_ISOFolder[i]); } @@ -244,6 +241,8 @@ void SConfig::SaveSettings() ini.Set("Core", "WiiSDCard", m_WiiSDCard); ini.Set("Core", "WiiKeyboard", m_WiiKeyboard); ini.Set("Core", "WiimoteReconnectOnLoad", m_WiimoteReconnectOnLoad); + ini.Set("Core", "WiimoteContinuousScanning", m_WiimoteContinuousScanning); + ini.Set("Core", "WiimoteEnableSpeaker", m_WiimoteEnableSpeaker); ini.Set("Core", "RunCompareServer", m_LocalCoreStartupParameter.bRunCompareServer); ini.Set("Core", "RunCompareClient", m_LocalCoreStartupParameter.bRunCompareClient); ini.Set("Core", "FrameLimit", m_Framelimit); @@ -285,7 +284,7 @@ void SConfig::LoadSettings() { for (int i = 0; i < numGCMPaths; i++) { - TCHAR tmp[16]; + char tmp[16]; sprintf(tmp, "GCMPath%i", i); std::string tmpPath; ini.Get("General", tmp, &tmpPath, ""); @@ -363,7 +362,11 @@ void SConfig::LoadSettings() // Core ini.Get("Core", "HLE_BS2", &m_LocalCoreStartupParameter.bHLE_BS2, false); +#ifdef _M_ARM + ini.Get("Core", "CPUCore", &m_LocalCoreStartupParameter.iCPUCore, 3); +#else ini.Get("Core", "CPUCore", &m_LocalCoreStartupParameter.iCPUCore, 1); +#endif ini.Get("Core", "DSPThread", &m_LocalCoreStartupParameter.bDSPThread, false); ini.Get("Core", "DSPHLE", &m_LocalCoreStartupParameter.bDSPHLE, true); ini.Get("Core", "CPUThread", &m_LocalCoreStartupParameter.bCPUThread, true); @@ -393,7 +396,9 @@ void SConfig::LoadSettings() ini.Get("Core", "WiiSDCard", &m_WiiSDCard, false); ini.Get("Core", "WiiKeyboard", &m_WiiKeyboard, false); - ini.Get("Core", "WiimoteReconnectOnLoad", &m_WiimoteReconnectOnLoad, true); + ini.Get("Core", "WiimoteReconnectOnLoad", &m_WiimoteReconnectOnLoad, true); + ini.Get("Core", "WiimoteContinuousScanning", &m_WiimoteContinuousScanning, false); + ini.Get("Core", "WiimoteEnableSpeaker", &m_WiimoteEnableSpeaker, true); ini.Get("Core", "RunCompareServer", &m_LocalCoreStartupParameter.bRunCompareServer, false); ini.Get("Core", "RunCompareClient", &m_LocalCoreStartupParameter.bRunCompareClient, false); ini.Get("Core", "MMU", &m_LocalCoreStartupParameter.bMMU, false); @@ -428,18 +433,3 @@ void SConfig::LoadSettings() m_SYSCONF = new SysConf(); } -void SConfig::LoadSettingsWii() -{ - IniFile ini; - //Wiimote configs - ini.Load((File::GetUserPath(D_CONFIG_IDX) + "Dolphin.ini")); - for (int i = 0; i < 4; i++) - { - char SectionName[32]; - sprintf(SectionName, "Wiimote%i", i + 1); - ini.Get(SectionName, "AutoReconnectRealWiimote", &m_WiiAutoReconnect[i], false); - } - ini.Load((File::GetUserPath(D_CONFIG_IDX) + "wiimote.ini")); - ini.Get("Real", "Unpair", &m_WiiAutoUnpair, false); - -} diff --git a/Source/Core/Core/Src/ConfigManager.h b/Source/Core/Core/Src/ConfigManager.h index e92d29ee65..4a36b37335 100644 --- a/Source/Core/Core/Src/ConfigManager.h +++ b/Source/Core/Core/Src/ConfigManager.h @@ -35,15 +35,15 @@ #define BACKEND_OPENAL "OpenAL" #define BACKEND_PULSEAUDIO "Pulse" #define BACKEND_XAUDIO2 "XAudio2" - +#define BACKEND_OPENSLES "OpenSLES" struct SConfig : NonCopyable { // Wii Devices bool m_WiiSDCard; bool m_WiiKeyboard; - bool m_WiiAutoReconnect[4]; - bool m_WiiAutoUnpair; bool m_WiimoteReconnectOnLoad; + bool m_WiimoteContinuousScanning; + bool m_WiimoteEnableSpeaker; // name of the last used filename std::string m_LastFilename; @@ -107,9 +107,6 @@ struct SConfig : NonCopyable // load settings void LoadSettings(); - //Special load settings - void LoadSettingsWii(); - // Return the permanent and somewhat globally used instance of this struct static SConfig& GetInstance() {return(*m_Instance);} diff --git a/Source/Core/Core/Src/Console.cpp b/Source/Core/Core/Src/Console.cpp index 759dc46bc5..b0ef416a84 100644 --- a/Source/Core/Core/Src/Console.cpp +++ b/Source/Core/Core/Src/Console.cpp @@ -98,8 +98,8 @@ void Console_Submit(const char *cmd) } CASE("dump") { - TCHAR temp[256]; - TCHAR filename[256]; + char temp[256]; + char filename[256]; u32 start; u32 end; sscanf(cmd, "%s %08x %08x %s", temp, &start, &end, filename); diff --git a/Source/Core/Core/Src/Core.cpp b/Source/Core/Core/Src/Core.cpp index 87348e5a74..61e3e404ed 100644 --- a/Source/Core/Core/Src/Core.cpp +++ b/Source/Core/Core/Src/Core.cpp @@ -54,7 +54,6 @@ #include "IPC_HLE/WII_IPC_HLE_Device_usb.h" #include "PowerPC/PowerPC.h" -#include "PowerPC/JitCommon/JitBase.h" #include "DSPEmulator.h" #include "ConfigManager.h" @@ -140,7 +139,7 @@ void DisplayMessage(const char *message, int time_in_ms) if (_CoreParameter.bRenderToMain && SConfig::GetInstance().m_InterfaceStatusbar) { - Host_UpdateStatusBar(message); + Host_UpdateStatusBar(message); } else Host_UpdateTitle(message); @@ -189,7 +188,7 @@ bool IsGPUThread() return IsCPUThread(); } } - + // This is called from the GUI thread. See the booting call schedule in // BootManager.cpp bool Init() @@ -310,7 +309,7 @@ void CpuThread() g_video_backend->Video_Prepare(); } - #if defined(_M_X64) + #if defined(_M_X64) || _M_ARM EMM::InstallExceptionHandler(); // Let's run under memory watch #endif diff --git a/Source/Core/Core/Src/DSP/DSPEmitter.cpp b/Source/Core/Core/Src/DSP/DSPEmitter.cpp index 2ce441bf31..12dac52e31 100644 --- a/Source/Core/Core/Src/DSP/DSPEmitter.cpp +++ b/Source/Core/Core/Src/DSP/DSPEmitter.cpp @@ -25,7 +25,7 @@ #include "DSPAnalyzer.h" #include "Jit/DSPJitUtil.h" #include "x64Emitter.h" -#include "ABI.h" +#include "x64ABI.h" #define MAX_BLOCK_SIZE 250 #define DSP_IDLE_SKIP_CYCLES 0x1000 diff --git a/Source/Core/Core/Src/DSP/DSPHWInterface.cpp b/Source/Core/Core/Src/DSP/DSPHWInterface.cpp index f2cbbc2b9f..e4c81e4a7a 100644 --- a/Source/Core/Core/Src/DSP/DSPHWInterface.cpp +++ b/Source/Core/Core/Src/DSP/DSPHWInterface.cpp @@ -252,7 +252,9 @@ static void gdsp_idma_out(u16 dsp_addr, u32 addr, u32 size) ERROR_LOG(DSPLLE, "*** idma_out IRAM_DSP (0x%04x) -> RAM (0x%08x) : size (0x%08x)", dsp_addr / 2, addr, size); } +#if _M_SSE >= 0x301 static const __m128i s_mask = _mm_set_epi32(0x0E0F0C0DL, 0x0A0B0809L, 0x06070405L, 0x02030001L); +#endif // TODO: These should eat clock cycles. static void gdsp_ddma_in(u16 dsp_addr, u32 addr, u32 size) diff --git a/Source/Core/Core/Src/DSP/Jit/DSPJitArithmetic.cpp b/Source/Core/Core/Src/DSP/Jit/DSPJitArithmetic.cpp index 0b75431de6..185ada8ba3 100644 --- a/Source/Core/Core/Src/DSP/Jit/DSPJitArithmetic.cpp +++ b/Source/Core/Core/Src/DSP/Jit/DSPJitArithmetic.cpp @@ -25,7 +25,7 @@ #include "DSPJitUtil.h" #endif #include "x64Emitter.h" -#include "ABI.h" +#include "x64ABI.h" using namespace Gen; // CLR $acR diff --git a/Source/Core/Core/Src/DSP/Jit/DSPJitBranch.cpp b/Source/Core/Core/Src/DSP/Jit/DSPJitBranch.cpp index 8ca770e35d..252550b84c 100644 --- a/Source/Core/Core/Src/DSP/Jit/DSPJitBranch.cpp +++ b/Source/Core/Core/Src/DSP/Jit/DSPJitBranch.cpp @@ -21,7 +21,7 @@ #include "../DSPAnalyzer.h" #include "DSPJitUtil.h" #include "x64Emitter.h" -#include "ABI.h" +#include "x64ABI.h" using namespace Gen; diff --git a/Source/Core/Core/Src/DSP/Jit/DSPJitCCUtil.cpp b/Source/Core/Core/Src/DSP/Jit/DSPJitCCUtil.cpp index e382b6114a..be7675378d 100644 --- a/Source/Core/Core/Src/DSP/Jit/DSPJitCCUtil.cpp +++ b/Source/Core/Core/Src/DSP/Jit/DSPJitCCUtil.cpp @@ -24,7 +24,7 @@ #include "../DSPEmitter.h" #include "DSPJitUtil.h" #include "x64Emitter.h" -#include "ABI.h" +#include "x64ABI.h" using namespace Gen; // In: RAX: s64 _Value diff --git a/Source/Core/Core/Src/DSP/Jit/DSPJitExtOps.cpp b/Source/Core/Core/Src/DSP/Jit/DSPJitExtOps.cpp index 8203f7cde1..40e39a89e9 100644 --- a/Source/Core/Core/Src/DSP/Jit/DSPJitExtOps.cpp +++ b/Source/Core/Core/Src/DSP/Jit/DSPJitExtOps.cpp @@ -18,7 +18,7 @@ #include "../DSPEmitter.h" #include "DSPJitUtil.h" #include "x64Emitter.h" -#include "ABI.h" +#include "x64ABI.h" using namespace Gen; diff --git a/Source/Core/Core/Src/DSP/Jit/DSPJitLoadStore.cpp b/Source/Core/Core/Src/DSP/Jit/DSPJitLoadStore.cpp index a784e2dd2d..248ed8f945 100644 --- a/Source/Core/Core/Src/DSP/Jit/DSPJitLoadStore.cpp +++ b/Source/Core/Core/Src/DSP/Jit/DSPJitLoadStore.cpp @@ -22,7 +22,7 @@ #include "../DSPEmitter.h" #include "DSPJitUtil.h" #include "x64Emitter.h" -#include "ABI.h" +#include "x64ABI.h" using namespace Gen; // SRS @M, $(0x18+S) diff --git a/Source/Core/Core/Src/DSP/Jit/DSPJitMisc.cpp b/Source/Core/Core/Src/DSP/Jit/DSPJitMisc.cpp index 8d8a635536..d0bf7a3822 100644 --- a/Source/Core/Core/Src/DSP/Jit/DSPJitMisc.cpp +++ b/Source/Core/Core/Src/DSP/Jit/DSPJitMisc.cpp @@ -20,7 +20,7 @@ #include "../DSPEmitter.h" #include "DSPJitUtil.h" #include "x64Emitter.h" -#include "ABI.h" +#include "x64ABI.h" using namespace Gen; //clobbers: diff --git a/Source/Core/Core/Src/DSP/Jit/DSPJitMultiplier.cpp b/Source/Core/Core/Src/DSP/Jit/DSPJitMultiplier.cpp index 1323de002d..0dcbf41877 100644 --- a/Source/Core/Core/Src/DSP/Jit/DSPJitMultiplier.cpp +++ b/Source/Core/Core/Src/DSP/Jit/DSPJitMultiplier.cpp @@ -27,7 +27,7 @@ #include "DSPJitUtil.h" #endif #include "x64Emitter.h" -#include "ABI.h" +#include "x64ABI.h" using namespace Gen; // Returns s64 in RAX diff --git a/Source/Core/Core/Src/DSP/Jit/DSPJitUtil.cpp b/Source/Core/Core/Src/DSP/Jit/DSPJitUtil.cpp index b9e166f698..2fb18f83da 100644 --- a/Source/Core/Core/Src/DSP/Jit/DSPJitUtil.cpp +++ b/Source/Core/Core/Src/DSP/Jit/DSPJitUtil.cpp @@ -20,7 +20,7 @@ #include "../DSPEmitter.h" #include "DSPJitUtil.h" #include "x64Emitter.h" -#include "ABI.h" +#include "x64ABI.h" using namespace Gen; diff --git a/Source/Core/Core/Src/DSP/assemble.cpp b/Source/Core/Core/Src/DSP/assemble.cpp index dd394ab82c..248b0d8ba8 100644 --- a/Source/Core/Core/Src/DSP/assemble.cpp +++ b/Source/Core/Core/Src/DSP/assemble.cpp @@ -754,7 +754,8 @@ bool DSPAssembler::AssembleFile(const char *fname, int pass) { int disable_text = 0; // modified by Hermes - std::ifstream fsrc(fname); + std::ifstream fsrc; + OpenFStream(fsrc, fname, std::ios_base::in); if (fsrc.fail()) { diff --git a/Source/Core/Core/Src/HW/BBA-TAP/TAP_Win32.cpp b/Source/Core/Core/Src/HW/BBA-TAP/TAP_Win32.cpp index 87ebd90344..03332d3012 100644 --- a/Source/Core/Core/Src/HW/BBA-TAP/TAP_Win32.cpp +++ b/Source/Core/Core/Src/HW/BBA-TAP/TAP_Win32.cpp @@ -25,7 +25,7 @@ namespace Win32TAPHelper { -bool IsTAPDevice(const char *guid) +bool IsTAPDevice(const TCHAR *guid) { HKEY netcard_key; LONG status; @@ -39,13 +39,13 @@ bool IsTAPDevice(const char *guid) for (;;) { - char enum_name[256]; - char unit_string[256]; + TCHAR enum_name[256]; + TCHAR unit_string[256]; HKEY unit_key; - char component_id_string[] = "ComponentId"; - char component_id[256]; - char net_cfg_instance_id_string[] = "NetCfgInstanceId"; - char net_cfg_instance_id[256]; + TCHAR component_id_string[] = _T("ComponentId"); + TCHAR component_id[256]; + TCHAR net_cfg_instance_id_string[] = _T("NetCfgInstanceId"); + TCHAR net_cfg_instance_id[256]; DWORD data_type; len = sizeof(enum_name); @@ -56,7 +56,7 @@ bool IsTAPDevice(const char *guid) else if (status != ERROR_SUCCESS) return false; - snprintf(unit_string, sizeof(unit_string), "%s\\%s", ADAPTER_KEY, enum_name); + _sntprintf(unit_string, sizeof(unit_string), _T("%s\\%s"), ADAPTER_KEY, enum_name); status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, unit_string, 0, KEY_READ, &unit_key); @@ -78,8 +78,8 @@ bool IsTAPDevice(const char *guid) if (status == ERROR_SUCCESS && data_type == REG_SZ) { - if (!strcmp(component_id, TAP_COMPONENT_ID) && - !strcmp(net_cfg_instance_id, guid)) + if (!_tcscmp(component_id, TAP_COMPONENT_ID) && + !_tcscmp(net_cfg_instance_id, guid)) { RegCloseKey(unit_key); RegCloseKey(netcard_key); @@ -96,7 +96,7 @@ bool IsTAPDevice(const char *guid) return false; } -bool GetGUIDs(std::vector& guids) +bool GetGUIDs(std::vector>& guids) { LONG status; HKEY control_net_key; @@ -111,12 +111,12 @@ bool GetGUIDs(std::vector& guids) while (!found_all) { - char enum_name[256]; - char connection_string[256]; + TCHAR enum_name[256]; + TCHAR connection_string[256]; HKEY connection_key; - char name_data[256]; + TCHAR name_data[256]; DWORD name_type; - const char name_string[] = "Name"; + const TCHAR name_string[] = _T("Name"); len = sizeof(enum_name); status = RegEnumKeyEx(control_net_key, i, enum_name, @@ -127,8 +127,8 @@ bool GetGUIDs(std::vector& guids) else if (status != ERROR_SUCCESS) return false; - snprintf(connection_string, sizeof(connection_string), - "%s\\%s\\Connection", NETWORK_CONNECTIONS_KEY, enum_name); + _sntprintf(connection_string, sizeof(connection_string), + _T("%s\\%s\\Connection"), NETWORK_CONNECTIONS_KEY, enum_name); status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, connection_string, 0, KEY_READ, &connection_key); @@ -165,15 +165,11 @@ bool GetGUIDs(std::vector& guids) return true; } -bool OpenTAP(HANDLE& adapter, const std::string device_guid) +bool OpenTAP(HANDLE& adapter, const std::basic_string& device_guid) { - char device_path[256]; + auto const device_path = USERMODEDEVICEDIR + device_guid + TAPSUFFIX; - /* Open Windows TAP-Win32 adapter */ - snprintf(device_path, sizeof(device_path), "%s%s%s", - USERMODEDEVICEDIR, device_guid.c_str(), TAPSUFFIX); - - adapter = CreateFile(device_path, GENERIC_READ | GENERIC_WRITE, 0, 0, + adapter = CreateFile(device_path.c_str(), GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, 0); if (adapter == INVALID_HANDLE_VALUE) @@ -192,7 +188,7 @@ bool CEXIETHERNET::Activate() return true; DWORD len; - std::vector device_guids; + std::vector> device_guids; if (!Win32TAPHelper::GetGUIDs(device_guids)) { diff --git a/Source/Core/Core/Src/HW/BBA-TAP/TAP_Win32.h b/Source/Core/Core/Src/HW/BBA-TAP/TAP_Win32.h index 2676a3fc7e..2a5bc52ffa 100644 --- a/Source/Core/Core/Src/HW/BBA-TAP/TAP_Win32.h +++ b/Source/Core/Core/Src/HW/BBA-TAP/TAP_Win32.h @@ -65,18 +65,18 @@ // Registry keys //================= -#define ADAPTER_KEY "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}" +#define ADAPTER_KEY _T("SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}") -#define NETWORK_CONNECTIONS_KEY "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}" +#define NETWORK_CONNECTIONS_KEY _T("SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}") //====================== // Filesystem prefixes //====================== -#define USERMODEDEVICEDIR "\\\\.\\Global\\" -#define SYSDEVICEDIR "\\Device\\" -#define USERDEVICEDIR "\\DosDevices\\Global\\" -#define TAPSUFFIX ".tap" +#define USERMODEDEVICEDIR _T("\\\\.\\Global\\") +#define SYSDEVICEDIR _T("\\Device\\") +#define USERDEVICEDIR _T("\\DosDevices\\Global\\") +#define TAPSUFFIX _T(".tap") //========================================================= // TAP_COMPONENT_ID -- This string defines the TAP driver @@ -84,4 +84,4 @@ // simultaneously. //========================================================= -#define TAP_COMPONENT_ID "tap0901" +#define TAP_COMPONENT_ID _T("tap0901") diff --git a/Source/Core/Core/Src/HW/DSPHLE/DSPHLE.cpp b/Source/Core/Core/Src/HW/DSPHLE/DSPHLE.cpp index b22be91104..6d2a1f9097 100644 --- a/Source/Core/Core/Src/HW/DSPHLE/DSPHLE.cpp +++ b/Source/Core/Core/Src/HW/DSPHLE/DSPHLE.cpp @@ -27,6 +27,7 @@ #include "UCodes/UCodes.h" #include "../AudioInterface.h" #include "ConfigManager.h" +#include "Core.h" DSPHLE::DSPHLE() { m_InitMixer = false; @@ -130,6 +131,14 @@ void DSPHLE::SwapUCode(u32 _crc) void DSPHLE::DoState(PointerWrap &p) { + bool isHLE = true; + p.Do(isHLE); + if (isHLE != true && p.GetMode() == PointerWrap::MODE_READ) + { + Core::DisplayMessage("State is incompatible with current DSP engine. Aborting load state.", 3000); + p.SetMode(PointerWrap::MODE_VERIFY); + return; + } bool prevInitMixer = m_InitMixer; p.Do(m_InitMixer); if (prevInitMixer != m_InitMixer && p.GetMode() == PointerWrap::MODE_READ) diff --git a/Source/Core/Core/Src/HW/DSPLLE/DSPLLE.cpp b/Source/Core/Core/Src/HW/DSPLLE/DSPLLE.cpp index 92053053de..2cbf39f457 100644 --- a/Source/Core/Core/Src/HW/DSPLLE/DSPLLE.cpp +++ b/Source/Core/Core/Src/HW/DSPLLE/DSPLLE.cpp @@ -26,6 +26,7 @@ #include "IniFile.h" #include "ConfigManager.h" #include "CPUDetect.h" +#include "Core.h" #include "DSPLLEGlobals.h" // Local #include "DSP/DSPInterpreter.h" @@ -56,6 +57,14 @@ Common::Event ppcEvent; void DSPLLE::DoState(PointerWrap &p) { + bool isHLE = false; + p.Do(isHLE); + if (isHLE != false && p.GetMode() == PointerWrap::MODE_READ) + { + Core::DisplayMessage("State is incompatible with current DSP engine. Aborting load state.", 3000); + p.SetMode(PointerWrap::MODE_VERIFY); + return; + } p.Do(g_dsp.r); p.Do(g_dsp.pc); #if PROFILE diff --git a/Source/Core/Core/Src/HW/GCMemcard.cpp b/Source/Core/Core/Src/HW/GCMemcard.cpp index dd15a32914..a2c9690b4e 100644 --- a/Source/Core/Core/Src/HW/GCMemcard.cpp +++ b/Source/Core/Core/Src/HW/GCMemcard.cpp @@ -432,7 +432,6 @@ std::string GCMemcard::DEntry_BIFlags(u8 index) const flags.push_back((x & 0x80) ? '1' : '0'); x = x << 1; } - flags.push_back(0); return flags; } @@ -469,7 +468,6 @@ std::string GCMemcard::DEntry_IconFmt(u8 index) const format.push_back((x & 0x80) ? '1' : '0'); x = x << 1; } - format.push_back(0); return format; } @@ -485,7 +483,6 @@ std::string GCMemcard::DEntry_AnimSpeed(u8 index) const speed.push_back((x & 0x80) ? '1' : '0'); x = x << 1; } - speed.push_back(0); return speed; } @@ -498,7 +495,6 @@ std::string GCMemcard::DEntry_Permissions(u8 index) const permissionsString.push_back((Permissions & 16) ? 'x' : 'M'); permissionsString.push_back((Permissions & 8) ? 'x' : 'C'); permissionsString.push_back((Permissions & 4) ? 'P' : 'x'); - permissionsString.push_back(0); return permissionsString; } diff --git a/Source/Core/Core/Src/HW/Memmap.cpp b/Source/Core/Core/Src/HW/Memmap.cpp index 88f6b2c358..6a6fb14212 100644 --- a/Source/Core/Core/Src/HW/Memmap.cpp +++ b/Source/Core/Core/Src/HW/Memmap.cpp @@ -419,132 +419,6 @@ u32 Read_Instruction(const u32 em_address) return inst.hex; } -u32 Read_Opcode_JIT_Uncached(const u32 _Address) -{ - u8* iCache; - u32 addr; - if (_Address & JIT_ICACHE_VMEM_BIT) - { - iCache = jit->GetBlockCache()->GetICacheVMEM(); - addr = _Address & JIT_ICACHE_MASK; - } - else if (_Address & JIT_ICACHE_EXRAM_BIT) - { - iCache = jit->GetBlockCache()->GetICacheEx(); - addr = _Address & JIT_ICACHEEX_MASK; - } - else - { - iCache = jit->GetBlockCache()->GetICache(); - addr = _Address & JIT_ICACHE_MASK; - } - u32 inst = *(u32*)(iCache + addr); - if (inst == JIT_ICACHE_INVALID_WORD) - { - u32 cache_block_start = addr & ~0x1f; - u32 mem_block_start = _Address & ~0x1f; - u8 *pMem = Memory::GetPointer(mem_block_start); - memcpy(iCache + cache_block_start, pMem, 32); - inst = *(u32*)(iCache + addr); - } - inst = Common::swap32(inst); - - if ((inst & 0xfc000000) == 0) - { - inst = jit->GetBlockCache()->GetOriginalFirstOp(inst); - } - - return inst; -} - -u32 Read_Opcode_JIT(u32 _Address) -{ -#ifdef FAST_ICACHE - if (bMMU && !bFakeVMEM && (_Address & ADDR_MASK_MEM1)) - { - _Address = Memory::TranslateAddress(_Address, FLAG_OPCODE); - if (_Address == 0) - { - return 0; - } - } - u32 inst = 0; - - // Bypass the icache for the external interrupt exception handler - if ( (_Address & 0x0FFFFF00) == 0x00000500 ) - inst = Read_Opcode_JIT_Uncached(_Address); - else - inst = PowerPC::ppcState.iCache.ReadInstruction(_Address); -#else - u32 inst = Memory::ReadUnchecked_U32(_Address); -#endif - return inst; -} - -// The following function is deprecated in favour of FAST_ICACHE -u32 Read_Opcode_JIT_LC(const u32 _Address) -{ -#ifdef JIT_UNLIMITED_ICACHE - if ((_Address & ~JIT_ICACHE_MASK) != 0x80000000 && (_Address & ~JIT_ICACHE_MASK) != 0x00000000 && - (_Address & ~JIT_ICACHE_MASK) != 0x7e000000 && // TLB area - (_Address & ~JIT_ICACHEEX_MASK) != 0x90000000 && (_Address & ~JIT_ICACHEEX_MASK) != 0x10000000) - { - PanicAlertT("iCacheJIT: Reading Opcode from %x. Please report.", _Address); - ERROR_LOG(MEMMAP, "iCacheJIT: Reading Opcode from %x. Please report.", _Address); - return 0; - } - u8* iCache; - u32 addr; - if (_Address & JIT_ICACHE_VMEM_BIT) - { - iCache = jit->GetBlockCache()->GetICacheVMEM(); - addr = _Address & JIT_ICACHE_MASK; - } - else if (_Address & JIT_ICACHE_EXRAM_BIT) - { - iCache = jit->GetBlockCache()->GetICacheEx(); - addr = _Address & JIT_ICACHEEX_MASK; - } - else - { - iCache = jit->GetBlockCache()->GetICache(); - addr = _Address & JIT_ICACHE_MASK; - } - u32 inst = *(u32*)(iCache + addr); - if (inst == JIT_ICACHE_INVALID_WORD) - inst = Memory::ReadUnchecked_U32(_Address); - else - inst = Common::swap32(inst); -#else - u32 inst = Memory::ReadUnchecked_U32(_Address); -#endif - if ((inst & 0xfc000000) == 0) - { - inst = jit->GetBlockCache()->GetOriginalFirstOp(inst); - } - return inst; -} - -// WARNING! No checks! -// We assume that _Address is cached -void Write_Opcode_JIT(const u32 _Address, const u32 _Value) -{ -#ifdef JIT_UNLIMITED_ICACHE - if (_Address & JIT_ICACHE_VMEM_BIT) - { - *(u32*)(jit->GetBlockCache()->GetICacheVMEM() + (_Address & JIT_ICACHE_MASK)) = Common::swap32(_Value); - } - else if (_Address & JIT_ICACHE_EXRAM_BIT) - { - *(u32*)(jit->GetBlockCache()->GetICacheEx() + (_Address & JIT_ICACHEEX_MASK)) = Common::swap32(_Value); - } - else - *(u32*)(jit->GetBlockCache()->GetICache() + (_Address & JIT_ICACHE_MASK)) = Common::swap32(_Value); -#else - Memory::WriteUnchecked_U32(_Value, _Address); -#endif -} - void WriteBigEData(const u8 *_pData, const u32 _Address, const u32 _iSize) { memcpy(GetPointer(_Address), _pData, _iSize); diff --git a/Source/Core/Core/Src/HW/Memmap.h b/Source/Core/Core/Src/HW/Memmap.h index 42ceb737ca..8662804185 100644 --- a/Source/Core/Core/Src/HW/Memmap.h +++ b/Source/Core/Core/Src/HW/Memmap.h @@ -119,11 +119,6 @@ inline u32 ReadFast32(const u32 _Address) // used by interpreter to read instructions, uses iCache u32 Read_Opcode(const u32 _Address); -// used by JIT to read instructions -u32 Read_Opcode_JIT(const u32 _Address); -// used by JIT. uses iCacheJIT. Reads in the "Locked cache" mode -u32 Read_Opcode_JIT_LC(const u32 _Address); -void Write_Opcode_JIT(const u32 _Address, const u32 _Value); // this is used by Debugger a lot. // For now, just reads from memory! u32 Read_Instruction(const u32 _Address); diff --git a/Source/Core/Core/Src/HW/Wiimote.cpp b/Source/Core/Core/Src/HW/Wiimote.cpp index 59fe8b7fa5..e45856f5f5 100644 --- a/Source/Core/Core/Src/HW/Wiimote.cpp +++ b/Source/Core/Core/Src/HW/Wiimote.cpp @@ -133,7 +133,7 @@ unsigned int GetAttached() // input/output: ptr // input: mode // -void DoState(unsigned char **ptr, int mode) +void DoState(u8 **ptr, PointerWrap::Mode mode) { // TODO: diff --git a/Source/Core/Core/Src/HW/Wiimote.h b/Source/Core/Core/Src/HW/Wiimote.h index 5e0ab8d05e..6b758abb5a 100644 --- a/Source/Core/Core/Src/HW/Wiimote.h +++ b/Source/Core/Core/Src/HW/Wiimote.h @@ -3,6 +3,7 @@ #define _WIIMOTE_H_ #include "../../InputCommon/Src/InputConfig.h" +#include "ChunkFile.h" #define MAX_WIIMOTES 4 @@ -25,7 +26,7 @@ void Shutdown(); void Initialize(void* const hwnd); unsigned int GetAttached(); -void DoState(unsigned char **ptr, int mode); +void DoState(u8 **ptr, PointerWrap::Mode mode); void EmuStateChange(EMUSTATE_CHANGE newState); InputPlugin *GetPlugin(); @@ -38,17 +39,12 @@ void Update(int _number); namespace WiimoteReal { -unsigned int Initialize(); +void Initialize(); void Shutdown(); void Refresh(); void LoadSettings(); -#ifdef _WIN32 -int PairUp(bool unpair = false); -int UnPair(); -#endif - } #endif diff --git a/Source/Core/Core/Src/HW/WiimoteEmu/EmuSubroutines.cpp b/Source/Core/Core/Src/HW/WiimoteEmu/EmuSubroutines.cpp index 5c34fff9ac..5710fd4f25 100644 --- a/Source/Core/Core/Src/HW/WiimoteEmu/EmuSubroutines.cpp +++ b/Source/Core/Core/Src/HW/WiimoteEmu/EmuSubroutines.cpp @@ -248,13 +248,12 @@ void Wiimote::RequestStatus(const wm_request_status* const rs) { using namespace WiimoteReal; - std::lock_guard lk(g_refresh_lock); + std::lock_guard lk(g_refresh_lock); if (g_wiimotes[m_index]) { - wm_request_status rpt; - rpt.rumble = 0; - g_wiimotes[m_index]->SendPacket(WM_REQUEST_STATUS, &rpt, sizeof(rpt)); + wm_request_status rpt = {}; + g_wiimotes[m_index]->QueueReport(WM_REQUEST_STATUS, &rpt, sizeof(rpt)); } return; @@ -298,7 +297,7 @@ void Wiimote::WriteData(const wm_write_data* const wd) { // writing the whole mii block each write :/ std::ofstream file; - file.open((File::GetUserPath(D_WIIUSER_IDX) + "mii.bin").c_str(), std::ios::binary | std::ios::out); + OpenFStream(file, File::GetUserPath(D_WIIUSER_IDX) + "mii.bin", std::ios::binary | std::ios::out); file.write((char*)m_eeprom + 0x0FCA, 0x02f0); file.close(); } diff --git a/Source/Core/Core/Src/HW/WiimoteEmu/Speaker.cpp b/Source/Core/Core/Src/HW/WiimoteEmu/Speaker.cpp index ba01239bf2..c743c80294 100644 --- a/Source/Core/Core/Src/HW/WiimoteEmu/Speaker.cpp +++ b/Source/Core/Core/Src/HW/WiimoteEmu/Speaker.cpp @@ -106,7 +106,7 @@ void Wiimote::SpeakerData(wm_speaker_data* sd) File::Delete("rmtdump.wav"); File::Delete("rmtdump.bin"); atexit(stopdamnwav); - ofile.open("rmtdump.bin", ofile.binary | ofile.out); + OpenFStream(ofile, "rmtdump.bin", ofile.binary | ofile.out); wav.Start("rmtdump.wav", 6000/*Common::swap16(m_reg_speaker.sample_rate)*/); } wav.AddMonoSamples(samples, sd->length*2); diff --git a/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.cpp b/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.cpp index 6fe6b81613..92018f7c21 100644 --- a/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.cpp +++ b/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.cpp @@ -704,7 +704,7 @@ void Wiimote::Update() { using namespace WiimoteReal; - std::lock_guard lk(g_refresh_lock); + std::lock_guard lk(g_refresh_lock); if (g_wiimotes[m_index]) { Report rpt = g_wiimotes[m_index]->ProcessReadQueue(); diff --git a/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteHid.h b/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteHid.h index fd7c549e8d..9d1a2092a0 100644 --- a/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteHid.h +++ b/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteHid.h @@ -201,6 +201,7 @@ struct wm_report #define WM_LEDS 0x11 struct wm_leds { u8 rumble : 1; + // real wii also sets bit 0x2 (unknown purpose) u8 : 3; u8 leds : 4; }; @@ -208,8 +209,9 @@ struct wm_leds { #define WM_REPORT_MODE 0x12 struct wm_report_mode { u8 rumble : 1; - u8 continuous : 1; // these 2 seem to be named wrong + // unsure what "all_the_time" actually is, the real wii does set it (bit 0x2) u8 all_the_time : 1; + u8 continuous : 1; u8 : 5; u8 mode; }; diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IODummy.cpp b/Source/Core/Core/Src/HW/WiimoteReal/IODummy.cpp index 49afee8ad1..3a017354eb 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/IODummy.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/IODummy.cpp @@ -21,9 +21,25 @@ namespace WiimoteReal { -int FindWiimotes(Wiimote **wm, int max_wiimotes) +WiimoteScanner::WiimoteScanner() { - return 0; + return; +} + +WiimoteScanner::~WiimoteScanner() +{} + +void WiimoteScanner::Update() +{} + +std::vector WiimoteScanner::FindWiimotes() +{ + return std::vector(); +} + +bool WiimoteScanner::IsReady() const +{ + return false; } bool Wiimote::Connect() @@ -31,22 +47,22 @@ bool Wiimote::Connect() return 0; } -void Wiimote::RealDisconnect() +void Wiimote::Disconnect() { return; } -bool Wiimote::IsOpen() const +bool Wiimote::IsConnected() const { - return IsConnected(); + return false; } -int Wiimote::IORead(unsigned char* buf) +int Wiimote::IORead(u8* buf) { return 0; } -int Wiimote::IOWrite(unsigned char* buf, int len) +int Wiimote::IOWrite(const u8* buf, int len) { return 0; } diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IONix.cpp b/Source/Core/Core/Src/HW/WiimoteReal/IONix.cpp index ec838d9313..87ddc5086b 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/IONix.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/IONix.cpp @@ -15,16 +15,6 @@ // Official SVN repository and contact information can be found at // http://code.google.com/p/dolphin-emu/ -#include -#include - -#include -#include -#include -#include -#include -#include - #include #include #include @@ -32,114 +22,116 @@ #include "Common.h" #include "WiimoteReal.h" -#include "Host.h" namespace WiimoteReal { -// Find wiimotes. -// Does not replace already found wiimotes even if they are disconnected. -// wm is an array of max_wiimotes wiimotes -// Returns the total number of found wiimotes. -int FindWiimotes(Wiimote** wm, int max_wiimotes) +WiimoteScanner::WiimoteScanner() + : m_run_thread() + , m_want_wiimotes() + , device_id(-1) + , device_sock(-1) { - int device_id; - int device_sock; - int found_devices; - int found_wiimotes = 0; - int i; - - // Count the number of already found wiimotes - for (i = 0; i < MAX_WIIMOTES; ++i) - { - if (wm[i]) - found_wiimotes++; - } - // Get the id of the first bluetooth device. - if ((device_id = hci_get_route(NULL)) < 0) + device_id = hci_get_route(NULL); + if (device_id < 0) { NOTICE_LOG(WIIMOTE, "Bluetooth not found."); - return found_wiimotes; + return; } // Create a socket to the device - if ((device_sock = hci_open_dev(device_id)) < 0) + device_sock = hci_open_dev(device_id); + if (device_sock < 0) { ERROR_LOG(WIIMOTE, "Unable to open bluetooth."); + return; + } +} + +bool WiimoteScanner::IsReady() const +{ + return device_sock > 0; +} + +WiimoteScanner::~WiimoteScanner() +{ + if (IsReady()) + close(device_sock); +} + +void WiimoteScanner::Update() +{} + +std::vector WiimoteScanner::FindWiimotes() +{ + std::vector found_wiimotes; + + // supposedly 1.28 seconds + int const wait_len = 1; + + int const max_infos = 255; + inquiry_info scan_infos[max_infos] = {}; + auto* scan_infos_ptr = scan_infos; + + // Scan for bluetooth devices + int const found_devices = hci_inquiry(device_id, wait_len, max_infos, NULL, &scan_infos_ptr, IREQ_CACHE_FLUSH); + if (found_devices < 0) + { + ERROR_LOG(WIIMOTE, "Error searching for bluetooth devices."); return found_wiimotes; } - int try_num = 0; - while ((try_num < 5) && (found_wiimotes < max_wiimotes)) + DEBUG_LOG(WIIMOTE, "Found %i bluetooth device(s).", found_devices); + + // Display discovered devices + for (int i = 0; i < found_devices; ++i) { - inquiry_info scan_info_arr[128]; - inquiry_info* scan_info = scan_info_arr; - memset(&scan_info_arr, 0, sizeof(scan_info_arr)); - - // Scan for bluetooth devices for approximately one second - found_devices = hci_inquiry(device_id, 1, 128, NULL, &scan_info, IREQ_CACHE_FLUSH); - if (found_devices < 0) + ERROR_LOG(WIIMOTE, "found a device..."); + + // BT names are a maximum of 248 bytes apparently + char name[255] = {}; + if (hci_read_remote_name(device_sock, &scan_infos[i].bdaddr, sizeof(name), name, 0) < 0) { - ERROR_LOG(WIIMOTE, "Error searching for bluetooth devices."); - return found_wiimotes; + ERROR_LOG(WIIMOTE, "name request failed"); + continue; } - DEBUG_LOG(WIIMOTE, "Found %i bluetooth device(s).", found_devices); - - // Display discovered devices - for (i = 0; (i < found_devices) && (found_wiimotes < max_wiimotes); ++i) + ERROR_LOG(WIIMOTE, "device name %s", name); + if (IsValidBluetoothName(name)) { - char name[1000]; - memset(name, 0, sizeof(name)); - ERROR_LOG(WIIMOTE, "found a device..."); - if (hci_read_remote_name(device_sock, &scan_info[i].bdaddr, sizeof(name), name, 0) < 0) { - ERROR_LOG(WIIMOTE, "name request failed"); - continue; - } - ERROR_LOG(WIIMOTE, "device name %s", name); - if (IsValidBluetoothName(name)) + bool new_wiimote = true; + + // TODO: do this + + // Determine if this wiimote has already been found. + //for (int j = 0; j < MAX_WIIMOTES && new_wiimote; ++j) + //{ + // if (wm[j] && bacmp(&scan_infos[i].bdaddr,&wm[j]->bdaddr) == 0) + // new_wiimote = false; + //} + + if (new_wiimote) { - bool new_wiimote = true; - // Determine if this wiimote has already been found. - for (int j = 0; j < MAX_WIIMOTES && new_wiimote; ++j) - { - if (wm[j] && bacmp(&scan_info[i].bdaddr,&wm[j]->bdaddr) == 0) - new_wiimote = false; - } + // Found a new device + char bdaddr_str[18] = {}; + ba2str(&scan_infos[i].bdaddr, bdaddr_str); - if (new_wiimote) - { - // Find an unused slot - unsigned int k = 0; - for (; k < MAX_WIIMOTES && !(WIIMOTE_SRC_REAL & g_wiimote_sources[k] && !wm[k]); ++k); - wm[k] = new Wiimote(k); - - // Found a new device - char bdaddr_str[18]; - ba2str(&scan_info[i].bdaddr, bdaddr_str); - - NOTICE_LOG(WIIMOTE, "Found wiimote %i, (%s).", - wm[k]->index + 1, bdaddr_str); - - wm[k]->bdaddr = scan_info[i].bdaddr; - ++found_wiimotes; - } + auto* const wm = new Wiimote; + wm->bdaddr = scan_infos[i].bdaddr; + found_wiimotes.push_back(wm); + + NOTICE_LOG(WIIMOTE, "Found wiimote (%s).", bdaddr_str); } } - try_num++; } - close(device_sock); return found_wiimotes; } // Connect to a wiimote with a known address. bool Wiimote::Connect() { - if (IsConnected()) - return false; - sockaddr_l2 addr; addr.l2_family = AF_BLUETOOTH; addr.l2_bdaddr = bdaddr; @@ -148,7 +140,7 @@ bool Wiimote::Connect() // Output channel addr.l2_psm = htobs(WM_OUTPUT_CHANNEL); if ((cmd_sock = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP)) == -1 || - connect(cmd_sock, (struct sockaddr*)&addr, sizeof(addr)) < 0) + connect(cmd_sock, (sockaddr*)&addr, sizeof(addr)) < 0) { DEBUG_LOG(WIIMOTE, "Unable to open output socket to wiimote."); close(cmd_sock); @@ -159,7 +151,7 @@ bool Wiimote::Connect() // Input channel addr.l2_psm = htobs(WM_INPUT_CHANNEL); if ((int_sock = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP)) == -1 || - connect(int_sock, (struct sockaddr*)&addr, sizeof(addr)) < 0) + connect(int_sock, (sockaddr*)&addr, sizeof(addr)) < 0) { DEBUG_LOG(WIIMOTE, "Unable to open input socket from wiimote."); close(int_sock); @@ -168,57 +160,27 @@ bool Wiimote::Connect() return false; } - NOTICE_LOG(WIIMOTE, "Connected to wiimote %i.", index + 1); - - m_connected = true; - - // Do the handshake - Handshake(); - - // Set LEDs - SetLEDs(WIIMOTE_LED_1 << index); - - m_wiimote_thread = std::thread(std::mem_fun(&Wiimote::ThreadFunc), this); - return true; } -// Disconnect a wiimote. -void Wiimote::RealDisconnect() +void Wiimote::Disconnect() { - if (!IsConnected()) - return; + close(cmd_sock); + close(int_sock); - NOTICE_LOG(WIIMOTE, "Disconnecting wiimote %i.", index + 1); - - m_connected = false; - - if (m_wiimote_thread.joinable()) - m_wiimote_thread.join(); - - Close(); + cmd_sock = -1; + int_sock = -1; } -void Wiimote::Close() +bool Wiimote::IsConnected() const { - if (IsOpen()) - { - Host_ConnectWiimote(index, false); - - close(cmd_sock); - close(int_sock); - - cmd_sock = -1; - int_sock = -1; - } + return cmd_sock != -1;// && int_sock != -1; } -bool Wiimote::IsOpen() const -{ - return IsConnected() && cmd_sock != -1 && int_sock != -1; -} - -int Wiimote::IORead(unsigned char *buf) +// positive = read packet +// negative = didn't read packet +// zero = error +int Wiimote::IORead(u8* buf) { // Block select for 1/2000th of a second timeval tv; @@ -232,11 +194,11 @@ int Wiimote::IORead(unsigned char *buf) if (select(int_sock + 1, &fds, NULL, NULL, &tv) == -1) { ERROR_LOG(WIIMOTE, "Unable to select wiimote %i input socket.", index + 1); - return 0; + return -1; } if (!FD_ISSET(int_sock, &fds)) - return 0; + return -1; // Read the pending message into the buffer int r = read(int_sock, buf, MAX_PAYLOAD); @@ -250,21 +212,15 @@ int Wiimote::IORead(unsigned char *buf) // This can happen if the bluetooth dongle is disconnected ERROR_LOG(WIIMOTE, "Bluetooth appears to be disconnected. " "Wiimote %i will be disconnected.", index + 1); - Close(); } - return 0; - } - else if (!r) - { - // Disconnect - Close(); + r = 0; } return r; } -int Wiimote::IOWrite(unsigned char* buf, int len) +int Wiimote::IOWrite(u8 const* buf, int len) { return write(int_sock, buf, len); } diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp b/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp index 529a48d15d..08a5db8217 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp @@ -17,7 +17,10 @@ #include #include -#include +#include +#include +#include +#include #include #include @@ -32,6 +35,9 @@ #include #include +//#define AUTHENTICATE_WIIMOTES +#define SHARE_WRITE_WIIMOTES + typedef struct _HIDD_ATTRIBUTES { ULONG Size; @@ -53,6 +59,8 @@ typedef BOOL (__stdcall *PBth_BluetoothFindRadioClose)(HBLUETOOTH_RADIO_FIND); typedef DWORD (__stdcall *PBth_BluetoothGetRadioInfo)(HANDLE, PBLUETOOTH_RADIO_INFO); typedef DWORD (__stdcall *PBth_BluetoothRemoveDevice)(const BLUETOOTH_ADDRESS*); typedef DWORD (__stdcall *PBth_BluetoothSetServiceState)(HANDLE, const BLUETOOTH_DEVICE_INFO*, const GUID*, DWORD); +typedef DWORD (__stdcall *PBth_BluetoothAuthenticateDevice)(HWND, HANDLE, BLUETOOTH_DEVICE_INFO*, PWCHAR, ULONG); +typedef DWORD (__stdcall *PBth_BluetoothEnumerateInstalledServices)(HANDLE, BLUETOOTH_DEVICE_INFO*, DWORD*, GUID*); PHidD_GetHidGuid HidD_GetHidGuid = NULL; PHidD_GetAttributes HidD_GetAttributes = NULL; @@ -67,12 +75,21 @@ PBth_BluetoothFindRadioClose Bth_BluetoothFindRadioClose = NULL; PBth_BluetoothGetRadioInfo Bth_BluetoothGetRadioInfo = NULL; PBth_BluetoothRemoveDevice Bth_BluetoothRemoveDevice = NULL; PBth_BluetoothSetServiceState Bth_BluetoothSetServiceState = NULL; +PBth_BluetoothAuthenticateDevice Bth_BluetoothAuthenticateDevice = NULL; +PBth_BluetoothEnumerateInstalledServices Bth_BluetoothEnumerateInstalledServices = NULL; HINSTANCE hid_lib = NULL; HINSTANCE bthprops_lib = NULL; static int initialized = 0; +std::unordered_map g_connect_times; + +#ifdef SHARE_WRITE_WIIMOTES +std::unordered_set> g_connected_wiimotes; +std::mutex g_connected_wiimotes_lock; +#endif + inline void init_lib() { if (!initialized) @@ -109,12 +126,15 @@ inline void init_lib() Bth_BluetoothGetRadioInfo = (PBth_BluetoothGetRadioInfo)GetProcAddress(bthprops_lib, "BluetoothGetRadioInfo"); Bth_BluetoothRemoveDevice = (PBth_BluetoothRemoveDevice)GetProcAddress(bthprops_lib, "BluetoothRemoveDevice"); Bth_BluetoothSetServiceState = (PBth_BluetoothSetServiceState)GetProcAddress(bthprops_lib, "BluetoothSetServiceState"); + Bth_BluetoothAuthenticateDevice = (PBth_BluetoothAuthenticateDevice)GetProcAddress(bthprops_lib, "BluetoothAuthenticateDevice"); + Bth_BluetoothEnumerateInstalledServices = (PBth_BluetoothEnumerateInstalledServices)GetProcAddress(bthprops_lib, "BluetoothEnumerateInstalledServices"); if (!Bth_BluetoothFindDeviceClose || !Bth_BluetoothFindFirstDevice || !Bth_BluetoothFindFirstRadio || !Bth_BluetoothFindNextDevice || !Bth_BluetoothFindNextRadio || !Bth_BluetoothFindRadioClose || !Bth_BluetoothGetRadioInfo || !Bth_BluetoothRemoveDevice || - !Bth_BluetoothSetServiceState) + !Bth_BluetoothSetServiceState || !Bth_BluetoothAuthenticateDevice || + !Bth_BluetoothEnumerateInstalledServices) { PanicAlertT("Failed to load bthprops.cpl"); exit(EXIT_FAILURE); @@ -127,312 +147,353 @@ inline void init_lib() namespace WiimoteReal { +template +void ProcessWiimotes(bool new_scan, T& callback); + +bool AttachWiimote(HANDLE hRadio, const BLUETOOTH_RADIO_INFO&, BLUETOOTH_DEVICE_INFO_STRUCT&); +void RemoveWiimote(BLUETOOTH_DEVICE_INFO_STRUCT&); +bool ForgetWiimote(BLUETOOTH_DEVICE_INFO_STRUCT&); + +WiimoteScanner::WiimoteScanner() + : m_run_thread() + , m_want_wiimotes() +{ + init_lib(); +} + +WiimoteScanner::~WiimoteScanner() +{ + // TODO: what do we want here? + ProcessWiimotes(false, [](HANDLE, BLUETOOTH_RADIO_INFO&, BLUETOOTH_DEVICE_INFO_STRUCT& btdi) + { + RemoveWiimote(btdi); + }); +} + +void WiimoteScanner::Update() +{ + bool forgot_some = false; + + ProcessWiimotes(false, [&](HANDLE, BLUETOOTH_RADIO_INFO&, BLUETOOTH_DEVICE_INFO_STRUCT& btdi) + { + forgot_some |= ForgetWiimote(btdi); + }); + + // Some hacks that allows disconnects to be detected before connections are handled + // workaround for wiimote 1 moving to slot 2 on temporary disconnect + if (forgot_some) + SLEEP(100); +} + // Find and connect wiimotes. // Does not replace already found wiimotes even if they are disconnected. // wm is an array of max_wiimotes wiimotes // Returns the total number of found and connected wiimotes. -int FindWiimotes(Wiimote** wm, int max_wiimotes) +std::vector WiimoteScanner::FindWiimotes() { - GUID device_id; - HANDLE dev; - HDEVINFO device_info; - int found_wiimotes = 0; - DWORD len; - SP_DEVICE_INTERFACE_DATA device_data; - PSP_DEVICE_INTERFACE_DETAIL_DATA detail_data = NULL; - HIDD_ATTRIBUTES attr; - - init_lib(); - - // Count the number of already found wiimotes - for (int i = 0; i < MAX_WIIMOTES; ++i) + ProcessWiimotes(true, [](HANDLE hRadio, const BLUETOOTH_RADIO_INFO& rinfo, BLUETOOTH_DEVICE_INFO_STRUCT& btdi) { - if (wm[i]) - found_wiimotes++; - } - - device_data.cbSize = sizeof(device_data); + ForgetWiimote(btdi); + AttachWiimote(hRadio, rinfo, btdi); + }); // Get the device id + GUID device_id; HidD_GetHidGuid(&device_id); // Get all hid devices connected - device_info = SetupDiGetClassDevs(&device_id, NULL, NULL, (DIGCF_DEVICEINTERFACE | DIGCF_PRESENT)); + HDEVINFO const device_info = SetupDiGetClassDevs(&device_id, NULL, NULL, (DIGCF_DEVICEINTERFACE | DIGCF_PRESENT)); - for (int index = 0; found_wiimotes < max_wiimotes; ++index) + std::vector wiimotes; + + SP_DEVICE_INTERFACE_DATA device_data; + device_data.cbSize = sizeof(device_data); + PSP_DEVICE_INTERFACE_DETAIL_DATA detail_data = NULL; + + for (int index = 0; SetupDiEnumDeviceInterfaces(device_info, NULL, &device_id, index, &device_data); ++index) { - if (detail_data) - { - free(detail_data); - detail_data = NULL; - } - - // Query the next hid device info - if (!SetupDiEnumDeviceInterfaces(device_info, NULL, &device_id, index, &device_data)) - break; - // Get the size of the data block required + DWORD len; SetupDiGetDeviceInterfaceDetail(device_info, &device_data, NULL, 0, &len, NULL); detail_data = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(len); detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); // Query the data for this device - if (!SetupDiGetDeviceInterfaceDetail(device_info, &device_data, detail_data, len, NULL, NULL)) - continue; - - // Determine if this wiimote has already been found. - bool found = false; - for(int i = 0; i < MAX_WIIMOTES; i++) + if (SetupDiGetDeviceInterfaceDetail(device_info, &device_data, detail_data, len, NULL, NULL)) { - if(wm[i] && (wm[i]->devicepath == detail_data->DevicePath)) - { - found = true; - break; - } + auto const wm = new Wiimote; + wm->devicepath = detail_data->DevicePath; + wiimotes.push_back(wm); } - if (found) - continue; - // Open new device - dev = CreateFile(detail_data->DevicePath, - (GENERIC_READ | GENERIC_WRITE), - (FILE_SHARE_READ | FILE_SHARE_WRITE), - NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); - if (dev == INVALID_HANDLE_VALUE) - continue; - - // Get device attributes - attr.Size = sizeof(attr); - HidD_GetAttributes(dev, &attr); - - // Find an unused slot - unsigned int k = 0; - for (; k < MAX_WIIMOTES && !(WIIMOTE_SRC_REAL & g_wiimote_sources[k] && !wm[k]); ++k); - wm[k] = new Wiimote(k); - wm[k]->dev_handle = dev; - wm[k]->devicepath = detail_data->DevicePath; - - if (!wm[k]->Connect()) - { - ERROR_LOG(WIIMOTE, "Unable to connect to wiimote %i.", wm[k]->index + 1); - delete wm[k]; - wm[k] = NULL; - CloseHandle(dev); - } - else - { - ++found_wiimotes; - } - } - - if (detail_data) free(detail_data); + } SetupDiDestroyDeviceInfoList(device_info); - return found_wiimotes; + // Don't mind me, just a random sleep to fix stuff on Windows + //if (!wiimotes.empty()) + // SLEEP(2000); + + return wiimotes; +} + +bool WiimoteScanner::IsReady() const +{ + // TODO: don't search for a radio each time + + BLUETOOTH_FIND_RADIO_PARAMS radioParam; + radioParam.dwSize = sizeof(radioParam); + + HANDLE hRadio; + HBLUETOOTH_RADIO_FIND hFindRadio = Bth_BluetoothFindFirstRadio(&radioParam, &hRadio); + + if (NULL != hFindRadio) + { + Bth_BluetoothFindRadioClose(hFindRadio); + return true; + } + else + { + return false; + } } // Connect to a wiimote with a known device path. bool Wiimote::Connect() { - if (IsConnected()) return false; + if (IsConnected()) + return false; - if (!dev_handle) +#ifdef SHARE_WRITE_WIIMOTES + std::lock_guard lk(g_connected_wiimotes_lock); + if (g_connected_wiimotes.count(devicepath) != 0) + return false; + + auto const open_flags = FILE_SHARE_READ | FILE_SHARE_WRITE; +#else + // Having no FILE_SHARE_WRITE disallows us from connecting to the same wiimote twice. + // (And disallows using wiimotes in use by other programs) + // This is what "WiiYourself" does. + // Apparently this doesn't work for everyone. It might be their fault. + auto const open_flags = FILE_SHARE_READ; +#endif + + dev_handle = CreateFile(devicepath.c_str(), + GENERIC_READ | GENERIC_WRITE, open_flags, + NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); + + if (dev_handle == INVALID_HANDLE_VALUE) { - dev_handle = CreateFile(devicepath.c_str(), - (GENERIC_READ | GENERIC_WRITE), - (FILE_SHARE_READ | FILE_SHARE_WRITE), - NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); - if (dev_handle == INVALID_HANDLE_VALUE) - return false; - } - - hid_overlap.hEvent = CreateEvent(NULL, 1, 1, _T("")); - hid_overlap.Offset = 0; - hid_overlap.OffsetHigh = 0; - - m_connected = true; - - // Try a handshake to see if the device is actually connected - if (!Handshake()) - { - m_connected = false; + dev_handle = 0; return false; } - // Set LEDs - SetLEDs(WIIMOTE_LED_1 << index); +#if 0 + HIDD_ATTRIBUTES attr; + attr.Size = sizeof(attr); + if (!HidD_GetAttributes(dev_handle, &attr)) + { + CloseHandle(dev_handle); + dev_handle = 0; + return false; + } +#endif - m_wiimote_thread = std::thread(std::mem_fun(&Wiimote::ThreadFunc), this); + hid_overlap_read = OVERLAPPED(); + hid_overlap_read.hEvent = CreateEvent(NULL, true, false, NULL); + hid_overlap_write = OVERLAPPED(); + hid_overlap_write.hEvent = CreateEvent(NULL, true, false, NULL); + + // TODO: thread isn't started here now, do this elsewhere // This isn't as drastic as it sounds, since the process in which the threads // reside is normal priority. Needed for keeping audio reports at a decent rate +/* if (!SetThreadPriority(m_wiimote_thread.native_handle(), THREAD_PRIORITY_TIME_CRITICAL)) { ERROR_LOG(WIIMOTE, "Failed to set wiimote thread priority"); } - - NOTICE_LOG(WIIMOTE, "Connected to wiimote %i.", index + 1); +*/ +#ifdef SHARE_WRITE_WIIMOTES + g_connected_wiimotes.insert(devicepath); +#endif return true; } -void Wiimote::RealDisconnect() +void Wiimote::Disconnect() { if (!IsConnected()) return; - m_connected = false; - - if (m_wiimote_thread.joinable()) - m_wiimote_thread.join(); - CloseHandle(dev_handle); dev_handle = 0; - ResetEvent(&hid_overlap); + CloseHandle(hid_overlap_read.hEvent); + CloseHandle(hid_overlap_write.hEvent); + +#ifdef SHARE_WRITE_WIIMOTES + std::lock_guard lk(g_connected_wiimotes_lock); + g_connected_wiimotes.erase(devicepath); +#endif } -bool Wiimote::IsOpen() const +bool Wiimote::IsConnected() const { - return IsConnected(); + return dev_handle != 0; } -int Wiimote::IORead(unsigned char* buf) +// positive = read packet +// negative = didn't read packet +// zero = error +int Wiimote::IORead(u8* buf) { - DWORD b, r; - - init_lib(); - - if (!IsConnected()) - return 0; - + // used below for a warning *buf = 0; - if (!ReadFile(dev_handle, buf, MAX_PAYLOAD, &b, &hid_overlap)) + + DWORD bytes; + ResetEvent(hid_overlap_read.hEvent); + if (!ReadFile(dev_handle, buf, MAX_PAYLOAD - 1, &bytes, &hid_overlap_read)) { - // Partial read - b = GetLastError(); + auto const err = GetLastError(); - if ((b == ERROR_HANDLE_EOF) || (b == ERROR_DEVICE_NOT_CONNECTED)) + if (ERROR_IO_PENDING == err) + { + auto const r = WaitForSingleObject(hid_overlap_read.hEvent, WIIMOTE_DEFAULT_TIMEOUT); + if (WAIT_TIMEOUT == r) + { + // Timeout - cancel and continue + if (*buf) + WARN_LOG(WIIMOTE, "Packet ignored. This may indicate a problem (timeout is %i ms).", + WIIMOTE_DEFAULT_TIMEOUT); + + CancelIo(dev_handle); + bytes = -1; + } + else if (WAIT_FAILED == r) + { + WARN_LOG(WIIMOTE, "A wait error occured on reading from wiimote %i.", index + 1); + bytes = 0; + } + else if (WAIT_OBJECT_0 == r) + { + if (!GetOverlappedResult(dev_handle, &hid_overlap_read, &bytes, TRUE)) + { + WARN_LOG(WIIMOTE, "GetOverlappedResult failed on wiimote %i.", index + 1); + bytes = 0; + } + } + else + { + bytes = 0; + } + } + else if (ERROR_HANDLE_EOF == err) { // Remote disconnect - RealDisconnect(); - return 0; + bytes = 0; } - - r = WaitForSingleObject(hid_overlap.hEvent, WIIMOTE_DEFAULT_TIMEOUT); - if (r == WAIT_TIMEOUT) + else if (ERROR_DEVICE_NOT_CONNECTED == err) { - // Timeout - cancel and continue - - if (*buf) - WARN_LOG(WIIMOTE, "Packet ignored. This may indicate a problem (timeout is %i ms).", - WIIMOTE_DEFAULT_TIMEOUT); - - CancelIo(dev_handle); - ResetEvent(hid_overlap.hEvent); - return 0; + // Remote disconnect + bytes = 0; } - else if (r == WAIT_FAILED) + else { - WARN_LOG(WIIMOTE, "A wait error occured on reading from wiimote %i.", index + 1); - return 0; - } - - if (!GetOverlappedResult(dev_handle, &hid_overlap, &b, 0)) - { - return 0; + bytes = 0; } } - // This needs to be done even if ReadFile fails, essential during init - // Move the data over one, so we can add back in data report indicator byte (here, 0xa1) - memmove(buf + 1, buf, MAX_PAYLOAD - 1); - buf[0] = 0xa1; + if (bytes > 0) + { + // Move the data over one, so we can add back in data report indicator byte (here, 0xa1) + std::copy_n(buf, MAX_PAYLOAD - 1, buf + 1); + buf[0] = 0xa1; - ResetEvent(hid_overlap.hEvent); - return MAX_PAYLOAD; // XXX + // TODO: is this really needed? + bytes = MAX_PAYLOAD; + } + + return bytes; } -int Wiimote::IOWrite(unsigned char* buf, int len) +int Wiimote::IOWrite(const u8* buf, int len) { - DWORD bytes, dw; - int i; - - init_lib(); - - if (!IsConnected()) - return 0; - switch (stack) { - case MSBT_STACK_UNKNOWN: - { - // Try to auto-detect the stack type - if (i = WriteFile(dev_handle, buf + 1, 22, &bytes, &hid_overlap)) - { - // Bluesoleil will always return 1 here, even if it's not connected - stack = MSBT_STACK_BLUESOLEIL; - return i; - } + case MSBT_STACK_UNKNOWN: + { + // Try to auto-detect the stack type + stack = MSBT_STACK_BLUESOLEIL; + if (IOWrite(buf, len)) + return 1; - if (i = HidD_SetOutputReport(dev_handle, buf + 1, len - 1)) - { - stack = MSBT_STACK_MS; - return i; - } + stack = MSBT_STACK_MS; + if (IOWrite(buf, len)) + return 1; - dw = GetLastError(); - // Checking for 121 = timeout on semaphore/device off/disconnected to - // avoid trouble with other stacks toshiba/widcomm - if (dw == 121) - { - NOTICE_LOG(WIIMOTE, "IOWrite[MSBT_STACK_UNKNOWN]: Timeout"); - RealDisconnect(); - } - else ERROR_LOG(WIIMOTE, - "IOWrite[MSBT_STACK_UNKNOWN]: ERROR: %08x", dw); - return 0; - } + stack = MSBT_STACK_UNKNOWN; + break; + } + case MSBT_STACK_MS: + { + auto result = HidD_SetOutputReport(dev_handle, const_cast(buf) + 1, len - 1); + //FlushFileBuffers(dev_handle); - case MSBT_STACK_MS: - i = HidD_SetOutputReport(dev_handle, buf + 1, len - 1); - dw = GetLastError(); - - if (dw == 121) + if (!result) + { + auto err = GetLastError(); + if (err == 121) { // Semaphore timeout NOTICE_LOG(WIIMOTE, "WiimoteIOWrite[MSBT_STACK_MS]: Unable to send data to wiimote"); - RealDisconnect(); - return 0; } - return i; + else + { + WARN_LOG(WIIMOTE, "IOWrite[MSBT_STACK_MS]: ERROR: %08x", err); + } + } - case MSBT_STACK_BLUESOLEIL: - return WriteFile(dev_handle, buf + 1, 22, &bytes, &hid_overlap); + return result; + break; + } + case MSBT_STACK_BLUESOLEIL: + { + u8 big_buf[MAX_PAYLOAD]; + if (len < MAX_PAYLOAD) + { + std::copy(buf, buf + len, big_buf); + std::fill(big_buf + len, big_buf + MAX_PAYLOAD, 0); + buf = big_buf; + } + + ResetEvent(hid_overlap_write.hEvent); + DWORD bytes = 0; + if (WriteFile(dev_handle, buf + 1, MAX_PAYLOAD - 1, &bytes, &hid_overlap_write)) + { + // WriteFile always returns true with bluesoleil. + return 1; + } + else + { + auto const err = GetLastError(); + if (ERROR_IO_PENDING == err) + { + CancelIo(dev_handle); + } + } + break; + } } return 0; } -int UnPair() +// invokes callback for each found wiimote bluetooth device +template +void ProcessWiimotes(bool new_scan, T& callback) { - // TODO: - return 0; -} - -// WiiMote Pair-Up, function will return amount of either new paired or unpaired devices -// negative number on failure -int PairUp(bool unpair) -{ - init_lib(); - - // match strings like "Nintendo RVL-WBC-01", "Nintendo RVL-CNT-01", "Nintendo RVL-CNT-01-TR" - const std::wregex wiimote_device_name(L"Nintendo RVL-\\w{3}-\\d{2}(-\\w{2})?"); - - int nPaired = 0; - BLUETOOTH_DEVICE_SEARCH_PARAMS srch; srch.dwSize = sizeof(srch); srch.fReturnAuthenticated = true; @@ -441,83 +502,50 @@ int PairUp(bool unpair) // fConnected BT Devices srch.fReturnConnected = true; srch.fReturnUnknown = true; - srch.fIssueInquiry = true; - srch.cTimeoutMultiplier = 2; // == (2 * 1.28) seconds + srch.fIssueInquiry = new_scan; + // multiple of 1.28 seconds + srch.cTimeoutMultiplier = 2; BLUETOOTH_FIND_RADIO_PARAMS radioParam; radioParam.dwSize = sizeof(radioParam); HANDLE hRadio; + + // TODO: save radio(s) in the WiimoteScanner constructor? // Enumerate BT radios HBLUETOOTH_RADIO_FIND hFindRadio = Bth_BluetoothFindFirstRadio(&radioParam, &hRadio); - - if (NULL == hFindRadio) - return -1; - while (hFindRadio) { BLUETOOTH_RADIO_INFO radioInfo; radioInfo.dwSize = sizeof(radioInfo); - // TODO: check for SUCCEEDED() - Bth_BluetoothGetRadioInfo(hRadio, &radioInfo); - - srch.hRadio = hRadio; - - BLUETOOTH_DEVICE_INFO btdi; - btdi.dwSize = sizeof(btdi); - - // Enumerate BT devices - HBLUETOOTH_DEVICE_FIND hFindDevice = Bth_BluetoothFindFirstDevice(&srch, &btdi); - while (hFindDevice) + auto const rinfo_result = Bth_BluetoothGetRadioInfo(hRadio, &radioInfo); + if (ERROR_SUCCESS == rinfo_result) { - // btdi.szName is sometimes missings it's content - it's a bt feature.. - DEBUG_LOG(WIIMOTE, "authed %i connected %i remembered %i ", - btdi.fAuthenticated, btdi.fConnected, btdi.fRemembered); + srch.hRadio = hRadio; - if (std::regex_match(btdi.szName, wiimote_device_name)) + BLUETOOTH_DEVICE_INFO btdi; + btdi.dwSize = sizeof(btdi); + + // Enumerate BT devices + HBLUETOOTH_DEVICE_FIND hFindDevice = Bth_BluetoothFindFirstDevice(&srch, &btdi); + while (hFindDevice) { - if (unpair) - { - if (SUCCEEDED(Bth_BluetoothRemoveDevice(&btdi.Address))) - { - NOTICE_LOG(WIIMOTE, - "Pair-Up: Automatically removed BT Device on shutdown: %08x", - GetLastError()); - ++nPaired; - } - } - else - { - if (false == btdi.fConnected) - { - // TODO: improve the read of the BT driver, esp. when batteries - // of the wiimote are removed while being fConnected - if (btdi.fRemembered) - { - // Make Windows forget old expired pairing. We can pretty - // much ignore the return value here. It either worked - // (ERROR_SUCCESS), or the device did not exist - // (ERROR_NOT_FOUND). In both cases, there is nothing left. - Bth_BluetoothRemoveDevice(&btdi.Address); - } + // btdi.szName is sometimes missings it's content - it's a bt feature.. + DEBUG_LOG(WIIMOTE, "authed %i connected %i remembered %i ", + btdi.fAuthenticated, btdi.fConnected, btdi.fRemembered); - // Activate service - const DWORD hr = Bth_BluetoothSetServiceState(hRadio, &btdi, - &HumanInterfaceDeviceServiceClass_UUID, BLUETOOTH_SERVICE_ENABLE); - if (SUCCEEDED(hr)) - ++nPaired; - else - ERROR_LOG(WIIMOTE, "Pair-Up: BluetoothSetServiceState() returned %08x", hr); - } + if (IsValidBluetoothName(UTF16ToUTF8(btdi.szName))) + { + callback(hRadio, radioInfo, btdi); } - } - if (false == Bth_BluetoothFindNextDevice(hFindDevice, &btdi)) - { - Bth_BluetoothFindDeviceClose(hFindDevice); - hFindDevice = NULL; + if (false == Bth_BluetoothFindNextDevice(hFindDevice, &btdi)) + { + Bth_BluetoothFindDeviceClose(hFindDevice); + hFindDevice = NULL; + } } } @@ -527,8 +555,84 @@ int PairUp(bool unpair) hFindRadio = NULL; } } +} - return nPaired; +void RemoveWiimote(BLUETOOTH_DEVICE_INFO_STRUCT& btdi) +{ + //if (btdi.fConnected) + { + if (SUCCEEDED(Bth_BluetoothRemoveDevice(&btdi.Address))) + { + NOTICE_LOG(WIIMOTE, "Removed BT Device", GetLastError()); + } + } +} + +bool AttachWiimote(HANDLE hRadio, const BLUETOOTH_RADIO_INFO& radio_info, BLUETOOTH_DEVICE_INFO_STRUCT& btdi) +{ + // We don't want "remembered" devices. + // SetServiceState will just fail with them.. + if (!btdi.fConnected && !btdi.fRemembered) + { + auto const& wm_addr = btdi.Address.rgBytes; + + NOTICE_LOG(WIIMOTE, "Found wiimote (%02x:%02x:%02x:%02x:%02x:%02x). Enabling HID service.", + wm_addr[0], wm_addr[1], wm_addr[2], wm_addr[3], wm_addr[4], wm_addr[5]); + +#if defined(AUTHENTICATE_WIIMOTES) + // Authenticate + auto const& radio_addr = radio_info.address.rgBytes; + const DWORD auth_result = Bth_BluetoothAuthenticateDevice(NULL, hRadio, &btdi, + std::vector(radio_addr, radio_addr + 6).data(), 6); + + if (ERROR_SUCCESS != auth_result) + ERROR_LOG(WIIMOTE, "AttachWiimote: BluetoothAuthenticateDevice returned %08x", auth_result); + + DWORD pcServices = 16; + GUID guids[16]; + // If this is not done, the Wii device will not remember the pairing + const DWORD srv_result = Bth_BluetoothEnumerateInstalledServices(hRadio, &btdi, &pcServices, guids); + + if (ERROR_SUCCESS != srv_result) + ERROR_LOG(WIIMOTE, "AttachWiimote: BluetoothEnumerateInstalledServices returned %08x", srv_result); +#endif + // Activate service + const DWORD hr = Bth_BluetoothSetServiceState(hRadio, &btdi, + &HumanInterfaceDeviceServiceClass_UUID, BLUETOOTH_SERVICE_ENABLE); + + g_connect_times[btdi.Address.ullLong] = std::time(nullptr); + + if (FAILED(hr)) + ERROR_LOG(WIIMOTE, "AttachWiimote: BluetoothSetServiceState returned %08x", hr); + else + return true; + } + + return false; +} + +// Removes remembered non-connected devices +bool ForgetWiimote(BLUETOOTH_DEVICE_INFO_STRUCT& btdi) +{ + if (!btdi.fConnected && btdi.fRemembered) + { + // Time to avoid RemoveDevice after SetServiceState. + // Sometimes SetServiceState takes a while.. + auto const avoid_forget_seconds = 5.0; + + auto pair_time = g_connect_times.find(btdi.Address.ullLong); + if (pair_time == g_connect_times.end() + || std::difftime(time(nullptr), pair_time->second) >= avoid_forget_seconds) + { + // Make Windows forget about device so it will re-find it if visible. + // This is also required to detect a disconnect for some reason.. + NOTICE_LOG(WIIMOTE, "Removing remembered wiimote."); + Bth_BluetoothRemoveDevice(&btdi.Address); + return true; + } + } + + return false; } }; diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm b/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm index 64de880180..cec18ed63a 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm +++ b/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm @@ -40,8 +40,11 @@ { IOBluetoothDevice *device = [l2capChannel getDevice]; WiimoteReal::Wiimote *wm = NULL; + + std::lock_guard lk(WiimoteReal::g_refresh_lock); - for (int i = 0; i < MAX_WIIMOTES; i++) { + for (int i = 0; i < MAX_WIIMOTES; i++) + { if (WiimoteReal::g_wiimotes[i] == NULL) continue; if ([device isEqual: WiimoteReal::g_wiimotes[i]->btd] == TRUE) @@ -77,8 +80,11 @@ { IOBluetoothDevice *device = [l2capChannel getDevice]; WiimoteReal::Wiimote *wm = NULL; + + std::lock_guard lk(WiimoteReal::g_refresh_lock); - for (int i = 0; i < MAX_WIIMOTES; i++) { + for (int i = 0; i < MAX_WIIMOTES; i++) + { if (WiimoteReal::g_wiimotes[i] == NULL) continue; if ([device isEqual: WiimoteReal::g_wiimotes[i]->btd] == TRUE) @@ -92,41 +98,47 @@ WARN_LOG(WIIMOTE, "Lost channel to wiimote %i", wm->index + 1); - wm->RealDisconnect(); + wm->Disconnect(); } @end namespace WiimoteReal { -// Find wiimotes. -// wm is an array of max_wiimotes wiimotes -// Returns the total number of found wiimotes. -int FindWiimotes(Wiimote **wm, int max_wiimotes) +WiimoteScanner::WiimoteScanner() + : m_run_thread() + , m_want_wiimotes() +{} + +WiimoteScanner::~WiimoteScanner() +{} + +void WiimoteScanner::Update() +{} + +std::vector WiimoteScanner::FindWiimotes() { + // TODO: find the device in the constructor and save it for later + + std::vector wiimotes; IOBluetoothHostController *bth; IOBluetoothDeviceInquiry *bti; SearchBT *sbt; NSEnumerator *en; - int found_devices = 0, found_wiimotes = 0; - - // Count the number of already found wiimotes - for (int i = 0; i < MAX_WIIMOTES; ++i) - if (wm[i]) - found_wiimotes++; bth = [[IOBluetoothHostController alloc] init]; - if ([bth addressAsString] == nil) { + if ([bth addressAsString] == nil) + { WARN_LOG(WIIMOTE, "No bluetooth host controller"); [bth release]; - return found_wiimotes; + return wiimotes; } sbt = [[SearchBT alloc] init]; - sbt->maxDevices = max_wiimotes - found_wiimotes; + sbt->maxDevices = 32; bti = [[IOBluetoothDeviceInquiry alloc] init]; [bti setDelegate: sbt]; - [bti setInquiryLength: 5]; + [bti setInquiryLength: 2]; if ([bti start] == kIOReturnSuccess) [bti retain]; @@ -136,10 +148,10 @@ int FindWiimotes(Wiimote **wm, int max_wiimotes) CFRunLoopRun(); [bti stop]; - found_devices = [[bti foundDevices] count]; + int found_devices = [[bti foundDevices] count]; - NOTICE_LOG(WIIMOTE, "Found %i bluetooth device%c", found_devices, - found_devices == 1 ? '\0' : 's'); + if (found_devices) + NOTICE_LOG(WIIMOTE, "Found %i bluetooth devices", found_devices); en = [[bti foundDevices] objectEnumerator]; for (int i = 0; i < found_devices; i++) @@ -147,42 +159,44 @@ int FindWiimotes(Wiimote **wm, int max_wiimotes) IOBluetoothDevice *dev = [en nextObject]; if (!IsValidBluetoothName([[dev name] UTF8String])) continue; - // Find an unused slot - for (int k = 0; k < MAX_WIIMOTES; k++) { - if (wm[k] != NULL || - !(g_wiimote_sources[k] & WIIMOTE_SRC_REAL)) - continue; - wm[k] = new Wiimote(k); - wm[k]->btd = dev; - found_wiimotes++; - break; - } + Wiimote *wm = new Wiimote(); + wm->btd = dev; + wiimotes.push_back(wm); } [bth release]; [bti release]; [sbt release]; - return found_wiimotes; + return wiimotes; +} + +bool WiimoteScanner::IsReady() const +{ + // TODO: only return true when a BT device is present + return true; } // Connect to a wiimote with a known address. bool Wiimote::Connect() { - ConnectBT *cbt = [[ConnectBT alloc] init]; - if (IsConnected()) return false; + ConnectBT *cbt = [[ConnectBT alloc] init]; + [btd openL2CAPChannelSync: &cchan withPSM: kBluetoothL2CAPPSMHIDControl delegate: cbt]; [btd openL2CAPChannelSync: &ichan withPSM: kBluetoothL2CAPPSMHIDInterrupt delegate: cbt]; - if (ichan == NULL || cchan == NULL) { + if (ichan == NULL || cchan == NULL) + { ERROR_LOG(WIIMOTE, "Unable to open L2CAP channels " "for wiimote %i", index + 1); - RealDisconnect(); + Disconnect(); + + [cbt release]; return false; } @@ -196,40 +210,37 @@ bool Wiimote::Connect() m_connected = true; - Handshake(); - SetLEDs(WIIMOTE_LED_1 << index); - - m_wiimote_thread = std::thread(std::mem_fun(&Wiimote::ThreadFunc), this); - [cbt release]; - return true; } // Disconnect a wiimote. -void Wiimote::RealDisconnect() +void Wiimote::Disconnect() { + if (btd != NULL) + [btd closeConnection]; + + if (ichan != NULL) + [ichan release]; + + if (cchan != NULL) + [cchan release]; + + btd = NULL; + cchan = NULL; + ichan = NULL; + if (!IsConnected()) return; NOTICE_LOG(WIIMOTE, "Disconnecting wiimote %i", index + 1); m_connected = false; - - if (m_wiimote_thread.joinable()) - m_wiimote_thread.join(); - - [btd closeConnection]; - [ichan release]; - [cchan release]; - btd = NULL; - cchan = NULL; - ichan = NULL; } -bool Wiimote::IsOpen() const +bool Wiimote::IsConnected() const { - return IsConnected(); + return m_connected; } int Wiimote::IORead(unsigned char *buf) @@ -246,14 +257,14 @@ int Wiimote::IORead(unsigned char *buf) return bytes; } -int Wiimote::IOWrite(unsigned char *buf, int len) +int Wiimote::IOWrite(const unsigned char *buf, int len) { IOReturn ret; if (!IsConnected()) return 0; - ret = [ichan writeAsync: buf length: len refcon: nil]; + ret = [ichan writeAsync: const_cast((void *)buf) length: 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 c726a836d9..3608c060fc 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp @@ -23,6 +23,8 @@ #include "IniFile.h" #include "StringUtil.h" #include "Timer.h" +#include "Host.h" +#include "ConfigManager.h" #include "WiimoteReal.h" @@ -33,36 +35,43 @@ unsigned int g_wiimote_sources[MAX_WIIMOTES]; namespace WiimoteReal { +void HandleFoundWiimotes(const std::vector&); +void TryToConnectWiimote(Wiimote*); +void HandleWiimoteDisconnect(int index); +void DoneWithWiimote(int index); + bool g_real_wiimotes_initialized = false; -unsigned int g_wiimotes_found = 0; -std::mutex g_refresh_lock; +std::recursive_mutex g_refresh_lock; -Wiimote *g_wiimotes[MAX_WIIMOTES]; +Wiimote* g_wiimotes[MAX_WIIMOTES]; -Wiimote::Wiimote(const unsigned int _index) - : index(_index) +WiimoteScanner g_wiimote_scanner; + +Wiimote::Wiimote() + : index() #ifdef __APPLE__ - , inputlen(0) + , btd(), ichan(), cchan(), inputlen(), m_connected() #elif defined(__linux__) && HAVE_BLUEZ , cmd_sock(-1), int_sock(-1) #elif defined(_WIN32) , dev_handle(0), stack(MSBT_STACK_UNKNOWN) #endif - , leds(0), m_last_data_report(Report((u8 *)NULL, 0)) - , m_channel(0), m_connected(false) + , m_last_data_report(Report((u8 *)NULL, 0)) + , m_channel(0), m_run_thread(false) { #if defined(__linux__) && HAVE_BLUEZ bdaddr = (bdaddr_t){{0, 0, 0, 0, 0, 0}}; #endif - - DisableDataReporting(); } Wiimote::~Wiimote() { - RealDisconnect(); + StopThread(); + if (IsConnected()) + Disconnect(); + ClearReadQueue(); // clear write queue @@ -71,26 +80,28 @@ Wiimote::~Wiimote() delete[] rpt.first; } -// Silly, copying data n stuff, o well, don't use this too often -void Wiimote::SendPacket(const u8 rpt_id, const void* const data, const unsigned int size) +// to be called from CPU thread +void Wiimote::QueueReport(u8 rpt_id, const void* _data, unsigned int size) { + auto const data = static_cast(_data); + Report rpt; rpt.second = size + 2; rpt.first = new u8[rpt.second]; - rpt.first[0] = 0xA1; + rpt.first[0] = WM_SET_REPORT | WM_BT_OUTPUT; rpt.first[1] = rpt_id; - memcpy(rpt.first + 2, data, size); + std::copy(data, data + size, rpt.first + 2); m_write_reports.Push(rpt); } void Wiimote::DisableDataReporting() { - wm_report_mode rpt; + wm_report_mode rpt = {}; rpt.mode = WM_REPORT_CORE; rpt.all_the_time = 0; rpt.continuous = 0; rpt.rumble = 0; - SendPacket(WM_REPORT_MODE, &rpt, sizeof(rpt)); + QueueReport(WM_REPORT_MODE, &rpt, sizeof(rpt)); } void Wiimote::ClearReadQueue() @@ -111,7 +122,7 @@ void Wiimote::ControlChannel(const u16 channel, const void* const data, const u3 { // Check for custom communication if (99 == channel) - Disconnect(); + EmuStop(); else { InterruptChannel(channel, data, size); @@ -124,24 +135,24 @@ void Wiimote::ControlChannel(const u16 channel, const void* const data, const u3 } } -void Wiimote::InterruptChannel(const u16 channel, const void* const data, const u32 size) +void Wiimote::InterruptChannel(const u16 channel, const void* const _data, const u32 size) { - if (0 == m_channel) // first interrupt/control channel sent + // first interrupt/control channel sent + if (channel != m_channel) { + m_channel = channel; + ClearReadQueue(); - // request status - wm_request_status rpt; - rpt.rumble = 0; - SendPacket(WM_REQUEST_STATUS, &rpt, sizeof(rpt)); + EmuStart(); } - - m_channel = channel; // this right? + + auto const data = static_cast(_data); Report rpt; rpt.first = new u8[size]; rpt.second = (u8)size; - memcpy(rpt.first, (u8*)data, size); + std::copy(data, data + size, rpt.first); // Convert output DATA packets to SET_REPORT packets. // Nintendo Wiimotes work without this translation, but 3rd @@ -150,13 +161,27 @@ void Wiimote::InterruptChannel(const u16 channel, const void* const data, const { rpt.first[0] = WM_SET_REPORT | WM_BT_OUTPUT; } - - if (rpt.first[0] == (WM_SET_REPORT | WM_BT_OUTPUT) && - rpt.first[1] == 0x18 && rpt.second == 23) + + // Disallow games from turning off all of the LEDs. + // It makes wiimote connection status confusing. + if (rpt.first[1] == WM_LEDS) { - m_audio_reports.Push(rpt); - return; - } + auto& leds_rpt = *reinterpret_cast(&rpt.first[2]); + if (0 == leds_rpt.leds) + { + // Turn on ALL of the LEDs. + leds_rpt.leds = 0xf; + } + } + else if (rpt.first[1] == WM_WRITE_SPEAKER_DATA + && !SConfig::GetInstance().m_WiimoteEnableSpeaker) + { + // Translate speaker data reports into rumble reports. + rpt.first[1] = WM_CMD_RUMBLE; + // Keep only the rumble bit. + rpt.first[2] &= 0x1; + rpt.second = 3; + } m_write_reports.Push(rpt); } @@ -168,7 +193,14 @@ bool Wiimote::Read() rpt.first = new unsigned char[MAX_PAYLOAD]; rpt.second = IORead(rpt.first); - if (rpt.second > 0 && m_channel > 0) { + if (0 == rpt.second) + { + WARN_LOG(WIIMOTE, "Wiimote::IORead failed. Disconnecting wiimote %d.", index + 1); + Disconnect(); + } + + if (rpt.second > 0 && m_channel > 0) + { // Add it to queue m_read_reports.Push(rpt); return true; @@ -180,23 +212,25 @@ bool Wiimote::Read() bool Wiimote::Write() { - Report rpt; - - if (last_audio_report.GetTimeDifference() > 5 && m_audio_reports.Pop(rpt)) + if (!m_write_reports.Empty()) { - IOWrite(rpt.first, rpt.second); - last_audio_report.Update(); + Report const& rpt = m_write_reports.Front(); - delete[] rpt.first; - return true; + bool const is_speaker_data = rpt.first[1] == WM_WRITE_SPEAKER_DATA; + + if (!is_speaker_data || m_last_audio_report.GetTimeDifference() > 5) + { + IOWrite(rpt.first, rpt.second); + + if (is_speaker_data) + m_last_audio_report.Update(); + + delete[] rpt.first; + m_write_reports.Pop(); + return true; + } } - else if (m_write_reports.Pop(rpt)) - { - IOWrite(rpt.first, rpt.second); - delete[] rpt.first; - return true; - } - + return false; } @@ -221,6 +255,12 @@ Report Wiimote::ProcessReadQueue() void Wiimote::Update() { + if (!IsConnected()) + { + HandleWiimoteDisconnect(index); + return; + } + // Pop through the queued reports Report const rpt = ProcessReadQueue(); @@ -234,123 +274,151 @@ void Wiimote::Update() delete[] rpt.first; } -void Wiimote::Disconnect() +bool Wiimote::Prepare(int _index) +{ + index = _index; + + // core buttons, no continuous reporting + u8 const mode_report[] = {WM_SET_REPORT | WM_BT_OUTPUT, WM_CMD_REPORT_TYPE, 0, 0x30}; + + // Set the active LEDs and turn on rumble. + u8 const led_report[] = {WM_SET_REPORT | WM_BT_OUTPUT, WM_CMD_LED, u8(WIIMOTE_LED_1 << index | 0x1)}; + + // Turn off rumble + u8 rumble_report[] = {WM_SET_REPORT | WM_BT_OUTPUT, WM_CMD_RUMBLE, 0}; + + // Request status report + u8 const req_status_report[] = {WM_SET_REPORT | WM_BT_OUTPUT, WM_REQUEST_STATUS, 0}; + // TODO: check for sane response? + + return (IOWrite(mode_report, sizeof(mode_report)) + && IOWrite(led_report, sizeof(led_report)) + && (SLEEP(200), IOWrite(rumble_report, sizeof(rumble_report))) + && IOWrite(req_status_report, sizeof(req_status_report))); +} + +void Wiimote::EmuStart() +{ + DisableDataReporting(); +} + +void Wiimote::EmuStop() { m_channel = 0; DisableDataReporting(); + + NOTICE_LOG(WIIMOTE, "Stopping wiimote data reporting"); } -bool Wiimote::IsConnected() const +unsigned int CalculateWantedWiimotes() { - return m_connected; + // Figure out how many real wiimotes are required + unsigned int wanted_wiimotes = 0; + for (unsigned int i = 0; i < MAX_WIIMOTES; ++i) + if (WIIMOTE_SRC_REAL & g_wiimote_sources[i] && !g_wiimotes[i]) + ++wanted_wiimotes; + + return wanted_wiimotes; } -// Rumble briefly -void Wiimote::Rumble() +void WiimoteScanner::WantWiimotes(bool do_want) { - if (!IsConnected()) - return; - - unsigned char buffer = 0x01; - DEBUG_LOG(WIIMOTE, "Starting rumble..."); - SendRequest(WM_CMD_RUMBLE, &buffer, 1); - - SLEEP(200); - - DEBUG_LOG(WIIMOTE, "Stopping rumble..."); - buffer = 0x00; - SendRequest(WM_CMD_RUMBLE, &buffer, 1); + m_want_wiimotes = do_want; } -// Set the active LEDs. -// leds is a bitwise or of WIIMOTE_LED_1 through WIIMOTE_LED_4. -void Wiimote::SetLEDs(int new_leds) +void WiimoteScanner::StartScanning() { - unsigned char buffer; - - if (!IsConnected()) - return; - - // Remove the lower 4 bits because they control rumble - buffer = leds = (new_leds & 0xF0); - - SendRequest(WM_CMD_LED, &buffer, 1); + if (!m_run_thread && IsReady()) + { + m_run_thread = true; + m_scan_thread = std::thread(std::mem_fun(&WiimoteScanner::ThreadFunc), this); + } } -// Send a handshake -bool Wiimote::Handshake() +void WiimoteScanner::StopScanning() { - // Set buffer[0] to 0x04 for continuous reporting - unsigned char buffer[2] = {0x04, 0x30}; - - if (!IsConnected()) - return 0; - - DEBUG_LOG(WIIMOTE, "Sending handshake to wiimote"); - - return SendRequest(WM_CMD_REPORT_TYPE, buffer, 2); + m_run_thread = false; + if (m_scan_thread.joinable()) + { + m_scan_thread.join(); + } } -// Send a packet to the wiimote. -// report_type should be one of WIIMOTE_CMD_LED, WIIMOTE_CMD_RUMBLE, etc. -bool Wiimote::SendRequest(unsigned char report_type, unsigned char* data, int length) +void CheckForDisconnectedWiimotes() { - unsigned char buffer[32] = {WM_SET_REPORT | WM_BT_OUTPUT, report_type}; + std::lock_guard lk(g_refresh_lock); - memcpy(buffer + 2, data, length); + for (unsigned int i = 0; i != MAX_WIIMOTES; ++i) + if (g_wiimotes[i] && !g_wiimotes[i]->IsConnected()) + HandleWiimoteDisconnect(i); +} - return (IOWrite(buffer, length + 2) != 0); +void WiimoteScanner::ThreadFunc() +{ + Common::SetCurrentThreadName("Wiimote Scanning Thread"); + + NOTICE_LOG(WIIMOTE, "Wiimote scanning has started"); + + while (m_run_thread) + { + std::vector found_wiimotes; + + //NOTICE_LOG(WIIMOTE, "in loop"); + + if (m_want_wiimotes) + found_wiimotes = FindWiimotes(); + else + { + // Does stuff needed to detect disconnects on Windows + Update(); + } + + //NOTICE_LOG(WIIMOTE, "after update"); + + // TODO: this is a fairly lame place for this + CheckForDisconnectedWiimotes(); + + HandleFoundWiimotes(found_wiimotes); + + //std::this_thread::yield(); + Common::SleepCurrentThread(500); + } + + NOTICE_LOG(WIIMOTE, "Wiimote scanning has stopped"); +} + +void Wiimote::StartThread() +{ + m_run_thread = true; + m_wiimote_thread = std::thread(std::mem_fun(&Wiimote::ThreadFunc), this); +} + +void Wiimote::StopThread() +{ + m_run_thread = false; + if (m_wiimote_thread.joinable()) + m_wiimote_thread.join(); } void Wiimote::ThreadFunc() { - char thname[] = "Wiimote # Thread"; - thname[8] = (char)('1' + index); - Common::SetCurrentThreadName(thname); - - // rumble briefly - Rumble(); + Common::SetCurrentThreadName("Wiimote Device Thread"); // main loop - while (IsOpen()) + while (m_run_thread && IsConnected()) { #ifdef __APPLE__ - while (Write()) {} - Common::SleepCurrentThread(1); + // Reading happens elsewhere on OSX + bool const did_something = Write(); #else bool const did_something = Write() || Read(); +#endif if (!did_something) Common::SleepCurrentThread(1); -#endif } } -#ifndef _WIN32 -// Connect all discovered wiimotes -// Return the number of wiimotes that successfully connected. -static int ConnectWiimotes(Wiimote** wm) -{ - int connected = 0; - - for (int i = 0; i < MAX_WIIMOTES; ++i) - { - if (!wm[i] || wm[i]->IsConnected()) - continue; - - if (wm[i]->Connect()) - ++connected; - else - { - delete wm[i]; - wm[i] = NULL; - } - } - - return connected; -} -#endif - void LoadSettings() { std::string ini_filename = File::GetUserPath(D_CONFIG_IDX) + WIIMOTE_INI_NAME ".ini"; @@ -368,116 +436,181 @@ void LoadSettings() } } -unsigned int Initialize() +// config dialog calls this when some settings change +void Initialize() { - // Return if already initialized + if (SConfig::GetInstance().m_WiimoteContinuousScanning) + g_wiimote_scanner.StartScanning(); + else + g_wiimote_scanner.StopScanning(); + + std::lock_guard lk(g_refresh_lock); + + g_wiimote_scanner.WantWiimotes(0 != CalculateWantedWiimotes()); + if (g_real_wiimotes_initialized) - return g_wiimotes_found; + return; - memset(g_wiimotes, 0, sizeof(g_wiimotes)); + NOTICE_LOG(WIIMOTE, "WiimoteReal::Initialize"); - // Only call FindWiimotes with the number of slots configured for real wiimotes - unsigned int wanted_wiimotes = 0; - for (unsigned int i = 0; i < MAX_WIIMOTES; ++i) - if (WIIMOTE_SRC_REAL & g_wiimote_sources[i]) - ++wanted_wiimotes; - - // Don't bother initializing if we don't want any real wiimotes - if (0 == wanted_wiimotes) - { - g_wiimotes_found = 0; - return 0; - } - - // Initialized g_real_wiimotes_initialized = true; - - g_wiimotes_found = FindWiimotes(g_wiimotes, wanted_wiimotes); - - DEBUG_LOG(WIIMOTE, "Found %i Real Wiimotes, %i wanted", - g_wiimotes_found, wanted_wiimotes); - -#ifndef _WIN32 - atexit(WiimoteReal::Shutdown); - g_wiimotes_found = ConnectWiimotes(g_wiimotes); -#endif - - DEBUG_LOG(WIIMOTE, "Connected to %i Real Wiimotes", g_wiimotes_found); - - return g_wiimotes_found; } void Shutdown(void) -{ - if (false == g_real_wiimotes_initialized) +{ + g_wiimote_scanner.StopScanning(); + + std::lock_guard lk(g_refresh_lock); + + if (!g_real_wiimotes_initialized) return; - // Uninitialized + NOTICE_LOG(WIIMOTE, "WiimoteReal::Shutdown"); + g_real_wiimotes_initialized = false; - // Delete wiimotes for (unsigned int i = 0; i < MAX_WIIMOTES; ++i) - if (g_wiimotes[i]) + HandleWiimoteDisconnect(i); +} + +void ChangeWiimoteSource(unsigned int index, int source) +{ + { + std::lock_guard lk(g_refresh_lock); + + g_wiimote_sources[index] = source; + g_wiimote_scanner.WantWiimotes(0 != CalculateWantedWiimotes()); + + // kill real connection (or swap to different slot) + DoneWithWiimote(index); + } + + // reconnect to emu + Host_ConnectWiimote(index, false); + if (WIIMOTE_SRC_EMU & source) + Host_ConnectWiimote(index, true); +} + +void TryToConnectWiimote(Wiimote* wm) +{ + std::unique_lock lk(g_refresh_lock); + + for (unsigned int i = 0; i != MAX_WIIMOTES; ++i) + { + if (WIIMOTE_SRC_REAL & g_wiimote_sources[i] + && !g_wiimotes[i]) { - delete g_wiimotes[i]; - g_wiimotes[i] = NULL; + if (wm->Connect() && wm->Prepare(i)) + { + NOTICE_LOG(WIIMOTE, "Connected to wiimote %i.", i + 1); + + std::swap(g_wiimotes[i], wm); + g_wiimotes[i]->StartThread(); + + Host_ConnectWiimote(i, true); + } + break; } + } + + g_wiimote_scanner.WantWiimotes(0 != CalculateWantedWiimotes()); + + lk.unlock(); + + delete wm; +} + +void DoneWithWiimote(int index) +{ + std::lock_guard lk(g_refresh_lock); + + if (g_wiimotes[index]) + { + g_wiimotes[index]->StopThread(); + + // First see if we can use this real wiimote in another slot. + for (unsigned int i = 0; i != MAX_WIIMOTES; ++i) + { + if (WIIMOTE_SRC_REAL & g_wiimote_sources[i] + && !g_wiimotes[i]) + { + if (g_wiimotes[index]->Prepare(i)) + { + std::swap(g_wiimotes[i], g_wiimotes[index]); + g_wiimotes[i]->StartThread(); + + Host_ConnectWiimote(i, true); + } + break; + } + } + } + + // else, just disconnect the wiimote + HandleWiimoteDisconnect(index); +} + +void HandleWiimoteDisconnect(int index) +{ + Wiimote* wm = NULL; + + { + std::lock_guard lk(g_refresh_lock); + std::swap(wm, g_wiimotes[index]); + g_wiimote_scanner.WantWiimotes(0 != CalculateWantedWiimotes()); + } + + if (wm) + { + delete wm; + NOTICE_LOG(WIIMOTE, "Disconnected wiimote %i.", index + 1); + } +} + +void HandleFoundWiimotes(const std::vector& wiimotes) +{ + std::for_each(wiimotes.begin(), wiimotes.end(), TryToConnectWiimote); } // This is called from the GUI thread void Refresh() { - std::lock_guard lk(g_refresh_lock); - -#ifdef _WIN32 - Shutdown(); - Initialize(); -#else - // Make sure real wiimotes have been initialized - if (!g_real_wiimotes_initialized) + g_wiimote_scanner.StopScanning(); + { - Initialize(); - return; + std::unique_lock lk(g_refresh_lock); + std::vector found_wiimotes; + + if (0 != CalculateWantedWiimotes()) + { + // Don't hang dolphin when searching + lk.unlock(); + found_wiimotes = g_wiimote_scanner.FindWiimotes(); + lk.lock(); } - // Find the number of slots configured for real wiimotes - unsigned int wanted_wiimotes = 0; - for (unsigned int i = 0; i < MAX_WIIMOTES; ++i) - if (WIIMOTE_SRC_REAL & g_wiimote_sources[i]) - ++wanted_wiimotes; + CheckForDisconnectedWiimotes(); - // Remove wiimotes that are paired with slots no longer configured for a - // real wiimote or that are disconnected - for (unsigned int i = 0; i < MAX_WIIMOTES; ++i) - if (g_wiimotes[i] && (!(WIIMOTE_SRC_REAL & g_wiimote_sources[i]) || - !g_wiimotes[i]->IsConnected())) + // Brief rumble for already connected wiimotes. + for (int i = 0; i != MAX_WIIMOTES; ++i) + { + if (g_wiimotes[i]) { - delete g_wiimotes[i]; - g_wiimotes[i] = NULL; - --g_wiimotes_found; + g_wiimotes[i]->StopThread(); + g_wiimotes[i]->Prepare(i); + g_wiimotes[i]->StartThread(); } - - // Scan for wiimotes if we want more - if (wanted_wiimotes > g_wiimotes_found) - { - // Scan for wiimotes - unsigned int num_wiimotes = FindWiimotes(g_wiimotes, wanted_wiimotes); - - DEBUG_LOG(WIIMOTE, "Found %i Real Wiimotes, %i wanted", num_wiimotes, wanted_wiimotes); - - // Connect newly found wiimotes. - int num_new_wiimotes = ConnectWiimotes(g_wiimotes); - - DEBUG_LOG(WIIMOTE, "Connected to %i additional Real Wiimotes", num_new_wiimotes); - - g_wiimotes_found = num_wiimotes; } -#endif + + HandleFoundWiimotes(found_wiimotes); + } + + Initialize(); } void InterruptChannel(int _WiimoteNumber, u16 _channelID, const void* _pData, u32 _Size) { - std::lock_guard lk(g_refresh_lock); + std::lock_guard lk(g_refresh_lock); if (g_wiimotes[_WiimoteNumber]) g_wiimotes[_WiimoteNumber]->InterruptChannel(_channelID, _pData, _Size); @@ -485,7 +618,7 @@ void InterruptChannel(int _WiimoteNumber, u16 _channelID, const void* _pData, u3 void ControlChannel(int _WiimoteNumber, u16 _channelID, const void* _pData, u32 _Size) { - std::lock_guard lk(g_refresh_lock); + std::lock_guard lk(g_refresh_lock); if (g_wiimotes[_WiimoteNumber]) g_wiimotes[_WiimoteNumber]->ControlChannel(_channelID, _pData, _Size); @@ -495,15 +628,21 @@ void ControlChannel(int _WiimoteNumber, u16 _channelID, const void* _pData, u32 // Read the Wiimote once void Update(int _WiimoteNumber) { - std::lock_guard lk(g_refresh_lock); + std::lock_guard lk(g_refresh_lock); if (g_wiimotes[_WiimoteNumber]) g_wiimotes[_WiimoteNumber]->Update(); + + // Wiimote::Update() may remove the wiimote if it was disconnected. + if (!g_wiimotes[_WiimoteNumber]) + { + Host_ConnectWiimote(_WiimoteNumber, false); + } } void StateChange(EMUSTATE_CHANGE newState) { - //std::lock_guard lk(g_refresh_lock); + //std::lock_guard lk(g_refresh_lock); // TODO: disable/enable auto reporting, maybe } diff --git a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h index edd4b4f71b..cfc66106b4 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h +++ b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h @@ -20,6 +20,7 @@ #define WIIMOTE_REAL_H #include +#include #include "WiimoteRealBase.h" #include "ChunkFile.h" @@ -42,7 +43,7 @@ class Wiimote : NonCopyable { friend class WiimoteEmu::Wiimote; public: - Wiimote(const unsigned int _index); + Wiimote(); ~Wiimote(); void ControlChannel(const u16 channel, const void* const data, const u32 size); @@ -53,16 +54,29 @@ public: bool Read(); bool Write(); - bool Connect(); - bool IsConnected() const; - bool IsOpen() const; - void Disconnect(); - void DisableDataReporting(); - void Rumble(); - void SendPacket(const u8 rpt_id, const void* const data, const unsigned int size); - void RealDisconnect(); - const unsigned int index; + void StartThread(); + void StopThread(); + + // "handshake" / stop packets + void EmuStart(); + void EmuStop(); + + // connecting and disconnecting from physical devices + // (using address inserted by FindWiimotes) + bool Connect(); + void Disconnect(); + + // TODO: change to something like IsRelevant + bool IsConnected() const; + + bool Prepare(int index); + + void DisableDataReporting(); + + void QueueReport(u8 rpt_id, const void* data, unsigned int size); + + int index; #if defined(__APPLE__) IOBluetoothDevice *btd; @@ -70,21 +84,19 @@ public: IOBluetoothL2CAPChannel *cchan; char input[MAX_PAYLOAD]; int inputlen; + bool m_connected; #elif defined(__linux__) && HAVE_BLUEZ bdaddr_t bdaddr; // Bluetooth address int cmd_sock; // Command socket int int_sock; // Interrupt socket - void Close(); - #elif defined(_WIN32) - std::string devicepath; // Unique wiimote reference + std::basic_string devicepath; // Unique wiimote reference //ULONGLONG btaddr; // Bluetooth address HANDLE dev_handle; // HID handle - OVERLAPPED hid_overlap; // Overlap handle + OVERLAPPED hid_overlap_read, hid_overlap_write; // Overlap handle enum win_bt_stack_t stack; // Type of bluetooth stack to use #endif - unsigned char leds; // Currently lit leds protected: Report m_last_data_report; @@ -92,23 +104,58 @@ protected: private: void ClearReadQueue(); - bool SendRequest(unsigned char report_type, unsigned char* data, int length); - bool Handshake(); - void SetLEDs(int leds); - int IORead(unsigned char* buf); - int IOWrite(unsigned char* buf, int len); + + int IORead(u8* buf); + int IOWrite(u8 const* buf, int len); + void ThreadFunc(); - bool m_connected; + bool m_run_thread; std::thread m_wiimote_thread; + Common::FifoQueue m_read_reports; Common::FifoQueue m_write_reports; - Common::FifoQueue m_audio_reports; - Common::Timer last_audio_report; + Common::Timer m_last_audio_report; }; -extern std::mutex g_refresh_lock; +class WiimoteScanner +{ +public: + WiimoteScanner(); + ~WiimoteScanner(); + + bool IsReady() const; + + void WantWiimotes(bool do_want); + + void StartScanning(); + void StopScanning(); + + std::vector FindWiimotes(); + + // function called when not looking for more wiimotes + void Update(); + +private: + void ThreadFunc(); + + std::thread m_scan_thread; + + volatile bool m_run_thread; + volatile bool m_want_wiimotes; + +#if defined(_WIN32) + + +#elif defined(__linux__) && HAVE_BLUEZ + int device_id; + int device_sock; +#endif +}; + +extern std::recursive_mutex g_refresh_lock; +extern WiimoteScanner g_wiimote_scanner; extern Wiimote *g_wiimotes[4]; void InterruptChannel(int _WiimoteNumber, u16 _channelID, const void* _pData, u32 _Size); @@ -119,6 +166,7 @@ void DoState(PointerWrap &p); void StateChange(EMUSTATE_CHANGE newState); int FindWiimotes(Wiimote** wm, int max_wiimotes); +void ChangeWiimoteSource(unsigned int index, int source); bool IsValidBluetoothName(const std::string& name); diff --git a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteRealBase.h b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteRealBase.h index 75a6d3e6a3..1a1f6676cf 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteRealBase.h +++ b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteRealBase.h @@ -41,6 +41,7 @@ #define WM_SET_REPORT 0xA0 #endif +// TODO: duplicated in WiimoteHid.h // Commands #define WM_CMD_RUMBLE 0x10 #define WM_CMD_LED 0x11 @@ -66,8 +67,9 @@ // End Wiimote internal codes -#define MAX_PAYLOAD 32 -#define WIIMOTE_DEFAULT_TIMEOUT 30 +// It's 23. NOT 32! +#define MAX_PAYLOAD 23 +#define WIIMOTE_DEFAULT_TIMEOUT 1000 #ifdef _WIN32 // Available bluetooth stacks for Windows. diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.cpp index 711d360874..acf5c921e9 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.cpp +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.cpp @@ -33,9 +33,6 @@ std::string HLE_IPC_BuildFilename(std::string path_wii, int _size) { std::string path_full = File::GetUserPath(D_WIIROOT_IDX); - if ((path_wii.length() > 0) && (path_wii[1] == '0')) - path_full += std::string("/title"); // this looks and feel like a hack... - // Replaces chars that FAT32 can't support with strings defined in /sys/replace for (auto i = replacements.begin(); i != replacements.end(); ++i) { @@ -48,39 +45,6 @@ std::string HLE_IPC_BuildFilename(std::string path_wii, int _size) return path_full; } -void HLE_IPC_CreateVirtualFATFilesystem() -{ - const int cdbSize = 0x01400000; - const std::string cdbPath = Common::GetTitleDataPath(TITLEID_SYSMENU) + "cdb.vff"; - if ((int)File::GetSize(cdbPath) < cdbSize) - { - // cdb.vff is a virtual Fat filesystem created on first launch of sysmenu - // we create it here as it is faster ~3 minutes for me when sysmenu does it ~1 second created here - const u8 cdbHDR[0x20] = {'V', 'F', 'F', 0x20, 0xfe, 0xff, 1, 0, 1, 0x40, 0, 0, 0, 0x20}; - const u8 cdbFAT[4] = {0xf0, 0xff, 0xff, 0xff}; - - File::IOFile cdbFile(cdbPath, "wb"); - if (cdbFile) - { - cdbFile.WriteBytes(cdbHDR, 0x20); - cdbFile.WriteBytes(cdbFAT, 0x4); - cdbFile.Seek(0x14020, SEEK_SET); - cdbFile.WriteBytes(cdbFAT, 0x4); - // 20 MiB file - cdbFile.Seek(cdbSize - 1, SEEK_SET); - // write the final 0 to 0 file from the second FAT to 20 MiB - cdbFile.WriteBytes(cdbHDR + 14, 1); - if (!cdbFile.IsGood()) - { - cdbFile.Close(); - File::Delete(cdbPath); - } - cdbFile.Flush(); - cdbFile.Close(); - } - } -} - CWII_IPC_HLE_Device_FileIO::CWII_IPC_HLE_Device_FileIO(u32 _DeviceID, const std::string& _rDeviceName) : IWII_IPC_HLE_Device(_DeviceID, _rDeviceName, false) // not a real hardware , m_Mode(0) @@ -139,82 +103,81 @@ bool CWII_IPC_HLE_Device_FileIO::Open(u32 _CommandAddress, u32 _Mode) return true; } -File::IOFile CWII_IPC_HLE_Device_FileIO::OpenFile() +// Opens file if needed. +// Clears any error state. +// Seeks to proper position position. +void CWII_IPC_HLE_Device_FileIO::PrepareFile() { - const char* open_mode = ""; - - switch (m_Mode) + if (!m_file.IsOpen()) { - case ISFS_OPEN_READ: - open_mode = "rb"; - break; - - case ISFS_OPEN_WRITE: - case ISFS_OPEN_RW: - open_mode = "r+b"; - break; - - default: - PanicAlertT("FileIO: Unknown open mode : 0x%02x", m_Mode); - break; + const char* open_mode = ""; + + switch (m_Mode) + { + case ISFS_OPEN_READ: + open_mode = "rb"; + break; + + case ISFS_OPEN_WRITE: + case ISFS_OPEN_RW: + open_mode = "r+b"; + break; + + default: + PanicAlertT("FileIO: Unknown open mode : 0x%02x", m_Mode); + break; + } + + m_file.Open(m_filepath, open_mode); } - return File::IOFile(m_filepath, open_mode); + m_file.Clear(); + m_file.Seek(m_SeekPos, SEEK_SET); } bool CWII_IPC_HLE_Device_FileIO::Seek(u32 _CommandAddress) { u32 ReturnValue = FS_RESULT_FATAL; - const u32 SeekPosition = Memory::Read_U32(_CommandAddress + 0xC); + const u32 SeekOffset = Memory::Read_U32(_CommandAddress + 0xC); const u32 Mode = Memory::Read_U32(_CommandAddress + 0x10); - if (auto file = OpenFile()) + PrepareFile(); + if (m_file) { ReturnValue = FS_RESULT_FATAL; - const u64 fileSize = file.GetSize(); - INFO_LOG(WII_IPC_FILEIO, "FileIO: Seek Pos: 0x%08x, Mode: %i (%s, Length=0x%08llx)", SeekPosition, Mode, m_Name.c_str(), fileSize); + const u64 fileSize = m_file.GetSize(); + INFO_LOG(WII_IPC_FILEIO, "FileIO: Seek Pos: 0x%08x, Mode: %i (%s, Length=0x%08llx)", SeekOffset, Mode, m_Name.c_str(), fileSize); + u64 wantedPos = 0; switch (Mode) { - case 0: - { - if (SeekPosition <= fileSize) - { - m_SeekPos = SeekPosition; - ReturnValue = m_SeekPos; - } - break; - } - case 1: - { - u32 wantedPos = SeekPosition+m_SeekPos; - if (wantedPos <= fileSize) - { - m_SeekPos = wantedPos; - ReturnValue = m_SeekPos; - } - break; - } - case 2: - { - u64 wantedPos = fileSize+m_SeekPos; - if (wantedPos <= fileSize) - { - m_SeekPos = wantedPos; - ReturnValue = m_SeekPos; - } - break; - } - default: - { - PanicAlert("CWII_IPC_HLE_Device_FileIO Unsupported seek mode %i", Mode); - ReturnValue = FS_RESULT_FATAL; - break; - } + case 0: + wantedPos = SeekOffset; + break; + + case 1: + wantedPos = m_SeekPos + (s32)SeekOffset; + break; + + case 2: + wantedPos = fileSize + (s32)SeekOffset; + break; + + default: + PanicAlert("CWII_IPC_HLE_Device_FileIO Unsupported seek mode %i", Mode); + ReturnValue = FS_RESULT_FATAL; + break; + } + + if (wantedPos <= fileSize) + { + m_SeekPos = wantedPos; + ReturnValue = m_SeekPos; } } else { + // TODO: This can't be right. ReturnValue = FS_FILE_NOT_EXIST; } Memory::Write_U32(ReturnValue, _CommandAddress + 0x4); @@ -227,9 +190,9 @@ bool CWII_IPC_HLE_Device_FileIO::Read(u32 _CommandAddress) u32 ReturnValue = FS_EACCESS; const u32 Address = Memory::Read_U32(_CommandAddress + 0xC); // Read to this memory address const u32 Size = Memory::Read_U32(_CommandAddress + 0x10); - - - if (auto file = OpenFile()) + + PrepareFile(); + if (m_file) { if (m_Mode == ISFS_OPEN_WRITE) { @@ -238,9 +201,8 @@ bool CWII_IPC_HLE_Device_FileIO::Read(u32 _CommandAddress) else { INFO_LOG(WII_IPC_FILEIO, "FileIO: Read 0x%x bytes to 0x%08x from %s", Size, Address, m_Name.c_str()); - file.Seek(m_SeekPos, SEEK_SET); - ReturnValue = (u32)fread(Memory::GetPointer(Address), 1, Size, file.GetHandle()); - if (ReturnValue != Size && ferror(file.GetHandle())) + ReturnValue = (u32)fread(Memory::GetPointer(Address), 1, Size, m_file.GetHandle()); + if (ReturnValue != Size && ferror(m_file.GetHandle())) { ReturnValue = FS_EACCESS; } @@ -267,8 +229,8 @@ bool CWII_IPC_HLE_Device_FileIO::Write(u32 _CommandAddress) const u32 Address = Memory::Read_U32(_CommandAddress + 0xC); // Write data from this memory address const u32 Size = Memory::Read_U32(_CommandAddress + 0x10); - - if (auto file = OpenFile()) + PrepareFile(); + if (m_file) { if (m_Mode == ISFS_OPEN_READ) { @@ -277,8 +239,7 @@ bool CWII_IPC_HLE_Device_FileIO::Write(u32 _CommandAddress) else { INFO_LOG(WII_IPC_FILEIO, "FileIO: Write 0x%04x bytes from 0x%08x to %s", Size, Address, m_Name.c_str()); - file.Seek(m_SeekPos, SEEK_SET); - if (file.WriteBytes(Memory::GetPointer(Address), Size)) + if (m_file.WriteBytes(Memory::GetPointer(Address), Size)) { ReturnValue = Size; m_SeekPos += Size; @@ -308,9 +269,10 @@ bool CWII_IPC_HLE_Device_FileIO::IOCtl(u32 _CommandAddress) { case ISFS_IOCTL_GETFILESTATS: { - if (auto file = OpenFile()) + PrepareFile(); + if (m_file) { - u32 m_FileLength = (u32)file.GetSize(); + u32 m_FileLength = (u32)m_file.GetSize(); const u32 BufferOut = Memory::Read_U32(_CommandAddress + 0x18); INFO_LOG(WII_IPC_FILEIO, "FileIO: ISFS_IOCTL_GETFILESTATS"); @@ -345,6 +307,7 @@ void CWII_IPC_HLE_Device_FileIO::DoState(PointerWrap &p) p.Do(m_Mode); p.Do(m_SeekPos); - + + m_file.Close(); m_filepath = HLE_IPC_BuildFilename(m_Name, 64); } diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.h b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.h index 3698d05c9f..fd33d7d69c 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.h +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.h @@ -22,7 +22,6 @@ #include "FileUtil.h" std::string HLE_IPC_BuildFilename(std::string _pFilename, int _size); -void HLE_IPC_CreateVirtualFATFilesystem(); class CWII_IPC_HLE_Device_FileIO : public IWII_IPC_HLE_Device { @@ -39,9 +38,9 @@ public: bool IOCtl(u32 _CommandAddress); void DoState(PointerWrap &p); - File::IOFile OpenFile(); - private: + void PrepareFile(); + enum { ISFS_OPEN_READ = 1, @@ -77,6 +76,7 @@ private: u32 m_Mode; u32 m_SeekPos; + File::IOFile m_file; std::string m_filepath; }; 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 3eb0096929..363176e18a 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 @@ -58,6 +58,7 @@ #include "CommonPaths.h" #include "IPC_HLE/WII_IPC_HLE_Device_usb.h" #include "../Movie.h" +#include "StringUtil.h" #ifdef _WIN32 #include @@ -926,7 +927,7 @@ u32 CWII_IPC_HLE_Device_es::ES_DIVerify(u8* _pTMD, u32 _sz) else { #ifdef _WIN32 - MoveFile(savePath.c_str(), (savePath + "../backup/").c_str()); + MoveFile(UTF8ToTStr(savePath).c_str(), UTF8ToTStr(savePath + "../backup/").c_str()); #else File::CopyDir(savePath.c_str(),(savePath + "../backup/").c_str()); File::DeleteDirRecursively(savePath.c_str()); @@ -940,7 +941,7 @@ u32 CWII_IPC_HLE_Device_es::ES_DIVerify(u8* _pTMD, u32 _sz) if (File::Exists((savePath + "banner.bin").c_str())) File::DeleteDirRecursively(savePath); #ifdef _WIN32 - MoveFile((savePath + "../backup/").c_str(), savePath.c_str()); + MoveFile(UTF8ToTStr(savePath + "../backup/").c_str(), UTF8ToTStr(savePath).c_str()); #else File::CopyDir((savePath + "../backup/").c_str(), savePath.c_str()); File::DeleteDirRecursively((savePath + "../backup/").c_str()); 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 38100e5d7a..5424542a73 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 @@ -377,7 +377,7 @@ s32 CWII_IPC_HLE_Device_fs::ExecuteCommand(u32 _Parameter, u32 _BufferIn, u32 _B u32 Addr = _BufferOut; Memory::Write_U32(OwnerID, Addr); Addr += 4; Memory::Write_U16(GroupID, Addr); Addr += 2; - memcpy(Memory::GetPointer(Addr), Filename.c_str(), Filename.size()); Addr += 64; + memcpy(Memory::GetPointer(Addr), Memory::GetPointer(_BufferIn), 64); Addr += 64; Memory::Write_U8(OwnerPerm, Addr); Addr += 1; Memory::Write_U8(GroupPerm, Addr); Addr += 1; Memory::Write_U8(OtherPerm, Addr); Addr += 1; diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_WiiMote.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_WiiMote.cpp index 6e06f60dd6..b3449ec059 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_WiiMote.cpp +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_WiiMote.cpp @@ -211,8 +211,7 @@ void CWII_IPC_HLE_WiiMote::EventConnectionAccepted() void CWII_IPC_HLE_WiiMote::EventDisconnect() { // Send disconnect message to plugin - u8 Message = WIIMOTE_DISCONNECT; - Wiimote::ControlChannel(m_ConnectionHandle & 0xFF, 99, &Message, 0); + Wiimote::ControlChannel(m_ConnectionHandle & 0xFF, 99, NULL, 0); m_ConnectionState = CONN_INACTIVE; // Clear channel flags diff --git a/Source/Core/Core/Src/NetPlay.h b/Source/Core/Core/Src/NetPlay.h index e77f972785..96ff78995a 100644 --- a/Source/Core/Core/Src/NetPlay.h +++ b/Source/Core/Core/Src/NetPlay.h @@ -34,7 +34,7 @@ struct Rpt : public std::vector typedef std::vector NetWiimote; -#define NETPLAY_VERSION "Dolphin NetPlay r6423" +#define NETPLAY_VERSION "Dolphin NetPlay 2013-03-03" // messages enum diff --git a/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp index 1d6ea2e70d..ffaea0e868 100644 --- a/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp +++ b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp @@ -28,8 +28,6 @@ #undef _interlockedbittestandreset #undef _interlockedbittestandset64 #undef _interlockedbittestandreset64 -#else -#include #endif #include "../../Core.h" @@ -514,4 +512,4 @@ void Interpreter::fsqrtx(UGeckoInstruction _inst) rPS0(_inst.FD) = sqrt(b); UpdateFPRF(rPS0(_inst.FD)); if (_inst.Rc) Helper_UpdateCR1(rPS0(_inst.FD)); -} \ No newline at end of file +} diff --git a/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_LoadStore.cpp b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_LoadStore.cpp index 5e665eb38e..8e406dbfab 100644 --- a/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_LoadStore.cpp +++ b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_LoadStore.cpp @@ -24,8 +24,7 @@ #include "Interpreter.h" #include "../../Core.h" -#include "../JitCommon/JitBase.h" -#include "../JitCommon/JitCache.h" +#include "../JitInterface.h" #include "Interpreter_FPUtils.h" @@ -363,34 +362,24 @@ void Interpreter::dcbf(UGeckoInstruction _inst) { NPC = PC + 12; }*/ - // Invalidate the jit block cache on dcbf - if (jit) - { u32 address = Helper_Get_EA_X(_inst); - jit->GetBlockCache()->InvalidateICache(address & ~0x1f, 32); - } + JitInterface::InvalidateICache(address & ~0x1f, 32); } void Interpreter::dcbi(UGeckoInstruction _inst) { // Removes a block from data cache. Since we don't emulate the data cache, we don't need to do anything to the data cache // However, we invalidate the jit block cache on dcbi - if (jit) - { u32 address = Helper_Get_EA_X(_inst); - jit->GetBlockCache()->InvalidateICache(address & ~0x1f, 32); - } + JitInterface::InvalidateICache(address & ~0x1f, 32); } void Interpreter::dcbst(UGeckoInstruction _inst) { // Cache line flush. Since we don't emulate the data cache, we don't need to do anything. // Invalidate the jit block cache on dcbst in case new code has been loaded via the data cache - if (jit) - { u32 address = Helper_Get_EA_X(_inst); - jit->GetBlockCache()->InvalidateICache(address & ~0x1f, 32); - } + JitInterface::InvalidateICache(address & ~0x1f, 32); } void Interpreter::dcbt(UGeckoInstruction _inst) @@ -409,7 +398,7 @@ void Interpreter::dcbz(UGeckoInstruction _inst) // HACK but works... we think if (!Core::g_CoreStartupParameter.bDCBZOFF) Memory::Memset(Helper_Get_EA_X(_inst) & (~31), 0, 32); - if (!jit) + if (!JitInterface::GetCore()) PowerPC::CheckExceptions(); } diff --git a/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp index 5a199b56c8..ff65f52471 100644 --- a/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp +++ b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp @@ -26,13 +26,6 @@ #undef _interlockedbittestandreset #undef _interlockedbittestandset64 #undef _interlockedbittestandreset64 -#else -static const unsigned short FPU_ROUND_NEAR = 0 << 10; -static const unsigned short FPU_ROUND_DOWN = 1 << 10; -static const unsigned short FPU_ROUND_UP = 2 << 10; -static const unsigned short FPU_ROUND_CHOP = 3 << 10; -static const unsigned short FPU_ROUND_MASK = 3 << 10; -#include #endif #include "CPUDetect.h" @@ -43,6 +36,7 @@ static const unsigned short FPU_ROUND_MASK = 3 << 10; #include "../../HW/SystemTimers.h" #include "../../Core.h" #include "Interpreter.h" +#include "FPURoundMode.h" #include "Interpreter_FPUtils.h" @@ -61,38 +55,11 @@ mffsx: 80036650 (huh?) // That is, set rounding mode etc when entering jit code or the interpreter loop // Restore rounding mode when calling anything external -const u32 MASKS = 0x1F80; // mask away the interrupts. -const u32 DAZ = 0x40; -const u32 FTZ = 0x8000; - static void FPSCRtoFPUSettings(UReg_FPSCR fp) { - // Set FPU rounding mode to mimic the PowerPC's -#ifdef _M_IX86 - // This shouldn't really be needed anymore since we use SSE -#ifdef _WIN32 - const int table[4] = - { - _RC_NEAR, - _RC_CHOP, - _RC_UP, - _RC_DOWN - }; - _set_controlfp(_MCW_RC, table[fp.RN]); -#else - const unsigned short table[4] = - { - FPU_ROUND_NEAR, - FPU_ROUND_CHOP, - FPU_ROUND_UP, - FPU_ROUND_DOWN - }; - unsigned short mode; - asm ("fstcw %0" : "=m" (mode) : ); - mode = (mode & ~FPU_ROUND_MASK) | table[fp.RN]; - asm ("fldcw %0" : : "m" (mode)); -#endif -#endif + + FPURoundMode::SetRoundMode(fp.RN); + if (fp.VE || fp.OE || fp.UE || fp.ZE || fp.XE) { //PanicAlert("FPSCR - exceptions enabled. Please report. VE=%i OE=%i UE=%i ZE=%i XE=%i", @@ -101,14 +68,6 @@ static void FPSCRtoFPUSettings(UReg_FPSCR fp) } // Also corresponding SSE rounding mode setting - static const u32 ssetable[4] = - { - (0 << 13) | MASKS, - (3 << 13) | MASKS, - (2 << 13) | MASKS, - (1 << 13) | MASKS, - }; - u32 csr = ssetable[FPSCR.RN]; if (FPSCR.NI) { // Either one of these two breaks Beyond Good & Evil. @@ -116,7 +75,7 @@ static void FPSCRtoFPUSettings(UReg_FPSCR fp) // csr |= DAZ; // csr |= FTZ; } - _mm_setcsr(csr); + FPURoundMode::SetSIMDMode(FPSCR.RN); } void Interpreter::mtfsb0x(UGeckoInstruction _inst) diff --git a/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_Tables.cpp b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_Tables.cpp index 8ea35503bf..fee8ed70d8 100644 --- a/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_Tables.cpp +++ b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_Tables.cpp @@ -267,7 +267,7 @@ static GekkoOPTemplate table31[] = {19, Interpreter::mfcr, {"mfcr", OPTYPE_SYSTEM, FL_OUT_D, 0, 0, 0, 0}}, {83, Interpreter::mfmsr, {"mfmsr", OPTYPE_SYSTEM, FL_OUT_D, 0, 0, 0, 0}}, {144, Interpreter::mtcrf, {"mtcrf", OPTYPE_SYSTEM, 0, 0, 0, 0, 0}}, - {146, Interpreter::mtmsr, {"mtmsr", OPTYPE_SYSTEM, FL_ENDBLOCK, 0, 0, 0, 0}}, + {146, Interpreter::mtmsr, {"mtmsr", OPTYPE_SYSTEM, FL_IN_S | FL_ENDBLOCK, 0, 0, 0, 0}}, {210, Interpreter::mtsr, {"mtsr", OPTYPE_SYSTEM, 0, 0, 0, 0, 0}}, {242, Interpreter::mtsrin, {"mtsrin", OPTYPE_SYSTEM, 0, 0, 0, 0, 0}}, {339, Interpreter::mfspr, {"mfspr", OPTYPE_SPR, FL_OUT_D, 0, 0, 0, 0}}, @@ -297,6 +297,7 @@ static GekkoOPTemplate table31_2[] = {10, Interpreter::addcx, {"addcx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_SET_CA | FL_RC_BIT, 0, 0, 0, 0}}, {522, Interpreter::addcx, {"addcox", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_SET_CA | FL_RC_BIT, 0, 0, 0, 0}}, {138, Interpreter::addex, {"addex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT, 0, 0, 0, 0}}, + {650, Interpreter::addex, {"addeox", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT, 0, 0, 0, 0}}, {234, Interpreter::addmex, {"addmex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT, 0, 0, 0, 0}}, {202, Interpreter::addzex, {"addzex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT, 0, 0, 0, 0}}, {491, Interpreter::divwx, {"divwx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 39, 0, 0, 0}}, diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp index 31caca0a43..710984571e 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp @@ -24,7 +24,7 @@ #include "Common.h" #include "x64Emitter.h" -#include "ABI.h" +#include "x64ABI.h" #include "Thunk.h" #include "../../HLE/HLE.h" #include "../../Core.h" @@ -338,7 +338,7 @@ void Jit64::WriteRfiExitDestInEAX() Cleanup(); ABI_CallFunction(reinterpret_cast(&PowerPC::CheckExceptions)); SUB(32, M(&CoreTiming::downcount), js.downcountAmount > 127 ? Imm32(js.downcountAmount) : Imm8(js.downcountAmount)); - JMP(asm_routines.dispatcher, true); + JMP(asm_routines.outerLoop, true); } void Jit64::WriteExceptionExit() @@ -357,7 +357,7 @@ void Jit64::WriteExternalExceptionExit() MOV(32, R(EAX), M(&PC)); MOV(32, M(&NPC), R(EAX)); ABI_CallFunction(reinterpret_cast(&PowerPC::CheckExternalExceptions)); - SUB(32, M(&CoreTiming::downcount), js.downcountAmount > 127 ? Imm32(js.downcountAmount) : Imm8(js.downcountAmount)); + SUB(32, M(&CoreTiming::downcount), js.downcountAmount > 127 ? Imm32(js.downcountAmount) : Imm8(js.downcountAmount)); JMP(asm_routines.dispatcher, true); } diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit.h b/Source/Core/Core/Src/PowerPC/Jit64/Jit.h index 1ebd476134..1d856d6291 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit.h +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit.h @@ -62,7 +62,7 @@ if (js.memcheck) \ SetJumpTarget(memException); -class Jit64 : public JitBase +class Jit64 : public Jitx86Base { private: GPRRegCache gpr; diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit64_Tables.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit64_Tables.cpp index ddb59903d2..cee1f4d048 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit64_Tables.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit64_Tables.cpp @@ -310,6 +310,7 @@ static GekkoOPTemplate table31_2[] = {10, &Jit64::addcx}, //"addcx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_SET_CA | FL_RC_BIT}}, {522, &Jit64::addcx}, //"addcox", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_SET_CA | FL_RC_BIT}}, {138, &Jit64::addex}, //"addex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}}, + {650, &Jit64::addex}, //"addeox", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}}, {234, &Jit64::addmex}, //"addmex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}}, {202, &Jit64::addzex}, //"addzex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}}, {491, &Jit64::divwx}, //"divwx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 39}}, diff --git a/Source/Core/Core/Src/PowerPC/Jit64/JitAsm.cpp b/Source/Core/Core/Src/PowerPC/Jit64/JitAsm.cpp index f7082cd1cc..df27a3a641 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/JitAsm.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/JitAsm.cpp @@ -15,7 +15,7 @@ // Official SVN repository and contact information can be found at // http://code.google.com/p/dolphin-emu/ -#include "ABI.h" +#include "x64ABI.h" #include "x64Emitter.h" #include "../../HW/Memmap.h" @@ -24,7 +24,7 @@ #include "../../CoreTiming.h" #include "MemoryUtil.h" -#include "ABI.h" +#include "x64ABI.h" #include "Jit.h" #include "../JitCommon/JitCache.h" @@ -204,7 +204,7 @@ void Jit64AsmRoutineManager::Generate() MOV(32, M(&NPC), R(EAX)); ABI_CallFunction(reinterpret_cast(&PowerPC::CheckExternalExceptions)); SetJumpTarget(noExtException); - + TEST(32, M((void*)PowerPC::GetStatePtr()), Imm32(0xFFFFFFFF)); J_CC(CC_Z, outerLoop, true); diff --git a/Source/Core/Core/Src/PowerPC/Jit64/JitAsm.h b/Source/Core/Core/Src/PowerPC/Jit64/JitAsm.h index e8df0877f7..19e1f41ba8 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/JitAsm.h +++ b/Source/Core/Core/Src/PowerPC/Jit64/JitAsm.h @@ -18,7 +18,6 @@ #ifndef _JIT64ASM_H #define _JIT64ASM_H -#include "x64Emitter.h" #include "../JitCommon/JitAsmCommon.h" // In Dolphin, we don't use inline assembly. Instead, we generate all machine-near diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStore.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStore.cpp index 04e4d09cc9..7c1d60ad09 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStore.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStore.cpp @@ -28,7 +28,7 @@ #include "../../HW/Memmap.h" #include "../PPCTables.h" #include "x64Emitter.h" -#include "ABI.h" +#include "x64ABI.h" #include "Jit.h" #include "JitAsm.h" diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStoreFloating.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStoreFloating.cpp index 9f61e097b8..5766eb3177 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStoreFloating.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStoreFloating.cpp @@ -27,7 +27,7 @@ #include "../PPCTables.h" #include "CPUDetect.h" #include "x64Emitter.h" -#include "ABI.h" +#include "x64ABI.h" #include "Jit.h" #include "JitAsm.h" diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStorePaired.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStorePaired.cpp index 3b14179cd4..924758ab3a 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStorePaired.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStorePaired.cpp @@ -28,7 +28,7 @@ #include "../PPCTables.h" #include "CPUDetect.h" #include "x64Emitter.h" -#include "ABI.h" +#include "x64ABI.h" #include "Jit.h" #include "JitAsm.h" diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit_SystemRegisters.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit_SystemRegisters.cpp index 14827129f8..0b6c0462d9 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit_SystemRegisters.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit_SystemRegisters.cpp @@ -23,7 +23,7 @@ #include "../PowerPC.h" #include "../PPCTables.h" #include "x64Emitter.h" -#include "ABI.h" +#include "x64ABI.h" #include "Thunk.h" #include "Jit.h" diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/IR_X86.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/IR_X86.cpp index ce47e2c3ac..3638ba8da6 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/IR_X86.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/IR_X86.cpp @@ -1991,8 +1991,10 @@ void JitIL::WriteCode() { } void ProfiledReJit() { - jit->SetCodePtr(jit->js.rewriteStart); - DoWriteCode(&((JitIL *)jit)->ibuild, (JitIL *)jit, true, false); - jit->js.curBlock->codeSize = (int)(jit->GetCodePtr() - jit->js.rewriteStart); - jit->GetBlockCache()->FinalizeBlock(jit->js.curBlock->blockNum, jit->jo.enableBlocklink, jit->js.curBlock->normalEntry); + JitIL *jitil = (JitIL *)jit; + jitil->SetCodePtr(jitil->js.rewriteStart); + DoWriteCode(&jitil->ibuild, jitil, true, false); + jitil->js.curBlock->codeSize = (int)(jitil->GetCodePtr() - jitil->js.rewriteStart); + jitil->GetBlockCache()->FinalizeBlock(jitil->js.curBlock->blockNum, jitil->jo.enableBlocklink, + jitil->js.curBlock->normalEntry); } diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp index d56c9ffee8..dc21228858 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp @@ -19,7 +19,7 @@ #include "Common.h" #include "x64Emitter.h" -#include "ABI.h" +#include "x64ABI.h" #include "Thunk.h" #include "../../HLE/HLE.h" #include "../../Core.h" diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.h b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.h index fdda098e44..8c579fa4bd 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.h +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.h @@ -57,7 +57,7 @@ #define DISABLE64 #endif -class JitIL : public JitBase +class JitIL : public Jitx86Base { private: diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/JitILAsm.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/JitILAsm.cpp index 74c290aa9c..aaa155072e 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/JitILAsm.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/JitILAsm.cpp @@ -15,7 +15,7 @@ // Official SVN repository and contact information can be found at // http://code.google.com/p/dolphin-emu/ -#include "ABI.h" +#include "x64ABI.h" #include "x64Emitter.h" #include "../../HW/Memmap.h" @@ -25,7 +25,7 @@ #include "MemoryUtil.h" #include "CPUDetect.h" -#include "ABI.h" +#include "x64ABI.h" #include "Thunk.h" #include "../../HW/GPFifo.h" @@ -211,14 +211,14 @@ void JitILAsmRoutineManager::Generate() doTiming = GetCodePtr(); ABI_CallFunction(reinterpret_cast(&CoreTiming::Advance)); - + testExceptions = GetCodePtr(); MOV(32, R(EAX), M(&PC)); MOV(32, M(&NPC), R(EAX)); ABI_CallFunction(reinterpret_cast(&PowerPC::CheckExceptions)); MOV(32, R(EAX), M(&NPC)); MOV(32, M(&PC), R(EAX)); - + TEST(32, M((void*)PowerPC::GetStatePtr()), Imm32(0xFFFFFFFF)); J_CC(CC_Z, outer_loop, true); //Landing pad for drec space diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_LoadStore.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_LoadStore.cpp index 45ceda694a..96902434a6 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_LoadStore.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_LoadStore.cpp @@ -27,7 +27,7 @@ #include "../../HW/Memmap.h" #include "../PPCTables.h" #include "x64Emitter.h" -#include "ABI.h" +#include "x64ABI.h" #include "JitIL.h" #include "JitILAsm.h" diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_LoadStoreFloating.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_LoadStoreFloating.cpp index e06d289cc4..c74abfd8e9 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_LoadStoreFloating.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_LoadStoreFloating.cpp @@ -27,7 +27,7 @@ #include "../PPCTables.h" #include "CPUDetect.h" #include "x64Emitter.h" -#include "ABI.h" +#include "x64ABI.h" #include "JitIL.h" #include "JitILAsm.h" diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_LoadStorePaired.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_LoadStorePaired.cpp index 2f0a0762fd..6e86804bec 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_LoadStorePaired.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_LoadStorePaired.cpp @@ -25,7 +25,7 @@ #include "../PPCTables.h" #include "CPUDetect.h" #include "x64Emitter.h" -#include "ABI.h" +#include "x64ABI.h" #include "JitIL.h" #include "JitILAsm.h" diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_SystemRegisters.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_SystemRegisters.cpp index f3e25dc2dd..70a6ea4843 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_SystemRegisters.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_SystemRegisters.cpp @@ -23,7 +23,7 @@ #include "../PowerPC.h" #include "../PPCTables.h" #include "x64Emitter.h" -#include "ABI.h" +#include "x64ABI.h" #include "Thunk.h" #include "JitIL.h" diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_Tables.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_Tables.cpp index 9418030b9c..fd920c4a48 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_Tables.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_Tables.cpp @@ -311,6 +311,7 @@ static GekkoOPTemplate table31_2[] = {10, &JitIL::Default}, //"addcx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_SET_CA | FL_RC_BIT}}, {522, &JitIL::Default}, //"addcox", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_SET_CA | FL_RC_BIT}}, {138, &JitIL::addex}, //"addex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}}, + {650, &JitIL::addex}, //"addeox", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}}, {234, &JitIL::Default}, //"addmex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}}, {202, &JitIL::addzex}, //"addzex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}}, {491, &JitIL::Default}, //"divwx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 39}}, diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/Jit.cpp b/Source/Core/Core/Src/PowerPC/JitArm32/Jit.cpp new file mode 100644 index 0000000000..3b2ee45111 --- /dev/null +++ b/Source/Core/Core/Src/PowerPC/JitArm32/Jit.cpp @@ -0,0 +1,497 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include + +#include "Common.h" +#include "../../HLE/HLE.h" +#include "../../Core.h" +#include "../../PatchEngine.h" +#include "../../CoreTiming.h" +#include "../../ConfigManager.h" +#include "../PowerPC.h" +#include "../Profiler.h" +#include "../PPCTables.h" +#include "../PPCAnalyst.h" +#include "../../HW/Memmap.h" +#include "../../HW/GPFifo.h" +#include "Jit.h" +#include "JitArm_Tables.h" +#include "ArmEmitter.h" +#include "../JitInterface.h" + +using namespace ArmGen; +using namespace PowerPC; + +static int CODE_SIZE = 1024*1024*32; +namespace CPUCompare +{ + extern u32 m_BlockStart; +} + +void JitArm::Init() +{ + AllocCodeSpace(CODE_SIZE); + blocks.Init(); + asm_routines.Init(); + // TODO: Investigate why the register cache crashes when only doing Init with + // the pointer to this. Seems for some reason it doesn't set the emitter pointer + // In the class for some reason? + gpr.Init(this); + gpr.SetEmitter(this); + fpr.Init(this); + fpr.SetEmitter(this); + jo.enableBlocklink = true; + jo.optimizeGatherPipe = false; +} + +void JitArm::ClearCache() +{ + ClearCodeSpace(); + blocks.Clear(); +} + +void JitArm::Shutdown() +{ + FreeCodeSpace(); + blocks.Shutdown(); + asm_routines.Shutdown(); +} + +// This is only called by Default() in this file. It will execute an instruction with the interpreter functions. +void JitArm::WriteCallInterpreter(UGeckoInstruction inst) +{ + gpr.Flush(); + fpr.Flush(); + Interpreter::_interpreterInstruction instr = GetInterpreterOp(inst); + MOVI2R(R0, inst.hex); + MOVI2R(R12, (u32)instr); + BL(R12); +} +void JitArm::unknown_instruction(UGeckoInstruction inst) +{ + PanicAlert("unknown_instruction %08x - Fix me ;)", inst.hex); +} + +void JitArm::Default(UGeckoInstruction _inst) +{ + WriteCallInterpreter(_inst.hex); +} + +void JitArm::HLEFunction(UGeckoInstruction _inst) +{ + gpr.Flush(); + fpr.Flush(); + MOVI2R(R0, js.compilerPC); + MOVI2R(R1, _inst.hex); + QuickCallFunction(R14, (void*)&HLE::Execute); + ARMReg rA = gpr.GetReg(); + LDR(rA, R9, PPCSTATE_OFF(PowerPC::ppcState, npc)); + WriteExitDestInR(rA); +} + +void JitArm::DoNothing(UGeckoInstruction _inst) +{ + // Yup, just don't do anything. +} + +static const bool ImHereDebug = false; +static const bool ImHereLog = false; +static std::map been_here; + +static void ImHere() +{ + static File::IOFile f; + if (ImHereLog) + { + if (!f) + { + f.Open("log32.txt", "w"); + } + fprintf(f.GetHandle(), "%08x\n", PC); + } + if (been_here.find(PC) != been_here.end()) + { + been_here.find(PC)->second++; + if ((been_here.find(PC)->second) & 1023) + return; + } + DEBUG_LOG(DYNA_REC, "I'm here - PC = %08x , LR = %08x", PC, LR); + been_here[PC] = 1; +} + +void JitArm::Cleanup() +{ + if (jo.optimizeGatherPipe && js.fifoBytesThisBlock > 0) + QuickCallFunction(R14, (void*)&GPFifo::CheckGatherPipe); +} +void JitArm::DoDownCount() +{ + ARMReg rA = gpr.GetReg(); + ARMReg rB = gpr.GetReg(); + MOVI2R(rA, (u32)&CoreTiming::downcount); + LDR(rB, rA); + if(js.downcountAmount < 255) // We can enlarge this if we used rotations + { + SUBS(rB, rB, js.downcountAmount); + STR(rA, rB); + } + else + { + ARMReg rC = gpr.GetReg(false); + MOVI2R(rC, js.downcountAmount); + SUBS(rB, rB, rC); + STR(rA, rB); + } + gpr.Unlock(rA, rB); +} +void JitArm::WriteExitDestInR(ARMReg Reg) +{ + STR(R9, Reg, PPCSTATE_OFF(PowerPC::ppcState, pc)); + Cleanup(); + DoDownCount(); + MOVI2R(Reg, (u32)asm_routines.dispatcher); + B(Reg); + gpr.Unlock(Reg); +} +void JitArm::WriteRfiExitDestInR(ARMReg Reg) +{ + STR(R9, Reg, PPCSTATE_OFF(PowerPC::ppcState, pc)); + Cleanup(); + DoDownCount(); + + MOVI2R(Reg, (u32)asm_routines.testExceptions); + B(Reg); + gpr.Unlock(Reg); // This was locked in the instruction beforehand +} +void JitArm::WriteExceptionExit() +{ + ARMReg A = gpr.GetReg(false); + Cleanup(); + DoDownCount(); + + MOVI2R(A, (u32)asm_routines.testExceptions); + B(A); +} +void JitArm::WriteExit(u32 destination, int exit_num) +{ + 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(); + + // Link opportunity! + int block = blocks.GetBlockNumberFromStartAddress(destination); + if (block >= 0 && jo.enableBlocklink) + { + // It exists! Joy of joy! + B(blocks.GetBlock(block)->checkedEntry); + b->linkStatus[exit_num] = true; + } + else + { + ARMReg A = gpr.GetReg(false); + MOVI2R(A, destination); + STR(R9, A, PPCSTATE_OFF(PowerPC::ppcState, pc)); + MOVI2R(A, (u32)asm_routines.dispatcher); + B(A); + } +} + +void STACKALIGN JitArm::Run() +{ + CompiledCode pExecAddr = (CompiledCode)asm_routines.enterCode; + pExecAddr(); +} + +void JitArm::SingleStep() +{ + CompiledCode pExecAddr = (CompiledCode)asm_routines.enterCode; + pExecAddr(); +} + +void JitArm::Trace() +{ + char regs[500] = ""; + char fregs[750] = ""; + +#ifdef JIT_LOG_GPR + for (int i = 0; i < 32; i++) + { + char reg[50]; + sprintf(reg, "r%02d: %08x ", i, PowerPC::ppcState.gpr[i]); + strncat(regs, reg, 500); + } +#endif + +#ifdef JIT_LOG_FPR + for (int i = 0; i < 32; i++) + { + char reg[50]; + sprintf(reg, "f%02d: %016x ", i, riPS0(i)); + strncat(fregs, reg, 750); + } +#endif + + DEBUG_LOG(DYNA_REC, "JITARM PC: %08x SRR0: %08x SRR1: %08x CRfast: %02x%02x%02x%02x%02x%02x%02x%02x FPSCR: %08x MSR: %08x LR: %08x %s %s", + PC, SRR0, SRR1, PowerPC::ppcState.cr_fast[0], PowerPC::ppcState.cr_fast[1], PowerPC::ppcState.cr_fast[2], PowerPC::ppcState.cr_fast[3], + PowerPC::ppcState.cr_fast[4], PowerPC::ppcState.cr_fast[5], PowerPC::ppcState.cr_fast[6], PowerPC::ppcState.cr_fast[7], PowerPC::ppcState.fpscr, + PowerPC::ppcState.msr, PowerPC::ppcState.spr[8], regs, fregs); +} + +void JitArm::PrintDebug(UGeckoInstruction inst, u32 level) +{ + if (level > 0) + printf("Start: %08x OP '%s' Info\n", (u32)GetCodePtr(), PPCTables::GetInstructionName(inst)); + if (level > 1) + { + GekkoOPInfo* Info = GetOpInfo(inst.hex); + printf("\tOuts\n"); + if (Info->flags & FL_OUT_A) + printf("\t-OUT_A: %x\n", inst.RA); + if(Info->flags & FL_OUT_D) + printf("\t-OUT_D: %x\n", inst.RD); + printf("\tIns\n"); + // A, AO, B, C, S + if(Info->flags & FL_IN_A) + printf("\t-IN_A: %x\n", inst.RA); + if(Info->flags & FL_IN_A0) + printf("\t-IN_A0: %x\n", inst.RA); + if(Info->flags & FL_IN_B) + printf("\t-IN_B: %x\n", inst.RB); + if(Info->flags & FL_IN_C) + printf("\t-IN_C: %x\n", inst.RC); + if(Info->flags & FL_IN_S) + printf("\t-IN_S: %x\n", inst.RS); + } +} + +void STACKALIGN JitArm::Jit(u32 em_address) +{ + if (GetSpaceLeft() < 0x10000 || blocks.IsFull() || Core::g_CoreStartupParameter.bJITNoBlockCache) + { + ClearCache(); + } + + int block_num = blocks.AllocateBlock(em_address); + JitBlock *b = blocks.GetBlock(block_num); + const u8* BlockPtr = DoJit(em_address, &code_buffer, b); + blocks.FinalizeBlock(block_num, jo.enableBlocklink, BlockPtr); +} +void JitArm::Break(UGeckoInstruction inst) +{ + BKPT(0x4444); +} + +const u8* JitArm::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBlock *b) +{ + int blockSize = code_buf->GetSize(); + // Memory exception on instruction fetch + bool memory_exception = false; + + // A broken block is a block that does not end in a branch + bool broken_block = false; + + if (Core::g_CoreStartupParameter.bEnableDebugging) + { + // Comment out the following to disable breakpoints (speed-up) + blockSize = 1; + broken_block = true; + Trace(); + } + + if (em_address == 0) + { + Core::SetState(Core::CORE_PAUSE); + PanicAlert("ERROR: Compiling at 0. LR=%08x CTR=%08x", LR, CTR); + } + + if (Core::g_CoreStartupParameter.bMMU && (em_address & JIT_ICACHE_VMEM_BIT)) + { + if (!Memory::TranslateAddress(em_address, Memory::FLAG_OPCODE)) + { + // Memory exception occurred during instruction fetch + memory_exception = true; + } + } + + + int size = 0; + js.isLastInstruction = false; + js.blockStart = em_address; + js.fifoBytesThisBlock = 0; + js.curBlock = b; + js.block_flags = 0; + js.cancel = false; + + // 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. + u32 nextPC = 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. + nextPC = 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; + + const u8 *start = GetCodePtr(); + b->checkedEntry = start; + b->runCount = 0; + + // Downcount flag check, Only valid for linked blocks + { + FixupBranch skip = B_CC(CC_PL); + ARMABI_MOVI2M((u32)&PC, js.blockStart); + ARMReg rA = gpr.GetReg(false); + MOVI2R(rA, (u32)asm_routines.doTiming); + B(rA); + SetJumpTarget(skip); + } + + const u8 *normalEntry = GetCodePtr(); + b->normalEntry = normalEntry; + + if(ImHereDebug) + QuickCallFunction(R14, (void *)&ImHere); //Used to get a trace of the last few blocks before a crash, sometimes VERY useful + + if (js.fpa.any) + { + // This block uses FPU - needs to add FP exception bailout + ARMReg A = gpr.GetReg(); + ARMReg C = gpr.GetReg(); + Operand2 Shift(2, 10); // 1 << 13 + MOVI2R(C, js.blockStart); // R3 + LDR(A, R9, PPCSTATE_OFF(PowerPC::ppcState, msr)); + TST(A, Shift); + FixupBranch b1 = B_CC(CC_NEQ); + STR(R9, C, PPCSTATE_OFF(PowerPC::ppcState, pc)); + MOVI2R(A, (u32)asm_routines.fpException); + B(A); + SetJumpTarget(b1); + gpr.Unlock(A, C); + } + // Conditionally add profiling code. + if (Profiler::g_ProfileBlocks) { + ARMReg rA = gpr.GetReg(); + ARMReg rB = gpr.GetReg(); + MOVI2R(rA, (u32)&b->runCount); // Load in to register + LDR(rB, rA); // Load the actual value in to R11. + ADD(rB, rB, 1); // Add one to the value + STR(rA, rB); // Now store it back in the memory location + // get start tic + PROFILER_QUERY_PERFORMANCE_COUNTER(&b->ticStart); + gpr.Unlock(rA, rB); + } + gpr.Start(js.gpa); + fpr.Start(js.fpa); + js.downcountAmount = 0; + if (!Core::g_CoreStartupParameter.bEnableDebugging) + { + for (int i = 0; i < size_of_merged_addresses; ++i) + { + const u32 address = merged_addresses[i]; + js.downcountAmount += PatchEngine::GetSpeedhackCycles(address); + } + } + + js.skipnext = false; + js.blockSize = size; + js.compilerPC = nextPC; + // Translate instructions + for (int i = 0; i < (int)size; i++) + { + js.compilerPC = ops[i].address; + js.op = &ops[i]; + js.instructionNumber = i; + const GekkoOPInfo *opinfo = ops[i].opinfo; + js.downcountAmount += (opinfo->numCyclesMinusOne + 1); + + if (i == (int)size - 1) + { + // WARNING - cmp->branch merging will screw this up. + js.isLastInstruction = true; + js.next_inst = 0; + if (Profiler::g_ProfileBlocks) { + // CAUTION!!! push on stack regs you use, do your stuff, then pop + PROFILER_VPUSH; + // get end tic + PROFILER_QUERY_PERFORMANCE_COUNTER(&b->ticStop); + // tic counter += (end tic - start tic) + PROFILER_ADD_DIFF_LARGE_INTEGER(&b->ticCounter, &b->ticStop, &b->ticStart); + PROFILER_VPOP; + } + } + else + { + // help peephole optimizations + js.next_inst = ops[i + 1].inst; + js.next_compilerPC = ops[i + 1].address; + } + if (jo.optimizeGatherPipe && js.fifoBytesThisBlock >= 32) + { + js.fifoBytesThisBlock -= 32; + // TODO: This needs thunkmanager for ARM + //ARMABI_CallFunction(thunks.ProtectFunction((void *)&GPFifo::CheckGatherPipe, 0)); + } + if (Core::g_CoreStartupParameter.bEnableDebugging) + { + // Add run count + ARMReg RA = gpr.GetReg(); + ARMReg RB = gpr.GetReg(); + MOVI2R(RA, (u32)&opinfo->runCount); + LDR(RB, RA); + ADD(RB, RB, 1); + STR(RA, RB); + gpr.Unlock(RA, RB); + } + if (!ops[i].skip) + { + PrintDebug(ops[i].inst, 0); + if (js.memcheck && (opinfo->flags & FL_USE_FPU)) + { + // Don't do this yet + BKPT(0x7777); + } + JitArmTables::CompileInstruction(ops[i]); + if (js.memcheck && (opinfo->flags & FL_LOADSTORE)) + { + // Don't do this yet + BKPT(0x666); + } + } + } + if (memory_exception) + BKPT(0x500); + if (broken_block) + { + printf("Broken Block going to 0x%08x\n", nextPC); + WriteExit(nextPC, 0); + } + + b->flags = js.block_flags; + b->codeSize = (u32)(GetCodePtr() - normalEntry); + b->originalSize = size; + FlushIcache(); + return start; +} + diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/Jit.h b/Source/Core/Core/Src/PowerPC/JitArm32/Jit.h new file mode 100644 index 0000000000..1dde0fa55f --- /dev/null +++ b/Source/Core/Core/Src/PowerPC/JitArm32/Jit.h @@ -0,0 +1,186 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +// ======================== +// See comments in Jit.cpp. +// ======================== + +// Mystery: Capcom vs SNK 800aa278 + +// CR flags approach: +// * Store that "N+Z flag contains CR0" or "S+Z flag contains CR3". +// * All flag altering instructions flush this +// * A flush simply does a conditional write to the appropriate CRx. +// * If flag available, branch code can become absolutely trivial. + +// Settings +// ---------- +#ifndef _JITARM_H +#define _JITARM_H +#include "../CPUCoreBase.h" +#include "../PPCAnalyst.h" +#include "JitArmCache.h" +#include "JitRegCache.h" +#include "JitFPRCache.h" +#include "JitAsm.h" +#include "../JitCommon/JitBase.h" + +// Use these to control the instruction selection +// #define INSTRUCTION_START Default(inst); return; +// #define INSTRUCTION_START PPCTables::CountInstruction(inst); +#define INSTRUCTION_START +#define JITDISABLE(type) \ + if (Core::g_CoreStartupParameter.bJITOff || \ + Core::g_CoreStartupParameter.bJIT##type##Off) \ + {Default(inst); return;} +#define PPCSTATE_OFF(str, elem) ((s32)STRUCT_OFF(PowerPC::ppcState, elem) - (s32)STRUCT_OFF(PowerPC::ppcState, spr[0])) +class JitArm : public JitBase, public ArmGen::ARMXCodeBlock +{ +private: + JitArmBlockCache blocks; + + JitArmAsmRoutineManager asm_routines; + + // TODO: Make arm specific versions of these, shouldn't be too hard to + // make it so we allocate some space at the start(?) of code generation + // and keep the registers in a cache. Will burn this bridge when we get to + // it. + ArmRegCache gpr; + ArmFPRCache fpr; + + PPCAnalyst::CodeBuffer code_buffer; + void DoDownCount(); + + void PrintDebug(UGeckoInstruction inst, u32 level); + + void Helper_UpdateCR1(ARMReg value); +public: + JitArm() : code_buffer(32000) {} + ~JitArm() {} + + void Init(); + void Shutdown(); + + // Jit! + + void Jit(u32 em_address); + const u8* DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBlock *b); + + JitBaseBlockCache *GetBlockCache() { return &blocks; } + + const u8 *BackPatch(u8 *codePtr, int accessType, u32 em_address, void *ctx); + + bool IsInCodeSpace(u8 *ptr) { return IsInSpace(ptr); } + + void Trace(); + + void ClearCache(); + + const u8 *GetDispatcher() { + return asm_routines.dispatcher; + } + CommonAsmRoutinesBase *GetAsmRoutines() { + return &asm_routines; + } + + const char *GetName() { + return "JITARM"; + } + // Run! + + void Run(); + void SingleStep(); + + // Utilities for use by opcodes + + void WriteExit(u32 destination, int exit_num); + void WriteExitDestInR(ARMReg Reg); + void WriteRfiExitDestInR(ARMReg Reg); + void WriteExceptionExit(); + void WriteCallInterpreter(UGeckoInstruction _inst); + void Cleanup(); + + void GenerateRC(int cr = 0); + void ComputeRC(int cr = 0); + + // TODO: This shouldn't be here + void StoreFromReg(ARMReg dest, ARMReg value, int accessSize, s32 offset); + void LoadToReg(ARMReg dest, ARMReg addr, int accessSize, s32 offset); + + // OPCODES + void unknown_instruction(UGeckoInstruction _inst); + void Default(UGeckoInstruction _inst); + void DoNothing(UGeckoInstruction _inst); + void HLEFunction(UGeckoInstruction _inst); + + void DynaRunTable4(UGeckoInstruction _inst); + void DynaRunTable19(UGeckoInstruction _inst); + void DynaRunTable31(UGeckoInstruction _inst); + void DynaRunTable59(UGeckoInstruction _inst); + void DynaRunTable63(UGeckoInstruction _inst); + + // Breakin shit + void Break(UGeckoInstruction _inst); + // Branch + void bx(UGeckoInstruction _inst); + void bcx(UGeckoInstruction _inst); + void bclrx(UGeckoInstruction _inst); + void sc(UGeckoInstruction _inst); + void rfi(UGeckoInstruction _inst); + void bcctrx(UGeckoInstruction _inst); + + // Integer + void addi(UGeckoInstruction _inst); + void addis(UGeckoInstruction _inst); + void addx(UGeckoInstruction _inst); + void cmp (UGeckoInstruction _inst); + void cmpi(UGeckoInstruction _inst); + void cmpli(UGeckoInstruction _inst); + void negx(UGeckoInstruction _inst); + void mulli(UGeckoInstruction _inst); + void ori(UGeckoInstruction _inst); + void oris(UGeckoInstruction _inst); + void orx(UGeckoInstruction _inst); + void rlwimix(UGeckoInstruction _inst); + void rlwinmx(UGeckoInstruction _inst); + void extshx(UGeckoInstruction inst); + void extsbx(UGeckoInstruction inst); + + // System Registers + void mtmsr(UGeckoInstruction _inst); + void mtspr(UGeckoInstruction _inst); + void mfspr(UGeckoInstruction _inst); + + // LoadStore + void icbi(UGeckoInstruction _inst); + void lbz(UGeckoInstruction _inst); + void lhz(UGeckoInstruction _inst); + void lwz(UGeckoInstruction _inst); + void lwzx(UGeckoInstruction _inst); + void stw(UGeckoInstruction _inst); + void stwu(UGeckoInstruction _inst); + + // Floating point + void fabsx(UGeckoInstruction _inst); + void faddx(UGeckoInstruction _inst); + void fmrx(UGeckoInstruction _inst); + + // Floating point loadStore + void lfs(UGeckoInstruction _inst); +}; + +#endif // _JIT64_H diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/JitArmCache.cpp b/Source/Core/Core/Src/PowerPC/JitArm32/JitArmCache.cpp new file mode 100644 index 0000000000..dd85699a6d --- /dev/null +++ b/Source/Core/Core/Src/PowerPC/JitArm32/JitArmCache.cpp @@ -0,0 +1,45 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +// Enable define below to enable oprofile integration. For this to work, +// it requires at least oprofile version 0.9.4, and changing the build +// system to link the Dolphin executable against libopagent. Since the +// dependency is a little inconvenient and this is possibly a slight +// performance hit, it's not enabled by default, but it's useful for +// locating performance issues. + +#include "../JitInterface.h" +#include "JitArmCache.h" + + +using namespace ArmGen; + + void JitArmBlockCache::WriteLinkBlock(u8* location, const u8* address) + { + ARMXEmitter emit(location); + emit.B(address); + } + void JitArmBlockCache::WriteDestroyBlock(const u8* location, u32 address) + { + ARMXEmitter emit((u8 *)location); + emit.MOVI2R(R11, address); + emit.MOVI2R(R12, (u32)jit->GetAsmRoutines()->dispatcher); + emit.STR(R9, R11, PPCSTATE_OFF(PowerPC::ppcState, pc)); + emit.B(R12); + } + + diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/JitArmCache.h b/Source/Core/Core/Src/PowerPC/JitArm32/JitArmCache.h new file mode 100644 index 0000000000..103947d5ad --- /dev/null +++ b/Source/Core/Core/Src/PowerPC/JitArm32/JitArmCache.h @@ -0,0 +1,33 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#ifndef _JITARMCACHE_H +#define _JITARMCACHE_H + +#include "../JitCommon/JitCache.h" + + +typedef void (*CompiledCode)(); + +class JitArmBlockCache : public JitBaseBlockCache +{ +private: + void WriteLinkBlock(u8* location, const u8* address); + void WriteDestroyBlock(const u8* location, u32 address); +}; + +#endif diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_BackPatch.cpp b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_BackPatch.cpp new file mode 100644 index 0000000000..677dc238a8 --- /dev/null +++ b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_BackPatch.cpp @@ -0,0 +1,164 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include + +#include "Common.h" + +#include "../../HW/Memmap.h" +#include "Jit.h" +#include "../JitCommon/JitBackpatch.h" +#include "StringUtil.h" + +#ifdef _M_X64 +static void BackPatchError(const std::string &text, u8 *codePtr, u32 emAddress) { + u64 code_addr = (u64)codePtr; + disassembler disasm; + char disbuf[256]; + memset(disbuf, 0, 256); +#ifdef _M_IX86 + disasm.disasm32(0, code_addr, codePtr, disbuf); +#else + disasm.disasm64(0, code_addr, codePtr, disbuf); +#endif + PanicAlert("%s\n\n" + "Error encountered accessing emulated address %08x.\n" + "Culprit instruction: \n%s\nat %#llx", + text.c_str(), emAddress, disbuf, code_addr); + return; +} +#endif + +// This generates some fairly heavy trampolines, but: +// 1) It's really necessary. We don't know anything about the context. +// 2) It doesn't really hurt. Only instructions that access I/O will get these, and there won't be +// that many of them in a typical program/game. +bool DisamLoadStore(const u32 inst, ARMReg &rD, u8 &accessSize, bool &Store) +{ + u8 op = (inst >> 20) & 0xFF; + printf("op: 0x%08x\n", op); + switch (op) + { + case 0x58: // STR + { + rD = (ARMReg)((inst >> 16) & 0xF); + Store = true; + accessSize = 32; + } + break; + case 0x59: // LDR + { + rD = (ARMReg)((inst >> 16) & 0xF); + Store = false; + accessSize = 32; + } + break; + case 0x05: // LDRH + { + rD = (ARMReg)((inst >> 16) & 0xF); + Store = false; + accessSize = 16; + } + break; + case 0x45 + 0x18: // LDRB + { + rD = (ARMReg)((inst >> 16) & 0xF); + Store = false; + accessSize = 8; + } + break; + case 0x44 + 0x18: // STRB + default: + return false; + } + return true; +} +const u8 *JitArm::BackPatch(u8 *codePtr, int accessType, u32 emAddress, void *ctx_void) +{ + // TODO: This ctx needs to be filled with our information + CONTEXT *ctx = (CONTEXT *)ctx_void; + + // We need to get the destination register before we start + u32 Value = *(u32*)codePtr; + ARMReg rD; + u8 accessSize; + bool Store; + + if (!DisamLoadStore(Value, rD, accessSize, Store)) + { + printf("Invalid backpatch at location 0x%08x(0x%08x)\n", ctx->reg_pc, Value); + exit(0); + } + + if (Store) + { + const u32 ARMREGOFFSET = 4 * 7; + ARMXEmitter emitter(codePtr - ARMREGOFFSET); + switch (accessSize) + { + case 8: // 8bit + //emitter.MOVI2R(R14, (u32)&Memory::Write_U8, false); // 1-2 + return 0; + break; + case 16: // 16bit + //emitter.MOVI2R(R14, (u32)&Memory::Write_U16, false); // 1-2 + return 0; + break; + case 32: // 32bit + emitter.MOVI2R(R14, (u32)&Memory::Write_U32, false); // 1-2 + break; + } + emitter.PUSH(4, R0, R1, R2, R3); // 3 + emitter.MOV(R0, rD); // Value - 4 + emitter.MOV(R1, R10); // Addr- 5 + emitter.BL(R14); // 6 + emitter.POP(4, R0, R1, R2, R3); // 7 + emitter.NOP(1); // 8 + u32 newPC = ctx->reg_pc - (ARMREGOFFSET + 4 * 4); + ctx->reg_pc = newPC; + emitter.FlushIcache(); + return codePtr; + } + else + { + const u32 ARMREGOFFSET = 4 * 6; + ARMXEmitter emitter(codePtr - ARMREGOFFSET); + switch (accessSize) + { + case 8: // 8bit + emitter.MOVI2R(R14, (u32)&Memory::Read_U8, false); // 2 + break; + case 16: // 16bit + emitter.MOVI2R(R14, (u32)&Memory::Read_U16, false); // 2 + break; + case 32: // 32bit + emitter.MOVI2R(R14, (u32)&Memory::Read_U32, false); // 2 + break; + } + emitter.PUSH(4, R0, R1, R2, R3); // 3 + emitter.MOV(R0, R10); // 4 + emitter.BL(R14); // 5 + emitter.MOV(R14, R0); // 6 + emitter.POP(4, R0, R1, R2, R3); // 7 + emitter.MOV(rD, R14); // 8 + ctx->reg_pc -= ARMREGOFFSET + (4 * 4); + emitter.FlushIcache(); + return codePtr; + } + return 0; +} + diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Branch.cpp b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Branch.cpp new file mode 100644 index 0000000000..1c401771d7 --- /dev/null +++ b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Branch.cpp @@ -0,0 +1,355 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ +#include "Common.h" +#include "Thunk.h" + +#include "../../Core.h" +#include "../PowerPC.h" +#include "../../CoreTiming.h" +#include "../PPCTables.h" +#include "ArmEmitter.h" + +#include "Jit.h" +#include "JitRegCache.h" +#include "JitAsm.h" + +// The branches are known good, or at least reasonably good. +// No need for a disable-mechanism. + +// If defined, clears CR0 at blr and bl-s. If the assumption that +// flags never carry over between functions holds, then the task for +// an optimizer becomes much easier. + +// #define ACID_TEST + +// Zelda and many more games seem to pass the Acid Test. + + +using namespace ArmGen; +void JitArm::sc(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Branch) + + gpr.Flush(); + fpr.Flush(); + + ARMABI_MOVI2M((u32)&PC, js.compilerPC + 4); // Destroys R12 and R14 + ARMReg rA = gpr.GetReg(); + LDR(rA, R9, PPCSTATE_OFF(PowerPC::ppcState, Exceptions)); + ORR(rA, rA, EXCEPTION_SYSCALL); + STR(R9, rA, PPCSTATE_OFF(PowerPC::ppcState, Exceptions)); + gpr.Unlock(rA); + + WriteExceptionExit(); +} + +void JitArm::rfi(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Branch) + + gpr.Flush(); + fpr.Flush(); + + // See Interpreter rfi for details + const u32 mask = 0x87C0FFFF; + const u32 clearMSR13 = 0xFFFBFFFF; // Mask used to clear the bit MSR[13] + // MSR = ((MSR & ~mask) | (SRR1 & mask)) & clearMSR13; + // R0 = MSR location + // R1 = MSR contents + // R2 = Mask + // R3 = Mask + ARMReg rA = gpr.GetReg(); + ARMReg rB = gpr.GetReg(); + ARMReg rC = gpr.GetReg(); + ARMReg rD = gpr.GetReg(); + MOVI2R(rB, (~mask) & clearMSR13); + MOVI2R(rC, mask & clearMSR13); + + LDR(rD, R9, PPCSTATE_OFF(PowerPC::ppcState, msr)); + + AND(rD, rD, rB); // rD = Masked MSR + STR(R9, rD, PPCSTATE_OFF(PowerPC::ppcState, msr)); + + LDR(rB, R9, PPCSTATE_OFF(PowerPC::ppcState, spr[SPR_SRR1])); // rB contains SRR1 here + + AND(rB, rB, rC); // rB contains masked SRR1 here + ORR(rB, rD, rB); // rB = Masked MSR OR masked SRR1 + + STR(R9, rB, PPCSTATE_OFF(PowerPC::ppcState, msr)); // STR rB in to rA + + LDR(rA, R9, PPCSTATE_OFF(PowerPC::ppcState, spr[SPR_SRR0])); + + gpr.Unlock(rB, rC, rD); + WriteRfiExitDestInR(rA); // rA gets unlocked here + //AND(32, M(&MSR), Imm32((~mask) & clearMSR13)); + //MOV(32, R(EAX), M(&SRR1)); + //AND(32, R(EAX), Imm32(mask & clearMSR13)); + //OR(32, M(&MSR), R(EAX)); + // NPC = SRR0; + //MOV(32, R(EAX), M(&SRR0)); + //WriteRfiExitDestInEAX(); +} + +void JitArm::bx(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Branch) + // We must always process the following sentence + // even if the blocks are merged by PPCAnalyst::Flatten(). + if (inst.LK) + { + ARMReg rA = gpr.GetReg(false); + u32 Jumpto = js.compilerPC + 4; + MOVI2R(rA, Jumpto); + STR(R9, rA, PPCSTATE_OFF(PowerPC::ppcState, spr[SPR_LR])); + //ARMABI_MOVI2M((u32)&LR, js.compilerPC + 4); + } + // If this is not the last instruction of a block, + // we will skip the rest process. + // Because PPCAnalyst::Flatten() merged the blocks. + if (!js.isLastInstruction) { + return; + } + + gpr.Flush(); + fpr.Flush(); + + u32 destination; + if (inst.AA) + destination = SignExt26(inst.LI << 2); + 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))); + #endif + if (destination == js.compilerPC) + { + //PanicAlert("Idle loop detected at %08x", destination); + // CALL(ProtectFunction(&CoreTiming::Idle, 0)); + // JMP(Asm::testExceptions, true); + // make idle loops go faster + js.downcountAmount += 8; + } + WriteExit(destination, 0); +} + +void JitArm::bcx(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Branch) + // USES_CR + _assert_msg_(DYNA_REC, js.isLastInstruction, "bcx not last instruction of block"); + + gpr.Flush(); + fpr.Flush(); + + ARMReg rA = gpr.GetReg(); + ARMReg rB = gpr.GetReg(); + FixupBranch pCTRDontBranch; + if ((inst.BO & BO_DONT_DECREMENT_FLAG) == 0) // Decrement and test CTR + { + LDR(rB, R9, PPCSTATE_OFF(PowerPC::ppcState, spr[SPR_CTR])); + SUBS(rB, rB, 1); + STR(R9, rB, PPCSTATE_OFF(PowerPC::ppcState, spr[SPR_CTR])); + + //SUB(32, M(&CTR), Imm8(1)); + if (inst.BO & BO_BRANCH_IF_CTR_0) + pCTRDontBranch = B_CC(CC_NEQ); + else + pCTRDontBranch = B_CC(CC_EQ); + } + + FixupBranch pConditionDontBranch; + if ((inst.BO & BO_DONT_CHECK_CONDITION) == 0) // Test a CR bit + { + LDRB(rA, R9, PPCSTATE_OFF(PowerPC::ppcState, cr_fast) + (inst.BI >> 2)); + TST(rA, 8 >> (inst.BI & 3)); + + //TEST(8, M(&PowerPC::ppcState.cr_fast[inst.BI >> 2]), Imm8(8 >> (inst.BI & 3))); + if (inst.BO & BO_BRANCH_IF_TRUE) // Conditional branch + pConditionDontBranch = B_CC(CC_EQ); // Zero + else + pConditionDontBranch = B_CC(CC_NEQ); // Not Zero + } + if (inst.LK) + { + u32 Jumpto = js.compilerPC + 4; + MOVI2R(rB, Jumpto); + STR(R9, rB, PPCSTATE_OFF(PowerPC::ppcState, spr[SPR_LR])); + //ARMABI_MOVI2M((u32)&LR, js.compilerPC + 4); // Careful, destroys R14, R12 + } + gpr.Unlock(rA, rB); + + u32 destination; + if(inst.AA) + destination = SignExt16(inst.BD << 2); + else + destination = js.compilerPC + SignExt16(inst.BD << 2); + WriteExit(destination, 0); + + 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); +} +void JitArm::bcctrx(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Branch) + + gpr.Flush(); + fpr.Flush(); + + // bcctrx doesn't decrement and/or test CTR + _dbg_assert_msg_(POWERPC, inst.BO_2 & BO_DONT_DECREMENT_FLAG, "bcctrx with decrement and test CTR option is invalid!"); + + if (inst.BO_2 & BO_DONT_CHECK_CONDITION) + { + // BO_2 == 1z1zz -> b always + + //NPC = CTR & 0xfffffffc; + ARMReg rA = gpr.GetReg(); + ARMReg rB = gpr.GetReg(); + + if(inst.LK_3) + { + u32 Jumpto = js.compilerPC + 4; + MOVI2R(rA, Jumpto); + STR(R9, rA, PPCSTATE_OFF(PowerPC::ppcState, spr[SPR_LR])); + // ARMABI_MOVI2M((u32)&LR, js.compilerPC + 4); + } + MVN(rB, 0x3); // 0xFFFFFFFC + LDR(rA, R9, PPCSTATE_OFF(PowerPC::ppcState, spr[SPR_CTR])); + AND(rA, rA, rB); + gpr.Unlock(rB); + WriteExitDestInR(rA); + } + else + { + // Rare condition seen in (just some versions of?) Nintendo's NES Emulator + + // BO_2 == 001zy -> b if false + // BO_2 == 011zy -> b if true + ARMReg rA = gpr.GetReg(); + ARMReg rB = gpr.GetReg(); + + LDRB(rA, R9, PPCSTATE_OFF(PowerPC::ppcState, cr_fast) + (inst.BI >> 2)); + TST(rA, 8 >> (inst.BI & 3)); + CCFlags branch; + if (inst.BO_2 & BO_BRANCH_IF_TRUE) + branch = CC_EQ; + else + branch = CC_NEQ; + FixupBranch b = B_CC(branch); + + LDR(rA, R9, PPCSTATE_OFF(PowerPC::ppcState, spr[SPR_CTR])); + MVN(rB, 0x3); // 0xFFFFFFFC + AND(rA, rA, rB); + + if (inst.LK_3){ + u32 Jumpto = js.compilerPC + 4; + MOVI2R(rB, Jumpto); + STR(R9, rB, PPCSTATE_OFF(PowerPC::ppcState, spr[SPR_LR])); + //ARMABI_MOVI2M((u32)&LR, js.compilerPC + 4); + } + gpr.Unlock(rB); // rA gets unlocked in WriteExitDestInR + WriteExitDestInR(rA); + + SetJumpTarget(b); + WriteExit(js.compilerPC + 4, 1); + } +} +void JitArm::bclrx(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Branch) + if (!js.isLastInstruction && + (inst.BO & (1 << 4)) && (inst.BO & (1 << 2))) { + if (inst.LK) + { + ARMReg rA = gpr.GetReg(false); + u32 Jumpto = js.compilerPC + 4; + MOVI2R(rA, Jumpto); + STR(R9, rA, PPCSTATE_OFF(PowerPC::ppcState, spr[SPR_LR])); + // ARMABI_MOVI2M((u32)&LR, js.compilerPC + 4); + } + return; + } + gpr.Flush(); + fpr.Flush(); + + ARMReg rA = gpr.GetReg(); + ARMReg rB = gpr.GetReg(); + FixupBranch pCTRDontBranch; + if ((inst.BO & BO_DONT_DECREMENT_FLAG) == 0) // Decrement and test CTR + { + LDR(rB, R9, PPCSTATE_OFF(PowerPC::ppcState, spr[SPR_CTR])); + SUBS(rB, rB, 1); + STR(R9, rB, PPCSTATE_OFF(PowerPC::ppcState, spr[SPR_CTR])); + + //SUB(32, M(&CTR), Imm8(1)); + if (inst.BO & BO_BRANCH_IF_CTR_0) + pCTRDontBranch = B_CC(CC_NEQ); + else + pCTRDontBranch = B_CC(CC_EQ); + } + + FixupBranch pConditionDontBranch; + if ((inst.BO & BO_DONT_CHECK_CONDITION) == 0) // Test a CR bit + { + LDRB(rA, R9, PPCSTATE_OFF(PowerPC::ppcState, cr_fast) + (inst.BI >> 2)); + TST(rA, 8 >> (inst.BI & 3)); + //TEST(8, M(&PowerPC::ppcState.cr_fast[inst.BI >> 2]), Imm8(8 >> (inst.BI & 3))); + if (inst.BO & BO_BRANCH_IF_TRUE) // Conditional branch + pConditionDontBranch = B_CC(CC_EQ); // Zero + else + pConditionDontBranch = B_CC(CC_NEQ); // Not Zero + } + + // 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))); + #endif + + //MOV(32, R(EAX), M(&LR)); + //AND(32, R(EAX), Imm32(0xFFFFFFFC)); + MVN(rB, 0x3); // 0xFFFFFFFC + LDR(rA, R9, PPCSTATE_OFF(PowerPC::ppcState, spr[SPR_LR])); + AND(rA, rA, rB); + if (inst.LK){ + u32 Jumpto = js.compilerPC + 4; + MOVI2R(rB, Jumpto); + STR(R9, rB, PPCSTATE_OFF(PowerPC::ppcState, spr[SPR_LR])); + //ARMABI_MOVI2M((u32)&LR, js.compilerPC + 4); + } + gpr.Unlock(rB); // rA gets unlocked in WriteExitDestInR + WriteExitDestInR(rA); + + 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); +} diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_FloatingPoint.cpp b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_FloatingPoint.cpp new file mode 100644 index 0000000000..fe4c0e3f22 --- /dev/null +++ b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_FloatingPoint.cpp @@ -0,0 +1,80 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "Common.h" +#include "Thunk.h" + +#include "../../Core.h" +#include "../PowerPC.h" +#include "../../ConfigManager.h" +#include "../../CoreTiming.h" +#include "../PPCTables.h" +#include "ArmEmitter.h" +#include "../../HW/Memmap.h" + + +#include "Jit.h" +#include "JitRegCache.h" +#include "JitFPRCache.h" +#include "JitAsm.h" + +void JitArm::Helper_UpdateCR1(ARMReg value) +{ + // Should just update exception flags, not do any compares. + PanicAlert("CR1"); +} + +void JitArm::fabsx(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(FloatingPoint) + + ARMReg vD = fpr.R0(inst.FD); + ARMReg vB = fpr.R0(inst.FB); + + VABS(vD, vB); + + if (inst.Rc) Helper_UpdateCR1(vD); +} + +void JitArm::faddx(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(FloatingPoint) + + ARMReg vD = fpr.R0(inst.FD); + ARMReg vA = fpr.R0(inst.FA); + ARMReg vB = fpr.R0(inst.FB); + + VADD(vD, vA, vB); + if (inst.Rc) Helper_UpdateCR1(vD); +} + +void JitArm::fmrx(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(FloatingPoint) + Default(inst); return; + + ARMReg vD = fpr.R0(inst.FD); + ARMReg vB = fpr.R0(inst.FB); + + VMOV(vD, vB); + + if (inst.Rc) Helper_UpdateCR1(vD); +} + diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Integer.cpp b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Integer.cpp new file mode 100644 index 0000000000..4b77830ef3 --- /dev/null +++ b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Integer.cpp @@ -0,0 +1,311 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ +#include "Common.h" +#include "Thunk.h" + +#include "../../Core.h" +#include "../PowerPC.h" +#include "../../CoreTiming.h" +#include "../PPCTables.h" +#include "ArmEmitter.h" + +#include "Jit.h" +#include "JitRegCache.h" +#include "JitAsm.h" +extern u32 Helper_Mask(u8 mb, u8 me); +// ADDI and RLWINMX broken for now + +// Assumes that Sign and Zero flags were set by the last operation. Preserves all flags and registers. +// Jit64 ComputerRC is signed +// JIT64 GenerateRC is unsigned +void JitArm::GenerateRC(int cr) { + ARMReg rB = gpr.GetReg(); + + MOV(rB, 0x4); // Result > 0 + SetCC(CC_EQ); MOV(rB, 0x2); // Result == 0 + SetCC(CC_MI); MOV(rB, 0x8); // Result < 0 + SetCC(); + + STRB(R9, rB, PPCSTATE_OFF(PowerPC::ppcState, cr_fast) + cr); + gpr.Unlock(rB); +} +void JitArm::ComputeRC(int cr) { + ARMReg rB = gpr.GetReg(); + + MOV(rB, 0x2); // Result == 0 + SetCC(CC_LT); MOV(rB, 0x8); // Result < 0 + SetCC(CC_GT); MOV(rB, 0x4); // Result > 0 + SetCC(); + + STRB(R9, rB, PPCSTATE_OFF(PowerPC::ppcState, cr_fast) + cr); + gpr.Unlock(rB); +} + +void JitArm::addi(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Integer) + + ARMReg RD = gpr.R(inst.RD); + + if (inst.RA) + { + ARMReg rA = gpr.GetReg(false); + ARMReg RA = gpr.R(inst.RA); + MOVI2R(rA, (u32)inst.SIMM_16); + ADD(RD, RA, rA); + } + else + MOVI2R(RD, inst.SIMM_16); +} +void JitArm::addis(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Integer) + + ARMReg RD = gpr.R(inst.RD); + if (inst.RA) + { + ARMReg rA = gpr.GetReg(false); + ARMReg RA = gpr.R(inst.RA); + MOVI2R(rA, inst.SIMM_16 << 16); + ADD(RD, RA, rA); + } + else + MOVI2R(RD, inst.SIMM_16 << 16); +} +void JitArm::addx(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Integer) + + ARMReg RA = gpr.R(inst.RA); + ARMReg RB = gpr.R(inst.RB); + ARMReg RD = gpr.R(inst.RD); + ADDS(RD, RA, RB); + if (inst.Rc) ComputeRC(); +} +// Wrong - 28/10/2012 +void JitArm::mulli(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Integer) + + Default(inst); return; + ARMReg RA = gpr.R(inst.RA); + ARMReg RD = gpr.R(inst.RD); + ARMReg rA = gpr.GetReg(); + MOVI2R(rA, inst.SIMM_16); + MUL(RD, RA, rA); + gpr.Unlock(rA); +} +void JitArm::ori(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Integer) + + ARMReg RA = gpr.R(inst.RA); + ARMReg RS = gpr.R(inst.RS); + ARMReg rA = gpr.GetReg(); + MOVI2R(rA, inst.UIMM); + ORR(RA, RS, rA); + gpr.Unlock(rA); +} +void JitArm::oris(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Integer) + + ARMReg RA = gpr.R(inst.RA); + ARMReg RS = gpr.R(inst.RS); + ARMReg rA = gpr.GetReg(); + MOVI2R(rA, inst.UIMM << 16); + ORR(RA, RS, rA); + gpr.Unlock(rA); +} +void JitArm::orx(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Integer) + + ARMReg rA = gpr.R(inst.RA); + ARMReg rS = gpr.R(inst.RS); + ARMReg rB = gpr.R(inst.RB); + ORRS(rA, rS, rB); + if (inst.Rc) + ComputeRC(); +} + +void JitArm::extshx(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Integer) + ARMReg RA, RS; + RA = gpr.R(inst.RA); + RS = gpr.R(inst.RS); + SXTH(RA, RS); + if (inst.Rc){ + CMP(RA, 0); + ComputeRC(); + } +} +void JitArm::extsbx(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Integer) + ARMReg RA, RS; + RA = gpr.R(inst.RA); + RS = gpr.R(inst.RS); + SXTB(RA, RS); + if (inst.Rc){ + CMP(RA, 0); + ComputeRC(); + } +} +void JitArm::cmp (UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Integer) + + ARMReg RA = gpr.R(inst.RA); + ARMReg RB = gpr.R(inst.RB); + int crf = inst.CRFD; + CMP(RA, RB); + ComputeRC(crf); +} +void JitArm::cmpi(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Integer) + + ARMReg RA = gpr.R(inst.RA); + int crf = inst.CRFD; + if (inst.SIMM_16 >= 0 && inst.SIMM_16 < 256) + { + CMP(RA, inst.SIMM_16); + } + else + { + ARMReg rA = gpr.GetReg(); + MOVI2R(rA, inst.SIMM_16); + CMP(RA, rA); + gpr.Unlock(rA); + } + ComputeRC(crf); +} +void JitArm::cmpli(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Integer) + + ARMReg RA = gpr.R(inst.RA); + ARMReg rA = gpr.GetReg(); + int crf = inst.CRFD; + u32 uimm = (u32)inst.UIMM; + if (uimm < 256) + { + CMP(RA, uimm); + } + else + { + MOVI2R(rA, (u32)inst.UIMM); + CMP(RA, rA); + } + // Unsigned GenerateRC() + + MOV(rA, 0x2); // Result == 0 + SetCC(CC_LO); MOV(rA, 0x8); // Result < 0 + SetCC(CC_HI); MOV(rA, 0x4); // Result > 0 + SetCC(); + + STRB(R9, rA, PPCSTATE_OFF(PowerPC::ppcState, cr_fast) + crf); + gpr.Unlock(rA); + +} +// Wrong - 27/10/2012 +void JitArm::negx(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Integer) + + Default(inst);return; + ARMReg RA = gpr.R(inst.RA); + ARMReg RD = gpr.R(inst.RD); + + RSBS(RD, RA, 0); + if (inst.Rc) + { + GenerateRC(); + } + if (inst.OE) + { + BKPT(0x333); + //GenerateOverflow(); + } +} +void JitArm::rlwimix(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Integer) + + u32 mask = Helper_Mask(inst.MB,inst.ME); + ARMReg RA = gpr.R(inst.RA); + ARMReg RS = gpr.R(inst.RS); + ARMReg rA = gpr.GetReg(); + ARMReg rB = gpr.GetReg(); + MOVI2R(rA, mask); + + Operand2 Shift(32 - inst.SH, ST_ROR, RS); // This rotates left, while ARM has only rotate right, so swap it. + if (inst.Rc) + { + BIC (rB, RA, rA); // RA & ~mask + AND (rA, rA, Shift); + ORRS(RA, rB, rA); + GenerateRC(); + } + else + { + BIC (rB, RA, rA); // RA & ~mask + AND (rA, rA, Shift); + ORR(RA, rB, rA); + } + gpr.Unlock(rA, rB); +} +void JitArm::rlwinmx(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Integer) + + u32 mask = Helper_Mask(inst.MB,inst.ME); + ARMReg RA = gpr.R(inst.RA); + ARMReg RS = gpr.R(inst.RS); + ARMReg rA = gpr.GetReg(); + MOVI2R(rA, mask); + + Operand2 Shift(32 - inst.SH, ST_ROR, RS); // This rotates left, while ARM has only rotate right, so swap it. + if (inst.Rc) + { + ANDS(RA, rA, Shift); + GenerateRC(); + } + else + AND (RA, rA, Shift); + gpr.Unlock(rA); + + //m_GPR[inst.RA] = _rotl(m_GPR[inst.RS],inst.SH) & mask; +} + diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_LoadStore.cpp b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_LoadStore.cpp new file mode 100644 index 0000000000..dd9f7cd807 --- /dev/null +++ b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_LoadStore.cpp @@ -0,0 +1,414 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "Common.h" +#include "Thunk.h" + +#include "../../Core.h" +#include "../PowerPC.h" +#include "../../ConfigManager.h" +#include "../../CoreTiming.h" +#include "../PPCTables.h" +#include "ArmEmitter.h" +#include "../../HW/Memmap.h" + + +#include "Jit.h" +#include "JitRegCache.h" +#include "JitAsm.h" + +#ifdef ANDROID +#define FASTMEM 0 +#else +#define FASTMEM 0 +#endif +void JitArm::stw(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(LoadStore) + + ARMReg RS = gpr.R(inst.RS); +#if FASTMEM + // R10 contains the dest address + ARMReg Value = R11; + ARMReg RA; + if (inst.RA) + RA = gpr.R(inst.RA); + MOV(Value, RS); + if (inst.RA) + { + MOVI2R(R10, inst.SIMM_16, false); + ADD(R10, R10, RA); + } + else + { + MOVI2R(R10, (u32)inst.SIMM_16, false); + NOP(1); + } + StoreFromReg(R10, Value, 32, 0); +#else + ARMReg ValueReg = gpr.GetReg(); + ARMReg Addr = gpr.GetReg(); + ARMReg Function = gpr.GetReg(); + + MOV(ValueReg, RS); + if (inst.RA) + { + MOVI2R(Addr, inst.SIMM_16); + ARMReg RA = gpr.R(inst.RA); + ADD(Addr, Addr, RA); + } + else + MOVI2R(Addr, (u32)inst.SIMM_16); + + MOVI2R(Function, (u32)&Memory::Write_U32); + PUSH(4, R0, R1, R2, R3); + MOV(R0, ValueReg); + MOV(R1, Addr); + BL(Function); + POP(4, R0, R1, R2, R3); + gpr.Unlock(ValueReg, Addr, Function); +#endif +} +void JitArm::stwu(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(LoadStore) + + ARMReg RA = gpr.R(inst.RA); + ARMReg RS = gpr.R(inst.RS); + ARMReg ValueReg = gpr.GetReg(); + ARMReg Addr = gpr.GetReg(); + ARMReg Function = gpr.GetReg(); + + MOVI2R(Addr, inst.SIMM_16); + ADD(Addr, Addr, RA); + + // Check and set the update before writing since calling a function can + // mess with the "special registers R11+ which may cause some issues. + LDR(Function, R9, PPCSTATE_OFF(PowerPC::ppcState, Exceptions)); + CMP(Function, EXCEPTION_DSI); + FixupBranch DoNotWrite = B_CC(CC_EQ); + MOV(RA, Addr); + SetJumpTarget(DoNotWrite); + + MOV(ValueReg, RS); + + MOVI2R(Function, (u32)&Memory::Write_U32); + PUSH(4, R0, R1, R2, R3); + MOV(R0, ValueReg); + MOV(R1, Addr); + BL(Function); + POP(4, R0, R1, R2, R3); + + gpr.Unlock(ValueReg, Addr, Function); +} +void JitArm::StoreFromReg(ARMReg dest, ARMReg value, int accessSize, s32 offset) +{ + ARMReg rA = gpr.GetReg(); + + // All this gets replaced on backpatch + MOVI2R(rA, Memory::MEMVIEW32_MASK, false); // 1-2 + AND(dest, dest, rA); // 3 + MOVI2R(rA, (u32)Memory::base, false); // 4-5 + ADD(dest, dest, rA); // 6 + switch (accessSize) + { + case 32: + REV(value, value); // 7 + break; + case 16: + REV16(value, value); + break; + case 8: + NOP(1); + break; + } + switch (accessSize) + { + case 32: + STR(dest, value); // 8 + break; + case 16: + // Not implemented + break; + case 8: + // Not implemented + break; + } + gpr.Unlock(rA); +} +void JitArm::LoadToReg(ARMReg dest, ARMReg addr, int accessSize, s32 offset) +{ + ARMReg rA = gpr.GetReg(); + MOVI2R(rA, offset, false); // -3 + ADD(addr, addr, rA); // - 1 + + // All this gets replaced on backpatch + MOVI2R(rA, Memory::MEMVIEW32_MASK, false); // 2 + AND(addr, addr, rA); // 3 + MOVI2R(rA, (u32)Memory::base, false); // 5 + ADD(addr, addr, rA); // 6 + switch (accessSize) + { + case 32: + LDR(dest, addr); // 7 + break; + case 16: + LDRH(dest, addr); + break; + case 8: + LDRB(dest, addr); + break; + } + switch (accessSize) + { + case 32: + REV(dest, dest); // 9 + break; + case 16: + REV16(dest, dest); + break; + case 8: + NOP(1); + break; + + } + gpr.Unlock(rA); +} +void JitArm::lbz(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(LoadStore) + + ARMReg rA = gpr.GetReg(); + ARMReg rB = gpr.GetReg(); + ARMReg RD = gpr.R(inst.RD); + LDR(rA, R9, PPCSTATE_OFF(PowerPC::ppcState, Exceptions)); + CMP(rA, EXCEPTION_DSI); + FixupBranch DoNotLoad = B_CC(CC_EQ); +#if FASTMEM + // Backpatch route + // Gets loaded in to RD + // Address is in R10 + gpr.Unlock(rA, rB); + if (inst.RA) + { + ARMReg RA = gpr.R(inst.RA); + MOV(R10, RA); // - 4 + } + else + MOV(R10, 0); // - 4 + LoadToReg(RD, R10, 8, inst.SIMM_16); +#else + + if (inst.RA) + { + MOVI2R(rB, inst.SIMM_16); + ARMReg RA = gpr.R(inst.RA); + ADD(rB, rB, RA); + } + else + MOVI2R(rB, (u32)inst.SIMM_16); + + MOVI2R(rA, (u32)&Memory::Read_U8); + PUSH(4, R0, R1, R2, R3); + MOV(R0, rB); + BL(rA); + MOV(rA, R0); + POP(4, R0, R1, R2, R3); + MOV(RD, rA); + gpr.Unlock(rA, rB); +#endif + SetJumpTarget(DoNotLoad); +} + +void JitArm::lhz(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(LoadStore) + + ARMReg rA = gpr.GetReg(); + ARMReg rB = gpr.GetReg(); + ARMReg RD = gpr.R(inst.RD); + LDR(rA, R9, PPCSTATE_OFF(PowerPC::ppcState, Exceptions)); + CMP(rA, EXCEPTION_DSI); + FixupBranch DoNotLoad = B_CC(CC_EQ); +#if 0 // FASTMEM + // Backpatch route + // Gets loaded in to RD + // Address is in R10 + gpr.Unlock(rA, rB); + if (inst.RA) + { + ARMReg RA = gpr.R(inst.RA); + printf("lhz jump to here: 0x%08x\n", (u32)GetCodePtr()); + MOV(R10, RA); // - 4 + } + else + { + printf("lhz jump to here: 0x%08x\n", (u32)GetCodePtr()); + MOV(R10, 0); // - 4 + } + LoadToReg(RD, R10, 16, (u32)inst.SIMM_16); +#else + + if (inst.RA) + { + MOVI2R(rB, inst.SIMM_16); + ARMReg RA = gpr.R(inst.RA); + ADD(rB, rB, RA); + } + else + MOVI2R(rB, (u32)inst.SIMM_16); + + MOVI2R(rA, (u32)&Memory::Read_U16); + PUSH(4, R0, R1, R2, R3); + MOV(R0, rB); + BL(rA); + MOV(rA, R0); + POP(4, R0, R1, R2, R3); + MOV(RD, rA); + gpr.Unlock(rA, rB); +#endif + SetJumpTarget(DoNotLoad); +} +void JitArm::lwz(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(LoadStore) + + ARMReg rA = gpr.GetReg(); + ARMReg rB = gpr.GetReg(); + ARMReg RD = gpr.R(inst.RD); + LDR(rA, R9, PPCSTATE_OFF(PowerPC::ppcState, Exceptions)); + CMP(rA, EXCEPTION_DSI); + FixupBranch DoNotLoad = B_CC(CC_EQ); + +#if FASTMEM + // Backpatch route + // Gets loaded in to RD + // Address is in R10 + gpr.Unlock(rA, rB); + if (inst.RA) + { + ARMReg RA = gpr.R(inst.RA); + MOV(R10, RA); // - 4 + } + else + MOV(R10, 0); // - 4 + LoadToReg(RD, R10, 32, (u32)inst.SIMM_16); +#else + if (inst.RA) + { + MOVI2R(rB, inst.SIMM_16); + ARMReg RA = gpr.R(inst.RA); + ADD(rB, rB, RA); + } + else + MOVI2R(rB, (u32)inst.SIMM_16); + + MOVI2R(rA, (u32)&Memory::Read_U32); + PUSH(4, R0, R1, R2, R3); + MOV(R0, rB); + BL(rA); + MOV(rA, R0); + POP(4, R0, R1, R2, R3); + MOV(RD, rA); + gpr.Unlock(rA, rB); +#endif + SetJumpTarget(DoNotLoad); + if (SConfig::GetInstance().m_LocalCoreStartupParameter.bSkipIdle && + (inst.hex & 0xFFFF0000) == 0x800D0000 && + (Memory::ReadUnchecked_U32(js.compilerPC + 4) == 0x28000000 || + (SConfig::GetInstance().m_LocalCoreStartupParameter.bWii && Memory::ReadUnchecked_U32(js.compilerPC + 4) == 0x2C000000)) && + Memory::ReadUnchecked_U32(js.compilerPC + 8) == 0x4182fff8) + { + gpr.Flush(); + fpr.Flush(); + + // if it's still 0, we can wait until the next event + TST(RD, RD); + FixupBranch noIdle = B_CC(CC_NEQ); + rA = gpr.GetReg(); + + MOVI2R(rA, (u32)&PowerPC::OnIdle); + MOVI2R(R0, PowerPC::ppcState.gpr[inst.RA] + (s32)(s16)inst.SIMM_16); + BL(rA); + + gpr.Unlock(rA); + WriteExceptionExit(); + + SetJumpTarget(noIdle); + + //js.compilerPC += 8; + return; + } +} +void JitArm::lwzx(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(LoadStore) + + ARMReg rA = gpr.GetReg(); + ARMReg rB = gpr.GetReg(); + + ARMReg RB = gpr.R(inst.RB); + ARMReg RD = gpr.R(inst.RD); + LDR(rA, R9, PPCSTATE_OFF(PowerPC::ppcState, Exceptions)); + CMP(rA, EXCEPTION_DSI); + FixupBranch DoNotLoad = B_CC(CC_EQ); +#if FASTMEM + // Backpatch route + // Gets loaded in to RD + // Address is in R10 + gpr.Unlock(rA, rB); + if (inst.RA) + { + ARMReg RA = gpr.R(inst.RA); + ADD(R10, RA, RB); // - 4 + } + else + MOV(R10, RB); // -4 + LoadToReg(RD, R10, 32, 0); +#else + if (inst.RA) + { + ARMReg RA = gpr.R(inst.RA); + ADD(rB, RA, RB); + } + else + MOV(rB, RB); + + MOVI2R(rA, (u32)&Memory::Read_U32); + PUSH(4, R0, R1, R2, R3); + MOV(R0, rB); + BL(rA); + MOV(rA, R0); + POP(4, R0, R1, R2, R3); + MOV(RD, rA); + gpr.Unlock(rA, rB); +#endif + SetJumpTarget(DoNotLoad); + //// u32 temp = Memory::Read_U32(_inst.RA ? (m_GPR[_inst.RA] + m_GPR[_inst.RB]) : m_GPR[_inst.RB]); +} +void JitArm::icbi(UGeckoInstruction inst) +{ + Default(inst); + WriteExit(js.compilerPC + 4, 0); +} + diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_LoadStoreFloating.cpp b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_LoadStoreFloating.cpp new file mode 100644 index 0000000000..5134dd9e88 --- /dev/null +++ b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_LoadStoreFloating.cpp @@ -0,0 +1,72 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "Common.h" +#include "Thunk.h" + +#include "../../Core.h" +#include "../PowerPC.h" +#include "../../ConfigManager.h" +#include "../../CoreTiming.h" +#include "../PPCTables.h" +#include "ArmEmitter.h" +#include "../../HW/Memmap.h" + + +#include "Jit.h" +#include "JitRegCache.h" +#include "JitFPRCache.h" +#include "JitAsm.h" + +void JitArm::lfs(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(LoadStoreFloating) + Default(inst); return; + + ARMReg rA = gpr.GetReg(); + ARMReg rB = gpr.GetReg(); + LDR(rA, R9, PPCSTATE_OFF(PowerPC::ppcState, Exceptions)); + CMP(rA, EXCEPTION_DSI); + FixupBranch DoNotLoad = B_CC(CC_EQ); + + if (inst.RA) + { + MOVI2R(rB, inst.SIMM_16); + ARMReg RA = gpr.R(inst.RA); + ADD(rB, rB, RA); + } + else + MOVI2R(rB, (u32)inst.SIMM_16); + + MOVI2R(rA, (u32)&Memory::Read_U32); + PUSH(4, R0, R1, R2, R3); + MOV(R0, rB); + BL(rA); + MOV(rA, R0); + POP(4, R0, R1, R2, R3); + + ARMReg v0 = fpr.R0(inst.FD, false); + ARMReg v1 = fpr.R1(inst.FD, false); + + VMOV(v0, rA, false); + VMOV(v1, rA, false); + + gpr.Unlock(rA, rB); + SetJumpTarget(DoNotLoad); +} + diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_SystemRegisters.cpp b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_SystemRegisters.cpp new file mode 100644 index 0000000000..512240537a --- /dev/null +++ b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_SystemRegisters.cpp @@ -0,0 +1,104 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ +#include "Common.h" +#include "Thunk.h" + +#include "../../Core.h" +#include "../PowerPC.h" +#include "../../CoreTiming.h" +#include "../PPCTables.h" +#include "ArmEmitter.h" + +#include "Jit.h" +#include "JitRegCache.h" +#include "JitAsm.h" + +void JitArm::mtspr(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(SystemRegisters) + + u32 iIndex = (inst.SPRU << 5) | (inst.SPRL & 0x1F); + ARMReg RD = gpr.R(inst.RD); + + switch (iIndex) + { + case SPR_LR: + case SPR_CTR: + case SPR_XER: + // These are safe to do the easy way, see the bottom of this function. + break; + + case SPR_GQR0: + case SPR_GQR0 + 1: + case SPR_GQR0 + 2: + case SPR_GQR0 + 3: + case SPR_GQR0 + 4: + case SPR_GQR0 + 5: + case SPR_GQR0 + 6: + case SPR_GQR0 + 7: + // Prevent recompiler from compiling in old quantizer values. + // If the value changed, destroy all blocks using this quantizer + // This will create a little bit of block churn, but hopefully not too bad. + { + /* + MOV(32, R(EAX), M(&PowerPC::ppcState.spr[iIndex])); // Load old value + CMP(32, R(EAX), gpr.R(inst.RD)); + FixupBranch skip_destroy = J_CC(CC_E, false); + int gqr = iIndex - SPR_GQR0; + ABI_CallFunctionC(ProtectFunction(&Jit64::DestroyBlocksWithFlag, 1), (u32)BLOCK_USE_GQR0 << gqr); + SetJumpTarget(skip_destroy);*/ + } + // TODO - break block if quantizers are written to. + default: + Default(inst); + return; + } + + // OK, this is easy. + STR(R9, RD, PPCSTATE_OFF(PowerPC::ppcState, spr) + iIndex * 4); +} + +void JitArm::mfspr(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(SystemRegisters) + + u32 iIndex = (inst.SPRU << 5) | (inst.SPRL & 0x1F); + ARMReg RD = gpr.R(inst.RD); + switch (iIndex) + { + case SPR_WPAR: + case SPR_DEC: + case SPR_TL: + case SPR_TU: + Default(inst); + return; + default: + LDR(RD, R9, PPCSTATE_OFF(PowerPC::ppcState, spr) + iIndex * 4); + break; + } +} +void JitArm::mtmsr(UGeckoInstruction inst) +{ + INSTRUCTION_START + // Don't interpret this, if we do we get thrown out + //JITDISABLE(SystemRegisters) + + STR(R9, gpr.R(inst.RS), PPCSTATE_OFF(PowerPC::ppcState, msr)); + WriteExit(js.compilerPC + 4, 0); +} diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Tables.cpp b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Tables.cpp new file mode 100644 index 0000000000..1929705df2 --- /dev/null +++ b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Tables.cpp @@ -0,0 +1,502 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "Jit.h" +#include "../JitInterface.h" +#include "JitArm_Tables.h" + +// Should be moved in to the Jit class +typedef void (JitArm::*_Instruction) (UGeckoInstruction instCode); + +static _Instruction dynaOpTable[64]; +static _Instruction dynaOpTable4[1024]; +static _Instruction dynaOpTable19[1024]; +static _Instruction dynaOpTable31[1024]; +static _Instruction dynaOpTable59[32]; +static _Instruction dynaOpTable63[1024]; + +void JitArm::DynaRunTable4(UGeckoInstruction _inst) {(this->*dynaOpTable4 [_inst.SUBOP10])(_inst);} +void JitArm::DynaRunTable19(UGeckoInstruction _inst) {(this->*dynaOpTable19[_inst.SUBOP10])(_inst);} +void JitArm::DynaRunTable31(UGeckoInstruction _inst) {(this->*dynaOpTable31[_inst.SUBOP10])(_inst);} +void JitArm::DynaRunTable59(UGeckoInstruction _inst) {(this->*dynaOpTable59[_inst.SUBOP5 ])(_inst);} +void JitArm::DynaRunTable63(UGeckoInstruction _inst) {(this->*dynaOpTable63[_inst.SUBOP10])(_inst);} + +struct GekkoOPTemplate +{ + int opcode; + _Instruction Inst; + //GekkoOPInfo opinfo; // Doesn't need opinfo, Interpreter fills it out +}; + +static GekkoOPTemplate primarytable[] = +{ + {4, &JitArm::DynaRunTable4}, //"RunTable4", OPTYPE_SUBTABLE | (4<<24), 0}}, + {19, &JitArm::DynaRunTable19}, //"RunTable19", OPTYPE_SUBTABLE | (19<<24), 0}}, + {31, &JitArm::DynaRunTable31}, //"RunTable31", OPTYPE_SUBTABLE | (31<<24), 0}}, + {59, &JitArm::DynaRunTable59}, //"RunTable59", OPTYPE_SUBTABLE | (59<<24), 0}}, + {63, &JitArm::DynaRunTable63}, //"RunTable63", OPTYPE_SUBTABLE | (63<<24), 0}}, + + {16, &JitArm::bcx}, //"bcx", OPTYPE_SYSTEM, FL_ENDBLOCK}}, + {18, &JitArm::bx}, //"bx", OPTYPE_SYSTEM, FL_ENDBLOCK}}, + + {1, &JitArm::HLEFunction}, //"HLEFunction", OPTYPE_SYSTEM, FL_ENDBLOCK}}, + {2, &JitArm::Default}, //"DynaBlock", OPTYPE_SYSTEM, 0}}, + {3, &JitArm::Break}, //"twi", OPTYPE_SYSTEM, FL_ENDBLOCK}}, + {17, &JitArm::sc}, //"sc", OPTYPE_SYSTEM, FL_ENDBLOCK, 1}}, + + {7, &JitArm::mulli}, //"mulli", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A | FL_RC_BIT, 2}}, + {8, &JitArm::Default}, //"subfic", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A | FL_SET_CA}}, + {10, &JitArm::cmpli}, //"cmpli", OPTYPE_INTEGER, FL_IN_A | FL_SET_CRn}}, + {11, &JitArm::cmpi}, //"cmpi", OPTYPE_INTEGER, FL_IN_A | FL_SET_CRn}}, + {12, &JitArm::Default}, //"addic", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A | FL_SET_CA}}, + {13, &JitArm::Default}, //"addic_rc", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A | FL_SET_CR0}}, + {14, &JitArm::addi}, //"addi", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A0}}, + {15, &JitArm::addis}, //"addis", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A0}}, + + {20, &JitArm::rlwimix}, //"rlwimix", OPTYPE_INTEGER, FL_OUT_A | FL_IN_A | FL_IN_S | FL_RC_BIT}}, + {21, &JitArm::rlwinmx}, //"rlwinmx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_RC_BIT}}, + {23, &JitArm::Default}, //"rlwnmx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_IN_B | FL_RC_BIT}}, + + {24, &JitArm::ori}, //"ori", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S}}, + {25, &JitArm::oris}, //"oris", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S}}, + {26, &JitArm::Default}, //"xori", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S}}, + {27, &JitArm::Default}, //"xoris", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S}}, + {28, &JitArm::Default}, //"andi_rc", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_SET_CR0}}, + {29, &JitArm::Default}, //"andis_rc", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_SET_CR0}}, + + {32, &JitArm::lwz}, //"lwz", OPTYPE_LOAD, FL_OUT_D | FL_IN_A}}, + {33, &JitArm::Default}, //"lwzu", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A}}, + {34, &JitArm::lbz}, //"lbz", OPTYPE_LOAD, FL_OUT_D | FL_IN_A}}, + {35, &JitArm::Default}, //"lbzu", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A}}, + {40, &JitArm::lhz}, //"lhz", OPTYPE_LOAD, FL_OUT_D | FL_IN_A}}, + {41, &JitArm::Default}, //"lhzu", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A}}, + {42, &JitArm::Default}, //"lha", OPTYPE_LOAD, FL_OUT_D | FL_IN_A}}, + {43, &JitArm::Default}, //"lhau", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A}}, + + {44, &JitArm::Default}, //"sth", OPTYPE_STORE, FL_IN_A | FL_IN_S}}, + {45, &JitArm::Default}, //"sthu", OPTYPE_STORE, FL_OUT_A | FL_IN_A | FL_IN_S}}, + {36, &JitArm::stw}, //"stw", OPTYPE_STORE, FL_IN_A | FL_IN_S}}, + {37, &JitArm::stwu}, //"stwu", OPTYPE_STORE, FL_OUT_A | FL_IN_A | FL_IN_S}}, + {38, &JitArm::Default}, //"stb", OPTYPE_STORE, FL_IN_A | FL_IN_S}}, + {39, &JitArm::Default}, //"stbu", OPTYPE_STORE, FL_OUT_A | FL_IN_A | FL_IN_S}}, + + {46, &JitArm::Default}, //"lmw", OPTYPE_SYSTEM, FL_EVIL, 10}}, + {47, &JitArm::Default}, //"stmw", OPTYPE_SYSTEM, FL_EVIL, 10}}, + + {48, &JitArm::lfs}, //"lfs", OPTYPE_LOADFP, FL_IN_A}}, + {49, &JitArm::Default}, //"lfsu", OPTYPE_LOADFP, FL_OUT_A | FL_IN_A}}, + {50, &JitArm::Default}, //"lfd", OPTYPE_LOADFP, FL_IN_A}}, + {51, &JitArm::Default}, //"lfdu", OPTYPE_LOADFP, FL_OUT_A | FL_IN_A}}, + + {52, &JitArm::Default}, //"stfs", OPTYPE_STOREFP, FL_IN_A}}, + {53, &JitArm::Default}, //"stfsu", OPTYPE_STOREFP, FL_OUT_A | FL_IN_A}}, + {54, &JitArm::Default}, //"stfd", OPTYPE_STOREFP, FL_IN_A}}, + {55, &JitArm::Default}, //"stfdu", OPTYPE_STOREFP, FL_OUT_A | FL_IN_A}}, + + {56, &JitArm::Default}, //"psq_l", OPTYPE_PS, FL_IN_A}}, + {57, &JitArm::Default}, //"psq_lu", OPTYPE_PS, FL_OUT_A | FL_IN_A}}, + {60, &JitArm::Default}, //"psq_st", OPTYPE_PS, FL_IN_A}}, + {61, &JitArm::Default}, //"psq_stu", OPTYPE_PS, FL_OUT_A | FL_IN_A}}, + + //missing: 0, 5, 6, 9, 22, 30, 62, 58 + {0, &JitArm::Default}, //"unknown_instruction", OPTYPE_UNKNOWN, 0}}, + {5, &JitArm::Default}, //"unknown_instruction", OPTYPE_UNKNOWN, 0}}, + {6, &JitArm::Default}, //"unknown_instruction", OPTYPE_UNKNOWN, 0}}, + {9, &JitArm::Default}, //"unknown_instruction", OPTYPE_UNKNOWN, 0}}, + {22, &JitArm::Default}, //"unknown_instruction", OPTYPE_UNKNOWN, 0}}, + {30, &JitArm::Default}, //"unknown_instruction", OPTYPE_UNKNOWN, 0}}, + {62, &JitArm::Default}, //"unknown_instruction", OPTYPE_UNKNOWN, 0}}, + {58, &JitArm::Default}, //"unknown_instruction", OPTYPE_UNKNOWN, 0}}, +}; + +static GekkoOPTemplate table4[] = +{ //SUBOP10 + {0, &JitArm::Default}, //"ps_cmpu0", OPTYPE_PS, FL_SET_CRn}}, + {32, &JitArm::Default}, //"ps_cmpo0", OPTYPE_PS, FL_SET_CRn}}, + {40, &JitArm::Default}, //"ps_neg", OPTYPE_PS, FL_RC_BIT}}, + {136, &JitArm::Default}, //"ps_nabs", OPTYPE_PS, FL_RC_BIT}}, + {264, &JitArm::Default}, //"ps_abs", OPTYPE_PS, FL_RC_BIT}}, + {64, &JitArm::Default}, //"ps_cmpu1", OPTYPE_PS, FL_RC_BIT}}, + {72, &JitArm::Default}, //"ps_mr", OPTYPE_PS, FL_RC_BIT}}, + {96, &JitArm::Default}, //"ps_cmpo1", OPTYPE_PS, FL_RC_BIT}}, + {528, &JitArm::Default}, //"ps_merge00", OPTYPE_PS, FL_RC_BIT}}, + {560, &JitArm::Default}, //"ps_merge01", OPTYPE_PS, FL_RC_BIT}}, + {592, &JitArm::Default}, //"ps_merge10", OPTYPE_PS, FL_RC_BIT}}, + {624, &JitArm::Default}, //"ps_merge11", OPTYPE_PS, FL_RC_BIT}}, + + {1014, &JitArm::Default}, //"dcbz_l", OPTYPE_SYSTEM, 0}}, +}; + +static GekkoOPTemplate table4_2[] = +{ + {10, &JitArm::Default}, //"ps_sum0", OPTYPE_PS, 0}}, + {11, &JitArm::Default}, //"ps_sum1", OPTYPE_PS, 0}}, + {12, &JitArm::Default}, //"ps_muls0", OPTYPE_PS, 0}}, + {13, &JitArm::Default}, //"ps_muls1", OPTYPE_PS, 0}}, + {14, &JitArm::Default}, //"ps_madds0", OPTYPE_PS, 0}}, + {15, &JitArm::Default}, //"ps_madds1", OPTYPE_PS, 0}}, + {18, &JitArm::Default}, //"ps_div", OPTYPE_PS, 0, 16}}, + {20, &JitArm::Default}, //"ps_sub", OPTYPE_PS, 0}}, + {21, &JitArm::Default}, //"ps_add", OPTYPE_PS, 0}}, + {23, &JitArm::Default}, //"ps_sel", OPTYPE_PS, 0}}, + {24, &JitArm::Default}, //"ps_res", OPTYPE_PS, 0}}, + {25, &JitArm::Default}, //"ps_mul", OPTYPE_PS, 0}}, + {26, &JitArm::Default}, //"ps_rsqrte", OPTYPE_PS, 0, 1}}, + {28, &JitArm::Default}, //"ps_msub", OPTYPE_PS, 0}}, + {29, &JitArm::Default}, //"ps_madd", OPTYPE_PS, 0}}, + {30, &JitArm::Default}, //"ps_nmsub", OPTYPE_PS, 0}}, + {31, &JitArm::Default}, //"ps_nmadd", OPTYPE_PS, 0}}, +}; + + +static GekkoOPTemplate table4_3[] = +{ + {6, &JitArm::Default}, //"psq_lx", OPTYPE_PS, 0}}, + {7, &JitArm::Default}, //"psq_stx", OPTYPE_PS, 0}}, + {38, &JitArm::Default}, //"psq_lux", OPTYPE_PS, 0}}, + {39, &JitArm::Default}, //"psq_stux", OPTYPE_PS, 0}}, +}; + +static GekkoOPTemplate table19[] = +{ + {528, &JitArm::bcctrx}, //"bcctrx", OPTYPE_BRANCH, FL_ENDBLOCK}}, + {16, &JitArm::bclrx}, //"bclrx", OPTYPE_BRANCH, FL_ENDBLOCK}}, + {257, &JitArm::Default}, //"crand", OPTYPE_CR, FL_EVIL}}, + {129, &JitArm::Default}, //"crandc", OPTYPE_CR, FL_EVIL}}, + {289, &JitArm::Default}, //"creqv", OPTYPE_CR, FL_EVIL}}, + {225, &JitArm::Default}, //"crnand", OPTYPE_CR, FL_EVIL}}, + {33, &JitArm::Default}, //"crnor", OPTYPE_CR, FL_EVIL}}, + {449, &JitArm::Default}, //"cror", OPTYPE_CR, FL_EVIL}}, + {417, &JitArm::Default}, //"crorc", OPTYPE_CR, FL_EVIL}}, + {193, &JitArm::Default}, //"crxor", OPTYPE_CR, FL_EVIL}}, + + {150, &JitArm::DoNothing}, //"isync", OPTYPE_ICACHE, FL_EVIL}}, + {0, &JitArm::Default}, //"mcrf", OPTYPE_SYSTEM, FL_EVIL}}, + + {50, &JitArm::rfi}, //"rfi", OPTYPE_SYSTEM, FL_ENDBLOCK | FL_CHECKEXCEPTIONS, 1}}, + {18, &JitArm::Break}, //"rfid", OPTYPE_SYSTEM, FL_ENDBLOCK | FL_CHECKEXCEPTIONS}} +}; + + +static GekkoOPTemplate table31[] = +{ + {28, &JitArm::Default}, //"andx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}}, + {60, &JitArm::Default}, //"andcx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}}, + {444, &JitArm::orx}, //"orx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}}, + {124, &JitArm::Default}, //"norx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}}, + {316, &JitArm::Default}, //"xorx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}}, + {412, &JitArm::Default}, //"orcx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}}, + {476, &JitArm::Default}, //"nandx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}}, + {284, &JitArm::Default}, //"eqvx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}}, + {0, &JitArm::cmp}, //"cmp", OPTYPE_INTEGER, FL_IN_AB | FL_SET_CRn}}, + {32, &JitArm::Default}, //"cmpl", OPTYPE_INTEGER, FL_IN_AB | FL_SET_CRn}}, + {26, &JitArm::Default}, //"cntlzwx",OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_RC_BIT}}, + {922, &JitArm::extshx}, //"extshx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_RC_BIT}}, + {954, &JitArm::extsbx}, //"extsbx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_RC_BIT}}, + {536, &JitArm::Default}, //"srwx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_B | FL_IN_S | FL_RC_BIT}}, + {792, &JitArm::Default}, //"srawx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_B | FL_IN_S | FL_RC_BIT}}, + {824, &JitArm::Default}, //"srawix", OPTYPE_INTEGER, FL_OUT_A | FL_IN_B | FL_IN_S | FL_RC_BIT}}, + {24, &JitArm::Default}, //"slwx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_B | FL_IN_S | FL_RC_BIT}}, + + {54, &JitArm::Default}, //"dcbst", OPTYPE_DCACHE, 0, 4}}, + {86, &JitArm::Default}, //"dcbf", OPTYPE_DCACHE, 0, 4}}, + {246, &JitArm::Default}, //"dcbtst", OPTYPE_DCACHE, 0, 1}}, + {278, &JitArm::Default}, //"dcbt", OPTYPE_DCACHE, 0, 1}}, + {470, &JitArm::Default}, //"dcbi", OPTYPE_DCACHE, 0, 4}}, + {758, &JitArm::Default}, //"dcba", OPTYPE_DCACHE, 0, 4}}, + {1014, &JitArm::Default}, //"dcbz", OPTYPE_DCACHE, 0, 4}}, + + //load word + {23, &JitArm::lwzx}, //"lwzx", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B}}, + {55, &JitArm::Default}, //"lwzux", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A | FL_IN_B}}, + + //load halfword + {279, &JitArm::Default}, //"lhzx", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B}}, + {311, &JitArm::Default}, //"lhzux", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A | FL_IN_B}}, + + //load halfword signextend + {343, &JitArm::Default}, //"lhax", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B}}, + {375, &JitArm::Default}, //"lhaux", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A | FL_IN_B}}, + + //load byte + {87, &JitArm::Default}, //"lbzx", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B}}, + {119, &JitArm::Default}, //"lbzux", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A | FL_IN_B}}, + + //load byte reverse + {534, &JitArm::Default}, //"lwbrx", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B}}, + {790, &JitArm::Default}, //"lhbrx", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B}}, + + // Conditional load/store (Wii SMP) + {150, &JitArm::Default}, //"stwcxd", OPTYPE_STORE, FL_EVIL | FL_SET_CR0}}, + {20, &JitArm::Default}, //"lwarx", OPTYPE_LOAD, FL_EVIL | FL_OUT_D | FL_IN_A0B | FL_SET_CR0}}, + + //load string (interpret these) + {533, &JitArm::Default}, //"lswx", OPTYPE_LOAD, FL_EVIL | FL_IN_A | FL_OUT_D}}, + {597, &JitArm::Default}, //"lswi", OPTYPE_LOAD, FL_EVIL | FL_IN_AB | FL_OUT_D}}, + + //store word + {151, &JitArm::Default}, //"stwx", OPTYPE_STORE, FL_IN_A0 | FL_IN_B}}, + {183, &JitArm::Default}, //"stwux", OPTYPE_STORE, FL_OUT_A | FL_IN_A | FL_IN_B}}, + + //store halfword + {407, &JitArm::Default}, //"sthx", OPTYPE_STORE, FL_IN_A0 | FL_IN_B}}, + {439, &JitArm::Default}, //"sthux", OPTYPE_STORE, FL_OUT_A | FL_IN_A | FL_IN_B}}, + + //store byte + {215, &JitArm::Default}, //"stbx", OPTYPE_STORE, FL_IN_A0 | FL_IN_B}}, + {247, &JitArm::Default}, //"stbux", OPTYPE_STORE, FL_OUT_A | FL_IN_A | FL_IN_B}}, + + //store bytereverse + {662, &JitArm::Default}, //"stwbrx", OPTYPE_STORE, FL_IN_A0 | FL_IN_B}}, + {918, &JitArm::Default}, //"sthbrx", OPTYPE_STORE, FL_IN_A | FL_IN_B}}, + + {661, &JitArm::Default}, //"stswx", OPTYPE_STORE, FL_EVIL}}, + {725, &JitArm::Default}, //"stswi", OPTYPE_STORE, FL_EVIL}}, + + // fp load/store + {535, &JitArm::Default}, //"lfsx", OPTYPE_LOADFP, FL_IN_A0 | FL_IN_B}}, + {567, &JitArm::Default}, //"lfsux", OPTYPE_LOADFP, FL_IN_A | FL_IN_B}}, + {599, &JitArm::Default}, //"lfdx", OPTYPE_LOADFP, FL_IN_A0 | FL_IN_B}}, + {631, &JitArm::Default}, //"lfdux", OPTYPE_LOADFP, FL_IN_A | FL_IN_B}}, + + {663, &JitArm::Default}, //"stfsx", OPTYPE_STOREFP, FL_IN_A0 | FL_IN_B}}, + {695, &JitArm::Default}, //"stfsux", OPTYPE_STOREFP, FL_IN_A | FL_IN_B}}, + {727, &JitArm::Default}, //"stfdx", OPTYPE_STOREFP, FL_IN_A0 | FL_IN_B}}, + {759, &JitArm::Default}, //"stfdux", OPTYPE_STOREFP, FL_IN_A | FL_IN_B}}, + {983, &JitArm::Default}, //"stfiwx", OPTYPE_STOREFP, FL_IN_A0 | FL_IN_B}}, + + {19, &JitArm::Default}, //"mfcr", OPTYPE_SYSTEM, FL_OUT_D}}, + {83, &JitArm::Default}, //"mfmsr", OPTYPE_SYSTEM, FL_OUT_D}}, + {144, &JitArm::Default}, //"mtcrf", OPTYPE_SYSTEM, 0}}, + {146, &JitArm::mtmsr}, //"mtmsr", OPTYPE_SYSTEM, FL_ENDBLOCK}}, + {210, &JitArm::Default}, //"mtsr", OPTYPE_SYSTEM, 0}}, + {242, &JitArm::Default}, //"mtsrin", OPTYPE_SYSTEM, 0}}, + {339, &JitArm::mfspr}, //"mfspr", OPTYPE_SPR, FL_OUT_D}}, + {467, &JitArm::mtspr}, //"mtspr", OPTYPE_SPR, 0, 2}}, + {371, &JitArm::Default}, //"mftb", OPTYPE_SYSTEM, FL_OUT_D | FL_TIMER}}, + {512, &JitArm::Default}, //"mcrxr", OPTYPE_SYSTEM, 0}}, + {595, &JitArm::Default}, //"mfsr", OPTYPE_SYSTEM, FL_OUT_D, 2}}, + {659, &JitArm::Default}, //"mfsrin", OPTYPE_SYSTEM, FL_OUT_D, 2}}, + + {4, &JitArm::Break}, //"tw", OPTYPE_SYSTEM, FL_ENDBLOCK, 1}}, + {598, &JitArm::Default}, //"sync", OPTYPE_SYSTEM, 0, 2}}, + {982, &JitArm::icbi}, //"icbi", OPTYPE_SYSTEM, FL_ENDBLOCK, 3}}, + + // Unused instructions on GC + {310, &JitArm::Default}, //"eciwx", OPTYPE_INTEGER, FL_RC_BIT}}, + {438, &JitArm::Default}, //"ecowx", OPTYPE_INTEGER, FL_RC_BIT}}, + {854, &JitArm::Default}, //"eieio", OPTYPE_INTEGER, FL_RC_BIT}}, + {306, &JitArm::Default}, //"tlbie", OPTYPE_SYSTEM, 0}}, + {370, &JitArm::Default}, //"tlbia", OPTYPE_SYSTEM, 0}}, + {566, &JitArm::Default}, //"tlbsync", OPTYPE_SYSTEM, 0}}, +}; + +static GekkoOPTemplate table31_2[] = +{ + {266, &JitArm::addx}, //"addx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT}}, + {778, &JitArm::addx}, //"addx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT}}, + {10, &JitArm::Default}, //"addcx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_SET_CA | FL_RC_BIT}}, + {138, &JitArm::Default}, //"addex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}}, + {234, &JitArm::Default}, //"addmex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}}, + {202, &JitArm::Default}, //"addzex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}}, + {491, &JitArm::Default}, //"divwx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 39}}, + {1003, &JitArm::Default}, //"divwox", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 39}}, + {459, &JitArm::Default}, //"divwux", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 39}}, + {971, &JitArm::Default}, //"divwuox", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 39}}, + {75, &JitArm::Default}, //"mulhwx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 4}}, + {11, &JitArm::Default}, //"mulhwux", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 4}}, + {235, &JitArm::Default}, //"mullwx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 4}}, + {747, &JitArm::Default}, //"mullwox", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 4}}, + {104, &JitArm::negx}, //"negx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT}}, + {40, &JitArm::Default}, //"subfx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT}}, + {552, &JitArm::Default}, //"subox", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT}}, + {8, &JitArm::Default}, //"subfcx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_SET_CA | FL_RC_BIT}}, + {136, &JitArm::Default}, //"subfex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}}, + {232, &JitArm::Default}, //"subfmex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}}, + {200, &JitArm::Default}, //"subfzex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}}, +}; + +static GekkoOPTemplate table59[] = +{ + {18, &JitArm::Default}, //{"fdivsx", OPTYPE_FPU, FL_RC_BIT_F, 16}}, + {20, &JitArm::Default}, //"fsubsx", OPTYPE_FPU, FL_RC_BIT_F}}, + {21, &JitArm::Default}, //"faddsx", OPTYPE_FPU, FL_RC_BIT_F}}, +// {22, &JitArm::Default}, //"fsqrtsx", OPTYPE_FPU, FL_RC_BIT_F}}, // Not implemented on gekko + {24, &JitArm::Default}, //"fresx", OPTYPE_FPU, FL_RC_BIT_F}}, + {25, &JitArm::Default}, //"fmulsx", OPTYPE_FPU, FL_RC_BIT_F}}, + {28, &JitArm::Default}, //"fmsubsx", OPTYPE_FPU, FL_RC_BIT_F}}, + {29, &JitArm::Default}, //"fmaddsx", OPTYPE_FPU, FL_RC_BIT_F}}, + {30, &JitArm::Default}, //"fnmsubsx", OPTYPE_FPU, FL_RC_BIT_F}}, + {31, &JitArm::Default}, //"fnmaddsx", OPTYPE_FPU, FL_RC_BIT_F}}, +}; + +static GekkoOPTemplate table63[] = +{ + {264, &JitArm::fabsx}, //"fabsx", OPTYPE_FPU, FL_RC_BIT_F}}, + {32, &JitArm::Default}, //"fcmpo", OPTYPE_FPU, FL_RC_BIT_F}}, + {0, &JitArm::Default}, //"fcmpu", OPTYPE_FPU, FL_RC_BIT_F}}, + {14, &JitArm::Default}, //"fctiwx", OPTYPE_FPU, FL_RC_BIT_F}}, + {15, &JitArm::Default}, //"fctiwzx", OPTYPE_FPU, FL_RC_BIT_F}}, + {72, &JitArm::fmrx}, //"fmrx", OPTYPE_FPU, FL_RC_BIT_F}}, + {136, &JitArm::Default}, //"fnabsx", OPTYPE_FPU, FL_RC_BIT_F}}, + {40, &JitArm::Default}, //"fnegx", OPTYPE_FPU, FL_RC_BIT_F}}, + {12, &JitArm::Default}, //"frspx", OPTYPE_FPU, FL_RC_BIT_F}}, + + {64, &JitArm::Default}, //"mcrfs", OPTYPE_SYSTEMFP, 0}}, + {583, &JitArm::Default}, //"mffsx", OPTYPE_SYSTEMFP, 0}}, + {70, &JitArm::Default}, //"mtfsb0x", OPTYPE_SYSTEMFP, 0, 2}}, + {38, &JitArm::Default}, //"mtfsb1x", OPTYPE_SYSTEMFP, 0, 2}}, + {134, &JitArm::Default}, //"mtfsfix", OPTYPE_SYSTEMFP, 0, 2}}, + {711, &JitArm::Default}, //"mtfsfx", OPTYPE_SYSTEMFP, 0, 2}}, +}; + +static GekkoOPTemplate table63_2[] = +{ + {18, &JitArm::Default}, //"fdivx", OPTYPE_FPU, FL_RC_BIT_F, 30}}, + {20, &JitArm::Default}, //"fsubx", OPTYPE_FPU, FL_RC_BIT_F}}, + {21, &JitArm::faddx}, //"faddx", OPTYPE_FPU, FL_RC_BIT_F}}, + {22, &JitArm::Default}, //"fsqrtx", OPTYPE_FPU, FL_RC_BIT_F}}, + {23, &JitArm::Default}, //"fselx", OPTYPE_FPU, FL_RC_BIT_F}}, + {25, &JitArm::Default}, //"fmulx", OPTYPE_FPU, FL_RC_BIT_F}}, + {26, &JitArm::Default}, //"frsqrtex", OPTYPE_FPU, FL_RC_BIT_F}}, + {28, &JitArm::Default}, //"fmsubx", OPTYPE_FPU, FL_RC_BIT_F}}, + {29, &JitArm::Default}, //"fmaddx", OPTYPE_FPU, FL_RC_BIT_F}}, + {30, &JitArm::Default}, //"fnmsubx", OPTYPE_FPU, FL_RC_BIT_F}}, + {31, &JitArm::Default}, //"fnmaddx", OPTYPE_FPU, FL_RC_BIT_F}}, +}; + + +namespace JitArmTables +{ + +void CompileInstruction(PPCAnalyst::CodeOp & op) +{ + JitArm *jitarm = (JitArm *)jit; + (jitarm->*dynaOpTable[op.inst.OPCD])(op.inst); + GekkoOPInfo *info = op.opinfo; + if (info) { +#ifdef OPLOG + if (!strcmp(info->opname, OP_TO_LOG)){ ///"mcrfs" + rsplocations.push_back(jit.js.compilerPC); + } +#endif + info->compileCount++; + info->lastUse = jit->js.compilerPC; + } +} + +void InitTables() +{ + // once initialized, tables are read-only + static bool initialized = false; + if (initialized) + return; + + //clear + for (int i = 0; i < 32; i++) + { + dynaOpTable59[i] = &JitArm::unknown_instruction; + } + + for (int i = 0; i < 1024; i++) + { + dynaOpTable4 [i] = &JitArm::unknown_instruction; + dynaOpTable19[i] = &JitArm::unknown_instruction; + dynaOpTable31[i] = &JitArm::unknown_instruction; + dynaOpTable63[i] = &JitArm::unknown_instruction; + } + + for (int i = 0; i < (int)(sizeof(primarytable) / sizeof(GekkoOPTemplate)); i++) + { + dynaOpTable[primarytable[i].opcode] = primarytable[i].Inst; + } + + for (int i = 0; i < 32; i++) + { + int fill = i << 5; + for (int j = 0; j < (int)(sizeof(table4_2) / sizeof(GekkoOPTemplate)); j++) + { + int op = fill+table4_2[j].opcode; + dynaOpTable4[op] = table4_2[j].Inst; + } + } + + for (int i = 0; i < 16; i++) + { + int fill = i << 6; + for (int j = 0; j < (int)(sizeof(table4_3) / sizeof(GekkoOPTemplate)); j++) + { + int op = fill+table4_3[j].opcode; + dynaOpTable4[op] = table4_3[j].Inst; + } + } + + for (int i = 0; i < (int)(sizeof(table4) / sizeof(GekkoOPTemplate)); i++) + { + int op = table4[i].opcode; + dynaOpTable4[op] = table4[i].Inst; + } + + for (int i = 0; i < (int)(sizeof(table31) / sizeof(GekkoOPTemplate)); i++) + { + int op = table31[i].opcode; + dynaOpTable31[op] = table31[i].Inst; + } + + for (int i = 0; i < 1; i++) + { + int fill = i << 9; + for (int j = 0; j < (int)(sizeof(table31_2) / sizeof(GekkoOPTemplate)); j++) + { + int op = fill + table31_2[j].opcode; + dynaOpTable31[op] = table31_2[j].Inst; + } + } + + for (int i = 0; i < (int)(sizeof(table19) / sizeof(GekkoOPTemplate)); i++) + { + int op = table19[i].opcode; + dynaOpTable19[op] = table19[i].Inst; + } + + for (int i = 0; i < (int)(sizeof(table59) / sizeof(GekkoOPTemplate)); i++) + { + int op = table59[i].opcode; + dynaOpTable59[op] = table59[i].Inst; + } + + for (int i = 0; i < (int)(sizeof(table63) / sizeof(GekkoOPTemplate)); i++) + { + int op = table63[i].opcode; + dynaOpTable63[op] = table63[i].Inst; + } + + for (int i = 0; i < 32; i++) + { + int fill = i << 5; + for (int j = 0; j < (int)(sizeof(table63_2) / sizeof(GekkoOPTemplate)); j++) + { + int op = fill + table63_2[j].opcode; + dynaOpTable63[op] = table63_2[j].Inst; + } + } + + initialized = true; + +} + +} // namespace diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Tables.h b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Tables.h new file mode 100644 index 0000000000..4904ce3984 --- /dev/null +++ b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Tables.h @@ -0,0 +1,29 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#ifndef JITARM_TABLES_H +#define JITARM_TABLES_H + +#include "../Gekko.h" +#include "../PPCTables.h" + +namespace JitArmTables +{ + void CompileInstruction(PPCAnalyst::CodeOp & op); + void InitTables(); +} +#endif diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/JitAsm.cpp b/Source/Core/Core/Src/PowerPC/JitArm32/JitAsm.cpp new file mode 100644 index 0000000000..5084ab44d6 --- /dev/null +++ b/Source/Core/Core/Src/PowerPC/JitArm32/JitAsm.cpp @@ -0,0 +1,174 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + + +#include "../../HW/Memmap.h" + +#include "../PowerPC.h" +#include "../../CoreTiming.h" +#include "MemoryUtil.h" + +#include "Jit.h" +#include "../JitCommon/JitCache.h" + +#include "../../HW/GPFifo.h" +#include "../../Core.h" +#include "JitAsm.h" +#include "ArmEmitter.h" + +using namespace ArmGen; + +//TODO - make an option +//#if _DEBUG +// bool enableDebug = false; +//#else +// bool enableDebug = false; +//#endif + +JitArmAsmRoutineManager asm_routines; + +void JitArmAsmRoutineManager::Generate() +{ + enterCode = GetCodePtr(); + PUSH(2, R11, _LR); // R11 is frame pointer in Debug. + + MOVI2R(R0, (u32)&CoreTiming::downcount); + MOVI2R(R9, (u32)&PowerPC::ppcState.spr[0]); + + FixupBranch skipToRealDispatcher = B(); + dispatcher = GetCodePtr(); + printf("Dispatcher is %p\n", dispatcher); + + // Downcount Check + // The result of slice decrementation should be in flags if somebody jumped here + // IMPORTANT - We jump on negative, not carry!!! + FixupBranch bail = B_CC(CC_MI); + + SetJumpTarget(skipToRealDispatcher); + dispatcherNoCheck = GetCodePtr(); + + // This block of code gets the address of the compiled block of code + // It runs though to the compiling portion if it isn't found + LDR(R12, R9, PPCSTATE_OFF(PowerPC::ppcState, pc));// Load the current PC into R12 + + MOVI2R(R14, JIT_ICACHE_MASK); // Potential for optimization + AND(R12, R12, R14); // R12 contains PC & JIT_ICACHE_MASK here. + // Confirmed good to this point 08-03-12 + + MOVI2R(R14, (u32)jit->GetBlockCache()->GetICache()); + // Confirmed That this loads the base iCache Location correctly 08-04-12 + + LDR(R12, R14, R12, true, true); // R12 contains iCache[PC & JIT_ICACHE_MASK] here + // R12 Confirmed this is the correct iCache Location loaded. + TST(R12, 0xFC); // Test to see if it is a JIT block. + + SetCC(CC_EQ); // Only run next part if R12 is zero + // Success, it is our Jitblock. + MOVI2R(R14, (u32)jit->GetBlockCache()->GetCodePointers()); + // LDR R14 right here to get CodePointers()[0] pointer. + REV(R12, R12); // Reversing this gives us our JITblock. + LSL(R12, R12, 2); // Multiply by four because address locations are u32 in size + LDR(R14, R14, R12, true, true); // Load the block address in to R14 + + B(R14); + + FixupBranch NextBlock = B(); // Jump to end so we can start a new block + SetCC(); // Return to always executing codes + + // If we get to this point, that means that we don't have the block cached to execute + // So call ArmJit to compile the block and then execute it. + MOVI2R(R14, (u32)&Jit); + LDR(R0, R9, PPCSTATE_OFF(PowerPC::ppcState, pc)); + BL(R14); + + B(dispatcherNoCheck); + + // fpException() + // Floating Point Exception Check, Jumped to if false + fpException = GetCodePtr(); + LDR(R0, R9, PPCSTATE_OFF(PowerPC::ppcState, Exceptions)); + ORR(R0, R0, EXCEPTION_FPU_UNAVAILABLE); + STR(R9, R0, PPCSTATE_OFF(PowerPC::ppcState, Exceptions)); + QuickCallFunction(R14, (void*)&PowerPC::CheckExceptions); + LDR(R0, R9, PPCSTATE_OFF(PowerPC::ppcState, npc)); + STR(R9, R0, PPCSTATE_OFF(PowerPC::ppcState, pc)); + B(dispatcher); + + SetJumpTarget(bail); + doTiming = GetCodePtr(); + // XXX: In JIT64, Advance() gets called /after/ the exception checking + // once it jumps back to the start of outerLoop + QuickCallFunction(R14, (void*)&CoreTiming::Advance); + + // Does exception checking + testExceptions = GetCodePtr(); + LDR(R0, R9, PPCSTATE_OFF(PowerPC::ppcState, pc)); + STR(R9, R0, PPCSTATE_OFF(PowerPC::ppcState, npc)); + QuickCallFunction(R14, (void*)&PowerPC::CheckExceptions); + LDR(R0, R9, PPCSTATE_OFF(PowerPC::ppcState, npc)); + STR(R9, R0, PPCSTATE_OFF(PowerPC::ppcState, pc)); + // Check the state pointer to see if we are exiting + // Gets checked on every exception check + MOVI2R(R0, (u32)PowerPC::GetStatePtr()); + MVN(R1, 0); + LDR(R0, R0); + TST(R0, R1); + FixupBranch Exit = B_CC(CC_NEQ); + + SetJumpTarget(NextBlock); + B(dispatcher); + + SetJumpTarget(Exit); + + POP(2, R11, _PC); + FlushIcache(); +} + +void JitArmAsmRoutineManager::GenerateCommon() +{ +/* fifoDirectWrite8 = AlignCode4(); + GenFifoWrite(8); + fifoDirectWrite16 = AlignCode4(); + GenFifoWrite(16); + fifoDirectWrite32 = AlignCode4(); + GenFifoWrite(32); + fifoDirectWriteFloat = AlignCode4(); + GenFifoFloatWrite(); + fifoDirectWriteXmm64 = AlignCode4(); + GenFifoXmm64Write(); + + GenQuantizedLoads(); + GenQuantizedStores(); + GenQuantizedSingleStores(); +*/ + //CMPSD(R(XMM0), M(&zero), + // TODO + + // Fast write routines - special case the most common hardware write + // TODO: use this. + // Even in x86, the param values will be in the right registers. + /* + const u8 *fastMemWrite8 = AlignCode16(); + CMP(32, R(ABI_PARAM2), Imm32(0xCC008000)); + FixupBranch skip_fast_write = J_CC(CC_NE, false); + MOV(32, EAX, M(&m_gatherPipeCount)); + MOV(8, MDisp(EAX, (u32)&m_gatherPipe), ABI_PARAM1); + ADD(32, 1, M(&m_gatherPipeCount)); + RET(); + SetJumpTarget(skip_fast_write); + CALL((void *)&Memory::Write_U8);*/ +} diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/JitAsm.h b/Source/Core/Core/Src/PowerPC/JitArm32/JitAsm.h new file mode 100644 index 0000000000..9a61e9e653 --- /dev/null +++ b/Source/Core/Core/Src/PowerPC/JitArm32/JitAsm.h @@ -0,0 +1,43 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#ifndef _JITARMASM_H +#define _JITARMASM_H +#include "ArmEmitter.h" +#include "../JitCommon/JitAsmCommon.h" +using namespace ArmGen; +class JitArmAsmRoutineManager : public CommonAsmRoutinesBase, public ARMXCodeBlock +{ +private: + void Generate(); + void GenerateCommon(); + +public: + void Init() { + AllocCodeSpace(8192); + Generate(); + WriteProtect(); + } + + void Shutdown() { + FreeCodeSpace(); + } +}; + +extern JitArmAsmRoutineManager asm_routines; + +#endif // _JIT64ASM_H diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/JitFPRCache.cpp b/Source/Core/Core/Src/PowerPC/JitArm32/JitFPRCache.cpp new file mode 100644 index 0000000000..99139d2c71 --- /dev/null +++ b/Source/Core/Core/Src/PowerPC/JitArm32/JitFPRCache.cpp @@ -0,0 +1,169 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "Jit.h" +#include "JitFPRCache.h" + +ArmFPRCache::ArmFPRCache() +{ + emit = 0; +} + +void ArmFPRCache::Init(ARMXEmitter *emitter) +{ + emit = emitter; + ARMReg *PPCRegs = GetPPCAllocationOrder(NUMPPCREG); + ARMReg *Regs = GetAllocationOrder(NUMARMREG); + + for(u8 a = 0; a < NUMPPCREG; ++a) + { + ArmCRegs[a].PPCReg = 33; + ArmCRegs[a].Reg = PPCRegs[a]; + ArmCRegs[a].LastLoad = 0; + ArmCRegs[a].PS1 = false; + } + for(u8 a = 0; a < NUMARMREG; ++a) + { + ArmRegs[a].Reg = Regs[a]; + ArmRegs[a].free = true; + } +} +void ArmFPRCache::Start(PPCAnalyst::BlockRegStats &stats) +{ + for(u8 a = 0; a < NUMPPCREG; ++a) + { + ArmCRegs[a].PPCReg = 33; + ArmCRegs[a].LastLoad = 0; + } +} +ARMReg *ArmFPRCache::GetPPCAllocationOrder(int &count) +{ + // This will return us the allocation order of the registers we can use on + // the ppc side. + static ARMReg allocationOrder[] = + { + D0, D1, D2, D3, D4, D5, D6, D7, D8, D9, D10, + D11, D12, D13, D14, D15, D16, D17, D18, D19, + D20, D21, D22, D23, D24, D25, D26, D27 + }; + count = sizeof(allocationOrder) / sizeof(const int); + return allocationOrder; +} +ARMReg *ArmFPRCache::GetAllocationOrder(int &count) +{ + // This will return us the allocation order of the registers we can use on + // the host side. + static ARMReg allocationOrder[] = + { + D31, D30, D29, D28 + }; + count = sizeof(allocationOrder) / sizeof(const int); + return allocationOrder; +} + +ARMReg ArmFPRCache::GetReg(bool AutoLock) +{ + for(u8 a = 0; a < NUMARMREG; ++a) + if(ArmRegs[a].free) + { + // Alright, this one is free + if (AutoLock) + ArmRegs[a].free = false; + return ArmRegs[a].Reg; + } + // Uh Oh, we have all them locked.... + _assert_msg_(_DYNA_REC_, false, "All available registers are locked dumb dumb"); + return D31; +} +void ArmFPRCache::Unlock(ARMReg V0) +{ + for(u8 RegNum = 0; RegNum < NUMARMREG; ++RegNum) + { + if(ArmRegs[RegNum].Reg == V0) + { + _assert_msg_(_DYNA_REC, !ArmRegs[RegNum].free, "This register is already unlocked"); + ArmRegs[RegNum].free = true; + } + } +} +ARMReg ArmFPRCache::GetPPCReg(u32 preg, bool PS1, bool preLoad) +{ + u32 HighestUsed = 0; + u8 Num = 0; + for(u8 a = 0; a < NUMPPCREG; ++a){ + ++ArmCRegs[a].LastLoad; + if (ArmCRegs[a].LastLoad > HighestUsed) + { + HighestUsed = ArmCRegs[a].LastLoad; + Num = a; + } + } + // Check if already Loaded + for(u8 a = 0; a < NUMPPCREG; ++a) + if (ArmCRegs[a].PPCReg == preg && ArmCRegs[a].PS1 == PS1) + { + ArmCRegs[a].LastLoad = 0; + return ArmCRegs[a].Reg; + } + // Check if we have a free register + for (u8 a = 0; a < NUMPPCREG; ++a) + if (ArmCRegs[a].PPCReg == 33) + { + u16 offset = PPCSTATE_OFF(PowerPC::ppcState, ps) + (preg * 16) + (PS1 ? 8 : 0); + if (preLoad) + emit->VLDR(ArmCRegs[a].Reg, R9, offset); + ArmCRegs[a].PPCReg = preg; + ArmCRegs[a].LastLoad = 0; + ArmCRegs[a].PS1 = PS1; + return ArmCRegs[a].Reg; + } + // Alright, we couldn't get a free space, dump that least used register + u16 offsetOld = PPCSTATE_OFF(PowerPC::ppcState, ps) + (ArmCRegs[Num].PPCReg * 16) + (ArmCRegs[Num].PS1 ? 8 : 0); + emit->VSTR(ArmCRegs[Num].Reg, R9, offsetOld); + + u16 offsetNew = PPCSTATE_OFF(PowerPC::ppcState, ps) + (preg * 16) + (PS1 ? 8 : 0); + if (preLoad) + emit->VLDR(ArmCRegs[Num].Reg, R9, offsetNew); + ArmCRegs[Num].PPCReg = preg; + ArmCRegs[Num].LastLoad = 0; + ArmCRegs[Num].PS1 = PS1; + return ArmCRegs[Num].Reg; + +} + +ARMReg ArmFPRCache::R0(u32 preg, bool preLoad) +{ + return GetPPCReg(preg, false, preLoad); +} + +ARMReg ArmFPRCache::R1(u32 preg, bool preLoad) +{ + return GetPPCReg(preg, true, preLoad); +} + +void ArmFPRCache::Flush() +{ + for(u8 a = 0; a < NUMPPCREG; ++a) + if (ArmCRegs[a].PPCReg != 33) + { + u16 offset = PPCSTATE_OFF(PowerPC::ppcState, ps) + (ArmCRegs[a].PPCReg * 16) + (ArmCRegs[a].PS1 ? 8 : 0); + emit->VSTR(ArmCRegs[a].Reg, R9, offset); + ArmCRegs[a].PPCReg = 33; + ArmCRegs[a].LastLoad = 0; + } +} + diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/JitFPRCache.h b/Source/Core/Core/Src/PowerPC/JitArm32/JitFPRCache.h new file mode 100644 index 0000000000..6b4f056409 --- /dev/null +++ b/Source/Core/Core/Src/PowerPC/JitArm32/JitFPRCache.h @@ -0,0 +1,62 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#ifndef _JITARMFPRCACHE_H +#define _JITARMFPRCACHE_H + +#include "ArmEmitter.h" +#include "../Gekko.h" +#include "../PPCAnalyst.h" +#include "JitRegCache.h" + +#define ARMFPUREGS 32 +using namespace ArmGen; + +class ArmFPRCache +{ +private: + PPCCachedReg regs[32]; + JRCPPC ArmCRegs[ARMFPUREGS]; + JRCReg ArmRegs[ARMFPUREGS]; + + int NUMPPCREG; + int NUMARMREG; + + ARMReg *GetAllocationOrder(int &count); + ARMReg *GetPPCAllocationOrder(int &count); + + ARMReg GetPPCReg(u32 preg, bool PS1, bool preLoad); + +protected: + ARMXEmitter *emit; + +public: + ArmFPRCache(); + ~ArmFPRCache() {} + + void Init(ARMXEmitter *emitter); + void Start(PPCAnalyst::BlockRegStats &stats); + + void SetEmitter(ARMXEmitter *emitter) {emit = emitter;} + + ARMReg GetReg(bool AutoLock = true); // Return a ARM register we can use. + void Unlock(ARMReg V0); + void Flush(); + ARMReg R0(u32 preg, bool preLoad = true); // Returns a cached register + ARMReg R1(u32 preg, bool preLoad = true); +}; +#endif diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/JitRegCache.cpp b/Source/Core/Core/Src/PowerPC/JitArm32/JitRegCache.cpp new file mode 100644 index 0000000000..0e5bc8d68a --- /dev/null +++ b/Source/Core/Core/Src/PowerPC/JitArm32/JitRegCache.cpp @@ -0,0 +1,168 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "Jit.h" +#include "JitRegCache.h" + +ArmRegCache::ArmRegCache() +{ + emit = 0; +} + +void ArmRegCache::Init(ARMXEmitter *emitter) +{ + emit = emitter; + ARMReg *PPCRegs = GetPPCAllocationOrder(NUMPPCREG); + ARMReg *Regs = GetAllocationOrder(NUMARMREG); + for(u8 a = 0; a < 32; ++a) + { + // This gives us the memory locations of the gpr registers so we can + // load them. + regs[a].location = (u8*)&PowerPC::ppcState.gpr[a]; + regs[a].UsesLeft = 0; + } + for(u8 a = 0; a < NUMPPCREG; ++a) + { + ArmCRegs[a].PPCReg = 33; + ArmCRegs[a].Reg = PPCRegs[a]; + ArmCRegs[a].LastLoad = 0; + } + for(u8 a = 0; a < NUMARMREG; ++a) + { + ArmRegs[a].Reg = Regs[a]; + ArmRegs[a].free = true; + } +} +void ArmRegCache::Start(PPCAnalyst::BlockRegStats &stats) +{ + for(u8 a = 0; a < NUMPPCREG; ++a) + { + ArmCRegs[a].PPCReg = 33; + ArmCRegs[a].LastLoad = 0; + } + for(u8 a = 0; a < 32; ++a) + regs[a].UsesLeft = stats.GetTotalNumAccesses(a); +} +ARMReg *ArmRegCache::GetPPCAllocationOrder(int &count) +{ + // This will return us the allocation order of the registers we can use on + // the ppc side. + static ARMReg allocationOrder[] = + { + R0, R1, R2, R3, R4, R5, R6, R7, R8 + }; + count = sizeof(allocationOrder) / sizeof(const int); + return allocationOrder; +} +ARMReg *ArmRegCache::GetAllocationOrder(int &count) +{ + // This will return us the allocation order of the registers we can use on + // the host side. + static ARMReg allocationOrder[] = + { + R14, R12, R11, R10 + }; + count = sizeof(allocationOrder) / sizeof(const int); + return allocationOrder; +} + +ARMReg ArmRegCache::GetReg(bool AutoLock) +{ + for(u8 a = 0; a < NUMARMREG; ++a) + if(ArmRegs[a].free) + { + // Alright, this one is free + if (AutoLock) + ArmRegs[a].free = false; + return ArmRegs[a].Reg; + } + // Uh Oh, we have all them locked.... + _assert_msg_(_DYNA_REC_, false, "All available registers are locked dumb dumb"); + return R0; +} +void ArmRegCache::Lock(ARMReg Reg) +{ + for(u8 RegNum = 0; RegNum < NUMARMREG; ++RegNum) + if(ArmRegs[RegNum].Reg == Reg) + { + _assert_msg_(_DYNA_REC, ArmRegs[RegNum].free, "This register is already locked"); + ArmRegs[RegNum].free = false; + } + _assert_msg_(_DYNA_REC, false, "Register %d can't be used with lock", Reg); +} +void ArmRegCache::Unlock(ARMReg R0, ARMReg R1, ARMReg R2, ARMReg R3) +{ + for(u8 RegNum = 0; RegNum < NUMARMREG; ++RegNum) + { + if(ArmRegs[RegNum].Reg == R0) + { + _assert_msg_(_DYNA_REC, !ArmRegs[RegNum].free, "This register is already unlocked"); + ArmRegs[RegNum].free = true; + } + if( R1 != INVALID_REG && ArmRegs[RegNum].Reg == R1) ArmRegs[RegNum].free = true; + if( R2 != INVALID_REG && ArmRegs[RegNum].Reg == R2) ArmRegs[RegNum].free = true; + if( R3 != INVALID_REG && ArmRegs[RegNum].Reg == R3) ArmRegs[RegNum].free = true; + } +} + +ARMReg ArmRegCache::R(u32 preg) +{ + u32 HighestUsed = 0; + u8 Num = 0; + for(u8 a = 0; a < NUMPPCREG; ++a){ + ++ArmCRegs[a].LastLoad; + if (ArmCRegs[a].LastLoad > HighestUsed) + { + HighestUsed = ArmCRegs[a].LastLoad; + Num = a; + } + } + // Check if already Loaded + for(u8 a = 0; a < NUMPPCREG; ++a) + if (ArmCRegs[a].PPCReg == preg) + { + ArmCRegs[a].LastLoad = 0; + return ArmCRegs[a].Reg; + } + // Check if we have a free register + for (u8 a = 0; a < NUMPPCREG; ++a) + if (ArmCRegs[a].PPCReg == 33) + { + emit->LDR(ArmCRegs[a].Reg, R9, PPCSTATE_OFF(PowerPC::ppcState, gpr) + preg * 4); + ArmCRegs[a].PPCReg = preg; + ArmCRegs[a].LastLoad = 0; + return ArmCRegs[a].Reg; + } + // Alright, we couldn't get a free space, dump that least used register + emit->STR(R9, ArmCRegs[Num].Reg, PPCSTATE_OFF(PowerPC::ppcState, gpr) + ArmCRegs[Num].PPCReg * 4); + emit->LDR(ArmCRegs[Num].Reg, R9, PPCSTATE_OFF(PowerPC::ppcState, gpr) + preg * 4); + ArmCRegs[Num].PPCReg = preg; + ArmCRegs[Num].LastLoad = 0; + return ArmCRegs[Num].Reg; +} + +void ArmRegCache::Flush() +{ + for(u8 a = 0; a < NUMPPCREG; ++a) + if (ArmCRegs[a].PPCReg != 33) + { + emit->STR(R9, ArmCRegs[a].Reg, PPCSTATE_OFF(PowerPC::ppcState, gpr) + ArmCRegs[a].PPCReg * 4); + ArmCRegs[a].PPCReg = 33; + ArmCRegs[a].LastLoad = 0; + } +} + diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/JitRegCache.h b/Source/Core/Core/Src/PowerPC/JitArm32/JitRegCache.h new file mode 100644 index 0000000000..7292ce1581 --- /dev/null +++ b/Source/Core/Core/Src/PowerPC/JitArm32/JitRegCache.h @@ -0,0 +1,92 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#ifndef _JITARMREGCACHE_H +#define _JITARMREGCACHE_H + +#include "ArmEmitter.h" +#include "../Gekko.h" +#include "../PPCAnalyst.h" + +using namespace ArmGen; +// This ARM Register cache actually pre loads the most used registers before +// the block to increase speed since every memory load requires two +// instructions to load it. We are going to use R0-RMAX as registers for the +// use of PPC Registers. +// Allocation order as follows +#define ARMREGS 16 +// Allocate R0 to R9 for PPC first. +// For General registers on the host side, start with R14 and go down as we go +// R13 is reserved for our stack pointer, don't ever use that. Unless you save +// it +// So we have R14, R12, R11, R10 to work with instructions + +struct PPCCachedReg +{ + const u8 *location; + u32 UsesLeft; +}; +struct JRCPPC +{ + u32 PPCReg; // Tied to which PPC Register + bool PS1; + ARMReg Reg; // Tied to which ARM Register + u32 LastLoad; +}; +struct JRCReg +{ + ARMReg Reg; // Which reg this is. + bool free; +}; +class ArmRegCache +{ +private: + PPCCachedReg regs[32]; + JRCPPC ArmCRegs[ARMREGS]; + JRCReg ArmRegs[ARMREGS]; // Four registers remaining + + int NUMPPCREG; + int NUMARMREG; + + ARMReg *GetAllocationOrder(int &count); + ARMReg *GetPPCAllocationOrder(int &count); + +protected: + ARMXEmitter *emit; + +public: + ArmRegCache(); + ~ArmRegCache() {} + + void Init(ARMXEmitter *emitter); + void Start(PPCAnalyst::BlockRegStats &stats); + + void SetEmitter(ARMXEmitter *emitter) {emit = emitter;} + + ARMReg GetReg(bool AutoLock = true); // Return a ARM register we can use. + void Lock(ARMReg reg); + void Unlock(ARMReg R0, ARMReg R1 = INVALID_REG, ARMReg R2 = INVALID_REG, ARMReg R3 = + INVALID_REG); + void Flush(); + ARMReg R(u32 preg); // Returns a cached register + +}; + + + + +#endif diff --git a/Source/Core/Core/Src/PowerPC/JitCommon/JitAsmCommon.cpp b/Source/Core/Core/Src/PowerPC/JitCommon/JitAsmCommon.cpp index 34b9a681e9..7f509dbf0e 100644 --- a/Source/Core/Core/Src/PowerPC/JitCommon/JitAsmCommon.cpp +++ b/Source/Core/Core/Src/PowerPC/JitCommon/JitAsmCommon.cpp @@ -15,7 +15,7 @@ // Official SVN repository and contact information can be found at // http://code.google.com/p/dolphin-emu/ -#include "ABI.h" +#include "x64ABI.h" #include "Thunk.h" #include "CPUDetect.h" #include "x64Emitter.h" @@ -26,7 +26,7 @@ #include "../../CoreTiming.h" #include "MemoryUtil.h" -#include "ABI.h" +#include "x64ABI.h" #include "../JitCommon/JitCache.h" #include "../../HW/GPFifo.h" diff --git a/Source/Core/Core/Src/PowerPC/JitCommon/JitAsmCommon.h b/Source/Core/Core/Src/PowerPC/JitCommon/JitAsmCommon.h index cbec27d2aa..a610a03326 100644 --- a/Source/Core/Core/Src/PowerPC/JitCommon/JitAsmCommon.h +++ b/Source/Core/Core/Src/PowerPC/JitCommon/JitAsmCommon.h @@ -21,16 +21,8 @@ #include "../JitCommon/Jit_Util.h" #include "Thunk.h" -class CommonAsmRoutines : public EmuCodeBlock { -protected: - void GenQuantizedLoads(); - void GenQuantizedStores(); - void GenQuantizedSingleStores(); - +class CommonAsmRoutinesBase { public: - void GenFifoWrite(int size); - void GenFifoXmm64Write(); - void GenFifoFloatWrite(); const u8 *fifoDirectWrite8; const u8 *fifoDirectWrite16; @@ -72,8 +64,23 @@ public: // In: XMM0: Bottom 32-bit slot holds the float to be written. const u8 **singleStoreQuantized; +}; + +class CommonAsmRoutines : public CommonAsmRoutinesBase, public EmuCodeBlock +{ +protected: + void GenQuantizedLoads(); + void GenQuantizedStores(); + void GenQuantizedSingleStores(); + +public: + void GenFifoWrite(int size); + void GenFifoXmm64Write(); + void GenFifoFloatWrite(); + private: ThunkManager thunks; + }; #endif diff --git a/Source/Core/Core/Src/PowerPC/JitCommon/JitBackpatch.cpp b/Source/Core/Core/Src/PowerPC/JitCommon/JitBackpatch.cpp index 3042cfedba..76e791a94c 100644 --- a/Source/Core/Core/Src/PowerPC/JitCommon/JitBackpatch.cpp +++ b/Source/Core/Core/Src/PowerPC/JitCommon/JitBackpatch.cpp @@ -25,7 +25,7 @@ #include "../../HW/Memmap.h" #include "x64Emitter.h" -#include "ABI.h" +#include "x64ABI.h" #include "Thunk.h" #include "x64Analyzer.h" @@ -160,7 +160,7 @@ const u8 *TrampolineCache::GetWriteTrampoline(const InstructionInfo &info) // 1) It's really necessary. We don't know anything about the context. // 2) It doesn't really hurt. Only instructions that access I/O will get these, and there won't be // that many of them in a typical program/game. -const u8 *JitBase::BackPatch(u8 *codePtr, int accessType, u32 emAddress, void *ctx_void) +const u8 *Jitx86Base::BackPatch(u8 *codePtr, int accessType, u32 emAddress, void *ctx_void) { #ifdef _M_X64 CONTEXT *ctx = (CONTEXT *)ctx_void; diff --git a/Source/Core/Core/Src/PowerPC/JitCommon/JitBackpatch.h b/Source/Core/Core/Src/PowerPC/JitCommon/JitBackpatch.h index 4b880eb86d..871a112c6c 100644 --- a/Source/Core/Core/Src/PowerPC/JitCommon/JitBackpatch.h +++ b/Source/Core/Core/Src/PowerPC/JitCommon/JitBackpatch.h @@ -34,6 +34,9 @@ // from the real context. struct CONTEXT { + #ifdef _M_ARM + u32 reg_pc; + #else #ifdef _M_X64 u64 Rip; u64 Rax; @@ -41,6 +44,7 @@ u32 Eip; u32 Eax; #endif + #endif }; #endif diff --git a/Source/Core/Core/Src/PowerPC/JitCommon/JitBase.h b/Source/Core/Core/Src/PowerPC/JitCommon/JitBase.h index 5352c06d04..158171be0f 100644 --- a/Source/Core/Core/Src/PowerPC/JitCommon/JitBase.h +++ b/Source/Core/Core/Src/PowerPC/JitCommon/JitBase.h @@ -32,12 +32,9 @@ #define JIT_OPCODE 0 -class JitBase : public CPUCoreBase, public EmuCodeBlock +class JitBase : public CPUCoreBase { protected: - JitBlockCache blocks; - TrampolineCache trampolines; - struct JitOptions { bool optimizeStack; @@ -85,14 +82,29 @@ public: // This should probably be removed from public: JitOptions jo; JitState js; - - JitBlockCache *GetBlockCache() { return &blocks; } + + virtual JitBaseBlockCache *GetBlockCache() = 0; virtual void Jit(u32 em_address) = 0; + virtual const u8 *BackPatch(u8 *codePtr, int accessType, u32 em_address, void *ctx) = 0; + + virtual const CommonAsmRoutinesBase *GetAsmRoutines() = 0; + + virtual bool IsInCodeSpace(u8 *ptr) = 0; +}; + +class Jitx86Base : public JitBase, public EmuCodeBlock +{ +protected: + JitBlockCache blocks; + TrampolineCache trampolines; +public: + JitBlockCache *GetBlockCache() { return &blocks; } + const u8 *BackPatch(u8 *codePtr, int accessType, u32 em_address, void *ctx); - virtual const CommonAsmRoutines *GetAsmRoutines() = 0; + bool IsInCodeSpace(u8 *ptr) { return IsInSpace(ptr); } }; extern JitBase *jit; diff --git a/Source/Core/Core/Src/PowerPC/JitCommon/JitCache.cpp b/Source/Core/Core/Src/PowerPC/JitCommon/JitCache.cpp index d409518bf9..415b37ca61 100644 --- a/Source/Core/Core/Src/PowerPC/JitCommon/JitCache.cpp +++ b/Source/Core/Core/Src/PowerPC/JitCommon/JitCache.cpp @@ -32,15 +32,13 @@ #include "MemoryUtil.h" #include "../../HW/Memmap.h" +#include "../JitInterface.h" #include "../../CoreTiming.h" #include "../PowerPC.h" #include "../PPCTables.h" #include "../PPCAnalyst.h" -#include "x64Emitter.h" -#include "x64Analyzer.h" - #include "JitCache.h" #include "JitBase.h" @@ -68,12 +66,12 @@ bool JitBlock::ContainsAddress(u32 em_address) return (em_address >= originalAddress && em_address < originalAddress + 4 * originalSize); } - bool JitBlockCache::IsFull() const + bool JitBaseBlockCache::IsFull() const { return GetNumBlocks() >= MAX_NUM_BLOCKS - 1; } - void JitBlockCache::Init() + void JitBaseBlockCache::Init() { MAX_NUM_BLOCKS = 65536*2; @@ -91,11 +89,11 @@ bool JitBlock::ContainsAddress(u32 em_address) } else { - PanicAlert("JitBlockCache::Init() - iCache is already initialized"); + PanicAlert("JitBaseBlockCache::Init() - iCache is already initialized"); } if (iCache == 0 || iCacheEx == 0 || iCacheVMEM == 0) { - PanicAlert("JitBlockCache::Init() - unable to allocate iCache"); + PanicAlert("JitBaseBlockCache::Init() - unable to allocate iCache"); } memset(iCache, JIT_ICACHE_INVALID_BYTE, JIT_ICACHE_SIZE); memset(iCacheEx, JIT_ICACHE_INVALID_BYTE, JIT_ICACHEEX_SIZE); @@ -104,7 +102,7 @@ bool JitBlock::ContainsAddress(u32 em_address) Clear(); } - void JitBlockCache::Shutdown() + void JitBaseBlockCache::Shutdown() { delete[] blocks; delete[] blockCodePointers; @@ -133,7 +131,7 @@ bool JitBlock::ContainsAddress(u32 em_address) // This clears the JIT cache. It's called from JitCache.cpp when the JIT cache // is full and when saving and loading states. - void JitBlockCache::Clear() + void JitBaseBlockCache::Clear() { if (IsFull()) Core::DisplayMessage("Clearing block cache.", 3000); @@ -151,7 +149,7 @@ bool JitBlock::ContainsAddress(u32 em_address) memset(blockCodePointers, 0, sizeof(u8*)*MAX_NUM_BLOCKS); } - void JitBlockCache::ClearSafe() + void JitBaseBlockCache::ClearSafe() { #ifdef JIT_UNLIMITED_ICACHE memset(iCache, JIT_ICACHE_INVALID_BYTE, JIT_ICACHE_SIZE); @@ -160,7 +158,7 @@ bool JitBlock::ContainsAddress(u32 em_address) #endif } - /*void JitBlockCache::DestroyBlocksWithFlag(BlockFlag death_flag) + /*void JitBaseBlockCache::DestroyBlocksWithFlag(BlockFlag death_flag) { for (int i = 0; i < num_blocks; i++) { @@ -171,23 +169,23 @@ bool JitBlock::ContainsAddress(u32 em_address) } }*/ - void JitBlockCache::Reset() + void JitBaseBlockCache::Reset() { Shutdown(); Init(); } - JitBlock *JitBlockCache::GetBlock(int no) + JitBlock *JitBaseBlockCache::GetBlock(int no) { return &blocks[no]; } - int JitBlockCache::GetNumBlocks() const + int JitBaseBlockCache::GetNumBlocks() const { return num_blocks; } - bool JitBlockCache::RangeIntersect(int s1, int e1, int s2, int e2) const + bool JitBaseBlockCache::RangeIntersect(int s1, int e1, int s2, int e2) const { // check if any endpoint is inside the other range if ((s1 >= s2 && s1 <= e2) || @@ -199,7 +197,7 @@ bool JitBlock::ContainsAddress(u32 em_address) return false; } - int JitBlockCache::AllocateBlock(u32 em_address) + int JitBaseBlockCache::AllocateBlock(u32 em_address) { JitBlock &b = blocks[num_blocks]; b.invalid = false; @@ -215,12 +213,12 @@ bool JitBlock::ContainsAddress(u32 em_address) return num_blocks - 1; } - void JitBlockCache::FinalizeBlock(int block_num, bool block_link, const u8 *code_ptr) + void JitBaseBlockCache::FinalizeBlock(int block_num, bool block_link, const u8 *code_ptr) { blockCodePointers[block_num] = code_ptr; JitBlock &b = blocks[block_num]; - b.originalFirstOpcode = Memory::Read_Opcode_JIT(b.originalAddress); - Memory::Write_Opcode_JIT(b.originalAddress, (JIT_OPCODE << 26) | block_num); + b.originalFirstOpcode = JitInterface::Read_Opcode_JIT(b.originalAddress); + JitInterface::Write_Opcode_JIT(b.originalAddress, (JIT_OPCODE << 26) | block_num); // Convert the logical address to a physical address for the block map u32 pAddr = b.originalAddress & 0x1FFFFFFF; @@ -264,29 +262,29 @@ bool JitBlock::ContainsAddress(u32 em_address) #endif } - const u8 **JitBlockCache::GetCodePointers() + const u8 **JitBaseBlockCache::GetCodePointers() { return blockCodePointers; } #ifdef JIT_UNLIMITED_ICACHE - u8* JitBlockCache::GetICache() + u8* JitBaseBlockCache::GetICache() { return iCache; } - u8* JitBlockCache::GetICacheEx() + u8* JitBaseBlockCache::GetICacheEx() { return iCacheEx; } - u8* JitBlockCache::GetICacheVMEM() + u8* JitBaseBlockCache::GetICacheVMEM() { return iCacheVMEM; } #endif - int JitBlockCache::GetBlockNumberFromStartAddress(u32 addr) + int JitBaseBlockCache::GetBlockNumberFromStartAddress(u32 addr) { if (!blocks) return -1; @@ -317,24 +315,24 @@ bool JitBlock::ContainsAddress(u32 em_address) return inst; } - void JitBlockCache::GetBlockNumbersFromAddress(u32 em_address, std::vector *block_numbers) + void JitBaseBlockCache::GetBlockNumbersFromAddress(u32 em_address, std::vector *block_numbers) { for (int i = 0; i < num_blocks; i++) if (blocks[i].ContainsAddress(em_address)) block_numbers->push_back(i); } - u32 JitBlockCache::GetOriginalFirstOp(int block_num) + u32 JitBaseBlockCache::GetOriginalFirstOp(int block_num) { if (block_num >= num_blocks) { - //PanicAlert("JitBlockCache::GetOriginalFirstOp - block_num = %u is out of range", block_num); + //PanicAlert("JitBaseBlockCache::GetOriginalFirstOp - block_num = %u is out of range", block_num); return block_num; } return blocks[block_num].originalFirstOpcode; } - CompiledCode JitBlockCache::GetCompiledCodeFromBlock(int block_num) + CompiledCode JitBaseBlockCache::GetCompiledCodeFromBlock(int block_num) { return (CompiledCode)blockCodePointers[block_num]; } @@ -345,7 +343,7 @@ bool JitBlock::ContainsAddress(u32 em_address) //Can be faster by doing a queue for blocks to link up, and only process those //Should probably be done - void JitBlockCache::LinkBlockExits(int i) + void JitBaseBlockCache::LinkBlockExits(int i) { JitBlock &b = blocks[i]; if (b.invalid) @@ -360,8 +358,7 @@ bool JitBlock::ContainsAddress(u32 em_address) int destinationBlock = GetBlockNumberFromStartAddress(b.exitAddress[e]); if (destinationBlock != -1) { - XEmitter emit(b.exitPtrs[e]); - emit.JMP(blocks[destinationBlock].checkedEntry, true); + WriteLinkBlock(b.exitPtrs[e], blocks[destinationBlock].checkedEntry); b.linkStatus[e] = true; } } @@ -370,7 +367,7 @@ bool JitBlock::ContainsAddress(u32 em_address) using namespace std; - void JitBlockCache::LinkBlock(int i) + void JitBaseBlockCache::LinkBlock(int i) { LinkBlockExits(i); JitBlock &b = blocks[i]; @@ -386,7 +383,7 @@ bool JitBlock::ContainsAddress(u32 em_address) } } - void JitBlockCache::UnlinkBlock(int i) + void JitBaseBlockCache::UnlinkBlock(int i) { JitBlock &b = blocks[i]; pair::iterator, multimap::iterator> ppp; @@ -403,7 +400,7 @@ bool JitBlock::ContainsAddress(u32 em_address) } } - void JitBlockCache::DestroyBlock(int block_num, bool invalidate) + void JitBaseBlockCache::DestroyBlock(int block_num, bool invalidate) { if (block_num < 0 || block_num >= num_blocks) { @@ -419,7 +416,7 @@ bool JitBlock::ContainsAddress(u32 em_address) } b.invalid = true; #ifdef JIT_UNLIMITED_ICACHE - Memory::Write_Opcode_JIT(b.originalAddress, b.originalFirstOpcode?b.originalFirstOpcode:JIT_ICACHE_INVALID_WORD); + JitInterface::Write_Opcode_JIT(b.originalAddress, b.originalFirstOpcode?b.originalFirstOpcode:JIT_ICACHE_INVALID_WORD); #else if (Memory::ReadFast32(b.originalAddress) == block_num) Memory::WriteUnchecked_U32(b.originalFirstOpcode, b.originalAddress); @@ -430,18 +427,10 @@ bool JitBlock::ContainsAddress(u32 em_address) // Send anyone who tries to run this block back to the dispatcher. // Not entirely ideal, but .. pretty good. // Spurious entrances from previously linked blocks can only come through checkedEntry - XEmitter emit((u8 *)b.checkedEntry); - emit.MOV(32, M(&PC), Imm32(b.originalAddress)); - emit.JMP(jit->GetAsmRoutines()->dispatcher, true); - // this is not needed really - /* - emit.SetCodePtr((u8 *)blockCodePointers[blocknum]); - emit.MOV(32, M(&PC), Imm32(b.originalAddress)); - emit.JMP(asm_routines.dispatcher, true); - */ + WriteDestroyBlock(b.checkedEntry, b.originalAddress); } - void JitBlockCache::InvalidateICache(u32 address, const u32 length) + void JitBaseBlockCache::InvalidateICache(u32 address, const u32 length) { // Convert the logical address to a physical address for the block map u32 pAddr = address & 0x1FFFFFFF; @@ -449,7 +438,7 @@ bool JitBlock::ContainsAddress(u32 em_address) // Optimize the common case of length == 32 which is used by Interpreter::dcb* bool destroy_block = true; if (length == 32) - { + { if (!valid_block[pAddr / 32]) destroy_block = false; else @@ -462,7 +451,7 @@ bool JitBlock::ContainsAddress(u32 em_address) { std::map, u32>::iterator it1 = block_map.lower_bound(std::make_pair(pAddr, 0)), it2 = it1; while (it2 != block_map.end() && it2->first.second < pAddr + length) - { + { #ifdef JIT_UNLIMITED_ICACHE JitBlock &b = blocks[it2->second]; if (b.originalAddress & JIT_ICACHE_VMEM_BIT) @@ -516,3 +505,14 @@ bool JitBlock::ContainsAddress(u32 em_address) } #endif } + void JitBlockCache::WriteLinkBlock(u8* location, const u8* address) + { + XEmitter emit(location); + emit.JMP(address, true); + } + void JitBlockCache::WriteDestroyBlock(const u8* location, u32 address) + { + XEmitter emit((u8 *)location); + emit.MOV(32, M(&PC), Imm32(address)); + emit.JMP(jit->GetAsmRoutines()->dispatcher, true); + } diff --git a/Source/Core/Core/Src/PowerPC/JitCommon/JitCache.h b/Source/Core/Core/Src/PowerPC/JitCommon/JitCache.h index 4214f33875..b148cb8090 100644 --- a/Source/Core/Core/Src/PowerPC/JitCommon/JitCache.h +++ b/Source/Core/Core/Src/PowerPC/JitCommon/JitCache.h @@ -78,7 +78,8 @@ struct JitBlock typedef void (*CompiledCode)(); -class JitBlockCache + +class JitBaseBlockCache { const u8 **blockCodePointers; JitBlock *blocks; @@ -97,9 +98,13 @@ class JitBlockCache void LinkBlockExits(int i); void LinkBlock(int i); void UnlinkBlock(int i); + + // Virtual for overloaded + virtual void WriteLinkBlock(u8* location, const u8* address) = 0; + virtual void WriteDestroyBlock(const u8* location, u32 address) = 0; public: - JitBlockCache() : + JitBaseBlockCache() : blockCodePointers(0), blocks(0), num_blocks(0), #ifdef JIT_UNLIMITED_ICACHE iCache(0), iCacheEx(0), iCacheVMEM(0), @@ -146,4 +151,11 @@ public: //void DestroyBlocksWithFlag(BlockFlag death_flag); }; +// x86 BlockCache +class JitBlockCache : public JitBaseBlockCache +{ +private: + void WriteLinkBlock(u8* location, const u8* address); + void WriteDestroyBlock(const u8* location, u32 address); +}; #endif diff --git a/Source/Core/Core/Src/PowerPC/JitCommon/Jit_Util.cpp b/Source/Core/Core/Src/PowerPC/JitCommon/Jit_Util.cpp index cc1327c695..f5c4cb022b 100644 --- a/Source/Core/Core/Src/PowerPC/JitCommon/Jit_Util.cpp +++ b/Source/Core/Core/Src/PowerPC/JitCommon/Jit_Util.cpp @@ -25,7 +25,7 @@ #include "../../HW/Memmap.h" #include "../PPCTables.h" #include "x64Emitter.h" -#include "ABI.h" +#include "x64ABI.h" #include "JitBase.h" #include "Jit_Util.h" diff --git a/Source/Core/Core/Src/PowerPC/JitInterface.cpp b/Source/Core/Core/Src/PowerPC/JitInterface.cpp new file mode 100644 index 0000000000..8fcdd9837f --- /dev/null +++ b/Source/Core/Core/Src/PowerPC/JitInterface.cpp @@ -0,0 +1,350 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include + +#ifdef _WIN32 +#include +#endif + +#include "JitInterface.h" +#include "JitCommon/JitBase.h" + +#ifndef _M_GENERIC +#include "Jit64IL/JitIL.h" +#include "Jit64/Jit.h" +#include "Jit64/Jit64_Tables.h" +#include "Jit64IL/JitIL_Tables.h" +#endif + +#ifdef _M_ARM +#include "JitArm32/Jit.h" +#include "JitArm32/JitArm_Tables.h" +#endif + +#include "Profiler.h" +#include "PPCSymbolDB.h" +#include "HW/Memmap.h" +#include "ConfigManager.h" + +bool bFakeVMEM = false; +bool bMMU = false; + +namespace JitInterface +{ + void DoState(PointerWrap &p) + { + if (jit && p.GetMode() == PointerWrap::MODE_READ) + jit->GetBlockCache()->ClearSafe(); + } + CPUCoreBase *InitJitCore(int core) + { + bFakeVMEM = SConfig::GetInstance().m_LocalCoreStartupParameter.iTLBHack == 1; + bMMU = SConfig::GetInstance().m_LocalCoreStartupParameter.bMMU; + + CPUCoreBase *ptr = NULL; + switch(core) + { + #ifndef _M_GENERIC + case 1: + { + ptr = new Jit64(); + break; + } + case 2: + { + ptr = new JitIL(); + break; + } + #endif + #ifdef _M_ARM + case 3: + { + ptr = new JitArm(); + break; + } + #endif + default: + { + PanicAlert("Unrecognizable cpu_core: %d", core); + return NULL; + break; + } + } + jit = static_cast(ptr); + jit->Init(); + return ptr; + } + void InitTables(int core) + { + switch(core) + { + #ifndef _M_GENERIC + case 1: + { + Jit64Tables::InitTables(); + break; + } + case 2: + { + JitILTables::InitTables(); + break; + } + #endif + #ifdef _M_ARM + case 3: + { + JitArmTables::InitTables(); + break; + } + #endif + default: + { + PanicAlert("Unrecognizable cpu_core: %d", core); + break; + } + } + } + CPUCoreBase *GetCore() + { + return jit; + } + + void WriteProfileResults(const char *filename) + { + // Can't really do this with no jit core available + #ifndef _M_GENERIC + + std::vector stats; + stats.reserve(jit->GetBlockCache()->GetNumBlocks()); + u64 cost_sum = 0; + #ifdef _WIN32 + u64 timecost_sum = 0; + u64 countsPerSec; + QueryPerformanceFrequency((LARGE_INTEGER *)&countsPerSec); + #endif + for (int i = 0; i < jit->GetBlockCache()->GetNumBlocks(); i++) + { + const JitBlock *block = jit->GetBlockCache()->GetBlock(i); + // Rough heuristic. Mem instructions should cost more. + u64 cost = block->originalSize * (block->runCount / 4); + #ifdef _WIN32 + u64 timecost = block->ticCounter; + #endif + // Todo: tweak. + if (block->runCount >= 1) + stats.push_back(BlockStat(i, cost)); + cost_sum += cost; + #ifdef _WIN32 + timecost_sum += timecost; + #endif + } + + sort(stats.begin(), stats.end()); + File::IOFile f(filename, "w"); + if (!f) + { + PanicAlert("failed to open %s", filename); + return; + } + fprintf(f.GetHandle(), "origAddr\tblkName\tcost\ttimeCost\tpercent\ttimePercent\tOvAllinBlkTime(ms)\tblkCodeSize\n"); + for (unsigned int i = 0; i < stats.size(); i++) + { + const JitBlock *block = jit->GetBlockCache()->GetBlock(stats[i].blockNum); + if (block) + { + std::string name = g_symbolDB.GetDescription(block->originalAddress); + double percent = 100.0 * (double)stats[i].cost / (double)cost_sum; + #ifdef _WIN32 + double timePercent = 100.0 * (double)block->ticCounter / (double)timecost_sum; + fprintf(f.GetHandle(), "%08x\t%s\t%llu\t%llu\t%.2lf\t%llf\t%lf\t%i\n", + block->originalAddress, name.c_str(), stats[i].cost, + block->ticCounter, percent, timePercent, + (double)block->ticCounter*1000.0/(double)countsPerSec, block->codeSize); + #else + fprintf(f.GetHandle(), "%08x\t%s\t%llu\t???\t%.2lf\t???\t???\t%i\n", + block->originalAddress, name.c_str(), stats[i].cost, percent, block->codeSize); + #endif + } + } + #endif + } + bool IsInCodeSpace(u8 *ptr) + { + return jit->IsInCodeSpace(ptr); + } + const u8 *BackPatch(u8 *codePtr, int accessType, u32 em_address, void *ctx) + { + return jit->BackPatch(codePtr, accessType, em_address, ctx); + } + + void ClearCache() + { + if (jit) + jit->ClearCache(); + } + void ClearSafe() + { + if (jit) + jit->GetBlockCache()->ClearSafe(); + } + + void InvalidateICache(u32 address, u32 size) + { + if (jit) + jit->GetBlockCache()->InvalidateICache(address, size); + } + + + // Memory functions + u32 Read_Opcode_JIT_Uncached(const u32 _Address) + { + u8* iCache; + u32 addr; + if (_Address & JIT_ICACHE_VMEM_BIT) + { + iCache = jit->GetBlockCache()->GetICacheVMEM(); + addr = _Address & JIT_ICACHE_MASK; + } + else if (_Address & JIT_ICACHE_EXRAM_BIT) + { + iCache = jit->GetBlockCache()->GetICacheEx(); + addr = _Address & JIT_ICACHEEX_MASK; + } + else + { + iCache = jit->GetBlockCache()->GetICache(); + addr = _Address & JIT_ICACHE_MASK; + } + u32 inst = *(u32*)(iCache + addr); + if (inst == JIT_ICACHE_INVALID_WORD) + { + u32 cache_block_start = addr & ~0x1f; + u32 mem_block_start = _Address & ~0x1f; + u8 *pMem = Memory::GetPointer(mem_block_start); + memcpy(iCache + cache_block_start, pMem, 32); + inst = *(u32*)(iCache + addr); + } + inst = Common::swap32(inst); + + if ((inst & 0xfc000000) == 0) + { + inst = jit->GetBlockCache()->GetOriginalFirstOp(inst); + } + + return inst; + } + + u32 Read_Opcode_JIT(u32 _Address) + { + #ifdef FAST_ICACHE + if (bMMU && !bFakeVMEM && (_Address & Memory::ADDR_MASK_MEM1)) + { + _Address = Memory::TranslateAddress(_Address, Memory::FLAG_OPCODE); + if (_Address == 0) + { + return 0; + } + } + u32 inst = 0; + + // Bypass the icache for the external interrupt exception handler + if ( (_Address & 0x0FFFFF00) == 0x00000500 ) + inst = Read_Opcode_JIT_Uncached(_Address); + else + inst = PowerPC::ppcState.iCache.ReadInstruction(_Address); + #else + u32 inst = Memory::ReadUnchecked_U32(_Address); + #endif + return inst; + } + + // The following function is deprecated in favour of FAST_ICACHE + u32 Read_Opcode_JIT_LC(const u32 _Address) + { + #ifdef JIT_UNLIMITED_ICACHE + if ((_Address & ~JIT_ICACHE_MASK) != 0x80000000 && (_Address & ~JIT_ICACHE_MASK) != 0x00000000 && + (_Address & ~JIT_ICACHE_MASK) != 0x7e000000 && // TLB area + (_Address & ~JIT_ICACHEEX_MASK) != 0x90000000 && (_Address & ~JIT_ICACHEEX_MASK) != 0x10000000) + { + PanicAlertT("iCacheJIT: Reading Opcode from %x. Please report.", _Address); + ERROR_LOG(MEMMAP, "iCacheJIT: Reading Opcode from %x. Please report.", _Address); + return 0; + } + u8* iCache; + u32 addr; + if (_Address & JIT_ICACHE_VMEM_BIT) + { + iCache = jit->GetBlockCache()->GetICacheVMEM(); + addr = _Address & JIT_ICACHE_MASK; + } + else if (_Address & JIT_ICACHE_EXRAM_BIT) + { + iCache = jit->GetBlockCache()->GetICacheEx(); + addr = _Address & JIT_ICACHEEX_MASK; + } + else + { + iCache = jit->GetBlockCache()->GetICache(); + addr = _Address & JIT_ICACHE_MASK; + } + u32 inst = *(u32*)(iCache + addr); + if (inst == JIT_ICACHE_INVALID_WORD) + inst = Memory::ReadUnchecked_U32(_Address); + else + inst = Common::swap32(inst); + #else + u32 inst = Memory::ReadUnchecked_U32(_Address); + #endif + if ((inst & 0xfc000000) == 0) + { + inst = jit->GetBlockCache()->GetOriginalFirstOp(inst); + } + return inst; + } + + // WARNING! No checks! + // We assume that _Address is cached + void Write_Opcode_JIT(const u32 _Address, const u32 _Value) + { + #ifdef JIT_UNLIMITED_ICACHE + if (_Address & JIT_ICACHE_VMEM_BIT) + { + *(u32*)(jit->GetBlockCache()->GetICacheVMEM() + (_Address & JIT_ICACHE_MASK)) = Common::swap32(_Value); + } + else if (_Address & JIT_ICACHE_EXRAM_BIT) + { + *(u32*)(jit->GetBlockCache()->GetICacheEx() + (_Address & JIT_ICACHEEX_MASK)) = Common::swap32(_Value); + } + else + *(u32*)(jit->GetBlockCache()->GetICache() + (_Address & JIT_ICACHE_MASK)) = Common::swap32(_Value); + #else + Memory::WriteUnchecked_U32(_Value, _Address); + #endif + } + + + void Shutdown() + { + if (jit) + { + jit->Shutdown(); + delete jit; + jit = NULL; + } + } +} diff --git a/Source/Core/Core/Src/PowerPC/JitInterface.h b/Source/Core/Core/Src/PowerPC/JitInterface.h new file mode 100644 index 0000000000..a01c3dfa6e --- /dev/null +++ b/Source/Core/Core/Src/PowerPC/JitInterface.h @@ -0,0 +1,56 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "ChunkFile.h" +#include "CPUCoreBase.h" + +namespace JitInterface +{ + void DoState(PointerWrap &p); + + CPUCoreBase *InitJitCore(int core); + void InitTables(int core); + CPUCoreBase *GetCore(); + + // Debugging + void WriteProfileResults(const char *filename); + + // Memory Utilities + bool IsInCodeSpace(u8 *ptr); + const u8 *BackPatch(u8 *codePtr, int accessType, u32 em_address, void *ctx); + + // used by JIT to read instructions + u32 Read_Opcode_JIT(const u32 _Address); + // used by JIT. uses iCacheJIT. Reads in the "Locked cache" mode + u32 Read_Opcode_JIT_LC(const u32 _Address); + void Write_Opcode_JIT(const u32 _Address, const u32 _Value); + + // Clearing CodeCache + void ClearCache(); + + void ClearSafe(); + + void InvalidateICache(u32 address, u32 size); + + void Shutdown(); +} +extern bool bFakeVMEM; +extern bool bMMU; + +#ifdef _M_ARM +#include "JitArm32/Jit.h" +#endif diff --git a/Source/Core/Core/Src/PowerPC/PPCAnalyst.cpp b/Source/Core/Core/Src/PowerPC/PPCAnalyst.cpp index fa9f278c29..15a85568de 100644 --- a/Source/Core/Core/Src/PowerPC/PPCAnalyst.cpp +++ b/Source/Core/Core/Src/PowerPC/PPCAnalyst.cpp @@ -21,6 +21,7 @@ #include "StringUtil.h" #include "Interpreter/Interpreter.h" #include "../HW/Memmap.h" +#include "JitInterface.h" #include "PPCTables.h" #include "PPCSymbolDB.h" #include "SignatureDB.h" @@ -368,7 +369,7 @@ u32 Flatten(u32 address, int *realsize, BlockStats *st, BlockRegStats *gpa, } else { - inst = Memory::Read_Opcode_JIT(address); + inst = JitInterface::Read_Opcode_JIT(address); } } diff --git a/Source/Core/Core/Src/PowerPC/PPCCache.cpp b/Source/Core/Core/Src/PowerPC/PPCCache.cpp index 6956e9db1c..a0e4c666a4 100644 --- a/Source/Core/Core/Src/PowerPC/PPCCache.cpp +++ b/Source/Core/Core/Src/PowerPC/PPCCache.cpp @@ -20,6 +20,7 @@ #include "PowerPC.h" #include "JitCommon/JitBase.h" #include "JitCommon/JitCache.h" +#include "JitInterface.h" namespace PowerPC { @@ -76,8 +77,7 @@ namespace PowerPC memset(lookup_table_ex, 0xff, sizeof(lookup_table_ex)); memset(lookup_table_vmem, 0xff, sizeof(lookup_table_vmem)); #endif - if (jit) - jit->GetBlockCache()->ClearSafe(); + JitInterface::ClearSafe(); } void InstructionCache::Init() @@ -109,8 +109,7 @@ namespace PowerPC } #endif valid[set] = 0; - if (jit) - jit->GetBlockCache()->InvalidateICache(addr & ~0x1f, 32); + JitInterface::InvalidateICache(addr & ~0x1f, 32); } u32 InstructionCache::ReadInstruction(u32 addr) diff --git a/Source/Core/Core/Src/PowerPC/PPCTables.cpp b/Source/Core/Core/Src/PowerPC/PPCTables.cpp index d96089cebb..a6975f5860 100644 --- a/Source/Core/Core/Src/PowerPC/PPCTables.cpp +++ b/Source/Core/Core/Src/PowerPC/PPCTables.cpp @@ -24,11 +24,7 @@ #include "FileUtil.h" #include "Interpreter/Interpreter.h" #include "Interpreter/Interpreter_Tables.h" -#include "Jit64IL/JitIL_Tables.h" -#include "Jit64/Jit64_Tables.h" - -#include "Jit64IL/JitIL.h" -#include "Jit64/Jit.h" +#include "JitInterface.h" struct op_inf { @@ -165,19 +161,9 @@ void InitTables(int cpu_core) // Interpreter break; } - case 1: - { - Jit64Tables::InitTables(); - break; - } - case 2: - { - JitILTables::InitTables(); - break; - } default: { - PanicAlert("Unrecognizable cpu_core: %d", cpu_core); + JitInterface::InitTables(cpu_core); break; } } diff --git a/Source/Core/Core/Src/PowerPC/PowerPC.cpp b/Source/Core/Core/Src/PowerPC/PowerPC.cpp index 8a7b817212..d4447331e7 100644 --- a/Source/Core/Core/Src/PowerPC/PowerPC.cpp +++ b/Source/Core/Core/Src/PowerPC/PowerPC.cpp @@ -29,12 +29,10 @@ #include "../HW/SystemTimers.h" #include "Interpreter/Interpreter.h" -#include "JitCommon/JitBase.h" -#include "Jit64IL/JitIL.h" -#include "Jit64/Jit.h" #include "PowerPC.h" #include "PPCTables.h" #include "CPUCoreBase.h" +#include "JitInterface.h" #include "../Host.h" #include "HW/EXI.h" @@ -87,8 +85,7 @@ void DoState(PointerWrap &p) // SystemTimers::DecrementerSet(); // SystemTimers::TimeBaseSet(); - if (jit && p.GetMode() == PointerWrap::MODE_READ) - jit->GetBlockCache()->ClearSafe(); + JitInterface::DoState(p); } void ResetRegisters() @@ -131,28 +128,18 @@ void ResetRegisters() void Init(int cpu_core) { - enum { - FPU_PREC_24 = 0 << 8, - FPU_PREC_53 = 2 << 8, - FPU_PREC_64 = 3 << 8, - FPU_PREC_MASK = 3 << 8, - }; -#ifdef _M_IX86 - // sets the floating-point lib to 53-bit - // PowerPC has a 53bit floating pipeline only - // eg: sscanf is very sensitive -#ifdef _WIN32 - _control87(_PC_53, MCW_PC); -#else - unsigned short _mode; - asm ("fstcw %0" : : "m" (_mode)); - _mode = (_mode & ~FPU_PREC_MASK) | FPU_PREC_53; - asm ("fldcw %0" : : "m" (_mode)); -#endif -#else - //x64 doesn't need this - fpu is done with SSE - //but still - set any useful sse options here -#endif + FPURoundMode::SetPrecisionMode(FPURoundMode::PREC_53); + + memset(ppcState.mojs, 0, sizeof(ppcState.mojs)); + memset(ppcState.sr, 0, sizeof(ppcState.sr)); + ppcState.DebugCount = 0; + ppcState.dtlb_last = 0; + ppcState.dtlb_last = 0; + memset(ppcState.dtlb_va, 0, sizeof(ppcState.dtlb_va)); + memset(ppcState.dtlb_pa, 0, sizeof(ppcState.dtlb_pa)); + ppcState.itlb_last = 0; + memset(ppcState.itlb_va, 0, sizeof(ppcState.itlb_va)); + memset(ppcState.itlb_pa, 0, sizeof(ppcState.itlb_pa)); memset(ppcState.mojs, 0, sizeof(ppcState.mojs)); memset(ppcState.sr, 0, sizeof(ppcState.sr)); @@ -179,27 +166,13 @@ void Init(int cpu_core) cpu_core_base = interpreter; break; } - case 1: - { - cpu_core_base = new Jit64(); - break; - } - case 2: - { - cpu_core_base = new JitIL(); - break; - } - default: - { - PanicAlert("Unrecognizable cpu_core: %d", cpu_core); - break; - } + default: + cpu_core_base = JitInterface::InitJitCore(cpu_core); + break; } if (cpu_core_base != interpreter) { - jit = static_cast(cpu_core_base); - jit->Init(); mode = MODE_JIT; } else @@ -213,12 +186,7 @@ void Init(int cpu_core) void Shutdown() { - if (jit) - { - jit->Shutdown(); - delete jit; - jit = NULL; - } + JitInterface::Shutdown(); interpreter->Shutdown(); cpu_core_base = NULL; state = CPU_POWERDOWN; @@ -244,7 +212,7 @@ void SetMode(CoreMode new_mode) case MODE_JIT: // Switching from interpreter to JIT. // Don't really need to do much. It'll work, the cache will refill itself. - cpu_core_base = jit; + cpu_core_base = JitInterface::GetCore(); break; } } diff --git a/Source/Core/Core/Src/PowerPC/Profiler.cpp b/Source/Core/Core/Src/PowerPC/Profiler.cpp index 3636b00717..fc8942f09b 100644 --- a/Source/Core/Core/Src/PowerPC/Profiler.cpp +++ b/Source/Core/Core/Src/PowerPC/Profiler.cpp @@ -15,17 +15,7 @@ // Official SVN repository and contact information can be found at // http://code.google.com/p/dolphin-emu/ -#include "JitCommon/JitBase.h" - -#include -#include - -#ifdef _WIN32 -#include -#endif - -#include "PPCSymbolDB.h" -#include "FileUtil.h" +#include "JitInterface.h" namespace Profiler { @@ -33,73 +23,9 @@ namespace Profiler bool g_ProfileBlocks; bool g_ProfileInstructions; -struct BlockStat -{ - BlockStat(int bn, u64 c) : blockNum(bn), cost(c) {} - int blockNum; - u64 cost; - - bool operator <(const BlockStat &other) const - { return cost > other.cost; } -}; - void WriteProfileResults(const char *filename) { - std::vector stats; - stats.reserve(jit->GetBlockCache()->GetNumBlocks()); - u64 cost_sum = 0; -#ifdef _WIN32 - u64 timecost_sum = 0; - u64 countsPerSec; - QueryPerformanceFrequency((LARGE_INTEGER *)&countsPerSec); -#endif - for (int i = 0; i < jit->GetBlockCache()->GetNumBlocks(); i++) - { - const JitBlock *block = jit->GetBlockCache()->GetBlock(i); - if (block && !block->invalid) - { - // Rough heuristic. Mem instructions should cost more. - u64 cost = block->originalSize * (block->runCount / 4); -#ifdef _WIN32 - u64 timecost = block->ticCounter; -#endif - // Todo: tweak. - if (block->runCount >= 1) - stats.push_back(BlockStat(i, cost)); - cost_sum += cost; -#ifdef _WIN32 - timecost_sum += timecost; -#endif - } - } - - sort(stats.begin(), stats.end()); - File::IOFile f(filename, "w"); - if (!f) - { - PanicAlert("failed to open %s", filename); - return; - } - fprintf(f.GetHandle(), "origAddr\tblkName\tcost\trunCount\ttimeCost\tpercent\ttimePercent\tOvAllinBlkTime(ms)\tblkCodeSize\n"); - for (unsigned int i = 0; i < stats.size(); i++) - { - const JitBlock *block = jit->GetBlockCache()->GetBlock(stats[i].blockNum); - if (block && !block->invalid) - { - std::string name = g_symbolDB.GetDescription(block->originalAddress); - double percent = 100.0 * (double)stats[i].cost / (double)cost_sum; -#ifdef _WIN32 - double timePercent = 100.0 * (double)block->ticCounter / (double)timecost_sum; - fprintf(f.GetHandle(), "%08x\t%s\t%llu\t%llu\t%llu\t%.2lf\t%llf\t%lf\t%i\n", - block->originalAddress, name.c_str(), stats[i].cost, block->runCount, - block->ticCounter, percent, timePercent, - (double)block->ticCounter*1000.0/(double)countsPerSec, block->codeSize); -#else - fprintf(f.GetHandle(), "%08x\t%s\t%llu\t???\t%.2lf\t???\t???\t%i\n", - block->originalAddress, name.c_str(), stats[i].cost, percent, block->codeSize); -#endif - } - } + JitInterface::WriteProfileResults(filename); } } // namespace diff --git a/Source/Core/Core/Src/PowerPC/Profiler.h b/Source/Core/Core/Src/PowerPC/Profiler.h index ada130e90f..b8beeaae72 100644 --- a/Source/Core/Core/Src/PowerPC/Profiler.h +++ b/Source/Core/Core/Src/PowerPC/Profiler.h @@ -57,6 +57,15 @@ #define PROFILER_VPOP #endif +struct BlockStat +{ + BlockStat(int bn, u64 c) : blockNum(bn), cost(c) {} + int blockNum; + u64 cost; + + bool operator <(const BlockStat &other) const + { return cost > other.cost; } +}; namespace Profiler { diff --git a/Source/Core/Core/Src/State.cpp b/Source/Core/Core/Src/State.cpp index 084a94e5f6..e0a9ab7858 100644 --- a/Source/Core/Core/Src/State.cpp +++ b/Source/Core/Core/Src/State.cpp @@ -71,7 +71,7 @@ static Common::Event g_compressAndDumpStateSyncEvent; static std::thread g_save_thread; // Don't forget to increase this after doing changes on the savestate system -static const u32 STATE_VERSION = 13; +static const u32 STATE_VERSION = 16; struct StateHeader { diff --git a/Source/Core/Core/Src/MemTools.cpp b/Source/Core/Core/Src/x64MemTools.cpp similarity index 96% rename from Source/Core/Core/Src/MemTools.cpp rename to Source/Core/Core/Src/x64MemTools.cpp index bb6fef6439..fff26b3cb3 100644 --- a/Source/Core/Core/Src/MemTools.cpp +++ b/Source/Core/Core/Src/x64MemTools.cpp @@ -52,8 +52,10 @@ #include "MemTools.h" #include "HW/Memmap.h" #include "PowerPC/PowerPC.h" +#include "PowerPC/JitInterface.h" +#ifndef _M_GENERIC #include "PowerPC/JitCommon/JitBase.h" -#include "PowerPC/JitCommon/JitBackpatch.h" +#endif #include "x64Analyzer.h" namespace EMM @@ -77,7 +79,7 @@ LONG NTAPI Handler(PEXCEPTION_POINTERS pPtrs) PVOID codeAddr = pPtrs->ExceptionRecord->ExceptionAddress; unsigned char *codePtr = (unsigned char*)codeAddr; - if (!jit->IsInCodeSpace(codePtr)) { + if (!JitInterface::IsInCodeSpace(codePtr)) { // Let's not prevent debugging. return (DWORD)EXCEPTION_CONTINUE_SEARCH; } @@ -107,7 +109,7 @@ LONG NTAPI Handler(PEXCEPTION_POINTERS pPtrs) //We could emulate the memory accesses here, but then they would still be around to take up //execution resources. Instead, we backpatch into a generic memory call and retry. - const u8 *new_rip = jit->BackPatch(codePtr, accessType, emAddress, ctx); + const u8 *new_rip = JitInterface::BackPatch(codePtr, accessType, emAddress, ctx); // Rip/Eip needs to be updated. if (new_rip) @@ -182,6 +184,7 @@ void print_trace(const char * msg) void sigsegv_handler(int signal, siginfo_t *info, void *raw_context) { +#ifndef _M_GENERIC if (signal != SIGSEGV) { // We are not interested in other signals - handle it as usual. @@ -203,7 +206,7 @@ void sigsegv_handler(int signal, siginfo_t *info, void *raw_context) #else u8 *fault_instruction_ptr = (u8 *)CREG_EIP(ctx); #endif - if (!jit->IsInCodeSpace(fault_instruction_ptr)) { + if (!JitInterface::IsInCodeSpace(fault_instruction_ptr)) { // Let's not prevent debugging. return; } @@ -240,6 +243,7 @@ void sigsegv_handler(int signal, siginfo_t *info, void *raw_context) CREG_EIP(ctx) = fake_ctx.Eip; #endif } +#endif } void InstallExceptionHandler() diff --git a/Source/Core/DiscIO/DiscIO.vcxproj b/Source/Core/DiscIO/DiscIO.vcxproj index 6dd24ddd44..722aae2040 100644 --- a/Source/Core/DiscIO/DiscIO.vcxproj +++ b/Source/Core/DiscIO/DiscIO.vcxproj @@ -44,7 +44,7 @@ false StaticLibrary - MultiByte + Unicode StaticLibrary @@ -54,7 +54,7 @@ false StaticLibrary - MultiByte + Unicode StaticLibrary diff --git a/Source/Core/DiscIO/Src/BannerLoader.cpp b/Source/Core/DiscIO/Src/BannerLoader.cpp index 6451c73670..d38c7e9ea4 100644 --- a/Source/Core/DiscIO/Src/BannerLoader.cpp +++ b/Source/Core/DiscIO/Src/BannerLoader.cpp @@ -22,180 +22,8 @@ #include "VolumeCreator.h" #include "FileUtil.h" -// HyperIris: dunno if this suitable, may be need move. -#ifdef _WIN32 -#include -#else -#include -#include -#include -#endif - -#ifndef ICONV_CONST -#if defined __FreeBSD__ || __NetBSD__ -#define ICONV_CONST const -#else -#define ICONV_CONST -#endif -#endif - namespace DiscIO { -void IBannerLoader::CopyToStringAndCheck(std::string& _rDestination, const char* _src) -{ - static bool bValidChars[256]; - static bool bInitialized = false; - - if (!bInitialized) - { - for (int i = 0; i < 0x20; i++) - { - bValidChars[i] = false; - } - - // generate valid chars - for (int i = 0x20; i < 256; i++) - { - bValidChars[i] = true; - } - - bValidChars[0x0a] = true; - //bValidChars[0xa9] = true; - //bValidChars[0xe9] = true; - - bInitialized = true; - } - - char destBuffer[2048] = {0}; - char* dest = destBuffer; - const char* src = _src; - - // copy the string and check for "unknown" characters - while (*src != 0x00) - { - u8 c = *src; - - if (c == 0x0a){c = 0x20;} - - if (bValidChars[c] == false) - { - src++; - continue; - } - - *dest = c; - dest++; - src++; - } - - // finalize the string - *dest = 0x00; - - _rDestination = destBuffer; -} - -bool IBannerLoader::CopyBeUnicodeToString( std::string& _rDestination, const u16* _src, int length ) -{ - bool returnCode = false; -#ifdef WIN32 - if (_src) - { - u16* buffer = new u16[length]; - if (buffer) - { - memcpy(buffer, _src, sizeof(u16)*length); - for (int i = 0; i < length; i++) - { - buffer[i] = swap16(buffer[i]); - } - - u32 ansiNameSize = WideCharToMultiByte(932, 0, - (LPCWSTR)buffer, (int)wcslen((LPCWSTR)buffer), - NULL, NULL, NULL, NULL); - if (ansiNameSize > 0) - { - char* pAnsiStrBuffer = new char[ansiNameSize + 1]; - if (pAnsiStrBuffer) - { - memset(pAnsiStrBuffer, 0, (ansiNameSize + 1) * sizeof(char)); - if (WideCharToMultiByte(932, 0, - (LPCWSTR)buffer, (int)wcslen((LPCWSTR)buffer), - pAnsiStrBuffer, ansiNameSize, NULL, NULL)) - { - _rDestination = pAnsiStrBuffer; - returnCode = true; - } - delete[] pAnsiStrBuffer; - } - } - delete[] buffer; - } - } -#else - if (_src) - { - iconv_t conv_desc = iconv_open("UTF-8", "CP932"); - if (conv_desc == (iconv_t) -1) - { - // Initialization failure. - if (errno == EINVAL) - { - ERROR_LOG(DISCIO, "Conversion from CP932 to UTF-8 is not supported."); - } - else - { - ERROR_LOG(DISCIO, "Iconv initialization failure: %s\n", strerror (errno)); - } - return false; - } - - char* src_buffer = new char[length]; - for (int i = 0; i < length; i++) - src_buffer[i] = swap16(_src[i]); - - size_t inbytes = sizeof(char) * length; - size_t outbytes = 2 * inbytes; - char* utf8_buffer = new char[outbytes + 1]; - memset(utf8_buffer, 0, (outbytes + 1) * sizeof(char)); - - // Save the buffer locations because iconv increments them - char* utf8_buffer_start = utf8_buffer; - char* src_buffer_start = src_buffer; - - size_t iconv_size = iconv(conv_desc, - (ICONV_CONST char**)&src_buffer, &inbytes, - &utf8_buffer, &outbytes); - - // Handle failures - if (iconv_size == (size_t) -1) - { - ERROR_LOG(DISCIO, "iconv failed."); - switch (errno) { - case EILSEQ: - ERROR_LOG(DISCIO, "Invalid multibyte sequence."); - break; - case EINVAL: - ERROR_LOG(DISCIO, "Incomplete multibyte sequence."); - break; - case E2BIG: - ERROR_LOG(DISCIO, "Insufficient space allocated for output buffer."); - break; - default: - ERROR_LOG(DISCIO, "Error: %s.", strerror(errno)); - } - } - else - { - _rDestination = utf8_buffer_start; - returnCode = true; - } - delete[] utf8_buffer_start; - delete[] src_buffer_start; - iconv_close(conv_desc); - } -#endif - return returnCode; -} IBannerLoader* CreateBannerLoader(DiscIO::IFileSystem& _rFileSystem, DiscIO::IVolume *pVolume) { @@ -203,9 +31,9 @@ IBannerLoader* CreateBannerLoader(DiscIO::IFileSystem& _rFileSystem, DiscIO::IVo { return new CBannerLoaderWii(pVolume); } - if (_rFileSystem.IsValid()) + if (_rFileSystem.IsValid()) { - return new CBannerLoaderGC(_rFileSystem); + return new CBannerLoaderGC(_rFileSystem, pVolume); } return NULL; diff --git a/Source/Core/DiscIO/Src/BannerLoader.h b/Source/Core/DiscIO/Src/BannerLoader.h index 1fe48dd364..b30ee17a46 100644 --- a/Source/Core/DiscIO/Src/BannerLoader.h +++ b/Source/Core/DiscIO/Src/BannerLoader.h @@ -18,6 +18,9 @@ #ifndef _BANNER_LOADER_H_ #define _BANNER_LOADER_H_ +#include +#include + #include "Filesystem.h" namespace DiscIO @@ -38,24 +41,9 @@ class IBannerLoader virtual bool GetBanner(u32* _pBannerImage) = 0; - virtual bool GetName(std::string* _rName) = 0; - virtual bool GetName(std::vector& _rNames) {return false;}; - virtual bool GetCompany(std::string& _rCompany) = 0; - - virtual bool GetDescription(std::string* _rDescription) = 0; - virtual bool GetDescription(std::wstring& _rDescription) {return false;}; - - - protected: - - void CopyToStringAndCheck(std::string& _rDestination, const char* _src); - - bool CopyBeUnicodeToString(std::string& _rDestination, const u16* _src, int length); - private: - u16 swap16(u16 data) - { - return ((data & 0xff00) >> 8) | ((data & 0xff) << 8); - } + virtual std::vector GetNames() = 0; + virtual std::string GetCompany() = 0; + virtual std::vector GetDescriptions() = 0; }; IBannerLoader* CreateBannerLoader(DiscIO::IFileSystem& _rFileSystem, DiscIO::IVolume *pVolume); diff --git a/Source/Core/DiscIO/Src/BannerLoaderGC.cpp b/Source/Core/DiscIO/Src/BannerLoaderGC.cpp index bf9f634ff8..d8ae259b16 100644 --- a/Source/Core/DiscIO/Src/BannerLoaderGC.cpp +++ b/Source/Core/DiscIO/Src/BannerLoaderGC.cpp @@ -23,13 +23,14 @@ namespace DiscIO { -CBannerLoaderGC::CBannerLoaderGC(DiscIO::IFileSystem& _rFileSystem) - : m_pBannerFile(NULL), - m_IsValid(false) +CBannerLoaderGC::CBannerLoaderGC(DiscIO::IFileSystem& _rFileSystem, DiscIO::IVolume* volume) + : m_pBannerFile(NULL) + , m_IsValid(false) + , m_country(volume->GetCountry()) { // load the opening.bnr size_t FileSize = (size_t) _rFileSystem.GetFileSize("opening.bnr"); - if (FileSize == sizeof(DVDBanner) || FileSize == sizeof(DVDBanner2)) + if (FileSize == BNR1_SIZE || FileSize == BNR2_SIZE) { m_pBannerFile = new u8[FileSize]; if (m_pBannerFile) @@ -62,7 +63,6 @@ bool CBannerLoaderGC::IsValid() return m_IsValid; } - bool CBannerLoaderGC::GetBanner(u32* _pBannerImage) { if (!IsValid()) @@ -70,132 +70,111 @@ bool CBannerLoaderGC::GetBanner(u32* _pBannerImage) return false; } - DVDBanner2* pBanner = (DVDBanner2*)m_pBannerFile; + auto const pBanner = (DVDBanner*)m_pBannerFile; decode5A3image(_pBannerImage, pBanner->image, DVD_BANNER_WIDTH, DVD_BANNER_HEIGHT); return true; } -bool CBannerLoaderGC::GetName(std::string _rName[]) +std::vector CBannerLoaderGC::GetNames() { - bool returnCode = false; + std::vector names; if (!IsValid()) { - return false; + return names; } + u32 name_count = 0; + // find Banner type switch (m_BNRType) { case CBannerLoaderGC::BANNER_BNR1: - { - DVDBanner* pBanner = (DVDBanner*)m_pBannerFile; - char tempBuffer[65] = {0}; - if (pBanner->comment.longTitle[0]) - { - memcpy(tempBuffer, pBanner->comment.longTitle, 64); - } - else - { - memcpy(tempBuffer, pBanner->comment.shortTitle, 32); - } - for (int i = 0; i < 6; i++) - { - CopyToStringAndCheck(_rName[i], tempBuffer); - } - returnCode = true; - } + name_count = 1; break; + case CBannerLoaderGC::BANNER_BNR2: - { - DVDBanner2* pBanner = (DVDBanner2*)m_pBannerFile; - - for (int i = 0; i < 6; i++) - { - char tempBuffer[65] = {0}; - if (pBanner->comment[i].longTitle[0]) - { - memcpy(tempBuffer, pBanner->comment[i].longTitle, 64); - } - else - { - memcpy(tempBuffer, pBanner->comment[i].shortTitle, 32); - } - CopyToStringAndCheck(_rName[i], tempBuffer); - } - - returnCode = true; - - } + name_count = 6; break; + default: break; } + + auto const banner = reinterpret_cast(m_pBannerFile); + + for (u32 i = 0; i != name_count; ++i) + { + auto& comment = banner->comment[i]; + + if (comment.longTitle[0]) + { + auto& data = comment.longTitle; + names.push_back(GetDecodedString(data)); + } + else + { + auto& data = comment.shortTitle; + names.push_back(GetDecodedString(data)); + } + } - return returnCode; + return names; } -bool CBannerLoaderGC::GetCompany(std::string& _rCompany) +std::string CBannerLoaderGC::GetCompany() { - _rCompany = "N/A"; + std::string company; - if (!IsValid()) + if (IsValid()) { - return(false); + auto const pBanner = (DVDBanner*)m_pBannerFile; + auto& data = pBanner->comment[0].shortMaker; + company = GetDecodedString(data); } - DVDBanner2* pBanner = (DVDBanner2*)m_pBannerFile; - - CopyToStringAndCheck(_rCompany, pBanner->comment[0].shortMaker); - - return true; + return company; } -bool CBannerLoaderGC::GetDescription(std::string* _rDescription) +std::vector CBannerLoaderGC::GetDescriptions() { - bool returnCode = false; + std::vector descriptions; if (!IsValid()) { - return false; + return descriptions; } + u32 desc_count = 0; + // find Banner type switch (m_BNRType) { case CBannerLoaderGC::BANNER_BNR1: - { - DVDBanner* pBanner = (DVDBanner*)m_pBannerFile; - char tempBuffer[129] = {0}; - memcpy(tempBuffer, pBanner->comment.comment, 128); - for (int i = 0; i < 6; i++) - { - CopyToStringAndCheck(_rDescription[i], tempBuffer); - } - returnCode = true; - } + desc_count = 1; break; - case CBannerLoaderGC::BANNER_BNR2: - { - DVDBanner2* pBanner = (DVDBanner2*)m_pBannerFile; - for (int i = 0; i< 6; i++) - { - char tempBuffer[129] = {0}; - memcpy(tempBuffer, pBanner->comment[i].comment, 128); - CopyToStringAndCheck(_rDescription[i], tempBuffer); - } - returnCode = true; - } + case CBannerLoaderGC::BANNER_BNR2: + desc_count = 6; break; + default: break; } - return returnCode; + + auto banner = reinterpret_cast(m_pBannerFile); + + for (u32 i = 0; i != desc_count; ++i) + { + auto& data = banner->comment[i].comment; + descriptions.push_back(GetDecodedString(data)); + } + + return descriptions; } @@ -223,13 +202,17 @@ CBannerLoaderGC::BANNER_TYPE CBannerLoaderGC::getBannerType() CBannerLoaderGC::BANNER_TYPE type = CBannerLoaderGC::BANNER_UNKNOWN; switch (bannerSignature) { + // "BNR1" case 0x31524e42: type = CBannerLoaderGC::BANNER_BNR1; break; + + // "BNR2" case 0x32524e42: type = CBannerLoaderGC::BANNER_BNR2; break; } return type; } + } // namespace diff --git a/Source/Core/DiscIO/Src/BannerLoaderGC.h b/Source/Core/DiscIO/Src/BannerLoaderGC.h index 0527c721c1..8b14a45d43 100644 --- a/Source/Core/DiscIO/Src/BannerLoaderGC.h +++ b/Source/Core/DiscIO/Src/BannerLoaderGC.h @@ -19,6 +19,8 @@ #define _BANNER_LOADER_GC_H_ #include "BannerLoader.h" +#include "VolumeGC.h" +#include "StringUtil.h" namespace DiscIO { @@ -26,15 +28,16 @@ class CBannerLoaderGC : public IBannerLoader { public: - CBannerLoaderGC(DiscIO::IFileSystem& _rFileSystem); + CBannerLoaderGC(DiscIO::IFileSystem& _rFileSystem, DiscIO::IVolume* volume); virtual ~CBannerLoaderGC(); virtual bool IsValid(); virtual bool GetBanner(u32* _pBannerImage); - virtual bool GetName(std::string* _rName); - virtual bool GetCompany(std::string& _rCompany); - virtual bool GetDescription(std::string* _rDescription); + + virtual std::vector GetNames(); + virtual std::string GetCompany(); + virtual std::vector GetDescriptions(); private: enum @@ -60,30 +63,35 @@ class CBannerLoaderGC char comment[128]; // Game description shown in IPL game start screen in two lines. }; - // "opening.bnr" file format for JP/US console - struct DVDBanner - { - u32 id; // 'BNR1' - u32 padding[7]; - u16 image[DVD_BANNER_WIDTH * DVD_BANNER_HEIGHT]; // RGB5A3 96x32 texture image - DVDBannerComment comment; - }; - // "opening.bnr" file format for EU console - struct DVDBanner2 + struct DVDBanner { u32 id; // 'BNR2' u32 padding[7]; u16 image[DVD_BANNER_WIDTH * DVD_BANNER_HEIGHT]; // RGB5A3 96x32 texture image - DVDBannerComment comment[6]; // Comments in six languages + DVDBannerComment comment[6]; // Comments in six languages (only 1 for BNR1 type) }; + static const u32 BNR1_SIZE = sizeof(DVDBanner) - sizeof(DVDBannerComment) * 5; + static const u32 BNR2_SIZE = sizeof(DVDBanner); + + template + std::string GetDecodedString(const char (&data)[N]) + { + auto const string_decoder = CVolumeGC::GetStringDecoder(m_country); + + // strnlen to trim NULLs + return string_decoder(std::string(data, strnlen(data, sizeof(data)))); + } + u8* m_pBannerFile; bool m_IsValid; BANNER_TYPE m_BNRType; void decode5A3image(u32* dst, u16* src, int width, int height); BANNER_TYPE getBannerType(); + + DiscIO::IVolume::ECountry const m_country; }; } // namespace diff --git a/Source/Core/DiscIO/Src/BannerLoaderWii.cpp b/Source/Core/DiscIO/Src/BannerLoaderWii.cpp index b23dc4d91a..f606ed8876 100644 --- a/Source/Core/DiscIO/Src/BannerLoaderWii.cpp +++ b/Source/Core/DiscIO/Src/BannerLoaderWii.cpp @@ -16,6 +16,7 @@ // http://code.google.com/p/dolphin-emu/ #include +#include #include "Common.h" #include "ColorUtil.h" @@ -144,73 +145,48 @@ bool CBannerLoaderWii::GetBanner(u32* _pBannerImage) return true; } -bool CBannerLoaderWii::GetStringFromComments(const CommentIndex index, std::string& s) -{ - bool ret = false; - - if (IsValid()) - { - // find Banner type - SWiiBanner *pBanner = (SWiiBanner*)m_pBannerFile; - - // Ensure the string is null-terminating, since the banner format - // doesn't require it - u16 *src = new u16[COMMENT_SIZE + 1]; - memcpy(src, &pBanner->m_Comment[index], COMMENT_SIZE * sizeof(u16)); - src[COMMENT_SIZE] = 0; - - ret = CopyBeUnicodeToString(s, src, COMMENT_SIZE + 1); - - delete [] src; - } - - return ret; -} - -bool CBannerLoaderWii::GetStringFromComments(const CommentIndex index, std::wstring& s) +bool CBannerLoaderWii::GetStringFromComments(const CommentIndex index, std::string& result) { if (IsValid()) { - // find Banner type - SWiiBanner* pBanner = (SWiiBanner*)m_pBannerFile; - - std::wstring description; - for (int i = 0; i < COMMENT_SIZE; ++i) - description.push_back(Common::swap16(pBanner->m_Comment[index][i])); - - s = description; + auto const banner = reinterpret_cast(m_pBannerFile); + auto const src_ptr = banner->m_Comment[index]; + + // Trim at first NULL + auto const length = std::find(src_ptr, src_ptr + COMMENT_SIZE, 0x0) - src_ptr; + + std::wstring src; + src.resize(length); + std::transform(src_ptr, src_ptr + src.size(), src.begin(), (u16(&)(u16))Common::swap16); + result = UTF16ToUTF8(src); + return true; } + return false; } -bool CBannerLoaderWii::GetName(std::string* _rName) +std::vector CBannerLoaderWii::GetNames() { - return GetStringFromComments(NAME_IDX, *_rName); -} + std::vector ret(1); + + if (!GetStringFromComments(NAME_IDX, ret[0])) + ret.clear(); -bool CBannerLoaderWii::GetName(std::vector& _rNames) -{ - std::wstring temp; - bool ret = GetStringFromComments(NAME_IDX, temp); - _rNames.push_back(temp); return ret; } -bool CBannerLoaderWii::GetCompany(std::string& _rCompany) +std::string CBannerLoaderWii::GetCompany() { - _rCompany = "N/A"; - return true; + return ""; } -bool CBannerLoaderWii::GetDescription(std::string* _rDescription) +std::vector CBannerLoaderWii::GetDescriptions() { - return GetStringFromComments(DESC_IDX, *_rDescription); -} - -bool CBannerLoaderWii::GetDescription(std::wstring& _rDescription) -{ - return GetStringFromComments(DESC_IDX, _rDescription); + std::vector result(1); + if (!GetStringFromComments(DESC_IDX, result[0])) + result.clear(); + return result; } void CBannerLoaderWii::decode5A3image(u32* dst, u16* src, int width, int height) diff --git a/Source/Core/DiscIO/Src/BannerLoaderWii.h b/Source/Core/DiscIO/Src/BannerLoaderWii.h index 83733cf5ed..036eeeacbd 100644 --- a/Source/Core/DiscIO/Src/BannerLoaderWii.h +++ b/Source/Core/DiscIO/Src/BannerLoaderWii.h @@ -35,15 +35,9 @@ class CBannerLoaderWii virtual bool GetBanner(u32* _pBannerImage); - virtual bool GetName(std::string* _rName); - - bool GetName(std::vector& _rNames); - - virtual bool GetCompany(std::string& _rCompany); - - virtual bool GetDescription(std::string* _rDescription); - - bool GetDescription(std::wstring& _rDescription); + virtual std::vector GetNames(); + virtual std::string GetCompany(); + virtual std::vector GetDescriptions(); private: @@ -81,7 +75,6 @@ class CBannerLoaderWii void decode5A3image(u32* dst, u16* src, int width, int height); bool GetStringFromComments(const CommentIndex index, std::string& s); - bool GetStringFromComments(const CommentIndex index, std::wstring& s); }; } // namespace diff --git a/Source/Core/DiscIO/Src/CISOBlob.cpp b/Source/Core/DiscIO/Src/CISOBlob.cpp index b3a2e31b2b..8d267c15fb 100644 --- a/Source/Core/DiscIO/Src/CISOBlob.cpp +++ b/Source/Core/DiscIO/Src/CISOBlob.cpp @@ -15,24 +15,30 @@ // Official SVN repository and contact information can be found at // http://code.google.com/p/dolphin-emu/ +#include +#include + #include "Blob.h" #include "CISOBlob.h" namespace DiscIO { +static const char CISO_MAGIC[] = "CISO"; + CISOFileReader::CISOFileReader(std::FILE* file) : m_file(file) { m_size = m_file.GetSize(); - - memset(&header, 0, sizeof(header)); + + CISOHeader header; m_file.ReadArray(&header, 1); + + m_block_size = header.block_size; - CISO_Map_t count = 0; - int idx; - for (idx = 0; idx < CISO_MAP_SIZE; idx++) - ciso_map[idx] = (header.map[idx] == 1) ? count++ : CISO_UNUSED_BLOCK; + MapType count = 0; + for (u32 idx = 0; idx < CISO_MAP_SIZE; idx++) + m_ciso_map[idx] = (1 == header.map[idx]) ? count++ : UNUSED_BLOCK_ID; } CISOFileReader* CISOFileReader::Create(const char* filename) @@ -46,34 +52,45 @@ CISOFileReader* CISOFileReader::Create(const char* filename) return NULL; } +u64 CISOFileReader::GetDataSize() const +{ + return GetRawSize(); +} + +u64 CISOFileReader::GetRawSize() const +{ + return m_size; +} + bool CISOFileReader::Read(u64 offset, u64 nbytes, u8* out_ptr) { - u64 bytesRead = 0; - while (bytesRead < nbytes) + while (nbytes != 0) { - u32 block = (u32)(offset / header.block_size); - u32 data_offset = offset % header.block_size; - u32 bytes_to_read = (u32)min((u64)(header.block_size - data_offset), nbytes); - if ((block >= CISO_MAP_SIZE) || (ciso_map[block] == CISO_UNUSED_BLOCK)) - { - memset(out_ptr, 0, bytes_to_read); - out_ptr += bytes_to_read; - offset += bytes_to_read; - bytesRead += bytes_to_read; - } - else + auto const block = offset / m_block_size; + auto const data_offset = offset % m_block_size; + + auto const bytes_to_read = std::min(m_block_size - data_offset, nbytes); + if (block < CISO_MAP_SIZE && UNUSED_BLOCK_ID != m_ciso_map[block]) { // calcualte the base address - u64 file_off = CISO_HEAD_SIZE + ciso_map[block] * (u64)header.block_size + data_offset; + auto const file_off = CISO_HEADER_SIZE + m_ciso_map[block] * m_block_size + data_offset; - if (!(m_file.Seek(file_off, SEEK_SET) && m_file.ReadBytes(out_ptr, bytes_to_read))) + if (!(m_file.Seek(file_off, SEEK_SET) && m_file.ReadArray(out_ptr, bytes_to_read))) return false; out_ptr += bytes_to_read; offset += bytes_to_read; - bytesRead += bytes_to_read; + nbytes -= bytes_to_read; + } + else + { + std::fill_n(out_ptr, bytes_to_read, 0); + out_ptr += bytes_to_read; + offset += bytes_to_read; + nbytes -= bytes_to_read; } } + return true; } @@ -81,8 +98,9 @@ bool IsCISOBlob(const char* filename) { File::IOFile f(filename, "rb"); - CISO_Head_t header; - return (f.ReadArray(&header, 1) && (memcmp(header.magic, CISO_MAGIC, sizeof(header.magic)) == 0)); + CISOHeader header; + return (f.ReadArray(&header, 1) && + std::equal(header.magic, header.magic + sizeof(header.magic), CISO_MAGIC)); } } // namespace diff --git a/Source/Core/DiscIO/Src/CISOBlob.h b/Source/Core/DiscIO/Src/CISOBlob.h index e87e616a21..9b490f0638 100644 --- a/Source/Core/DiscIO/Src/CISOBlob.h +++ b/Source/Core/DiscIO/Src/CISOBlob.h @@ -21,43 +21,45 @@ #include "Blob.h" #include "FileUtil.h" -#define CISO_MAGIC "CISO" -#define CISO_HEAD_SIZE (0x8000) -#define CISO_MAP_SIZE (CISO_HEAD_SIZE - 8) - namespace DiscIO { bool IsCISOBlob(const char* filename); -// Blocks that won't compress to less than 97% of the original size are stored as-is. -struct CISO_Head_t +static const u32 CISO_HEADER_SIZE = 0x8000; +static const u32 CISO_MAP_SIZE = CISO_HEADER_SIZE - sizeof(u32) - sizeof(char) * 4; + +struct CISOHeader { - u8 magic[4]; // "CISO" - u32 block_size; // stored as litte endian (not network byte order) - u8 map[CISO_MAP_SIZE]; // 0=unused, 1=used, others=invalid + // "CISO" + char magic[4]; + + // little endian + u32 block_size; + + // 0=unused, 1=used, others=invalid + u8 map[CISO_MAP_SIZE]; }; -typedef u16 CISO_Map_t; - -const CISO_Map_t CISO_UNUSED_BLOCK = (CISO_Map_t)~0; - class CISOFileReader : public IBlobReader { - File::IOFile m_file; - CISOFileReader(std::FILE* file); - s64 m_size; - public: static CISOFileReader* Create(const char* filename); - u64 GetDataSize() const { return m_size; } - u64 GetRawSize() const { return m_size; } + u64 GetDataSize() const; + u64 GetRawSize() const; bool Read(u64 offset, u64 nbytes, u8* out_ptr); private: - CISO_Head_t header; - CISO_Map_t ciso_map[CISO_MAP_SIZE]; + CISOFileReader(std::FILE* file); + + typedef u16 MapType; + static const MapType UNUSED_BLOCK_ID = -1; + + File::IOFile m_file; + u64 m_size; + u32 m_block_size; + MapType m_ciso_map[CISO_MAP_SIZE]; }; } // namespace diff --git a/Source/Core/DiscIO/Src/DriveBlob.cpp b/Source/Core/DiscIO/Src/DriveBlob.cpp index e69f8ff34c..2638f3fac4 100644 --- a/Source/Core/DiscIO/Src/DriveBlob.cpp +++ b/Source/Core/DiscIO/Src/DriveBlob.cpp @@ -16,6 +16,7 @@ // http://code.google.com/p/dolphin-emu/ #include "DriveBlob.h" +#include "StringUtil.h" namespace DiscIO { @@ -23,12 +24,9 @@ namespace DiscIO DriveReader::DriveReader(const char *drive) { #ifdef _WIN32 - char path[MAX_PATH]; - strncpy(path, drive, 3); - path[2] = 0; - sprintf(path, "\\\\.\\%s", drive); SectorReader::SetSectorSize(2048); - hDisc = CreateFile(path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, + auto const path = UTF8ToTStr(std::string("\\\\.\\") + drive); + hDisc = CreateFile(path.c_str(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, NULL); if (hDisc != INVALID_HANDLE_VALUE) { diff --git a/Source/Core/DiscIO/Src/FileSystemGCWii.cpp b/Source/Core/DiscIO/Src/FileSystemGCWii.cpp index 47651e2f23..93b569e043 100644 --- a/Source/Core/DiscIO/Src/FileSystemGCWii.cpp +++ b/Source/Core/DiscIO/Src/FileSystemGCWii.cpp @@ -20,6 +20,7 @@ #include #include +#include #include "FileSystemGCWii.h" #include "StringUtil.h" @@ -27,10 +28,10 @@ namespace DiscIO { CFileSystemGCWii::CFileSystemGCWii(const IVolume *_rVolume) - : IFileSystem(_rVolume), - m_Initialized(false), - m_Valid(false), - m_OffsetShift(0) + : IFileSystem(_rVolume) + , m_Initialized(false) + , m_Valid(false) + , m_OffsetShift(0) { m_Valid = DetectFileSystem(); } @@ -213,9 +214,16 @@ u32 CFileSystemGCWii::Read32(u64 _Offset) const return Common::swap32(Temp); } -void CFileSystemGCWii::GetStringFromOffset(u64 _Offset, char* Filename) const +std::string CFileSystemGCWii::GetStringFromOffset(u64 _Offset) const { - m_rVolume->Read(_Offset, 255, (u8*)Filename); + std::string data; + data.resize(255); + m_rVolume->Read(_Offset, data.size(), (u8*)&data[0]); + data.erase(std::find(data.begin(), data.end(), 0x00), data.end()); + + // TODO: Should we really always use SHIFT-JIS? + // It makes some filenames in Pikmin (NTSC-U) sane, but is it correct? + return SHIFTJISToUTF8(data); } size_t CFileSystemGCWii::GetFileList(std::vector &_rFilenames) @@ -311,18 +319,16 @@ size_t CFileSystemGCWii::BuildFilenames(const size_t _FirstIndex, const size_t _ { SFileInfo *rFileInfo = &m_FileInfoVector[CurrentIndex]; u64 uOffset = _NameTableOffset + (rFileInfo->m_NameOffset & 0xFFFFFF); - char filename[512]; - memset(filename, 0, sizeof(filename)); - GetStringFromOffset(uOffset, filename); + std::string filename = GetStringFromOffset(uOffset); // check next index if (rFileInfo->IsDirectory()) { // this is a directory, build up the new szDirectory if (_szDirectory != NULL) - CharArrayFromFormat(rFileInfo->m_FullPath, "%s%s/", _szDirectory, filename); + CharArrayFromFormat(rFileInfo->m_FullPath, "%s%s/", _szDirectory, filename.c_str()); else - CharArrayFromFormat(rFileInfo->m_FullPath, "%s/", filename); + CharArrayFromFormat(rFileInfo->m_FullPath, "%s/", filename.c_str()); CurrentIndex = BuildFilenames(CurrentIndex + 1, (size_t) rFileInfo->m_FileSize, rFileInfo->m_FullPath, _NameTableOffset); } @@ -330,9 +336,9 @@ size_t CFileSystemGCWii::BuildFilenames(const size_t _FirstIndex, const size_t _ { // this is a filename if (_szDirectory != NULL) - CharArrayFromFormat(rFileInfo->m_FullPath, "%s%s", _szDirectory, filename); + CharArrayFromFormat(rFileInfo->m_FullPath, "%s%s", _szDirectory, filename.c_str()); else - CharArrayFromFormat(rFileInfo->m_FullPath, "%s", filename); + CharArrayFromFormat(rFileInfo->m_FullPath, "%s", filename.c_str()); CurrentIndex++; } diff --git a/Source/Core/DiscIO/Src/FileSystemGCWii.h b/Source/Core/DiscIO/Src/FileSystemGCWii.h index 0e7d836d75..9054ade272 100644 --- a/Source/Core/DiscIO/Src/FileSystemGCWii.h +++ b/Source/Core/DiscIO/Src/FileSystemGCWii.h @@ -28,7 +28,7 @@ namespace DiscIO class CFileSystemGCWii : public IFileSystem { public: - CFileSystemGCWii(const IVolume *_rVolume); + CFileSystemGCWii(const IVolume* _rVolume); virtual ~CFileSystemGCWii(); virtual bool IsValid() const { return m_Valid; } virtual u64 GetFileSize(const char* _rFullPath); @@ -44,11 +44,11 @@ public: private: bool m_Initialized; bool m_Valid; - u32 m_OffsetShift; // WII offsets are all shifted + std::vector m_FileInfoVector; u32 Read32(u64 _Offset) const; - void GetStringFromOffset(u64 _Offset, char* Filename) const; + std::string GetStringFromOffset(u64 _Offset) const; const SFileInfo* FindFileInfo(const char* _rFullPath); bool DetectFileSystem(); void InitFileSystem(); diff --git a/Source/Core/DiscIO/Src/Volume.h b/Source/Core/DiscIO/Src/Volume.h index 557c71c31f..c19aaf93a8 100644 --- a/Source/Core/DiscIO/Src/Volume.h +++ b/Source/Core/DiscIO/Src/Volume.h @@ -22,6 +22,7 @@ #include #include "Common.h" +#include "StringUtil.h" namespace DiscIO { @@ -37,8 +38,9 @@ public: virtual void GetTMD(u8*, u32 *_sz) const { *_sz=0; } virtual std::string GetUniqueID() const = 0; virtual std::string GetMakerID() const = 0; - virtual std::string GetName() const = 0; - virtual bool GetWName(std::vector& _rwNames) const { return false; } + // TODO: eliminate? + virtual std::string GetName() const; + virtual std::vector GetNames() const = 0; virtual u32 GetFSTSize() const = 0; virtual std::string GetApploaderDate() const = 0; virtual bool SupportsIntegrityCheck() const { return false; } diff --git a/Source/Core/DiscIO/Src/VolumeCommon.cpp b/Source/Core/DiscIO/Src/VolumeCommon.cpp index 415af2725a..4ab433680d 100644 --- a/Source/Core/DiscIO/Src/VolumeCommon.cpp +++ b/Source/Core/DiscIO/Src/VolumeCommon.cpp @@ -111,5 +111,13 @@ u8 GetSysMenuRegion(u16 _TitleVersion) } } -}; +std::string IVolume::GetName() const +{ + auto names = GetNames(); + if (names.empty()) + return ""; + else + return names[0]; +} +} diff --git a/Source/Core/DiscIO/Src/VolumeDirectory.cpp b/Source/Core/DiscIO/Src/VolumeDirectory.cpp index dc76e2e641..be7cdeb565 100644 --- a/Source/Core/DiscIO/Src/VolumeDirectory.cpp +++ b/Source/Core/DiscIO/Src/VolumeDirectory.cpp @@ -207,11 +207,10 @@ std::string CVolumeDirectory::GetMakerID() const return "VOID"; } -std::string CVolumeDirectory::GetName() const +std::vector CVolumeDirectory::GetNames() const { _dbg_assert_(DVDINTERFACE, m_diskHeader); - std::string name = (char*)(m_diskHeader + 0x20); - return name; + return std::vector(1, (char*)(m_diskHeader + 0x20)); } void CVolumeDirectory::SetName(std::string _Name) diff --git a/Source/Core/DiscIO/Src/VolumeDirectory.h b/Source/Core/DiscIO/Src/VolumeDirectory.h index 0547be3b8a..880a6eebc1 100644 --- a/Source/Core/DiscIO/Src/VolumeDirectory.h +++ b/Source/Core/DiscIO/Src/VolumeDirectory.h @@ -50,7 +50,7 @@ public: std::string GetMakerID() const; - std::string GetName() const; + std::vector GetNames() const; void SetName(std::string); u32 GetFSTSize() const; diff --git a/Source/Core/DiscIO/Src/VolumeGC.cpp b/Source/Core/DiscIO/Src/VolumeGC.cpp index 09e2c5eaa9..6210172790 100644 --- a/Source/Core/DiscIO/Src/VolumeGC.cpp +++ b/Source/Core/DiscIO/Src/VolumeGC.cpp @@ -91,16 +91,17 @@ std::string CVolumeGC::GetMakerID() const return makerID; } -std::string CVolumeGC::GetName() const +std::vector CVolumeGC::GetNames() const { - if (m_pReader == NULL) - return ""; + std::vector names; + + auto const string_decoder = GetStringDecoder(GetCountry()); - char name[128]; - if (!Read(0x20, 0x60, (u8*)&name)) - return ""; + char name[0x60 + 1] = {}; + if (m_pReader != NULL && Read(0x20, 0x60, (u8*)name)) + names.push_back(string_decoder(name)); - return name; + return names; } u32 CVolumeGC::GetFSTSize() const @@ -144,4 +145,10 @@ bool CVolumeGC::IsDiscTwo() const return discTwo; } +auto CVolumeGC::GetStringDecoder(ECountry country) -> StringDecoder +{ + return (COUNTRY_JAPAN == country || COUNTRY_TAIWAN == country) ? + SHIFTJISToUTF8 : CP1252ToUTF8; +} + } // namespace diff --git a/Source/Core/DiscIO/Src/VolumeGC.h b/Source/Core/DiscIO/Src/VolumeGC.h index 4221df9493..d7729ee04c 100644 --- a/Source/Core/DiscIO/Src/VolumeGC.h +++ b/Source/Core/DiscIO/Src/VolumeGC.h @@ -34,12 +34,16 @@ public: bool RAWRead(u64 _Offset, u64 _Length, u8* _pBuffer) const; std::string GetUniqueID() const; std::string GetMakerID() const; - std::string GetName() const; + std::vector GetNames() const; u32 GetFSTSize() const; std::string GetApploaderDate() const; ECountry GetCountry() const; u64 GetSize() const; bool IsDiscTwo() const; + + typedef std::string(*StringDecoder)(const std::string&); + + static StringDecoder GetStringDecoder(ECountry country); private: IBlobReader* m_pReader; diff --git a/Source/Core/DiscIO/Src/VolumeWad.cpp b/Source/Core/DiscIO/Src/VolumeWad.cpp index 2f9f0ef961..a10e5bdb42 100644 --- a/Source/Core/DiscIO/Src/VolumeWad.cpp +++ b/Source/Core/DiscIO/Src/VolumeWad.cpp @@ -15,6 +15,7 @@ // Official SVN repository and contact information can be found at // http://code.google.com/p/dolphin-emu/ +#include #include #include "VolumeWad.h" @@ -107,78 +108,42 @@ bool CVolumeWAD::GetTitleID(u8* _pBuffer) const return true; } -bool CVolumeWAD::GetWName(std::vector& _rwNames) const +std::vector CVolumeWAD::GetNames() const { - u32 footer_size; + std::vector names; + u32 footer_size; if (!Read(0x1C, 4, (u8*)&footer_size)) { - return false; + return names; } + + footer_size = Common::swap32(footer_size); + //Japanese, English, German, French, Spanish, Italian, Dutch, unknown, unknown, Korean - - // Offset to the english title - for (int i = 0; i < 10; i++) + for (int i = 0; i != 10; ++i) { - u16 temp[42]; - std::wstring out_temp; + static const u32 string_length = 42; + static const u32 bytes_length = string_length * sizeof(u16); + + u16 temp[string_length]; - if (!Read(0x9C + (i*84) + OpeningBnrOffset, 84, (u8*)&temp) || Common::swap32(footer_size) < 0xF1 - || !temp[0]) + if (footer_size < 0xF1 || !Read(0x9C + (i * bytes_length) + OpeningBnrOffset, bytes_length, (u8*)&temp)) { - _rwNames.push_back(L""); - continue; - } - for (int j = 0; j < 42; ++j) - { - u16 t = Common::swap16(temp[j]); - if (t == 0 && j > 0) - { - if (out_temp.at(out_temp.size()-1) != ' ') - out_temp.push_back(' '); - } - else - out_temp.push_back(t); - } - - _rwNames.push_back(out_temp); - } - return true; -} - -std::string CVolumeWAD::GetName() const -{ - u32 footer_size; - - if (!Read(0x1C, 4, (u8*)&footer_size)) - return ""; - - - //Japanese, English, German, French, Spanish, Italian, Dutch, unknown, unknown, Korean - - // Offset to the english title - char temp[84]; - if (!Read(0xF1 + OpeningBnrOffset, 84, (u8*)&temp) || Common::swap32(footer_size) < 0xF1 || - !Common::swap16(temp[0])) - return ""; - - // Remove the null bytes due to 16bit char length - std::string out_temp; - for (unsigned int i = 0; i < sizeof(temp); i+=2) - { - // Replace null chars with a single space per null section - if (temp[i] == '\0' && i > 0) - { - if (out_temp.at(out_temp.size()-1) != ' ') - out_temp.push_back(' '); + names.push_back(""); } else - out_temp.push_back(temp[i]); + { + std::wstring out_temp; + out_temp.resize(string_length); + std::transform(temp, temp + out_temp.size(), out_temp.begin(), (u16(&)(u16))Common::swap16); + out_temp.erase(std::find(out_temp.begin(), out_temp.end(), 0x00), out_temp.end()); + + names.push_back(UTF16ToUTF8(out_temp)); + } } - // Make it a null terminated string - out_temp.replace(out_temp.end()-1, out_temp.end(), 1, '\0'); - return out_temp; + return names; } u64 CVolumeWAD::GetSize() const diff --git a/Source/Core/DiscIO/Src/VolumeWad.h b/Source/Core/DiscIO/Src/VolumeWad.h index 956844acd1..afc16766a2 100644 --- a/Source/Core/DiscIO/Src/VolumeWad.h +++ b/Source/Core/DiscIO/Src/VolumeWad.h @@ -38,8 +38,7 @@ public: bool GetTitleID(u8* _pBuffer) const; std::string GetUniqueID() const; std::string GetMakerID() const; - std::string GetName() const; - bool GetWName(std::vector& _rwNames) const; + std::vector GetNames() const; u32 GetFSTSize() const { return 0; } std::string GetApploaderDate() const { return "0"; } ECountry GetCountry() const; diff --git a/Source/Core/DiscIO/Src/VolumeWiiCrypted.cpp b/Source/Core/DiscIO/Src/VolumeWiiCrypted.cpp index ca010b5ae4..32aa92bd08 100644 --- a/Source/Core/DiscIO/Src/VolumeWiiCrypted.cpp +++ b/Source/Core/DiscIO/Src/VolumeWiiCrypted.cpp @@ -16,6 +16,7 @@ // http://code.google.com/p/dolphin-emu/ #include "VolumeWiiCrypted.h" +#include "VolumeGC.h" #include "StringUtil.h" #include "Crypto/sha1.h" @@ -168,21 +169,17 @@ std::string CVolumeWiiCrypted::GetMakerID() const return makerID; } -std::string CVolumeWiiCrypted::GetName() const +std::vector CVolumeWiiCrypted::GetNames() const { - if (m_pReader == NULL) - { - return std::string(); - } + std::vector names; + + auto const string_decoder = CVolumeGC::GetStringDecoder(GetCountry()); - char name[0xFF]; + char name[0xFF] = {}; + if (m_pReader != NULL && Read(0x20, 0x60, (u8*)&name)) + names.push_back(string_decoder(name)); - if (!Read(0x20, 0x60, (u8*)&name)) - { - return std::string(); - } - - return name; + return names; } u32 CVolumeWiiCrypted::GetFSTSize() const diff --git a/Source/Core/DiscIO/Src/VolumeWiiCrypted.h b/Source/Core/DiscIO/Src/VolumeWiiCrypted.h index 5010e46bbd..56c2a8a363 100644 --- a/Source/Core/DiscIO/Src/VolumeWiiCrypted.h +++ b/Source/Core/DiscIO/Src/VolumeWiiCrypted.h @@ -37,7 +37,7 @@ public: void GetTMD(u8* _pBuffer, u32* _sz) const; std::string GetUniqueID() const; std::string GetMakerID() const; - std::string GetName() const; + std::vector GetNames() const; u32 GetFSTSize() const; std::string GetApploaderDate() const; ECountry GetCountry() const; diff --git a/Source/Core/DiscIO/Src/WiiWad.cpp b/Source/Core/DiscIO/Src/WiiWad.cpp index 24e091f9f4..fa44108586 100644 --- a/Source/Core/DiscIO/Src/WiiWad.cpp +++ b/Source/Core/DiscIO/Src/WiiWad.cpp @@ -49,7 +49,8 @@ WiiWAD::WiiWAD(const std::string& _rName) if (pReader == NULL || File::IsDirectory(_rName)) { m_Valid = false; - return; + if(pReader) delete pReader; + return; } m_Valid = ParseWAD(*pReader); diff --git a/Source/Core/DolphinWX/CMakeLists.txt b/Source/Core/DolphinWX/CMakeLists.txt index bac11a95f3..5f848e45a0 100644 --- a/Source/Core/DolphinWX/CMakeLists.txt +++ b/Source/Core/DolphinWX/CMakeLists.txt @@ -10,21 +10,21 @@ set(LIBS core ${GTK2_LIBRARIES} ${XRANDR_LIBRARIES} ${X11_LIBRARIES}) - -if(SDL2_FOUND) - # Using shared SDL2 - set(LIBS ${LIBS} ${SDL2_LIBRARY}) -else(SDL2_FOUND) - if(SDL_FOUND) - # Using shared SDL - set(LIBS ${LIBS} ${SDL_LIBRARY}) - else(SDL_FOUND) - # Using static SDL from Externals - set(LIBS ${LIBS} SDL) +if(NOT ANDROID) + if(SDL2_FOUND) + # Using shared SDL2 + set(LIBS ${LIBS} ${SDL2_LIBRARY}) + else(SDL2_FOUND) + if(SDL_FOUND) + # Using shared SDL + set(LIBS ${LIBS} ${SDL_LIBRARY}) + else(SDL_FOUND) + # Using static SDL from Externals + set(LIBS ${LIBS} SDL) + endif() endif() endif() - if(LIBAV_FOUND) set(LIBS ${LIBS} ${LIBAV_LIBRARIES}) endif() @@ -79,13 +79,18 @@ if(wxWidgets_FOUND) set(WXLIBS ${wxWidgets_LIBRARIES}) else() - set(SRCS - Src/MainNoGUI.cpp) + if(ANDROID) + set(SRCS Src/MainAndroid.cpp) + else() + set(SRCS Src/MainNoGUI.cpp) + endif() endif() if(USE_EGL) - set(SRCS ${SRCS} Src/GLInterface/EGL.cpp - Src/GLInterface/X11_Util.cpp) + if(NOT ANDROID) + set(SRCS ${SRCS} Src/GLInterface/EGL_X11.cpp + Src/GLInterface/X11_Util.cpp) + endif() else() if(WIN32) set(SRCS ${SRCS} Src/GLInterface/GLW.cpp) @@ -123,7 +128,9 @@ elseif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") set_source_files_properties(${RESOURCES} PROPERTIES MACOSX_PACKAGE_LOCATION Resources) else() - set(SRCS ${SRCS} Src/X11Utils.cpp) + if(NOT ANDROID) + set(SRCS ${SRCS} Src/X11Utils.cpp) + endif() endif() if(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD" OR @@ -142,67 +149,85 @@ else() set(DOLPHIN_EXE ${DOLPHIN_EXE_BASE}-nogui) endif() -add_executable(${DOLPHIN_EXE} ${SRCS}) -target_link_libraries(${DOLPHIN_EXE} ${LIBS} ${WXLIBS}) - -if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") - include(BundleUtilities) - set(BUNDLE_PATH ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${DOLPHIN_EXE}.app) - - # Ask for an application bundle. - set_target_properties(${DOLPHIN_EXE} PROPERTIES - MACOSX_BUNDLE true - MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist.in - ) - - # Fix up the bundle after it is finished. - # There does not seem to be an easy way to run CMake commands post-build, - # so we invoke CMake again on a generated script. - file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/postprocess_bundle.cmake " - include(BundleUtilities) - message(\"Fixing up application bundle: ${BUNDLE_PATH}\") - set(BU_CHMOD_BUNDLE_ITEMS ON) - fixup_bundle(\"${BUNDLE_PATH}\" \"\" \"\") - ") - add_custom_command(TARGET ${DOLPHIN_EXE} POST_BUILD - COMMAND ${CMAKE_COMMAND} -P postprocess_bundle.cmake - ) - - # Copy data files into application bundle. - file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/copy_data_into_bundle.cmake " - file(INSTALL ${CMAKE_SOURCE_DIR}/Data/Sys ${CMAKE_SOURCE_DIR}/Data/User - DESTINATION ${BUNDLE_PATH}/Contents/Resources - ) - file(GLOB TRANSLATION_FILES RELATIVE ${CMAKE_BINARY_DIR} - ${CMAKE_BINARY_DIR}/*.gmo - ) - foreach(TRANSLATION_FILE \${TRANSLATION_FILES}) - string(REPLACE \".gmo\" \".lproj\" TRANSLATION_DIR - \${TRANSLATION_FILE} - ) - # It would be better to copy to the new name as a single action, - # but I can't figure out a way to let CMake do that. - file(COPY ${CMAKE_BINARY_DIR}/\${TRANSLATION_FILE} - DESTINATION ${BUNDLE_PATH}/Contents/Resources/\${TRANSLATION_DIR} - NO_SOURCE_PERMISSIONS - ) - file(RENAME - ${BUNDLE_PATH}/Contents/Resources/\${TRANSLATION_DIR}/\${TRANSLATION_FILE} - ${BUNDLE_PATH}/Contents/Resources/\${TRANSLATION_DIR}/dolphin-emu.mo - ) - endforeach(TRANSLATION_FILE) - ") - add_custom_target(CopyDataIntoBundle ALL - COMMAND ${CMAKE_COMMAND} -P copy_data_into_bundle.cmake - VERBATIM - ) - - # Install bundle into systemwide /Applications directory. - install(DIRECTORY ${BUNDLE_PATH} DESTINATION /Applications - USE_SOURCE_PERMISSIONS - ) +if(ANDROID) + add_library(${DOLPHIN_EXE} SHARED ${SRCS}) + target_link_libraries(${DOLPHIN_EXE} + log + android + "-Wl,--whole-archive" + ${LIBS} + "-Wl,--no-whole-archive" + ) else() - install(TARGETS ${DOLPHIN_EXE} RUNTIME DESTINATION ${bindir}) + add_executable(${DOLPHIN_EXE} ${SRCS}) + target_link_libraries(${DOLPHIN_EXE} ${LIBS} ${WXLIBS}) + if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + include(BundleUtilities) + set(BUNDLE_PATH ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${DOLPHIN_EXE}.app) + + # Ask for an application bundle. + set_target_properties(${DOLPHIN_EXE} PROPERTIES + MACOSX_BUNDLE true + MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist.in + ) + + # Install Cg framework into application bundle. + copy_resolved_framework_into_bundle( + # Our framework in "Externals" does not have "Versions/Current/" in + # its path; work around the missing directory levels using "././". + "${CMAKE_SOURCE_DIR}/Externals/Cg/Cg.framework/././Cg" + "${BUNDLE_PATH}/Contents/Frameworks/Cg.framework/././Cg" + ) + + # Fix up the bundle after it is finished. + # There does not seem to be an easy way to run CMake commands post-build, + # so we invoke CMake again on a generated script. + file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/postprocess_bundle.cmake " + include(BundleUtilities) + message(\"Fixing up application bundle: ${BUNDLE_PATH}\") + set(BU_CHMOD_BUNDLE_ITEMS ON) + fixup_bundle(\"${BUNDLE_PATH}\" \"\" \"\") + ") + add_custom_command(TARGET ${DOLPHIN_EXE} POST_BUILD + COMMAND ${CMAKE_COMMAND} -P postprocess_bundle.cmake + ) + + # Copy data files into application bundle. + file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/copy_data_into_bundle.cmake " + file(INSTALL ${CMAKE_SOURCE_DIR}/Data/Sys ${CMAKE_SOURCE_DIR}/Data/User + DESTINATION ${BUNDLE_PATH}/Contents/Resources + ) + file(GLOB TRANSLATION_FILES RELATIVE ${CMAKE_BINARY_DIR} + ${CMAKE_BINARY_DIR}/*.gmo + ) + foreach(TRANSLATION_FILE \${TRANSLATION_FILES}) + string(REPLACE \".gmo\" \".lproj\" TRANSLATION_DIR + \${TRANSLATION_FILE} + ) + # It would be better to copy to the new name as a single action, + # but I can't figure out a way to let CMake do that. + file(COPY ${CMAKE_BINARY_DIR}/\${TRANSLATION_FILE} + DESTINATION ${BUNDLE_PATH}/Contents/Resources/\${TRANSLATION_DIR} + NO_SOURCE_PERMISSIONS + ) + file(RENAME + ${BUNDLE_PATH}/Contents/Resources/\${TRANSLATION_DIR}/\${TRANSLATION_FILE} + ${BUNDLE_PATH}/Contents/Resources/\${TRANSLATION_DIR}/dolphin-emu.mo + ) + endforeach(TRANSLATION_FILE) + ") + add_custom_target(CopyDataIntoBundle ALL + COMMAND ${CMAKE_COMMAND} -P copy_data_into_bundle.cmake + VERBATIM + ) + + # Install bundle into systemwide /Applications directory. + install(DIRECTORY ${BUNDLE_PATH} DESTINATION /Applications + USE_SOURCE_PERMISSIONS + ) + else() + install(TARGETS ${DOLPHIN_EXE} RUNTIME DESTINATION ${bindir}) + endif() endif() set(CPACK_PACKAGE_EXECUTABLES ${CPACK_PACKAGE_EXECUTABLES} ${DOLPHIN_EXE}) diff --git a/Source/Core/DolphinWX/Src/ARCodeAddEdit.cpp b/Source/Core/DolphinWX/Src/ARCodeAddEdit.cpp index c3ed12bbea..e08753f40f 100644 --- a/Source/Core/DolphinWX/Src/ARCodeAddEdit.cpp +++ b/Source/Core/DolphinWX/Src/ARCodeAddEdit.cpp @@ -17,6 +17,7 @@ #include "ARCodeAddEdit.h" #include "ARDecrypt.h" +#include "WxUtils.h" extern std::vector arCodes; @@ -38,7 +39,7 @@ CARCodeAddEdit::CARCodeAddEdit(int _selection, wxWindow* parent, wxWindowID id, } else { - currentName = wxString(arCodes.at(selection).name.c_str(), *wxConvCurrent); + currentName = StrToWxStr(arCodes.at(selection).name); tempEntries = arCodes.at(selection); } @@ -73,7 +74,7 @@ CARCodeAddEdit::CARCodeAddEdit(int _selection, wxWindow* parent, wxWindowID id, void CARCodeAddEdit::ChangeEntry(wxSpinEvent& event) { ActionReplay::ARCode currentCode = arCodes.at((int)arCodes.size() - event.GetPosition()); - EditCheatName->SetValue(wxString(currentCode.name.c_str(), *wxConvCurrent)); + EditCheatName->SetValue(StrToWxStr(currentCode.name)); UpdateTextCtrl(currentCode); } @@ -84,7 +85,7 @@ void CARCodeAddEdit::SaveCheatData(wxCommandEvent& WXUNUSED (event)) // Split the entered cheat into lines. std::vector userInputLines; - SplitString(std::string(EditCheatCode->GetValue().mb_str()), '\n', userInputLines); + SplitString(WxStrToStr(EditCheatCode->GetValue()), '\n', userInputLines); for (size_t i = 0; i < userInputLines.size(); i++) { @@ -148,7 +149,7 @@ void CARCodeAddEdit::SaveCheatData(wxCommandEvent& WXUNUSED (event)) // Add a new AR cheat code. ActionReplay::ARCode newCheat; - newCheat.name = std::string(EditCheatName->GetValue().mb_str()); + newCheat.name = WxStrToStr(EditCheatName->GetValue()); newCheat.ops = decryptedLines; newCheat.active = true; @@ -157,7 +158,7 @@ void CARCodeAddEdit::SaveCheatData(wxCommandEvent& WXUNUSED (event)) else { // Update the currently-selected AR cheat code. - arCodes.at(selection).name = std::string(EditCheatName->GetValue().mb_str()); + arCodes.at(selection).name = WxStrToStr(EditCheatName->GetValue()); arCodes.at(selection).ops = decryptedLines; } diff --git a/Source/Core/DolphinWX/Src/AboutDolphin.cpp b/Source/Core/DolphinWX/Src/AboutDolphin.cpp index 5e1825b6ae..5126274601 100644 --- a/Source/Core/DolphinWX/Src/AboutDolphin.cpp +++ b/Source/Core/DolphinWX/Src/AboutDolphin.cpp @@ -17,6 +17,7 @@ #include "Common.h" #include "AboutDolphin.h" +#include "WxUtils.h" #include "../resources/dolphin_logo.cpp" #include "scmrev.h" @@ -62,7 +63,7 @@ AboutDolphin::AboutDolphin(wxWindow *parent, wxWindowID id, "and should not be used to play games you do\n" "not legally own."; wxStaticText* const Message = new wxStaticText(this, wxID_ANY, - wxString::FromAscii(Text.c_str())); + StrToWxStr(Text)); Message->Wrap(GetSize().GetWidth()); wxBoxSizer* const sInfo = new wxBoxSizer(wxVERTICAL); diff --git a/Source/Core/DolphinWX/Src/CheatsWindow.cpp b/Source/Core/DolphinWX/Src/CheatsWindow.cpp index 63ddced86b..fb3c3cbb23 100644 --- a/Source/Core/DolphinWX/Src/CheatsWindow.cpp +++ b/Source/Core/DolphinWX/Src/CheatsWindow.cpp @@ -24,6 +24,7 @@ #include "ISOProperties.h" #include "HW/Memmap.h" #include "Frame.h" +#include "WxUtils.h" #define MAX_CHEAT_SEARCH_RESULTS_DISPLAY 256 @@ -273,7 +274,7 @@ void wxCheatsWindow::Load_ARCodes() { ARCode code = GetARCode(i); ARCodeIndex ind; - u32 index = m_CheckListBox_CheatsList->Append(wxString(code.name.c_str(), *wxConvCurrent)); + u32 index = m_CheckListBox_CheatsList->Append(StrToWxStr(code.name)); m_CheckListBox_CheatsList->Check(index, code.active); ind.index = i; ind.uiIndex = index; @@ -291,18 +292,18 @@ void wxCheatsWindow::OnEvent_CheatsList_ItemSelected(wxCommandEvent& WXUNUSED (e if ((int)indexList[i].uiIndex == index) { ARCode code = GetARCode(i); - m_Label_Codename->SetLabel(_("Name: ") + wxString(code.name.c_str(), *wxConvCurrent)); + m_Label_Codename->SetLabel(_("Name: ") + StrToWxStr(code.name)); char text[CHAR_MAX]; char* numcodes = text; sprintf(numcodes, "Number of Codes: %lu", (unsigned long)code.ops.size()); - m_Label_NumCodes->SetLabel(wxString::FromAscii(numcodes)); + m_Label_NumCodes->SetLabel(StrToWxStr(numcodes)); m_ListBox_CodesList->Clear(); for (size_t j = 0; j < code.ops.size(); j++) { char text2[CHAR_MAX]; char* ops = text2; sprintf(ops, "%08x %08x", code.ops[j].cmd_addr, code.ops[j].value); - m_ListBox_CodesList->Append(wxString::FromAscii(ops)); + m_ListBox_CodesList->Append(StrToWxStr(ops)); } } } @@ -347,7 +348,7 @@ void wxCheatsWindow::OnEvent_ButtonUpdateLog_Press(wxCommandEvent& WXUNUSED (eve const std::vector &arLog = ActionReplay::GetSelfLog(); for (u32 i = 0; i < arLog.size(); i++) { - m_TextCtrl_Log->AppendText(wxString::FromAscii(arLog[i].c_str())); + m_TextCtrl_Log->AppendText(StrToWxStr(arLog[i])); } } @@ -619,7 +620,7 @@ void CreateCodeDialog::PressOK(wxCommandEvent& ev) // create the new code ActionReplay::ARCode new_cheat; new_cheat.active = false; - new_cheat.name = std::string(code_name.ToAscii()); + new_cheat.name = WxStrToStr(code_name); const ActionReplay::AREntry new_entry(code_address, code_value); new_cheat.ops.push_back(new_entry); diff --git a/Source/Core/DolphinWX/Src/ConfigMain.cpp b/Source/Core/DolphinWX/Src/ConfigMain.cpp index 4daf263b63..329906a301 100644 --- a/Source/Core/DolphinWX/Src/ConfigMain.cpp +++ b/Source/Core/DolphinWX/Src/ConfigMain.cpp @@ -33,6 +33,7 @@ #include "IPC_HLE/WII_IPC_HLE.h" #include "NANDContentLoader.h" +#include "WxUtils.h" #include "Globals.h" // Local #include "ConfigMain.h" #include "ConfigManager.h" @@ -52,6 +53,21 @@ using std::function; #define TEXT_BOX(page, text) new wxStaticText(page, wxID_ANY, text, wxDefaultPosition, wxDefaultSize) +struct CPUCore +{ + int CPUid; + const char *name; +}; +const CPUCore CPUCores[] = { + {0, "Interpreter (VERY slow)"}, +#ifdef _M_ARM + {3, "Arm JIT (experimental)"}, +#else + {1, "JIT Recompiler (recommended)"}, + {2, "JITIL experimental recompiler"}, +#endif +}; + extern CFrame* main_frame; // keep these in sync with CConfigMain::InitializeGUILists @@ -100,7 +116,6 @@ static const wxLanguage langIds[] = #define EXIDEV_AM_BB_STR _trans("AM-Baseboard") #define EXIDEV_GECKO_STR "USBGecko" -#define CSTR_TRANS(a) wxString(wxGetTranslation(wxT(a))).mb_str() #define WXSTR_TRANS(a) wxString(wxGetTranslation(wxT(a))) #ifdef WIN32 //only used with xgettext to be picked up as translatable string. @@ -188,7 +203,7 @@ CConfigMain::CConfigMain(wxWindow* parent, wxWindowID id, const wxString& title, // Update selected ISO paths for(u32 i = 0; i < SConfig::GetInstance().m_ISOFolder.size(); i++) { - ISOPaths->Append(wxString(SConfig::GetInstance().m_ISOFolder[i].c_str(), *wxConvCurrent)); + ISOPaths->Append(StrToWxStr(SConfig::GetInstance().m_ISOFolder[i])); } } @@ -241,7 +256,6 @@ void CConfigMain::UpdateGUI() PathsPage->Disable(); } } - void CConfigMain::InitializeGUILists() { // General page @@ -253,10 +267,9 @@ void CConfigMain::InitializeGUILists() arrayStringFor_Framelimit.Add(wxString::Format(wxT("%i"), i)); // Emulator Engine - arrayStringFor_CPUEngine.Add(_("Interpreter (VERY slow)")); - arrayStringFor_CPUEngine.Add(_("JIT Recompiler (recommended)")); - arrayStringFor_CPUEngine.Add(_("JITIL experimental recompiler")); - + for (unsigned int a = 0; a < (sizeof(CPUCores) / sizeof(CPUCore)); ++a) + arrayStringFor_CPUEngine.Add(_(CPUCores[a].name)); + // DSP Engine arrayStringFor_DSPEngine.Add(_("DSP HLE emulation (fast)")); arrayStringFor_DSPEngine.Add(_("DSP LLE recompiler")); @@ -329,7 +342,9 @@ void CConfigMain::InitializeGUIValues() UseFPSForLimiting->SetValue(SConfig::GetInstance().b_UseFPS); // General - Advanced - CPUEngine->SetSelection(startup_params.iCPUCore); + for (unsigned int a = 0; a < (sizeof(CPUCores) / sizeof(CPUCore)); ++a) + if (CPUCores[a].CPUid == startup_params.iCPUCore) + CPUEngine->SetSelection(a); _NTSCJ->SetValue(startup_params.bForceNTSCJ); @@ -477,10 +492,10 @@ void CConfigMain::InitializeGUIValues() // Paths RecursiveISOPath->SetValue(SConfig::GetInstance().m_RecursiveISOFolder); - DefaultISO->SetPath(wxString(startup_params.m_strDefaultGCM.c_str(), *wxConvCurrent)); - DVDRoot->SetPath(wxString(startup_params.m_strDVDRoot.c_str(), *wxConvCurrent)); - ApploaderPath->SetPath(wxString(startup_params.m_strApploader.c_str(), *wxConvCurrent)); - NANDRoot->SetPath(wxString(SConfig::GetInstance().m_NANDPath.c_str(), *wxConvCurrent)); + DefaultISO->SetPath(StrToWxStr(startup_params.m_strDefaultGCM)); + DVDRoot->SetPath(StrToWxStr(startup_params.m_strDVDRoot)); + ApploaderPath->SetPath(StrToWxStr(startup_params.m_strApploader)); + NANDRoot->SetPath(StrToWxStr(SConfig::GetInstance().m_NANDPath)); } void CConfigMain::InitializeGUITooltips() @@ -620,6 +635,7 @@ void CConfigMain::CreateGUIControls() { SConfig::GetInstance().m_LocalCoreStartupParameter.theme_name = theme_selection->GetStringSelection(); main_frame->InitBitmaps(); + main_frame->UpdateGameList(); })); auto const scInterface = new wxBoxSizer(wxHORIZONTAL); @@ -887,7 +903,7 @@ void CConfigMain::CoreSettingsChanged(wxCommandEvent& event) break; // Core - Advanced case ID_CPUENGINE: - SConfig::GetInstance().m_LocalCoreStartupParameter.iCPUCore = CPUEngine->GetSelection(); + SConfig::GetInstance().m_LocalCoreStartupParameter.iCPUCore = CPUCores[CPUEngine->GetSelection()].CPUid; if (main_frame->g_pCodeWindow) main_frame->g_pCodeWindow->GetMenuBar()->Check(IDM_INTERPRETER, SConfig::GetInstance().m_LocalCoreStartupParameter.iCPUCore?false:true); @@ -957,10 +973,10 @@ void CConfigMain::AudioSettingsChanged(wxCommandEvent& event) break; case ID_BACKEND: - VolumeSlider->Enable(SupportsVolumeChanges(std::string(BackendSelection->GetStringSelection().mb_str()))); - Latency->Enable(std::string(BackendSelection->GetStringSelection().mb_str()) == BACKEND_OPENAL); - DPL2Decoder->Enable(std::string(BackendSelection->GetStringSelection().mb_str()) == BACKEND_OPENAL); - SConfig::GetInstance().sBackend = BackendSelection->GetStringSelection().mb_str(); + VolumeSlider->Enable(SupportsVolumeChanges(WxStrToStr(BackendSelection->GetStringSelection()))); + Latency->Enable(WxStrToStr(BackendSelection->GetStringSelection()) == BACKEND_OPENAL); + DPL2Decoder->Enable(WxStrToStr(BackendSelection->GetStringSelection()) == BACKEND_OPENAL); + SConfig::GetInstance().sBackend = WxStrToStr(BackendSelection->GetStringSelection()); AudioCommon::UpdateSoundStream(); break; @@ -981,9 +997,9 @@ void CConfigMain::AddAudioBackends() for (std::vector::const_iterator iter = backends.begin(); iter != backends.end(); ++iter) { - BackendSelection->Append(wxString::FromAscii((*iter).c_str())); + BackendSelection->Append(StrToWxStr(*iter)); int num = BackendSelection->\ - FindString(wxString::FromAscii(SConfig::GetInstance().sBackend.c_str())); + FindString(StrToWxStr(SConfig::GetInstance().sBackend)); BackendSelection->SetSelection(num); } } @@ -1045,12 +1061,12 @@ void CConfigMain::GCSettingsChanged(wxCommandEvent& event) void CConfigMain::ChooseMemcardPath(std::string& strMemcard, bool isSlotA) { - std::string filename = std::string(wxFileSelector( + std::string filename = WxStrToStr(wxFileSelector( _("Choose a file to open"), - wxString::FromUTF8(File::GetUserPath(D_GCUSER_IDX).c_str()), + StrToWxStr(File::GetUserPath(D_GCUSER_IDX)), isSlotA ? wxT(GC_MEMCARDA) : wxT(GC_MEMCARDB), wxEmptyString, - _("Gamecube Memory Cards (*.raw,*.gcp)") + wxString(wxT("|*.raw;*.gcp"))).mb_str()); + _("Gamecube Memory Cards (*.raw,*.gcp)") + wxString(wxT("|*.raw;*.gcp")))); if (!filename.empty()) { @@ -1241,7 +1257,7 @@ void CConfigMain::AddRemoveISOPaths(wxCommandEvent& event) SConfig::GetInstance().m_ISOFolder.clear(); for (unsigned int i = 0; i < ISOPaths->GetCount(); i++) - SConfig::GetInstance().m_ISOFolder.push_back(std::string(ISOPaths->GetStrings()[i].mb_str())); + SConfig::GetInstance().m_ISOFolder.push_back(WxStrToStr(ISOPaths->GetStrings()[i])); } void CConfigMain::RecursiveDirectoryChanged(wxCommandEvent& WXUNUSED (event)) @@ -1252,24 +1268,25 @@ void CConfigMain::RecursiveDirectoryChanged(wxCommandEvent& WXUNUSED (event)) void CConfigMain::DefaultISOChanged(wxFileDirPickerEvent& WXUNUSED (event)) { - SConfig::GetInstance().m_LocalCoreStartupParameter.m_strDefaultGCM = DefaultISO->GetPath().mb_str(); + SConfig::GetInstance().m_LocalCoreStartupParameter.m_strDefaultGCM = WxStrToStr(DefaultISO->GetPath()); } void CConfigMain::DVDRootChanged(wxFileDirPickerEvent& WXUNUSED (event)) { - SConfig::GetInstance().m_LocalCoreStartupParameter.m_strDVDRoot = DVDRoot->GetPath().mb_str(); + SConfig::GetInstance().m_LocalCoreStartupParameter.m_strDVDRoot = WxStrToStr(DVDRoot->GetPath()); } void CConfigMain::ApploaderPathChanged(wxFileDirPickerEvent& WXUNUSED (event)) { - SConfig::GetInstance().m_LocalCoreStartupParameter.m_strApploader = ApploaderPath->GetPath().mb_str(); + SConfig::GetInstance().m_LocalCoreStartupParameter.m_strApploader = WxStrToStr(ApploaderPath->GetPath()); } void CConfigMain::NANDRootChanged(wxFileDirPickerEvent& WXUNUSED (event)) { std::string NANDPath = - SConfig::GetInstance().m_NANDPath = File::GetUserPath(D_WIIROOT_IDX, std::string(NANDRoot->GetPath().mb_str())); - NANDRoot->SetPath(wxString(NANDPath.c_str(), *wxConvCurrent)); + SConfig::GetInstance().m_NANDPath = + File::GetUserPath(D_WIIROOT_IDX, WxStrToStr(NANDRoot->GetPath())); + NANDRoot->SetPath(StrToWxStr(NANDPath)); SConfig::GetInstance().m_SYSCONF->UpdateLocation(); DiscIO::cUIDsys::AccessInstance().UpdateLocation(); DiscIO::CSharedContent::AccessInstance().UpdateLocation(); diff --git a/Source/Core/DolphinWX/Src/Debugger/BreakpointDlg.cpp b/Source/Core/DolphinWX/Src/Debugger/BreakpointDlg.cpp index 58e73b167e..96dbac8ff8 100644 --- a/Source/Core/DolphinWX/Src/Debugger/BreakpointDlg.cpp +++ b/Source/Core/DolphinWX/Src/Debugger/BreakpointDlg.cpp @@ -19,6 +19,7 @@ #include "StringUtil.h" #include "PowerPC/PowerPC.h" #include "BreakpointWindow.h" +#include "../WxUtils.h" BEGIN_EVENT_TABLE(BreakPointDlg, wxDialog) EVT_BUTTON(wxID_OK, BreakPointDlg::OnOK) @@ -42,14 +43,14 @@ void BreakPointDlg::OnOK(wxCommandEvent& event) { wxString AddressString = m_pEditAddress->GetLineText(0); u32 Address = 0; - if (AsciiToHex(AddressString.mb_str(), Address)) + if (AsciiToHex(WxStrToStr(AddressString).c_str(), Address)) { PowerPC::breakpoints.Add(Address); Parent->NotifyUpdate(); Close(); } else - PanicAlert("The address %s is invalid.", (const char *)AddressString.ToUTF8()); + PanicAlert("The address %s is invalid.", WxStrToStr(AddressString).c_str()); event.Skip(); } diff --git a/Source/Core/DolphinWX/Src/Debugger/BreakpointView.cpp b/Source/Core/DolphinWX/Src/Debugger/BreakpointView.cpp index 496cb8fe5d..a23e9194fd 100644 --- a/Source/Core/DolphinWX/Src/Debugger/BreakpointView.cpp +++ b/Source/Core/DolphinWX/Src/Debugger/BreakpointView.cpp @@ -23,6 +23,7 @@ #include "PowerPC/PPCSymbolDB.h" #include "PowerPC/PowerPC.h" #include "HW/Memmap.h" +#include "../WxUtils.h" CBreakPointView::CBreakPointView(wxWindow* parent, const wxWindowID id) : wxListCtrl(parent, id, wxDefaultPosition, wxDefaultSize, @@ -50,20 +51,20 @@ void CBreakPointView::Update() if (!rBP.bTemporary) { wxString temp; - temp = wxString::FromAscii(rBP.bOn ? "on" : " "); + temp = StrToWxStr(rBP.bOn ? "on" : " "); int Item = InsertItem(0, temp); - temp = wxString::FromAscii("BP"); + temp = StrToWxStr("BP"); SetItem(Item, 1, temp); Symbol *symbol = g_symbolDB.GetSymbolFromAddr(rBP.iAddress); if (symbol) { - temp = wxString::FromAscii(g_symbolDB.GetDescription(rBP.iAddress)); + temp = StrToWxStr(g_symbolDB.GetDescription(rBP.iAddress)); SetItem(Item, 2, temp); } sprintf(szBuffer, "%08x", rBP.iAddress); - temp = wxString::FromAscii(szBuffer); + temp = StrToWxStr(szBuffer); SetItem(Item, 3, temp); SetItemData(Item, rBP.iAddress); @@ -76,27 +77,27 @@ void CBreakPointView::Update() const TMemCheck& rMemCheck = rMemChecks[i]; wxString temp; - temp = wxString::FromAscii((rMemCheck.Break || rMemCheck.Log) ? "on" : " "); + temp = StrToWxStr((rMemCheck.Break || rMemCheck.Log) ? "on" : " "); int Item = InsertItem(0, temp); - temp = wxString::FromAscii("MC"); + temp = StrToWxStr("MC"); SetItem(Item, 1, temp); Symbol *symbol = g_symbolDB.GetSymbolFromAddr(rMemCheck.StartAddress); if (symbol) { - temp = wxString::FromAscii(g_symbolDB.GetDescription(rMemCheck.StartAddress)); + temp = StrToWxStr(g_symbolDB.GetDescription(rMemCheck.StartAddress)); SetItem(Item, 2, temp); } sprintf(szBuffer, "%08x to %08x", rMemCheck.StartAddress, rMemCheck.EndAddress); - temp = wxString::FromAscii(szBuffer); + temp = StrToWxStr(szBuffer); SetItem(Item, 3, temp); size_t c = 0; if (rMemCheck.OnRead) szBuffer[c++] = 'r'; if (rMemCheck.OnWrite) szBuffer[c++] = 'w'; szBuffer[c] = 0x00; - temp = wxString::FromAscii(szBuffer); + temp = StrToWxStr(szBuffer); SetItem(Item, 4, temp); SetItemData(Item, rMemCheck.StartAddress); diff --git a/Source/Core/DolphinWX/Src/Debugger/CodeView.cpp b/Source/Core/DolphinWX/Src/Debugger/CodeView.cpp index f696aaab64..31ad19d6da 100644 --- a/Source/Core/DolphinWX/Src/Debugger/CodeView.cpp +++ b/Source/Core/DolphinWX/Src/Debugger/CodeView.cpp @@ -23,6 +23,7 @@ #include "Host.h" #include "CodeView.h" #include "SymbolDB.h" +#include "../WxUtils.h" #include #include @@ -223,7 +224,7 @@ void CCodeView::OnPopupMenu(wxCommandEvent& event) { char disasm[256]; debugger->disasm(selection, disasm, 256); - wxTheClipboard->SetData(new wxTextDataObject(wxString::FromAscii(disasm))); + wxTheClipboard->SetData(new wxTextDataObject(StrToWxStr(disasm))); } break; @@ -231,7 +232,7 @@ void CCodeView::OnPopupMenu(wxCommandEvent& event) { char temp[24]; sprintf(temp, "%08x", debugger->readInstruction(selection)); - wxTheClipboard->SetData(new wxTextDataObject(wxString::FromAscii(temp))); + wxTheClipboard->SetData(new wxTextDataObject(StrToWxStr(temp))); } break; @@ -252,7 +253,7 @@ void CCodeView::OnPopupMenu(wxCommandEvent& event) debugger->disasm(addr, disasm, 256); text = text + StringFromFormat("%08x: ", addr) + disasm + "\r\n"; } - wxTheClipboard->SetData(new wxTextDataObject(wxString::FromAscii(text.c_str()))); + wxTheClipboard->SetData(new wxTextDataObject(StrToWxStr(text))); } } break; @@ -297,12 +298,12 @@ void CCodeView::OnPopupMenu(wxCommandEvent& event) Symbol *symbol = symbol_db->GetSymbolFromAddr(selection); if (symbol) { - wxTextEntryDialog input_symbol(this, wxString::FromAscii("Rename symbol:"), + wxTextEntryDialog input_symbol(this, StrToWxStr("Rename symbol:"), wxGetTextFromUserPromptStr, - wxString::FromAscii(symbol->name.c_str())); + StrToWxStr(symbol->name)); if (input_symbol.ShowModal() == wxID_OK) { - symbol->name = input_symbol.GetValue().mb_str(); + symbol->name = WxStrToStr(input_symbol.GetValue()); Refresh(); // Redraw to show the renamed symbol } Host_NotifyMapLoaded(); @@ -327,23 +328,23 @@ void CCodeView::OnMouseUpR(wxMouseEvent& event) wxMenu* menu = new wxMenu; //menu->Append(IDM_GOTOINMEMVIEW, "&Goto in mem view"); menu->Append(IDM_FOLLOWBRANCH, - wxString::FromAscii("&Follow branch"))->Enable(AddrToBranch(selection) ? true : false); + StrToWxStr("&Follow branch"))->Enable(AddrToBranch(selection) ? true : false); menu->AppendSeparator(); #if wxUSE_CLIPBOARD - menu->Append(IDM_COPYADDRESS, wxString::FromAscii("Copy &address")); - menu->Append(IDM_COPYFUNCTION, wxString::FromAscii("Copy &function"))->Enable(isSymbol); - menu->Append(IDM_COPYCODE, wxString::FromAscii("Copy &code line")); - menu->Append(IDM_COPYHEX, wxString::FromAscii("Copy &hex")); + menu->Append(IDM_COPYADDRESS, StrToWxStr("Copy &address")); + menu->Append(IDM_COPYFUNCTION, StrToWxStr("Copy &function"))->Enable(isSymbol); + menu->Append(IDM_COPYCODE, StrToWxStr("Copy &code line")); + menu->Append(IDM_COPYHEX, StrToWxStr("Copy &hex")); menu->AppendSeparator(); #endif - menu->Append(IDM_RENAMESYMBOL, wxString::FromAscii("Rename &symbol"))->Enable(isSymbol); + menu->Append(IDM_RENAMESYMBOL, StrToWxStr("Rename &symbol"))->Enable(isSymbol); menu->AppendSeparator(); menu->Append(IDM_RUNTOHERE, _("&Run To Here")); menu->Append(IDM_ADDFUNCTION, _("&Add function")); - menu->Append(IDM_JITRESULTS, wxString::FromAscii("PPC vs X86")); - menu->Append(IDM_INSERTBLR, wxString::FromAscii("Insert &blr")); - menu->Append(IDM_INSERTNOP, wxString::FromAscii("Insert &nop")); - menu->Append(IDM_PATCHALERT, wxString::FromAscii("Patch alert")); + menu->Append(IDM_JITRESULTS, StrToWxStr("PPC vs X86")); + menu->Append(IDM_INSERTBLR, StrToWxStr("Insert &blr")); + menu->Append(IDM_INSERTNOP, StrToWxStr("Insert &nop")); + menu->Append(IDM_PATCHALERT, StrToWxStr("Patch alert")); PopupMenu(menu); event.Skip(true); } @@ -489,7 +490,7 @@ void CCodeView::OnPaint(wxPaintEvent& event) dc.SetTextForeground(_T("#000000")); } - dc.DrawText(wxString::FromAscii(dis2), 17 + 17*charWidth, rowY1); + dc.DrawText(StrToWxStr(dis2), 17 + 17*charWidth, rowY1); // ------------ } @@ -499,7 +500,7 @@ void CCodeView::OnPaint(wxPaintEvent& event) else dc.SetTextForeground(_T("#8000FF")); // purple - dc.DrawText(wxString::FromAscii(dis), 17 + (plain ? 1*charWidth : 9*charWidth), rowY1); + dc.DrawText(StrToWxStr(dis), 17 + (plain ? 1*charWidth : 9*charWidth), rowY1); if (desc[0] == 0) { @@ -513,7 +514,7 @@ void CCodeView::OnPaint(wxPaintEvent& event) //UnDecorateSymbolName(desc,temp,255,UNDNAME_COMPLETE); if (strlen(desc)) { - dc.DrawText(wxString::FromAscii(desc), 17 + 35 * charWidth, rowY1); + dc.DrawText(StrToWxStr(desc), 17 + 35 * charWidth, rowY1); } } diff --git a/Source/Core/DolphinWX/Src/Debugger/CodeWindow.cpp b/Source/Core/DolphinWX/Src/Debugger/CodeWindow.cpp index 1c0776862c..9172a3af9a 100644 --- a/Source/Core/DolphinWX/Src/Debugger/CodeWindow.cpp +++ b/Source/Core/DolphinWX/Src/Debugger/CodeWindow.cpp @@ -30,6 +30,7 @@ #include "CodeWindow.h" #include "CodeView.h" +#include "../WxUtils.h" #include "FileUtil.h" #include "Core.h" #include "HW/Memmap.h" @@ -38,6 +39,7 @@ #include "LogManager.h" #include "HW/CPU.h" #include "PowerPC/PowerPC.h" +#include "PowerPC/JitInterface.h" #include "Debugger/PPCDebugInterface.h" #include "Debugger/Debugger_SymbolMap.h" #include "PowerPC/PPCAnalyst.h" @@ -45,8 +47,6 @@ #include "PowerPC/PPCSymbolDB.h" #include "PowerPC/SignatureDB.h" #include "PowerPC/PPCTables.h" -#include "PowerPC/JitCommon/JitBase.h" -#include "PowerPC/JitCommon/JitCache.h" // for ClearCache() #include "ConfigManager.h" @@ -211,7 +211,7 @@ void CCodeWindow::OnAddrBoxChange(wxCommandEvent& event) wxTextCtrl* pAddrCtrl = (wxTextCtrl*)GetToolBar()->FindControl(IDM_ADDRBOX); wxString txt = pAddrCtrl->GetValue(); - std::string text(txt.mb_str()); + std::string text(WxStrToStr(txt)); text = StripSpaces(text); if (text.size() == 8) { @@ -260,8 +260,7 @@ void CCodeWindow::SingleStep() { if (CCPU::IsStepping()) { - if (jit) - jit->GetBlockCache()->InvalidateICache(PC, 4); + JitInterface::InvalidateICache(PC, 4); CCPU::StepOpcode(&sync_event); wxThread::Sleep(20); // need a short wait here @@ -314,7 +313,7 @@ void CCodeWindow::UpdateLists() Symbol *caller_symbol = g_symbolDB.GetSymbolFromAddr(caller_addr); if (caller_symbol) { - int idx = callers->Append(wxString::FromAscii(StringFromFormat + int idx = callers->Append(StrToWxStr(StringFromFormat ("< %s (%08x)", caller_symbol->name.c_str(), caller_addr).c_str())); callers->SetClientData(idx, (void*)(u64)caller_addr); } @@ -327,7 +326,7 @@ void CCodeWindow::UpdateLists() Symbol *call_symbol = g_symbolDB.GetSymbolFromAddr(call_addr); if (call_symbol) { - int idx = calls->Append(wxString::FromAscii(StringFromFormat + int idx = calls->Append(StrToWxStr(StringFromFormat ("> %s (%08x)", call_symbol->name.c_str(), call_addr).c_str())); calls->SetClientData(idx, (void*)(u64)call_addr); } @@ -346,12 +345,12 @@ void CCodeWindow::UpdateCallstack() for (size_t i = 0; i < stack.size(); i++) { - int idx = callstack->Append(wxString::FromAscii(stack[i].Name.c_str())); + int idx = callstack->Append(StrToWxStr(stack[i].Name)); callstack->SetClientData(idx, (void*)(u64)stack[i].vAddress); } if (!ret) - callstack->Append(wxString::FromAscii("invalid callstack")); + callstack->Append(StrToWxStr("invalid callstack")); } // Create CPU Mode menus @@ -362,7 +361,7 @@ void CCodeWindow::CreateMenu(const SCoreStartupParameter& _LocalCoreStartupParam wxMenu* pCoreMenu = new wxMenu; wxMenuItem* interpreter = pCoreMenu->Append(IDM_INTERPRETER, _("&Interpreter core"), - wxString::FromAscii("This is necessary to get break points" + StrToWxStr("This is necessary to get break points" " and stepping to work as explained in the Developer Documentation. But it can be very" " slow, perhaps slower than 1 fps."), wxITEM_CHECK); @@ -430,7 +429,7 @@ void CCodeWindow::CreateMenuOptions(wxMenu* pMenu) boottopause->Check(bBootToPause); wxMenuItem* automaticstart = pMenu->Append(IDM_AUTOMATICSTART, _("&Automatic start"), - wxString::FromAscii( + StrToWxStr( "Automatically load the Default ISO when Dolphin starts, or the last game you loaded," " if you have not given it an elf file with the --elf command line. [This can be" " convenient if you are bug-testing with a certain game and want to rebuild" @@ -492,10 +491,8 @@ void CCodeWindow::OnCPUMode(wxCommandEvent& event) } // Clear the JIT cache to enable these changes - if (jit) - { - jit->ClearCache(); - } + JitInterface::ClearCache(); + // Update UpdateButtonStates(); } @@ -509,7 +506,7 @@ void CCodeWindow::OnJitMenu(wxCommandEvent& event) break; case IDM_CLEARCODECACHE: - jit->ClearCache(); + JitInterface::ClearCache(); break; case IDM_SEARCHINSTRUCTION: @@ -519,10 +516,10 @@ void CCodeWindow::OnJitMenu(wxCommandEvent& event) for (u32 addr = 0x80000000; addr < 0x80100000; addr += 4) { const char *name = PPCTables::GetInstructionName(Memory::ReadUnchecked_U32(addr)); - if (name && !strcmp((const char *)str.mb_str(), name)) + auto const wx_name = WxStrToStr(str); + if (name && (wx_name == name)) { - std::string mb_str(str.mb_str()); - NOTICE_LOG(POWERPC, "Found %s at %08x", mb_str.c_str(), addr); + NOTICE_LOG(POWERPC, "Found %s at %08x", wx_name.c_str(), addr); } } break; diff --git a/Source/Core/DolphinWX/Src/Debugger/CodeWindowFunctions.cpp b/Source/Core/DolphinWX/Src/Debugger/CodeWindowFunctions.cpp index 706b398dce..ef4622d14f 100644 --- a/Source/Core/DolphinWX/Src/Debugger/CodeWindowFunctions.cpp +++ b/Source/Core/DolphinWX/Src/Debugger/CodeWindowFunctions.cpp @@ -25,6 +25,7 @@ #include "DebuggerUIUtil.h" +#include "../WxUtils.h" #include "RegisterWindow.h" #include "BreakpointWindow.h" #include "MemoryWindow.h" @@ -65,7 +66,7 @@ void CCodeWindow::Load() std::string fontDesc; ini.Get("General", "DebuggerFont", &fontDesc); if (!fontDesc.empty()) - DebuggerFont.SetNativeFontInfoUserDesc(wxString::FromAscii(fontDesc.c_str())); + DebuggerFont.SetNativeFontInfoUserDesc(StrToWxStr(fontDesc)); // Boot to pause or not ini.Get("General", "AutomaticStart", &bAutomaticStart, false); @@ -107,7 +108,7 @@ void CCodeWindow::Save() ini.Load(File::GetUserPath(F_DEBUGGERCONFIG_IDX)); ini.Set("General", "DebuggerFont", - std::string(DebuggerFont.GetNativeFontInfoUserDesc().mb_str())); + WxStrToStr(DebuggerFont.GetNativeFontInfoUserDesc())); // Boot to pause or not ini.Set("General", "AutomaticStart", GetMenuBar()->IsChecked(IDM_AUTOMATICSTART)); @@ -154,7 +155,7 @@ void CCodeWindow::CreateMenuSymbols(wxMenuBar *pMenuBar) pSymbolsMenu->Append(IDM_SAVEMAPFILE, _("&Save symbol map")); pSymbolsMenu->AppendSeparator(); pSymbolsMenu->Append(IDM_SAVEMAPFILEWITHCODES, _("Save code"), - wxString::FromAscii("Save the entire disassembled code. This may take a several seconds" + StrToWxStr("Save the entire disassembled code. This may take a several seconds" " and may require between 50 and 100 MB of hard drive space. It will only save code" " that are in the first 4 MB of memory, if you are debugging a game that load .rel" " files with code to memory you may want to increase that to perhaps 8 MB, you can do" @@ -208,7 +209,7 @@ void CCodeWindow::OnProfilerMenu(wxCommandEvent& event) break; } wxString OpenCommand; - OpenCommand = filetype->GetOpenCommand(wxString::From8BitData(filename.c_str())); + OpenCommand = filetype->GetOpenCommand(StrToWxStr(filename)); if(!OpenCommand.IsEmpty()) wxExecute(OpenCommand, wxEXEC_SYNC); } @@ -284,7 +285,8 @@ void CCodeWindow::OnSymbolsMenu(wxCommandEvent& event) if (!path.IsEmpty()) { - std::ifstream f(path.mb_str()); + std::ifstream f; + OpenFStream(f, WxStrToStr(path), std::ios_base::in); std::string line; while (std::getline(f, line)) @@ -312,13 +314,13 @@ void CCodeWindow::OnSymbolsMenu(wxCommandEvent& event) { wxTextEntryDialog input_prefix( this, - wxString::FromAscii("Only export symbols with prefix:\n(Blank for all symbols)"), + StrToWxStr("Only export symbols with prefix:\n(Blank for all symbols)"), wxGetTextFromUserPromptStr, wxEmptyString); if (input_prefix.ShowModal() == wxID_OK) { - std::string prefix(input_prefix.GetValue().mb_str()); + std::string prefix(WxStrToStr(input_prefix.GetValue())); wxString path = wxFileSelector( _T("Save signature as"), wxEmptyString, wxEmptyString, wxEmptyString, @@ -328,8 +330,7 @@ void CCodeWindow::OnSymbolsMenu(wxCommandEvent& event) { SignatureDB db; db.Initialize(&g_symbolDB, prefix.c_str()); - std::string filename(path.mb_str()); - db.Save(path.mb_str()); + db.Save(WxStrToStr(path).c_str()); } } } @@ -343,7 +344,7 @@ void CCodeWindow::OnSymbolsMenu(wxCommandEvent& event) if (!path.IsEmpty()) { SignatureDB db; - db.Load(path.mb_str()); + db.Load(WxStrToStr(path).c_str()); db.Apply(&g_symbolDB); } } @@ -366,7 +367,7 @@ void CCodeWindow::NotifyMapLoaded() symbols->Clear(); for (PPCSymbolDB::XFuncMap::iterator iter = g_symbolDB.GetIterator(); iter != g_symbolDB.End(); ++iter) { - int idx = symbols->Append(wxString::FromAscii(iter->second.name.c_str())); + int idx = symbols->Append(StrToWxStr(iter->second.name)); symbols->SetClientData(idx, (void*)&iter->second); } symbols->Thaw(); diff --git a/Source/Core/DolphinWX/Src/Debugger/DSPDebugWindow.cpp b/Source/Core/DolphinWX/Src/Debugger/DSPDebugWindow.cpp index a4591d3994..e77b57399e 100644 --- a/Source/Core/DolphinWX/Src/Debugger/DSPDebugWindow.cpp +++ b/Source/Core/DolphinWX/Src/Debugger/DSPDebugWindow.cpp @@ -22,6 +22,7 @@ #include +#include "../WxUtils.h" #include "StringUtil.h" #include "DSPDebugWindow.h" #include "DSPRegisterView.h" @@ -220,7 +221,7 @@ void DSPDebuggerLLE::UpdateSymbolMap() for (SymbolDB::XFuncMap::iterator iter = DSPSymbols::g_dsp_symbol_db.GetIterator(); iter != DSPSymbols::g_dsp_symbol_db.End(); ++iter) { - int idx = m_SymbolList->Append(wxString::FromAscii(iter->second.name.c_str())); + int idx = m_SymbolList->Append(StrToWxStr(iter->second.name)); m_SymbolList->SetClientData(idx, (void*)&iter->second); } m_SymbolList->Thaw(); @@ -250,8 +251,7 @@ void DSPDebuggerLLE::OnAddrBoxChange(wxCommandEvent& event) wxTextCtrl* pAddrCtrl = (wxTextCtrl*)m_Toolbar->FindControl(ID_ADDRBOX); wxString txt = pAddrCtrl->GetValue(); - std::string text(txt.mb_str()); - text = StripSpaces(text); + auto text = StripSpaces(WxStrToStr(txt)); if (text.size()) { u32 addr; diff --git a/Source/Core/DolphinWX/Src/Debugger/DSPRegisterView.cpp b/Source/Core/DolphinWX/Src/Debugger/DSPRegisterView.cpp index ca275ba66a..b8634e14dc 100644 --- a/Source/Core/DolphinWX/Src/Debugger/DSPRegisterView.cpp +++ b/Source/Core/DolphinWX/Src/Debugger/DSPRegisterView.cpp @@ -17,7 +17,7 @@ #include "DSPDebugWindow.h" #include "DSPRegisterView.h" - +#include "../WxUtils.h" wxString CDSPRegTable::GetValue(int row, int col) { @@ -25,7 +25,7 @@ wxString CDSPRegTable::GetValue(int row, int col) { switch (col) { - case 0: return wxString::FromAscii(pdregname(row)); + case 0: return StrToWxStr(pdregname(row)); case 1: return wxString::Format(wxT("0x%04x"), DSPCore_ReadRegister(row)); default: return wxEmptyString; } diff --git a/Source/Core/DolphinWX/Src/Debugger/JitWindow.cpp b/Source/Core/DolphinWX/Src/Debugger/JitWindow.cpp index 69cee04db5..7f98af6c57 100644 --- a/Source/Core/DolphinWX/Src/Debugger/JitWindow.cpp +++ b/Source/Core/DolphinWX/Src/Debugger/JitWindow.cpp @@ -37,6 +37,7 @@ #include "Core.h" #include "StringUtil.h" #include "LogManager.h" +#include "../WxUtils.h" #include "../Globals.h" @@ -119,9 +120,9 @@ void CJitWindow::Compare(u32 em_address) } // Do not merge this "if" with the above - block_num changes inside it. if (block_num < 0) { - ppc_box->SetValue(wxString::FromAscii(StringFromFormat("(non-code address: %08x)", - em_address).c_str())); - x86_box->SetValue(wxString::FromAscii(StringFromFormat("(no translation)").c_str())); + ppc_box->SetValue(StrToWxStr(StringFromFormat("(non-code address: %08x)", + em_address))); + x86_box->SetValue(StrToWxStr(StringFromFormat("(no translation)"))); delete[] xDis; return; } @@ -150,7 +151,7 @@ void CJitWindow::Compare(u32 em_address) *sptr++ = 10; num_x86_instructions++; } - x86_box->SetValue(wxString::FromAscii((char*)xDis)); + x86_box->SetValue(StrToWxStr((char*)xDis)); // == Fill in ppc box u32 ppc_addr = block->originalAddress; @@ -189,11 +190,11 @@ void CJitWindow::Compare(u32 em_address) sptr += sprintf(sptr, "Num bytes: PPC: %i x86: %i (blowup: %i%%)\n", size * 4, block->codeSize, 100 * (block->codeSize / (4 * size) - 1)); - ppc_box->SetValue(wxString::FromAscii((char*)xDis)); + ppc_box->SetValue(StrToWxStr((char*)xDis)); } else { - ppc_box->SetValue(wxString::FromAscii(StringFromFormat( - "(non-code address: %08x)", em_address).c_str())); - x86_box->SetValue(wxString::FromAscii("---")); + ppc_box->SetValue(StrToWxStr(StringFromFormat( + "(non-code address: %08x)", em_address))); + x86_box->SetValue("---"); } delete[] xDis; diff --git a/Source/Core/DolphinWX/Src/Debugger/MemoryCheckDlg.cpp b/Source/Core/DolphinWX/Src/Debugger/MemoryCheckDlg.cpp index f66e781ca3..41e09a7451 100644 --- a/Source/Core/DolphinWX/Src/Debugger/MemoryCheckDlg.cpp +++ b/Source/Core/DolphinWX/Src/Debugger/MemoryCheckDlg.cpp @@ -15,6 +15,7 @@ // Official SVN repository and contact information can be found at // http://code.google.com/p/dolphin-emu/ +#include "../WxUtils.h" #include "MemoryCheckDlg.h" #include "Common.h" #include "StringUtil.h" @@ -79,9 +80,9 @@ void MemoryCheckDlg::OnOK(wxCommandEvent& event) u32 StartAddress, EndAddress; bool EndAddressOK = EndAddressString.Len() && - AsciiToHex(EndAddressString.mb_str(), EndAddress); + AsciiToHex(WxStrToStr(EndAddressString).c_str(), EndAddress); - if (AsciiToHex(StartAddressString.mb_str(), StartAddress) && + if (AsciiToHex(WxStrToStr(StartAddressString).c_str(), StartAddress) && (OnRead || OnWrite) && (Log || Break)) { TMemCheck MemCheck; diff --git a/Source/Core/DolphinWX/Src/Debugger/MemoryView.cpp b/Source/Core/DolphinWX/Src/Debugger/MemoryView.cpp index c6244fb7de..14d1aed8c0 100644 --- a/Source/Core/DolphinWX/Src/Debugger/MemoryView.cpp +++ b/Source/Core/DolphinWX/Src/Debugger/MemoryView.cpp @@ -22,6 +22,8 @@ #include "HW/Memmap.h" #include "MemoryView.h" +#include "../WxUtils.h" + #include #include @@ -149,7 +151,7 @@ void CMemoryView::OnPopupMenu(wxCommandEvent& event) { char temp[24]; sprintf(temp, "%08x", debugger->readExtraMemory(memory, selection)); - wxTheClipboard->SetData(new wxTextDataObject(wxString::FromAscii(temp))); + wxTheClipboard->SetData(new wxTextDataObject(StrToWxStr(temp))); } break; #endif @@ -186,16 +188,16 @@ void CMemoryView::OnMouseDownR(wxMouseEvent& event) wxMenu* menu = new wxMenu; //menu.Append(IDM_GOTOINMEMVIEW, "&Goto in mem view"); #if wxUSE_CLIPBOARD - menu->Append(IDM_COPYADDRESS, wxString::FromAscii("Copy &address")); - menu->Append(IDM_COPYHEX, wxString::FromAscii("Copy &hex")); + menu->Append(IDM_COPYADDRESS, StrToWxStr("Copy &address")); + menu->Append(IDM_COPYHEX, StrToWxStr("Copy &hex")); #endif - menu->Append(IDM_TOGGLEMEMORY, wxString::FromAscii("Toggle &memory")); + menu->Append(IDM_TOGGLEMEMORY, StrToWxStr("Toggle &memory")); wxMenu* viewAsSubMenu = new wxMenu; - viewAsSubMenu->Append(IDM_VIEWASFP, wxString::FromAscii("FP value")); - viewAsSubMenu->Append(IDM_VIEWASASCII, wxString::FromAscii("ASCII")); - viewAsSubMenu->Append(IDM_VIEWASHEX, wxString::FromAscii("Hex")); - menu->AppendSubMenu(viewAsSubMenu, wxString::FromAscii("View As:")); + viewAsSubMenu->Append(IDM_VIEWASFP, StrToWxStr("FP value")); + viewAsSubMenu->Append(IDM_VIEWASASCII, StrToWxStr("ASCII")); + viewAsSubMenu->Append(IDM_VIEWASHEX, StrToWxStr("Hex")); + menu->AppendSubMenu(viewAsSubMenu, StrToWxStr("View As:")); PopupMenu(menu); } @@ -285,7 +287,7 @@ void CMemoryView::OnPaint(wxPaintEvent& event) char mem[256]; debugger->getRawMemoryString(memory, address, mem, 256); dc.SetTextForeground(_T("#000080")); - dc.DrawText(wxString::FromAscii(mem), 17+fontSize*(8), rowY1); + dc.DrawText(StrToWxStr(mem), 17+fontSize*(8), rowY1); dc.SetTextForeground(_T("#000000")); } @@ -361,9 +363,9 @@ void CMemoryView::OnPaint(wxPaintEvent& event) char desc[256] = ""; if (viewAsType != VIEWAS_HEX) - dc.DrawText(wxString::FromAscii(dis), textPlacement + fontSize*(8 + 8), rowY1); + dc.DrawText(StrToWxStr(dis), textPlacement + fontSize*(8 + 8), rowY1); else - dc.DrawText(wxString::FromAscii(dis), textPlacement, rowY1); + dc.DrawText(StrToWxStr(dis), textPlacement, rowY1); if (desc[0] == 0) strcpy(desc, debugger->getDescription(address).c_str()); @@ -371,7 +373,7 @@ void CMemoryView::OnPaint(wxPaintEvent& event) dc.SetTextForeground(_T("#0000FF")); if (strlen(desc)) - dc.DrawText(wxString::FromAscii(desc), 17+fontSize*((8+8+8+30)*2), rowY1); + dc.DrawText(StrToWxStr(desc), 17+fontSize*((8+8+8+30)*2), rowY1); // Show blue memory check dot if (debugger->isMemCheck(address)) diff --git a/Source/Core/DolphinWX/Src/Debugger/MemoryWindow.cpp b/Source/Core/DolphinWX/Src/Debugger/MemoryWindow.cpp index 5673d7b7c1..4b87cfa154 100644 --- a/Source/Core/DolphinWX/Src/Debugger/MemoryWindow.cpp +++ b/Source/Core/DolphinWX/Src/Debugger/MemoryWindow.cpp @@ -20,6 +20,8 @@ #include #include #include + +#include "../WxUtils.h" #include "MemoryWindow.h" #include "HW/CPU.h" #include "PowerPC/PowerPC.h" @@ -152,8 +154,8 @@ void CMemoryWindow::JumpToAddress(u32 _Address) void CMemoryWindow::SetMemoryValue(wxCommandEvent& event) { - std::string str_addr = std::string(addrbox->GetValue().mb_str()); - std::string str_val = std::string(valbox->GetValue().mb_str()); + std::string str_addr = WxStrToStr(addrbox->GetValue()); + std::string str_val = WxStrToStr(valbox->GetValue()); u32 addr; u32 val; @@ -179,7 +181,7 @@ void CMemoryWindow::OnAddrBoxChange(wxCommandEvent& event) if (txt.size()) { u32 addr; - sscanf(txt.mb_str(), "%08x", &addr); + sscanf(WxStrToStr(txt).c_str(), "%08x", &addr); memview->Center(addr & ~3); } @@ -349,10 +351,7 @@ void CMemoryWindow::onSearch(wxCommandEvent& event) tmpstr = new char[newsize + 1]; memset(tmpstr, 0, newsize + 1); } - //sprintf(tmpstr, "%s%s", tmpstr, rawData.c_str()); - //strcpy(&tmpstr[1], rawData.ToAscii()); - //memcpy(&tmpstr[1], &rawData.c_str()[0], rawData.size()); - sprintf(tmpstr, "%s%s", tmpstr, (const char *)rawData.mb_str()); + sprintf(tmpstr, "%s%s", tmpstr, WxStrToStr(rawData).c_str()); tmp2 = &Dest.front(); count = 0; for(i = 0; i < strlen(tmpstr); i++) @@ -376,7 +375,7 @@ void CMemoryWindow::onSearch(wxCommandEvent& event) tmpstr = new char[size+1]; tmp2 = &Dest.front(); - sprintf(tmpstr, "%s", (const char *)rawData.mb_str()); + sprintf(tmpstr, "%s", WxStrToStr(rawData).c_str()); for(i = 0; i < size; i++) tmp2[i] = tmpstr[i]; @@ -393,7 +392,7 @@ void CMemoryWindow::onSearch(wxCommandEvent& event) u32 addr = 0; if (txt.size()) { - sscanf(txt.mb_str(), "%08x", &addr); + sscanf(WxStrToStr(txt).c_str(), "%08x", &addr); } i = addr+4; for( ; i < szRAM; i++) diff --git a/Source/Core/DolphinWX/Src/Debugger/RegisterView.cpp b/Source/Core/DolphinWX/Src/Debugger/RegisterView.cpp index c4a30fd522..0c414cb522 100644 --- a/Source/Core/DolphinWX/Src/Debugger/RegisterView.cpp +++ b/Source/Core/DolphinWX/Src/Debugger/RegisterView.cpp @@ -20,6 +20,7 @@ #include "PowerPC/PowerPC.h" #include "HW/ProcessorInterface.h" #include "IniFile.h" +#include "../WxUtils.h" // F-zero 80005e60 wtf?? @@ -51,9 +52,9 @@ wxString CRegTable::GetValue(int row, int col) { if (row < 32) { switch (col) { - case 0: return wxString::FromAscii(GetGPRName(row)); + case 0: return StrToWxStr(GetGPRName(row)); case 1: return wxString::Format(wxT("%08x"), GPR(row)); - case 2: return wxString::FromAscii(GetFPRName(row)); + case 2: return StrToWxStr(GetFPRName(row)); case 3: return wxString::Format(wxT("%016llx"), riPS0(row)); case 4: return wxString::Format(wxT("%016llx"), riPS1(row)); default: return wxEmptyString; @@ -61,7 +62,7 @@ wxString CRegTable::GetValue(int row, int col) } else { if (row - 32 < NUM_SPECIALS) { switch (col) { - case 0: return wxString::FromAscii(special_reg_names[row - 32]); + case 0: return StrToWxStr(special_reg_names[row - 32]); case 1: return wxString::Format(wxT("%08x"), GetSpecialRegValue(row - 32)); default: return wxEmptyString; } @@ -91,7 +92,7 @@ static void SetSpecialRegValue(int reg, u32 value) { void CRegTable::SetValue(int row, int col, const wxString& strNewVal) { u32 newVal = 0; - if (TryParse(std::string(strNewVal.mb_str()), &newVal)) + if (TryParse(WxStrToStr(strNewVal), &newVal)) { if (row < 32) { if (col == 1) diff --git a/Source/Core/DolphinWX/Src/FifoPlayerDlg.cpp b/Source/Core/DolphinWX/Src/FifoPlayerDlg.cpp index 81268e3467..6e18c192eb 100644 --- a/Source/Core/DolphinWX/Src/FifoPlayerDlg.cpp +++ b/Source/Core/DolphinWX/Src/FifoPlayerDlg.cpp @@ -22,6 +22,7 @@ #include "FifoPlayer/FifoPlayer.h" #include "FifoPlayer/FifoRecorder.h" #include "OpcodeDecoding.h" +#include "WxUtils.h" #include #include @@ -395,7 +396,7 @@ void FifoPlayerDlg::OnSaveFile(wxCommandEvent& WXUNUSED(event)) if (!path.empty()) { wxBeginBusyCursor(); - bool result = file->Save(path.mb_str()); + bool result = file->Save(WxStrToStr(path).c_str()); wxEndBusyCursor(); if (!result) @@ -752,10 +753,10 @@ void FifoPlayerDlg::OnObjectCmdListSelectionChanged(wxCommandEvent& event) char name[64]="\0", desc[512]="\0"; GetBPRegInfo(cmddata+1, name, sizeof(name), desc, sizeof(desc)); newLabel = _("BP register "); - newLabel += (name[0] != '\0') ? wxString(name, *wxConvCurrent) : wxString::Format(_("UNKNOWN_%02X"), *(cmddata+1)); + newLabel += (name[0] != '\0') ? StrToWxStr(name) : wxString::Format(_("UNKNOWN_%02X"), *(cmddata+1)); newLabel += wxT(":\n"); if (desc[0] != '\0') - newLabel += wxString(desc, *wxConvCurrent); + newLabel += StrToWxStr(desc); else newLabel += _("No description available"); } diff --git a/Source/Core/DolphinWX/Src/Frame.cpp b/Source/Core/DolphinWX/Src/Frame.cpp index d390b8afcd..a0a030081e 100644 --- a/Source/Core/DolphinWX/Src/Frame.cpp +++ b/Source/Core/DolphinWX/Src/Frame.cpp @@ -100,37 +100,6 @@ CPanel::CPanel( else SetCursor(wxNullCursor); break; - - case WIIMOTE_DISCONNECT: - if (SConfig::GetInstance().m_LocalCoreStartupParameter.bWii) - { - const int wiimote_idx = lParam; - const int wiimote_num = wiimote_idx + 1; - - //Auto reconnect if option is turned on. - //TODO: Make this only auto reconnect wiimotes that have the option activated. - SConfig::GetInstance().LoadSettingsWii();//Make sure we are using the newest settings. - if (SConfig::GetInstance().m_WiiAutoReconnect[wiimote_idx]) - { - GetUsbPointer()->AccessWiiMote(wiimote_idx | 0x100)->Activate(true); - NOTICE_LOG(WIIMOTE, "Wiimote %i has been auto-reconnected...", wiimote_num); - } - else - { - // The Wiimote has been disconnected, we offer reconnect here. - wxMessageDialog *dlg = new wxMessageDialog( - this, - wxString::Format(_("Wiimote %i has been disconnected by system.\nMaybe this game doesn't support multi-wiimote,\nor maybe it is due to idle time out or other reason.\nDo you want to reconnect immediately?"), wiimote_num), - _("Reconnect Wiimote Confirm"), - wxYES_NO | wxSTAY_ON_TOP | wxICON_INFORMATION, //wxICON_QUESTION, - wxDefaultPosition); - - if (dlg->ShowModal() == wxID_YES) - GetUsbPointer()->AccessWiiMote(wiimote_idx | 0x100)->Activate(true); - - dlg->Destroy(); - } - } } break; @@ -690,7 +659,7 @@ void CFrame::OnGameListCtrl_ItemActivated(wxListEvent& WXUNUSED (event)) // 1. Boot the selected iso // 2. Boot the default or last loaded iso. // 3. Call BrowseForDirectory if the gamelist is empty - if (!m_GameListCtrl->GetGameNames().size() && + if (!m_GameListCtrl->GetISO(0) && !((SConfig::GetInstance().m_ListGC && SConfig::GetInstance().m_ListWii && SConfig::GetInstance().m_ListWad) && @@ -724,7 +693,7 @@ void CFrame::OnGameListCtrl_ItemActivated(wxListEvent& WXUNUSED (event)) m_GameListCtrl->Update(); } - else if (!m_GameListCtrl->GetGameNames().size()) + else if (!m_GameListCtrl->GetISO(0)) m_GameListCtrl->BrowseForDirectory(); else // Game started by double click @@ -735,7 +704,7 @@ bool IsHotkey(wxKeyEvent &event, int Id) { return (event.GetKeyCode() != WXK_NONE && event.GetKeyCode() == SConfig::GetInstance().m_LocalCoreStartupParameter.iHotkey[Id] && - event.GetModifiers() == SConfig::GetInstance().m_LocalCoreStartupParameter.iHotkeyModifier[Id]); + event.GetModifiers() == SConfig::GetInstance().m_LocalCoreStartupParameter.iHotkeyModifier[Id]); } int GetCmdForHotkey(unsigned int key) diff --git a/Source/Core/DolphinWX/Src/FrameAui.cpp b/Source/Core/DolphinWX/Src/FrameAui.cpp index 0550c5cd39..6f10d46722 100644 --- a/Source/Core/DolphinWX/Src/FrameAui.cpp +++ b/Source/Core/DolphinWX/Src/FrameAui.cpp @@ -21,6 +21,7 @@ #include "Globals.h" // Local #include "Frame.h" #include "LogWindow.h" +#include "WxUtils.h" #include "ConfigManager.h" // Core @@ -548,7 +549,7 @@ void CFrame::OnDropDownToolbarItem(wxAuiToolBarEvent& event) for (u32 i = 0; i < Perspectives.size(); i++) { wxMenuItem* mItem = new wxMenuItem(menuPopup, IDM_PERSPECTIVES_0 + i, - wxString::FromAscii(Perspectives[i].Name.c_str()), + StrToWxStr(Perspectives[i].Name), wxT(""), wxITEM_CHECK); menuPopup->Append(mItem); if (i == ActivePerspective) mItem->Check(true); @@ -580,7 +581,7 @@ void CFrame::OnToolBar(wxCommandEvent& event) return; } SaveIniPerspectives(); - GetStatusBar()->SetStatusText(wxString::FromAscii(std::string + GetStatusBar()->SetStatusText(StrToWxStr(std::string ("Saved " + Perspectives[ActivePerspective].Name).c_str()), 0); break; case IDM_PERSPECTIVES_ADD_PANE: @@ -633,7 +634,7 @@ void CFrame::OnDropDownToolbarSelect(wxCommandEvent& event) } SPerspectives Tmp; - Tmp.Name = dlg.GetValue().mb_str(); + Tmp.Name = WxStrToStr(dlg.GetValue()); Tmp.Perspective = m_Mgr->SavePerspective(); ActivePerspective = (u32)Perspectives.size(); @@ -870,7 +871,7 @@ void CFrame::LoadIniPerspectives() ini.Get(_Section.c_str(), "Width", &_Width, "70,25"); ini.Get(_Section.c_str(), "Height", &_Height, "80,80"); - Tmp.Perspective = wxString::FromAscii(_Perspective.c_str()); + Tmp.Perspective = StrToWxStr(_Perspective); SplitString(_Width, ',', _SWidth); SplitString(_Height, ',', _SHeight); @@ -940,7 +941,7 @@ void CFrame::SaveIniPerspectives() for (u32 i = 0; i < Perspectives.size(); i++) { std::string _Section = "P - " + Perspectives[i].Name; - ini.Set(_Section.c_str(), "Perspective", Perspectives[i].Perspective.mb_str()); + ini.Set(_Section.c_str(), "Perspective", WxStrToStr(Perspectives[i].Perspective)); std::string SWidth = "", SHeight = ""; for (u32 j = 0; j < Perspectives[i].Width.size(); j++) diff --git a/Source/Core/DolphinWX/Src/FrameTools.cpp b/Source/Core/DolphinWX/Src/FrameTools.cpp index 56dde8e2ce..4b1fc820a9 100644 --- a/Source/Core/DolphinWX/Src/FrameTools.cpp +++ b/Source/Core/DolphinWX/Src/FrameTools.cpp @@ -101,7 +101,7 @@ void CFrame::CreateMenu() drives = cdio_get_devices(); // Windows Limitation of 24 character drives for (unsigned int i = 0; i < drives.size() && i < 24; i++) { - externalDrive->Append(IDM_DRIVE1 + i, wxString::FromAscii(drives[i].c_str())); + externalDrive->Append(IDM_DRIVE1 + i, StrToWxStr(drives[i])); } fileMenu->AppendSeparator(); @@ -601,12 +601,10 @@ void CFrame::DoOpen(bool Boot) // Should we boot a new game or just change the disc? if (Boot && !path.IsEmpty()) - BootGame(std::string(path.mb_str())); + BootGame(WxStrToStr(path)); else { - char newDiscpath[2048]; - strncpy(newDiscpath, path.mb_str(), strlen(path.mb_str())+1); - DVDInterface::ChangeDisc(newDiscpath); + DVDInterface::ChangeDisc(WxStrToStr(path).c_str()); } } @@ -693,7 +691,7 @@ void CFrame::OnPlayRecording(wxCommandEvent& WXUNUSED (event)) GetMenuBar()->FindItem(IDM_RECORDREADONLY)->Check(true); } - if(Movie::PlayInput(path.mb_str())) + if (Movie::PlayInput(WxStrToStr(path).c_str())) BootGame(std::string("")); } @@ -1015,7 +1013,7 @@ void CFrame::DoStop() X11Utils::InhibitScreensaver(X11Utils::XDisplayFromHandle(GetHandle()), X11Utils::XWindowFromHandle(GetHandle()), false); #endif - m_RenderFrame->SetTitle(wxString::FromAscii(scm_rev_str)); + m_RenderFrame->SetTitle(StrToWxStr(scm_rev_str)); // Destroy the renderer frame when not rendering to main m_RenderParent->Unbind(wxEVT_SIZE, &CFrame::OnRenderParentResize, this); @@ -1081,7 +1079,7 @@ void CFrame::DoRecordingSave() if(path.IsEmpty()) return; - Movie::SaveRecording(path.mb_str()); + Movie::SaveRecording(WxStrToStr(path).c_str()); if (!paused) DoPause(); @@ -1212,7 +1210,7 @@ void CFrame::StatusBarMessage(const char * Text, ...) vsnprintf(Str, MAX_BYTES, Text, ArgPtr); va_end(ArgPtr); - if (this->GetStatusBar()->IsEnabled()) this->GetStatusBar()->SetStatusText(wxString::FromAscii(Str),0); + if (this->GetStatusBar()->IsEnabled()) this->GetStatusBar()->SetStatusText(StrToWxStr(Str),0); } @@ -1248,7 +1246,8 @@ void CFrame::OnImportSave(wxCommandEvent& WXUNUSED (event)) if (!path.IsEmpty()) { - CWiiSaveCrypted* saveFile = new CWiiSaveCrypted(path.mb_str()); + // TODO: Does this actually need to be dynamically allocated for some reason? + CWiiSaveCrypted* saveFile = new CWiiSaveCrypted(WxStrToStr(path).c_str()); delete saveFile; } } @@ -1288,7 +1287,7 @@ void CFrame::OnInstallWAD(wxCommandEvent& event) _T("Wii WAD file (*.wad)|*.wad"), wxFD_OPEN | wxFD_PREVIEW | wxFD_FILE_MUST_EXIST, this); - fileName = path.mb_str(); + fileName = WxStrToStr(path); break; } default: @@ -1354,11 +1353,7 @@ void CFrame::ConnectWiimote(int wm_idx, bool connect) GetUsbPointer()->AccessWiiMote(wm_idx | 0x100)->Activate(connect); wxString msg(wxString::Format(wxT("Wiimote %i %s"), wm_idx + 1, connect ? wxT("Connected") : wxT("Disconnected"))); - Core::DisplayMessage(msg.ToAscii(), 3000); - - // Wait for the wiimote to connect - while (GetUsbPointer()->AccessWiiMote(wm_idx | 0x100)->IsConnected() != connect) - {} + Core::DisplayMessage(WxStrToStr(msg), 3000); Host_UpdateMainFrame(); } } @@ -1398,7 +1393,7 @@ void CFrame::OnLoadStateFromFile(wxCommandEvent& WXUNUSED (event)) this); if (!path.IsEmpty()) - State::LoadAs((const char*)path.mb_str()); + State::LoadAs(WxStrToStr(path)); } void CFrame::OnSaveStateToFile(wxCommandEvent& WXUNUSED (event)) @@ -1412,7 +1407,7 @@ void CFrame::OnSaveStateToFile(wxCommandEvent& WXUNUSED (event)) this); if (!path.IsEmpty()) - State::SaveAs((const char*)path.mb_str()); + State::SaveAs(WxStrToStr(path)); } void CFrame::OnLoadLastState(wxCommandEvent& WXUNUSED (event)) diff --git a/Source/Core/DolphinWX/Src/GLInterface.h b/Source/Core/DolphinWX/Src/GLInterface.h index 307ce2b69d..2db10b2dac 100644 --- a/Source/Core/DolphinWX/Src/GLInterface.h +++ b/Source/Core/DolphinWX/Src/GLInterface.h @@ -18,19 +18,24 @@ #define _GLINTERFACE_H_ #include "Thread.h" - -#if defined(USE_EGL) && USE_EGL -#include "GLInterface/EGL.h" +#ifdef ANDROID +#include +#include +#elif defined(USE_EGL) && USE_EGL +#include "GLInterface/EGL_X11.h" #elif defined(__APPLE__) #include "GLInterface/AGL.h" #elif defined(_WIN32) #include "GLInterface/WGL.h" #elif defined(HAVE_X11) && HAVE_X11 #include "GLInterface/GLX.h" +#else +#error Platform doesnt have a GLInterface #endif typedef struct { -#if defined(USE_EGL) && USE_EGL // This is currently a X11/EGL implementation for desktop +#ifdef ANDROID +#elif defined(USE_EGL) && USE_EGL // This is currently a X11/EGL implementation for desktop int screen; Display *dpy; Display *evdpy; diff --git a/Source/Core/DolphinWX/Src/GLInterface/EGL.cpp b/Source/Core/DolphinWX/Src/GLInterface/EGL_X11.cpp similarity index 98% rename from Source/Core/DolphinWX/Src/GLInterface/EGL.cpp rename to Source/Core/DolphinWX/Src/GLInterface/EGL_X11.cpp index 304eb92059..ccb2fc04b8 100644 --- a/Source/Core/DolphinWX/Src/GLInterface/EGL.cpp +++ b/Source/Core/DolphinWX/Src/GLInterface/EGL_X11.cpp @@ -19,7 +19,7 @@ #include "RenderBase.h" #include "../GLInterface.h" -#include "EGL.h" +#include "EGL_X11.h" // Show the current FPS void cInterfaceEGL::UpdateFPSDisplay(const char *text) @@ -141,7 +141,7 @@ bool cInterfaceEGL::Create(void *&window_handle) return false; } - GLWin.egl_surf = eglCreateWindowSurface(GLWin.egl_dpy, config, GLWin.win, NULL); + GLWin.egl_surf = eglCreateWindowSurface(GLWin.egl_dpy, config, (NativeWindowType)GLWin.win, NULL); if (!GLWin.egl_surf) { ERROR_LOG(VIDEO, "Error: eglCreateWindowSurface failed\n"); return false; diff --git a/Source/Core/DolphinWX/Src/GLInterface/EGL.h b/Source/Core/DolphinWX/Src/GLInterface/EGL_X11.h similarity index 98% rename from Source/Core/DolphinWX/Src/GLInterface/EGL.h rename to Source/Core/DolphinWX/Src/GLInterface/EGL_X11.h index 513fb2ce4a..e47573e4d8 100644 --- a/Source/Core/DolphinWX/Src/GLInterface/EGL.h +++ b/Source/Core/DolphinWX/Src/GLInterface/EGL_X11.h @@ -20,6 +20,7 @@ #include #ifdef USE_GLES #include +#include #else #include #include diff --git a/Source/Core/DolphinWX/Src/GLInterface/InterfaceBase.h b/Source/Core/DolphinWX/Src/GLInterface/InterfaceBase.h index c2d1ffc54b..1c00a1fd89 100644 --- a/Source/Core/DolphinWX/Src/GLInterface/InterfaceBase.h +++ b/Source/Core/DolphinWX/Src/GLInterface/InterfaceBase.h @@ -23,11 +23,11 @@ protected: u32 s_backbuffer_width; u32 s_backbuffer_height; public: - virtual void Swap() = 0; - virtual void UpdateFPSDisplay(const char *Text) = 0; - virtual bool Create(void *&window_handle) = 0; - virtual bool MakeCurrent() = 0; - virtual void Shutdown() = 0; + virtual void Swap() {} + virtual void UpdateFPSDisplay(const char *Text) {} + virtual bool Create(void *&window_handle) { return true; } + virtual bool MakeCurrent() { return true; } + virtual void Shutdown() {} virtual void SwapInterval(int Interval) { } virtual u32 GetBackBufferWidth() { return s_backbuffer_width; } diff --git a/Source/Core/DolphinWX/Src/GameListCtrl.cpp b/Source/Core/DolphinWX/Src/GameListCtrl.cpp index 6fd298ad81..bf09161555 100644 --- a/Source/Core/DolphinWX/Src/GameListCtrl.cpp +++ b/Source/Core/DolphinWX/Src/GameListCtrl.cpp @@ -35,6 +35,7 @@ #include "CDUtils.h" #include "WxUtils.h" #include "Main.h" +#include "MathUtil.h" #include "../resources/Flag_Europe.xpm" #include "../resources/Flag_Germany.xpm" @@ -257,7 +258,7 @@ void CGameListCtrl::BrowseForDirectory() if (dialog.ShowModal() == wxID_OK) { - std::string sPath(dialog.GetPath().mb_str()); + std::string sPath(WxStrToStr(dialog.GetPath())); std::vector::iterator itResult = std::find( SConfig::GetInstance().m_ISOFolder.begin(), SConfig::GetInstance().m_ISOFolder.end(), sPath); @@ -285,10 +286,6 @@ void CGameListCtrl::Update() m_imageListSmall = NULL; } - // NetPlay : Set/Reset the GameList string - m_gameList.clear(); - m_gamePath.clear(); - Hide(); ScanForISOs(); @@ -384,35 +381,18 @@ void CGameListCtrl::Update() SetFocus(); } -wxString NiceSizeFormat(s64 _size) +wxString NiceSizeFormat(u64 _size) { - const char* sizes[] = {"b", "KB", "MB", "GB", "TB", "PB", "EB"}; - int s = 0; - int frac = 0; + const char* const unit_symbols[] = {"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"}; + + auto const unit = Log2(std::max(_size, 1)) / 10; + auto const unit_size = (1 << (unit * 10)); + + // ugly rounding integer math + auto const value = (_size + unit_size / 2) / unit_size; + auto const frac = (_size % unit_size * 10 + unit_size / 2) / unit_size % 10; - while (_size > (s64)1024) - { - s++; - frac = (int)_size & 1023; - _size /= (s64)1024; - } - - float f = (float)_size + ((float)frac / 1024.0f); - - wxString NiceString; - char tempstr[32]; - sprintf(tempstr,"%3.1f %s", f, sizes[s]); - NiceString = wxString::FromAscii(tempstr); - return(NiceString); -} - -std::string CGameListCtrl::GetGamePaths() const -{ - return m_gamePath; -} -std::string CGameListCtrl::GetGameNames() const -{ - return m_gameList; + return StrToWxStr(StringFromFormat("%llu.%llu %s", value, frac, unit_symbols[unit])); } void CGameListCtrl::InsertItemInReportView(long _Index) @@ -423,25 +403,7 @@ void CGameListCtrl::InsertItemInReportView(long _Index) // company: 0x007030 int ImageIndex = -1; -#ifdef _WIN32 - wxCSConv SJISConv(*(wxCSConv*)wxConvCurrent); - static bool validCP932 = ::IsValidCodePage(932) != 0; - if (validCP932) - { - SJISConv = wxCSConv(wxFontMapper::GetEncodingName(wxFONTENCODING_SHIFT_JIS)); - } - else - { - WARN_LOG(COMMON, "Cannot Convert from Charset Windows Japanese cp 932"); - } -#else - // on linux the wrong string is returned from wxFontMapper::GetEncodingName(wxFONTENCODING_SHIFT_JIS) - // it returns CP-932, in order to use iconv we need to use CP932 - wxCSConv SJISConv(wxT("CP932")); -#endif - GameListItem& rISOFile = *m_ISOFiles[_Index]; - m_gamePath.append(rISOFile.GetFileName() + '\n'); // Insert a first row with nothing in it, that will be used as the Index long ItemIndex = InsertItem(_Index, wxEmptyString); @@ -454,55 +416,33 @@ void CGameListCtrl::InsertItemInReportView(long _Index) // Set the game's banner in the second column SetItemColumnImage(_Index, COLUMN_BANNER, ImageIndex); - - std::wstring wstring_name; - const std::wstring& wstring_description = rISOFile.GetDescription(); - std::string company; - wxString name; - wxString description; - - // We show the company string on Gamecube only - // On Wii we show the description instead as the company string is empty - if (rISOFile.GetPlatform() == GameListItem::GAMECUBE_DISC) - company = rISOFile.GetCompany().c_str(); int SelectedLanguage = SConfig::GetInstance().m_LocalCoreStartupParameter.SelectedLanguage; + + // Is this sane? switch (rISOFile.GetCountry()) { case DiscIO::IVolume::COUNTRY_TAIWAN: case DiscIO::IVolume::COUNTRY_JAPAN: - { - rISOFile.GetName(wstring_name, -1); - name = wxString(rISOFile.GetName(0).c_str(), SJISConv); - m_gameList.append(StringFromFormat("%s (J)\n", (const char *)name.c_str())); - description = wxString(company.size() ? company.c_str() : - rISOFile.GetDescription(0).c_str(), SJISConv); - } + SelectedLanguage = -1; break; + case DiscIO::IVolume::COUNTRY_USA: SelectedLanguage = 0; + break; + default: - { - wxCSConv WindowsCP1252(wxFontMapper::GetEncodingName(wxFONTENCODING_CP1252)); - rISOFile.GetName(wstring_name, SelectedLanguage); - - name = wxString(rISOFile.GetName(SelectedLanguage).c_str(), WindowsCP1252); - m_gameList.append(StringFromFormat("%s (%c)\n", - rISOFile.GetName(SelectedLanguage).c_str(), - (rISOFile.GetCountry() == DiscIO::IVolume::COUNTRY_USA) ? 'U' : 'E')); - description = wxString(company.size() ? company.c_str() : - rISOFile.GetDescription(SelectedLanguage).c_str(), WindowsCP1252); - } break; } + + std::string const name = rISOFile.GetName(SelectedLanguage); + SetItem(_Index, COLUMN_TITLE, StrToWxStr(name), -1); - if (wstring_name.length()) - name = wstring_name.c_str(); - if (wstring_description.length()) - description = wstring_description.c_str(); - - SetItem(_Index, COLUMN_TITLE, name, -1); - SetItem(_Index, COLUMN_NOTES, description, -1); + // We show the company string on Gamecube only + // On Wii we show the description instead as the company string is empty + std::string const notes = (rISOFile.GetPlatform() == GameListItem::GAMECUBE_DISC) ? + rISOFile.GetCompany() : rISOFile.GetDescription(SelectedLanguage); + SetItem(_Index, COLUMN_NOTES, StrToWxStr(notes), -1); // Emulation state SetItemColumnImage(_Index, COLUMN_EMULATION_STATE, m_EmuStateImageIndex[rISOFile.GetEmuState()]); @@ -614,7 +554,7 @@ void CGameListCtrl::ScanForISOs() // Update with the progress (i) and the message dialog.Update(i, wxString::Format(_("Scanning %s"), - wxString(FileName.c_str(), *wxConvCurrent).c_str())); + StrToWxStr(FileName))); if (dialog.WasCancelled()) break; @@ -858,7 +798,7 @@ void CGameListCtrl::OnMouseMotion(wxMouseEvent& event) char temp[2048]; sprintf(temp, "^ %s%s%s", emuState[emu_state - 1], issues.size() > 0 ? " :\n" : "", issues.c_str()); - toolTip = new wxEmuStateTip(this, wxString(temp, *wxConvCurrent), &toolTip); + toolTip = new wxEmuStateTip(this, StrToWxStr(temp), &toolTip); } else toolTip = new wxEmuStateTip(this, _("Not Set"), &toolTip); @@ -999,8 +939,7 @@ void CGameListCtrl::OnOpenContainingFolder(wxCommandEvent& WXUNUSED (event)) if (!iso) return; - wxString strPath(iso->GetFileName().c_str(), wxConvUTF8); - wxFileName path = wxFileName::FileName(strPath); + wxFileName path = wxFileName::FileName(StrToWxStr(iso->GetFileName())); path.MakeAbsolute(); WxUtils::Explore(path.GetPath().char_str()); } @@ -1115,9 +1054,9 @@ void CGameListCtrl::OnWiki(wxCommandEvent& WXUNUSED (event)) void CGameListCtrl::MultiCompressCB(const char* text, float percent, void* arg) { percent = (((float)m_currentItem) + percent) / (float)m_numberItem; - wxString textString(StringFromFormat("%s (%i/%i) - %s", + wxString textString(StrToWxStr(StringFromFormat("%s (%i/%i) - %s", m_currentFilename.c_str(), (int)m_currentItem+1, - (int)m_numberItem, text).c_str(), *wxConvCurrent); + (int)m_numberItem, text))); ((wxProgressDialog*)arg)->Update((int)(percent*1000), textString); } @@ -1170,13 +1109,13 @@ void CGameListCtrl::CompressSelection(bool _compress) std::string OutputFileName; BuildCompleteFilename(OutputFileName, - (const char *)browseDialog.GetPath().mb_str(wxConvUTF8), + WxStrToStr(browseDialog.GetPath()), FileName); - if (wxFileExists(wxString::FromAscii(OutputFileName.c_str())) && + if (wxFileExists(StrToWxStr(OutputFileName)) && wxMessageBox( wxString::Format(_("The file %s already exists.\nDo you wish to replace it?"), - wxString(OutputFileName.c_str(), *wxConvCurrent).c_str()), + StrToWxStr(OutputFileName)), _("Confirm File Overwrite"), wxYES_NO) == wxNO) continue; @@ -1198,13 +1137,13 @@ void CGameListCtrl::CompressSelection(bool _compress) std::string OutputFileName; BuildCompleteFilename(OutputFileName, - (const char *)browseDialog.GetPath().mb_str(wxConvUTF8), + WxStrToStr(browseDialog.GetPath()), FileName); - if (wxFileExists(wxString::FromAscii(OutputFileName.c_str())) && + if (wxFileExists(StrToWxStr(OutputFileName)) && wxMessageBox( wxString::Format(_("The file %s already exists.\nDo you wish to replace it?"), - wxString(OutputFileName.c_str(), *wxConvCurrent).c_str()), + StrToWxStr(OutputFileName)), _("Confirm File Overwrite"), wxYES_NO) == wxNO) continue; @@ -1225,7 +1164,7 @@ void CGameListCtrl::CompressSelection(bool _compress) void CGameListCtrl::CompressCB(const char* text, float percent, void* arg) { ((wxProgressDialog*)arg)-> - Update((int)(percent*1000), wxString(text, *wxConvCurrent)); + Update((int)(percent*1000), StrToWxStr(text)); } void CGameListCtrl::OnCompressGCM(wxCommandEvent& WXUNUSED (event)) @@ -1251,8 +1190,8 @@ void CGameListCtrl::OnCompressGCM(wxCommandEvent& WXUNUSED (event)) path = wxFileSelector( _("Save decompressed GCM/ISO"), - wxString(FilePath.c_str(), *wxConvCurrent), - wxString(FileName.c_str(), *wxConvCurrent) + FileType.After('*'), + StrToWxStr(FilePath), + StrToWxStr(FileName) + FileType.After('*'), wxEmptyString, FileType + wxT("|") + wxGetTranslation(wxALL_FILES), wxFD_SAVE, @@ -1262,8 +1201,8 @@ void CGameListCtrl::OnCompressGCM(wxCommandEvent& WXUNUSED (event)) { path = wxFileSelector( _("Save compressed GCM/ISO"), - wxString(FilePath.c_str(), *wxConvCurrent), - wxString(FileName.c_str(), *wxConvCurrent) + _T(".gcz"), + StrToWxStr(FilePath), + StrToWxStr(FileName) + _T(".gcz"), wxEmptyString, _("All compressed GC/Wii ISO files (gcz)") + wxString::Format(wxT("|*.gcz|%s"), wxGetTranslation(wxALL_FILES)), diff --git a/Source/Core/DolphinWX/Src/GameListCtrl.h b/Source/Core/DolphinWX/Src/GameListCtrl.h index 5d97c12724..f1923e97c5 100644 --- a/Source/Core/DolphinWX/Src/GameListCtrl.h +++ b/Source/Core/DolphinWX/Src/GameListCtrl.h @@ -47,10 +47,6 @@ public: void Update(); - // Net Play method - std::string GetGamePaths() const; - std::string GetGameNames() const; - void BrowseForDirectory(); const GameListItem *GetSelectedISO(); const GameListItem *GetISO(size_t index) const; @@ -84,10 +80,6 @@ private: } } - // NetPlay string for the gamelist - std::string m_gameList; - std::string m_gamePath; - int last_column; int last_sort; wxSize lastpos; diff --git a/Source/Core/DolphinWX/Src/GeckoCodeDiag.cpp b/Source/Core/DolphinWX/Src/GeckoCodeDiag.cpp index e015c55ae8..76d4833c0b 100644 --- a/Source/Core/DolphinWX/Src/GeckoCodeDiag.cpp +++ b/Source/Core/DolphinWX/Src/GeckoCodeDiag.cpp @@ -13,6 +13,7 @@ // If not, see http://www.gnu.org/licenses/ #include "GeckoCodeDiag.h" +#include "WxUtils.h" #include @@ -76,7 +77,7 @@ void CodeConfigPanel::UpdateCodeList() gcodes_end = m_gcodes.end(); for (; gcodes_iter!=gcodes_end; ++gcodes_iter) { - m_listbox_gcodes->Append(wxString(gcodes_iter->name.c_str(), *wxConvCurrent)); + m_listbox_gcodes->Append(StrToWxStr(gcodes_iter->name)); if (gcodes_iter->enabled) m_listbox_gcodes->Check(m_listbox_gcodes->GetCount()-1, true); } @@ -109,7 +110,7 @@ void CodeConfigPanel::UpdateInfoBox(wxCommandEvent&) if (sel > -1) { - m_infobox.label_name->SetLabel(wxGetTranslation(wxstr_name) + wxString(m_gcodes[sel].name.c_str(), *wxConvCurrent)); + m_infobox.label_name->SetLabel(wxGetTranslation(wxstr_name) + StrToWxStr(m_gcodes[sel].name)); // notes textctrl m_infobox.textctrl_notes->Clear(); @@ -117,10 +118,10 @@ void CodeConfigPanel::UpdateInfoBox(wxCommandEvent&) notes_iter = m_gcodes[sel].notes.begin(), notes_end = m_gcodes[sel].notes.end(); for (; notes_iter!=notes_end; ++notes_iter) - m_infobox.textctrl_notes->AppendText(wxString(notes_iter->c_str(), *wxConvCurrent)); + m_infobox.textctrl_notes->AppendText(StrToWxStr(*notes_iter)); m_infobox.textctrl_notes->ScrollLines(-99); // silly - m_infobox.label_creator->SetLabel(wxGetTranslation(wxstr_creator) + wxString(m_gcodes[sel].creator.c_str(), *wxConvCurrent)); + m_infobox.label_creator->SetLabel(wxGetTranslation(wxstr_creator) + StrToWxStr(m_gcodes[sel].creator)); // add codes to info listbox std::vector::const_iterator diff --git a/Source/Core/DolphinWX/Src/ISOFile.cpp b/Source/Core/DolphinWX/Src/ISOFile.cpp index 1e4164b7aa..797780c32e 100644 --- a/Source/Core/DolphinWX/Src/ISOFile.cpp +++ b/Source/Core/DolphinWX/Src/ISOFile.cpp @@ -28,15 +28,16 @@ #include "StringUtil.h" #include "Hash.h" #include "IniFile.h" +#include "WxUtils.h" #include "Filesystem.h" #include "BannerLoader.h" #include "FileSearch.h" #include "CompressedBlob.h" #include "ChunkFile.h" -#include "../resources/no_banner.cpp" +#include "ConfigManager.h" -#define CACHE_REVISION 0x10F +#define CACHE_REVISION 0x112 #define DVD_BANNER_WIDTH 96 #define DVD_BANNER_HEIGHT 32 @@ -65,26 +66,10 @@ GameListItem::GameListItem(const std::string& _rFileName) else { m_Platform = WII_WAD; - pVolume->GetWName(m_wNames); } - m_Company = "N/A"; + m_volume_names = pVolume->GetNames(); - - m_Name[0] = pVolume->GetName(); - - if(m_Name[0] == "") // Couldn't find the name in the WAD... - { - std::string FileName; - SplitPath(m_FileName, NULL, &FileName, NULL); - m_Name[0] = FileName; // Then just display the filename... Better than something like "No Name" - } - - for (int i = 0; i < 6; i++) - { - m_Name[i] = m_Name[0]; - m_Description[i] = "No Description"; - } m_Country = pVolume->GetCountry(); m_FileSize = File::GetSize(_rFileName); m_VolumeSize = pVolume->GetSize(); @@ -104,12 +89,9 @@ GameListItem::GameListItem(const std::string& _rFileName) { if (pBannerLoader->IsValid()) { - m_wNames.clear(); - pBannerLoader->GetName(m_wNames); - pBannerLoader->GetName(m_Name); - pBannerLoader->GetCompany(m_Company); - pBannerLoader->GetDescription(m_wDescription); - pBannerLoader->GetDescription(m_Description); + m_names = pBannerLoader->GetNames(); + m_company = pBannerLoader->GetCompany(); + m_descriptions = pBannerLoader->GetDescriptions(); if (pBannerLoader->GetBanner(g_ImageTemp)) { @@ -129,25 +111,6 @@ GameListItem::GameListItem(const std::string& _rFileName) delete pFileSystem; } - std::vector::iterator i, end = m_wNames.end(); - std::wstring wFileName; - for (i = m_wNames.begin(); i != end; ++i) - { - if (*i == L"") - { - if (!wFileName.length()) - { - std::string FileName; - SplitPath(m_FileName, NULL, &FileName, NULL); - int length = FileName.length(); - wFileName.reserve(length+1); - for (int j = 0; j < length; ++j) - wFileName.push_back(FileName[j]); - wFileName.push_back(0); - } - *i = wFileName; - } - } delete pVolume; @@ -174,10 +137,16 @@ GameListItem::GameListItem(const std::string& _rFileName) } else { + std::string theme = SConfig::GetInstance().m_LocalCoreStartupParameter.theme_name + "/"; + std::string dir = File::GetUserPath(D_THEMES_IDX) + theme; + +#if !defined(_WIN32) + // If theme does not exist in user's dir load from shared directory + if (!File::Exists(dir)) + dir = SHARED_USER_DIR THEMES_DIR "/" + theme; +#endif // default banner - wxMemoryInputStream istream(no_banner_png, sizeof no_banner_png); - wxImage iNoBanner(istream, wxBITMAP_TYPE_PNG); - m_Image = iNoBanner; + m_Image = wxImage(dir + "nobanner.png", wxBITMAP_TYPE_PNG); } } @@ -202,33 +171,10 @@ void GameListItem::SaveToCache() void GameListItem::DoState(PointerWrap &p) { - p.Do(m_Name[0]); p.Do(m_Name[1]); p.Do(m_Name[2]); - p.Do(m_Name[3]); p.Do(m_Name[4]); p.Do(m_Name[5]); - - int wNamesSize = m_wNames.size(); - p.Do(wNamesSize); - - if (p.mode == p.MODE_READ) - { - for (int i = 0; i < wNamesSize; ++i) - { - std::wstring temp; - p.Do(temp); - m_wNames.push_back(temp); - } - } - else - { - for (int i = 0; i < wNamesSize; ++i) - { - p.Do(m_wNames[i]); - } - } - - p.Do(m_Company); - p.Do(m_Description[0]); p.Do(m_Description[1]); p.Do(m_Description[2]); - p.Do(m_Description[3]); p.Do(m_Description[4]); p.Do(m_Description[5]); - p.Do(m_wDescription); + p.Do(m_volume_names); + p.Do(m_company); + p.Do(m_names); + p.Do(m_descriptions); p.Do(m_UniqueID); p.Do(m_FileSize); p.Do(m_VolumeSize); @@ -257,49 +203,73 @@ std::string GameListItem::CreateCacheFilename() return fullname; } -const std::string& GameListItem::GetDescription(int index) const +std::string GameListItem::GetCompany() const { - if ((index >=0) && (index < 6)) - { - return m_Description[index]; - } - return m_Description[0]; + if (m_company.empty()) + return "N/A"; + else + return m_company; } -const std::wstring& GameListItem::GetDescription() const +// (-1 = Japanese, 0 = English, etc) +std::string GameListItem::GetDescription(int _index) const { - return m_wDescription; + const u32 index = _index + 1; + + if (index < m_descriptions.size()) + return m_descriptions[index]; + + if (!m_descriptions.empty()) + return m_descriptions[0]; + + return ""; } -const std::string& GameListItem::GetName(int index) const +// (-1 = Japanese, 0 = English, etc) +std::string GameListItem::GetVolumeName(int _index) const { - if ((index >=0) && (index < 6)) - { - return m_Name[index]; - } - return m_Name[0]; + u32 const index = _index + 1; + + if (index < m_volume_names.size() && !m_volume_names[index].empty()) + return m_volume_names[index]; + + if (!m_volume_names.empty()) + return m_volume_names[0]; + + return ""; } -bool GameListItem::GetName(std::wstring& wName, int index) const +// (-1 = Japanese, 0 = English, etc) +std::string GameListItem::GetBannerName(int _index) const { - // This function will only succeed for wii discs with banners or WADs - // utilize the same array as for gc discs (-1= Japanese, 0 = English etc - index++; - if ((index >= 0) && (index < 10)) + u32 const index = _index + 1; + + if (index < m_names.size() && !m_names[index].empty()) + return m_names[index]; + + if (!m_names.empty()) + return m_names[0]; + + return ""; +} + +// (-1 = Japanese, 0 = English, etc) +std::string GameListItem::GetName(int _index) const +{ + // Prefer name from banner, fallback to name from volume, fallback to filename + + std::string name = GetBannerName(_index); + + if (name.empty()) + name = GetVolumeName(_index); + + if (name.empty()) { - if (m_wNames.size() > (size_t)index) - { - wName = m_wNames[index]; - return true; - } + // No usable name, return filename (better than nothing) + SplitPath(GetFileName(), NULL, &name, NULL); } - if (m_wNames.size() > 0) - { - wName = m_wNames[0]; - return true; - } - return false; + return name; } const std::string GameListItem::GetWiiFSPath() const @@ -325,7 +295,7 @@ const std::string GameListItem::GetWiiFSPath() const File::CreateFullPath(Path); if (Path[0] == '.') - ret = std::string(wxGetCwd().mb_str()) + std::string(Path).substr(strlen(ROOT_DIR)); + ret = WxStrToStr(wxGetCwd()) + std::string(Path).substr(strlen(ROOT_DIR)); else ret = std::string(Path); } diff --git a/Source/Core/DolphinWX/Src/ISOFile.h b/Source/Core/DolphinWX/Src/ISOFile.h index e58dcf7713..354a2f7fad 100644 --- a/Source/Core/DolphinWX/Src/ISOFile.h +++ b/Source/Core/DolphinWX/Src/ISOFile.h @@ -18,6 +18,9 @@ #ifndef __ISOFILE_H_ #define __ISOFILE_H_ +#include +#include + #include "Volume.h" #include "VolumeCreator.h" @@ -34,11 +37,11 @@ public: bool IsValid() const {return m_Valid;} const std::string& GetFileName() const {return m_FileName;} - const std::string& GetName(int index) const; - bool GetName(std::wstring& wName, int index=0) const; - const std::string& GetCompany() const {return m_Company;} - const std::string& GetDescription(int index) const; - const std::wstring& GetDescription() const; + std::string GetBannerName(int index) const; + std::string GetVolumeName(int index) const; + std::string GetName(int index) const; + std::string GetCompany() const; + std::string GetDescription(int index = 0) const; const std::string& GetUniqueID() const {return m_UniqueID;} const std::string GetWiiFSPath() const; DiscIO::IVolume::ECountry GetCountry() const {return m_Country;} @@ -65,11 +68,15 @@ public: private: std::string m_FileName; - std::string m_Name[6]; - std::vector m_wNames; - std::string m_Company; - std::string m_Description[6]; - std::wstring m_wDescription; + + // TODO: eliminate this and overwrite with names from banner when available? + std::vector m_volume_names; + + // Stuff from banner + std::string m_company; + std::vector m_names; + std::vector m_descriptions; + std::string m_UniqueID; std::string m_issues; diff --git a/Source/Core/DolphinWX/Src/ISOProperties.cpp b/Source/Core/DolphinWX/Src/ISOProperties.cpp index c44aad5d5b..f6ca1cb851 100644 --- a/Source/Core/DolphinWX/Src/ISOProperties.cpp +++ b/Source/Core/DolphinWX/Src/ISOProperties.cpp @@ -23,6 +23,7 @@ #include "CommonPaths.h" #include "Globals.h" +#include "WxUtils.h" #include "VolumeCreator.h" #include "Filesystem.h" #include "ISOProperties.h" @@ -136,7 +137,8 @@ CISOProperties::CISOProperties(const std::string fileName, wxWindow* parent, wxW else { // Will fail out if GameConfig folder doesn't exist - std::ofstream f(GameIniFile.c_str()); + std::ofstream f; + OpenFStream(f, GameIniFile, std::ios_base::out); if (f) { f << "# " << OpenISO->GetUniqueID() << " - " << OpenISO->GetName() << '\n' @@ -150,21 +152,14 @@ CISOProperties::CISOProperties(const std::string fileName, wxWindow* parent, wxW LoadGameConfig(); else wxMessageBox(wxString::Format(_("Could not create %s"), - wxString::From8BitData(GameIniFile.c_str()).c_str()), + StrToWxStr(GameIniFile).c_str()), _("Error"), wxOK|wxICON_ERROR, this); } // Disk header and apploader - std::wstring wname; - wxString name; - if (OpenGameListItem->GetName(wname)) - name = wname.c_str(); - else - name = wxString(OpenISO->GetName().c_str(), wxConvUTF8); - m_Name->SetValue(name); - - m_GameID->SetValue(wxString(OpenISO->GetUniqueID().c_str(), wxConvUTF8)); + m_Name->SetValue(StrToWxStr(OpenISO->GetName())); + m_GameID->SetValue(StrToWxStr(OpenISO->GetUniqueID())); switch (OpenISO->GetCountry()) { case DiscIO::IVolume::COUNTRY_EUROPE: @@ -204,9 +199,9 @@ CISOProperties::CISOProperties(const std::string fileName, wxWindow* parent, wxW m_Country->SetValue(_("UNKNOWN")); break; } - wxString temp = _T("0x") + wxString::From8BitData(OpenISO->GetMakerID().c_str()); + wxString temp = _T("0x") + StrToWxStr(OpenISO->GetMakerID()); m_MakerID->SetValue(temp); - m_Date->SetValue(wxString::From8BitData(OpenISO->GetApploaderDate().c_str())); + m_Date->SetValue(StrToWxStr(OpenISO->GetApploaderDate())); m_FST->SetValue(wxString::Format(wxT("%u"), OpenISO->GetFSTSize())); // Here we set all the info to be shown (be it SJIS or Ascii) + we set the window title @@ -271,12 +266,12 @@ size_t CISOProperties::CreateDirectoryTree(wxTreeItemId& parent, // check next index if (rFileInfo->IsDirectory()) { - wxTreeItemId item = m_Treectrl->AppendItem(parent, wxString::From8BitData(itemName), 1, 1); + wxTreeItemId item = m_Treectrl->AppendItem(parent, StrToWxStr(itemName), 1, 1); CurrentIndex = CreateDirectoryTree(item, fileInfos, CurrentIndex + 1, (size_t)rFileInfo->m_FileSize); } else { - m_Treectrl->AppendItem(parent, wxString::From8BitData(itemName), 2, 2); + m_Treectrl->AppendItem(parent, StrToWxStr(itemName), 2, 2); CurrentIndex++; } } @@ -663,10 +658,10 @@ void CISOProperties::OnExtractFile(wxCommandEvent& WXUNUSED (event)) { int partitionNum = wxAtoi(File.SubString(10, 11)); File.Remove(0, 12); // Remove "Partition x/" - WiiDisc.at(partitionNum).FileSystem->ExportFile(File.mb_str(), Path.mb_str()); + WiiDisc.at(partitionNum).FileSystem->ExportFile(WxStrToStr(File).c_str(), WxStrToStr(Path).c_str()); } else - pFileSystem->ExportFile(File.mb_str(), Path.mb_str()); + pFileSystem->ExportFile(WxStrToStr(File).c_str(), WxStrToStr(Path).c_str()); } void CISOProperties::ExportDir(const char* _rFullPath, const char* _rExportFolder, const int partitionNum) @@ -727,7 +722,7 @@ void CISOProperties::ExportDir(const char* _rFullPath, const char* _rExportFolde (u32)(((float)(i - index[0]) / (float)(index[1] - index[0])) * 100))); dialog.Update(i, wxString::Format(_("Extracting %s"), - wxString(fst[i]->m_FullPath, *wxConvCurrent).c_str())); + StrToWxStr(fst[i]->m_FullPath))); if (dialog.WasCancelled()) break; @@ -778,9 +773,9 @@ void CISOProperties::OnExtractDir(wxCommandEvent& event) { if (DiscIO::IsVolumeWiiDisc(OpenISO)) for (u32 i = 0; i < WiiDisc.size(); i++) - ExportDir(NULL, Path.mb_str(), i); + ExportDir(NULL, WxStrToStr(Path).c_str(), i); else - ExportDir(NULL, Path.mb_str()); + ExportDir(NULL, WxStrToStr(Path).c_str()); return; } @@ -798,10 +793,10 @@ void CISOProperties::OnExtractDir(wxCommandEvent& event) { int partitionNum = wxAtoi(Directory.SubString(10, 11)); Directory.Remove(0, 12); // Remove "Partition x/" - ExportDir(Directory.mb_str(), Path.mb_str(), partitionNum); + ExportDir(WxStrToStr(Directory).c_str(), WxStrToStr(Path).c_str(), partitionNum); } else - ExportDir(Directory.mb_str(), Path.mb_str()); + ExportDir(WxStrToStr(Directory).c_str(), WxStrToStr(Path).c_str()); } void CISOProperties::OnExtractDataFromHeader(wxCommandEvent& event) @@ -821,15 +816,15 @@ void CISOProperties::OnExtractDataFromHeader(wxCommandEvent& event) bool ret = false; if (event.GetId() == IDM_EXTRACTAPPLOADER) { - ret = FS->ExportApploader(Path.mb_str()); + ret = FS->ExportApploader(WxStrToStr(Path).c_str()); } else if (event.GetId() == IDM_EXTRACTDOL) { - ret = FS->ExportDOL(Path.mb_str()); + ret = FS->ExportDOL(WxStrToStr(Path).c_str()); } if (!ret) - PanicAlertT("Failed to extract to %s!", (const char *)Path.mb_str()); + PanicAlertT("Failed to extract to %s!", WxStrToStr(Path).c_str()); } class IntegrityCheckThread : public wxThread @@ -989,7 +984,7 @@ void CISOProperties::LoadGameConfig() GameIni.Get("EmuState", "EmulationIssues", &sTemp); if (!sTemp.empty()) { - EmuIssues->SetValue(wxString(sTemp.c_str(), *wxConvCurrent)); + EmuIssues->SetValue(StrToWxStr(sTemp)); } EmuIssues->Enable(EmuState->GetSelection() != 0); @@ -1075,7 +1070,7 @@ bool CISOProperties::SaveGameConfig() GameIni.Get("EmuState","EmulationIssues", &sTemp); if (EmuIssues->GetValue() != sTemp) bRefreshList = true; - GameIni.Set("EmuState", "EmulationIssues", (const char*)EmuIssues->GetValue().mb_str(*wxConvCurrent)); + GameIni.Set("EmuState", "EmulationIssues", WxStrToStr(EmuIssues->GetValue())); PatchList_Save(); ActionReplayList_Save(); @@ -1086,7 +1081,7 @@ bool CISOProperties::SaveGameConfig() void CISOProperties::OnEditConfig(wxCommandEvent& WXUNUSED (event)) { - if (wxFileExists(wxString::From8BitData(GameIniFile.c_str()))) + if (File::Exists(GameIniFile)) { SaveGameConfig(); @@ -1107,7 +1102,7 @@ void CISOProperties::OnEditConfig(wxCommandEvent& WXUNUSED (event)) } } wxString OpenCommand; - OpenCommand = filetype->GetOpenCommand(wxString::From8BitData(GameIniFile.c_str())); + OpenCommand = filetype->GetOpenCommand(StrToWxStr(GameIniFile)); if(OpenCommand.IsEmpty()) PanicAlertT("Couldn't find open command for extension 'ini'!"); else @@ -1156,7 +1151,7 @@ void CISOProperties::PatchList_Load() for (std::vector::const_iterator it = onFrame.begin(); it != onFrame.end(); ++it) { PatchEngine::Patch p = *it; - Patches->Append(wxString(p.name.c_str(), *wxConvCurrent)); + Patches->Append(StrToWxStr(p.name)); Patches->Check(index, p.active); ++index; } @@ -1209,7 +1204,7 @@ void CISOProperties::PatchButtonClicked(wxCommandEvent& event) CPatchAddEdit dlg(-1, this, 1, _("Add Patch")); if (dlg.ShowModal() == wxID_OK) { - Patches->Append(wxString(onFrame.back().name.c_str(), *wxConvCurrent)); + Patches->Append(StrToWxStr(onFrame.back().name)); Patches->Check((unsigned int)(onFrame.size() - 1), onFrame.back().active); } } @@ -1238,7 +1233,7 @@ void CISOProperties::ActionReplayList_Load() for (std::vector::const_iterator it = arCodes.begin(); it != arCodes.end(); ++it) { ActionReplay::ARCode arCode = *it; - Cheats->Append(wxString(arCode.name.c_str(), *wxConvCurrent)); + Cheats->Append(StrToWxStr(arCode.name)); Cheats->Check(index, arCode.active); ++index; } @@ -1256,7 +1251,7 @@ void CISOProperties::ActionReplayList_Save() for (std::vector::const_iterator iter2 = code.ops.begin(); iter2 != code.ops.end(); ++iter2) { - lines.push_back(std::string(wxString::Format(wxT("%08X %08X"), iter2->cmd_addr, iter2->value).mb_str())); + lines.push_back(WxStrToStr(wxString::Format(wxT("%08X %08X"), iter2->cmd_addr, iter2->value))); } ++index; } @@ -1280,7 +1275,7 @@ void CISOProperties::ActionReplayButtonClicked(wxCommandEvent& event) CARCodeAddEdit dlg(-1, this, 1, _("Add ActionReplay Code")); if (dlg.ShowModal() == wxID_OK) { - Cheats->Append(wxString::From8BitData(arCodes.back().name.c_str())); + Cheats->Append(StrToWxStr(arCodes.back().name)); Cheats->Check((unsigned int)(arCodes.size() - 1), arCodes.back().active); } } @@ -1306,56 +1301,26 @@ void CISOProperties::OnChangeBannerLang(wxCommandEvent& event) void CISOProperties::ChangeBannerDetails(int lang) { - std::wstring wname; - wxString shortName, - comment, - maker; - -#ifdef _WIN32 - wxCSConv SJISConv(*(wxCSConv*)wxConvCurrent); - static bool validCP932 = ::IsValidCodePage(932) != 0; - if (validCP932) - { - SJISConv = wxCSConv(wxFontMapper::GetEncodingName(wxFONTENCODING_SHIFT_JIS)); - } - else - { - WARN_LOG(COMMON, "Cannot Convert from Charset Windows Japanese cp 932"); - } -#else - // on linux the wrong string is returned from wxFontMapper::GetEncodingName(wxFONTENCODING_SHIFT_JIS) - // it returns CP-932, in order to use iconv we need to use CP932 - wxCSConv SJISConv(wxT("CP932")); -#endif + // why? switch (OpenGameListItem->GetCountry()) { case DiscIO::IVolume::COUNTRY_TAIWAN: case DiscIO::IVolume::COUNTRY_JAPAN: - - if (OpenGameListItem->GetName(wname, -1)) - shortName = wname.c_str(); - else - shortName = wxString(OpenGameListItem->GetName(0).c_str(), SJISConv); - - if ((comment = OpenGameListItem->GetDescription().c_str()).size() == 0) - comment = wxString(OpenGameListItem->GetDescription(0).c_str(), SJISConv); - maker = wxString(OpenGameListItem->GetCompany().c_str(), SJISConv); + lang = -1; break; + case DiscIO::IVolume::COUNTRY_USA: lang = 0; + break; + default: - { - wxCSConv WindowsCP1252(wxFontMapper::GetEncodingName(wxFONTENCODING_CP1252)); - if (OpenGameListItem->GetName(wname, lang)) - shortName = wname.c_str(); - else - shortName = wxString(OpenGameListItem->GetName(lang).c_str(), WindowsCP1252); - if ((comment = OpenGameListItem->GetDescription().c_str()).size() == 0) - comment = wxString(OpenGameListItem->GetDescription(lang).c_str(), WindowsCP1252); - maker = wxString(OpenGameListItem->GetCompany().c_str(), WindowsCP1252); - } break; } + + wxString const shortName = StrToWxStr(OpenGameListItem->GetBannerName(lang)); + wxString const comment = StrToWxStr(OpenGameListItem->GetDescription(lang)); + wxString const maker = StrToWxStr(OpenGameListItem->GetCompany()); + // Updates the informations shown in the window m_ShortName->SetValue(shortName); m_Comment->SetValue(comment); @@ -1364,5 +1329,6 @@ void CISOProperties::ChangeBannerDetails(int lang) std::string filename, extension; SplitPath(OpenGameListItem->GetFileName(), 0, &filename, &extension); // Also sets the window's title - SetTitle(wxString(StringFromFormat("%s%s: %s - ", filename.c_str(), extension.c_str(), OpenGameListItem->GetUniqueID().c_str()).c_str(), *wxConvCurrent)+shortName); + SetTitle(StrToWxStr(StringFromFormat("%s%s: %s - ", filename.c_str(), + extension.c_str(), OpenGameListItem->GetUniqueID().c_str())) + shortName); } diff --git a/Source/Core/DolphinWX/Src/InputConfigDiag.cpp b/Source/Core/DolphinWX/Src/InputConfigDiag.cpp index 1efcf98af6..14772d8676 100644 --- a/Source/Core/DolphinWX/Src/InputConfigDiag.cpp +++ b/Source/Core/DolphinWX/Src/InputConfigDiag.cpp @@ -17,10 +17,7 @@ #include "InputConfigDiag.h" #include "UDPConfigDiag.h" - -#define WXSTR_FROM_STR(s) (wxString::FromUTF8((s).c_str())) -#define WXTSTR_FROM_CSTR(s) (wxGetTranslation(wxString::FromUTF8(s))) -#define STR_FROM_WXSTR(w) (std::string((w).ToUTF8())) +#include "WxUtils.h" void GamepadPage::ConfigUDPWii(wxCommandEvent &event) { @@ -37,7 +34,7 @@ void GamepadPage::ConfigExtension(wxCommandEvent& event) if (ex->switch_extension) { wxDialog dlg(this, -1, - WXTSTR_FROM_CSTR(ex->attachments[ex->switch_extension]->GetName().c_str()), + StrToWxStr(ex->attachments[ex->switch_extension]->GetName()), wxDefaultPosition, wxDefaultSize); wxBoxSizer* const main_szr = new wxBoxSizer(wxVERTICAL); @@ -67,7 +64,7 @@ PadSettingExtension::PadSettingExtension(wxWindow* const parent, ControllerEmu:: e = extension->attachments.end(); for (; i!=e; ++i) - ((wxChoice*)wxcontrol)->Append(WXTSTR_FROM_CSTR((*i)->GetName().c_str())); + ((wxChoice*)wxcontrol)->Append(StrToWxStr((*i)->GetName())); UpdateGUI(); } @@ -83,7 +80,7 @@ void PadSettingExtension::UpdateValue() } PadSettingCheckBox::PadSettingCheckBox(wxWindow* const parent, ControlState& _value, const char* const label) - : PadSetting(new wxCheckBox(parent, -1, WXTSTR_FROM_CSTR(label), wxDefaultPosition)) + : PadSetting(new wxCheckBox(parent, -1, StrToWxStr(label), wxDefaultPosition)) , value(_value) { UpdateGUI(); @@ -119,8 +116,8 @@ ControlDialog::ControlDialog(GamepadPage* const parent, InputPlugin& plugin, Con m_devq = m_parent->controller->default_device; // GetStrings() sounds slow :/ - //device_cbox = new wxComboBox(this, -1, WXSTR_FROM_STR(ref->device_qualifier.ToString()), wxDefaultPosition, wxSize(256,-1), parent->device_cbox->GetStrings(), wxTE_PROCESS_ENTER); - device_cbox = new wxComboBox(this, -1, WXSTR_FROM_STR(m_devq.ToString()), wxDefaultPosition, wxSize(256,-1), parent->device_cbox->GetStrings(), wxTE_PROCESS_ENTER); + //device_cbox = new wxComboBox(this, -1, StrToWxStr(ref->device_qualifier.ToString()), wxDefaultPosition, wxSize(256,-1), parent->device_cbox->GetStrings(), wxTE_PROCESS_ENTER); + device_cbox = new wxComboBox(this, -1, StrToWxStr(m_devq.ToString()), wxDefaultPosition, wxSize(256,-1), parent->device_cbox->GetStrings(), wxTE_PROCESS_ENTER); device_cbox->Bind(wxEVT_COMMAND_COMBOBOX_SELECTED, &ControlDialog::SetDevice, this); device_cbox->Bind(wxEVT_COMMAND_TEXT_ENTER, &ControlDialog::SetDevice, this); @@ -145,9 +142,9 @@ ControlButton::ControlButton(wxWindow* const parent, ControllerInterface::Contro , control_reference(_ref) { if (label.empty()) - SetLabel(WXSTR_FROM_STR(_ref->expression)); + SetLabel(StrToWxStr(_ref->expression)); else - SetLabel(WXSTR_FROM_STR(label)); + SetLabel(StrToWxStr(label)); } void InputConfigDialog::UpdateProfileComboBox() @@ -169,7 +166,7 @@ void InputConfigDialog::UpdateProfileComboBox() for (; si!=se; ++si) { std::string str(si->begin() + si->find_last_of('/') + 1 , si->end() - 4) ; - strs.push_back(WXSTR_FROM_STR(str)); + strs.push_back(StrToWxStr(str)); } std::vector< GamepadPage* >::iterator i = m_padpages.begin(), @@ -209,7 +206,7 @@ void ControlDialog::UpdateListContents() i = dev->Inputs().begin(), e = dev->Inputs().end(); for (; i!=e; ++i) - control_lbox->Append(WXSTR_FROM_STR((*i)->GetName())); + control_lbox->Append(StrToWxStr((*i)->GetName())); } else { @@ -218,7 +215,7 @@ void ControlDialog::UpdateListContents() i = dev->Outputs().begin(), e = dev->Outputs().end(); for (; i!=e; ++i) - control_lbox->Append(WXSTR_FROM_STR((*i)->GetName())); + control_lbox->Append(StrToWxStr((*i)->GetName())); } } } @@ -227,7 +224,7 @@ void ControlDialog::SelectControl(const std::string& name) { //UpdateGUI(); - const int f = control_lbox->FindString(WXSTR_FROM_STR(name)); + const int f = control_lbox->FindString(StrToWxStr(name)); if (f >= 0) control_lbox->Select(f); } @@ -235,7 +232,7 @@ void ControlDialog::SelectControl(const std::string& name) void ControlDialog::UpdateGUI() { // update textbox - textctrl->SetValue(WXSTR_FROM_STR(control_reference->expression)); + textctrl->SetValue(StrToWxStr(control_reference->expression)); // updates the "bound controls:" label m_bound_label->SetLabel(wxString::Format(_("Bound Controls: %lu"), @@ -244,7 +241,7 @@ void ControlDialog::UpdateGUI() void GamepadPage::UpdateGUI() { - device_cbox->SetValue(WXSTR_FROM_STR(controller->default_device.ToString())); + device_cbox->SetValue(StrToWxStr(controller->default_device.ToString())); std::vector< ControlGroupBox* >::const_iterator g = control_groups.begin(), ge = control_groups.end(); @@ -255,7 +252,7 @@ void GamepadPage::UpdateGUI() , e = (*g)->control_buttons.end(); for (; i!=e; ++i) //if (std::string::npos == (*i)->control_reference->expression.find_first_of("`|&!#")) - (*i)->SetLabel(WXSTR_FROM_STR((*i)->control_reference->expression)); + (*i)->SetLabel(StrToWxStr((*i)->control_reference->expression)); //else //(*i)->SetLabel(wxT("...")); @@ -294,7 +291,7 @@ void GamepadPage::LoadDefaults(wxCommandEvent&) void ControlDialog::SetControl(wxCommandEvent&) { - control_reference->expression = STR_FROM_WXSTR(textctrl->GetValue()); + control_reference->expression = WxStrToStr(textctrl->GetValue()); std::lock_guard lk(m_plugin.controls_lock); g_controller_interface.UpdateReference(control_reference, m_parent->controller->default_device); @@ -304,10 +301,10 @@ void ControlDialog::SetControl(wxCommandEvent&) void GamepadPage::SetDevice(wxCommandEvent&) { - controller->default_device.FromString(STR_FROM_WXSTR(device_cbox->GetValue())); + controller->default_device.FromString(WxStrToStr(device_cbox->GetValue())); // show user what it was validated as - device_cbox->SetValue(WXSTR_FROM_STR(controller->default_device.ToString())); + device_cbox->SetValue(StrToWxStr(controller->default_device.ToString())); // this will set all the controls to this default device controller->UpdateDefaultDevice(); @@ -319,10 +316,10 @@ void GamepadPage::SetDevice(wxCommandEvent&) void ControlDialog::SetDevice(wxCommandEvent&) { - m_devq.FromString(STR_FROM_WXSTR(device_cbox->GetValue())); + m_devq.FromString(WxStrToStr(device_cbox->GetValue())); // show user what it was validated as - device_cbox->SetValue(WXSTR_FROM_STR(m_devq.ToString())); + device_cbox->SetValue(StrToWxStr(m_devq.ToString())); // update gui UpdateListContents(); @@ -349,12 +346,12 @@ void ControlDialog::SetSelectedControl(wxCommandEvent&) // non-default device if (false == (m_devq == m_parent->controller->default_device)) - expr.append(wxT('`')).append(WXSTR_FROM_STR(m_devq.ToString())).append(wxT('`')); + expr.append(wxT('`')).append(StrToWxStr(m_devq.ToString())).append(wxT('`')); // append the control name expr += control_lbox->GetString(num); - control_reference->expression = STR_FROM_WXSTR(expr); + control_reference->expression = WxStrToStr(expr); std::lock_guard lk(m_plugin.controls_lock); g_controller_interface.UpdateReference(control_reference, m_parent->controller->default_device); @@ -380,12 +377,12 @@ void ControlDialog::AppendControl(wxCommandEvent& event) // non-default device if (false == (m_devq == m_parent->controller->default_device)) - expr.append(wxT('`')).append(WXSTR_FROM_STR(m_devq.ToString())).append(wxT('`')); + expr.append(wxT('`')).append(StrToWxStr(m_devq.ToString())).append(wxT('`')); // append the control name expr += control_lbox->GetString(num); - control_reference->expression = STR_FROM_WXSTR(expr); + control_reference->expression = WxStrToStr(expr); std::lock_guard lk(m_plugin.controls_lock); g_controller_interface.UpdateReference(control_reference, m_parent->controller->default_device); @@ -475,7 +472,7 @@ void GamepadPage::DetectControl(wxCommandEvent& event) g_controller_interface.UpdateReference(btn->control_reference, controller->default_device); } - btn->SetLabel(WXSTR_FROM_STR(btn->control_reference->expression)); + btn->SetLabel(StrToWxStr(btn->control_reference->expression)); } } @@ -565,7 +562,7 @@ void GamepadPage::GetProfilePath(std::string& path) path += PROFILES_PATH; path += m_plugin.profile_name; path += '/'; - path += STR_FROM_WXSTR(profile_cbox->GetValue()); + path += WxStrToStr(profile_cbox->GetValue()); path += ".ini"; } } @@ -615,7 +612,7 @@ void GamepadPage::DeleteProfile(wxCommandEvent&) if (File::Exists(fnamecstr) && AskYesNoT("Are you sure you want to delete \"%s\"?", - STR_FROM_WXSTR(profile_cbox->GetValue()).c_str())) + WxStrToStr(profile_cbox->GetValue()).c_str())) { File::Delete(fnamecstr); @@ -637,9 +634,9 @@ void InputConfigDialog::UpdateDeviceComboBox() for (; di!=de; ++di) { dq.FromDevice(*di); - (*i)->device_cbox->Append(WXSTR_FROM_STR(dq.ToString())); + (*i)->device_cbox->Append(StrToWxStr(dq.ToString())); } - (*i)->device_cbox->SetValue(WXSTR_FROM_STR((*i)->controller->default_device.ToString())); + (*i)->device_cbox->SetValue(StrToWxStr((*i)->controller->default_device.ToString())); } } @@ -680,7 +677,7 @@ ControlGroupBox::ControlGroupBox(ControllerEmu::ControlGroup* const group, wxWin for (; ci != ce; ++ci) { - wxStaticText* const label = new wxStaticText(parent, -1, WXTSTR_FROM_CSTR((*ci)->name)); + wxStaticText* const label = new wxStaticText(parent, -1, StrToWxStr((*ci)->name)); ControlButton* const control_button = new ControlButton(parent, (*ci)->control_ref, 80); control_button->SetFont(m_SmallFont); @@ -734,7 +731,7 @@ ControlGroupBox::ControlGroupBox(ControllerEmu::ControlGroup* const group, wxWin PadSettingSpin* setting = new PadSettingSpin(parent, *i); setting->wxcontrol->Bind(wxEVT_COMMAND_SPINCTRL_UPDATED, &GamepadPage::AdjustSetting, eventsink); options.push_back(setting); - szr->Add(new wxStaticText(parent, -1, WXTSTR_FROM_CSTR((*i)->name))); + szr->Add(new wxStaticText(parent, -1, StrToWxStr((*i)->name))); szr->Add(setting->wxcontrol, 0, wxLEFT, 0); } @@ -760,7 +757,7 @@ ControlGroupBox::ControlGroupBox(ControllerEmu::ControlGroup* const group, wxWin options.push_back(threshold_cbox); wxBoxSizer* const szr = new wxBoxSizer(wxHORIZONTAL); - szr->Add(new wxStaticText(parent, -1, WXTSTR_FROM_CSTR(group->settings[0]->name)), + szr->Add(new wxStaticText(parent, -1, StrToWxStr(group->settings[0]->name)), 0, wxCENTER|wxRIGHT, 3); szr->Add(threshold_cbox->wxcontrol, 0, wxRIGHT, 3); @@ -795,7 +792,7 @@ ControlGroupBox::ControlGroupBox(ControllerEmu::ControlGroup* const group, wxWin setting->wxcontrol->Bind(wxEVT_COMMAND_SPINCTRL_UPDATED, &GamepadPage::AdjustSetting, eventsink); options.push_back(setting); wxBoxSizer* const szr = new wxBoxSizer(wxHORIZONTAL); - szr->Add(new wxStaticText(parent, -1, WXTSTR_FROM_CSTR((*i)->name)), 0, wxCENTER|wxRIGHT, 3); + szr->Add(new wxStaticText(parent, -1, StrToWxStr((*i)->name)), 0, wxCENTER|wxRIGHT, 3); szr->Add(setting->wxcontrol, 0, wxRIGHT, 3); Add(szr, 0, wxALL|wxCENTER, 3); } @@ -859,7 +856,7 @@ ControlGroupsSizer::ControlGroupsSizer(ControllerEmu* const controller, wxWindow { ControlGroupBox* control_group_box = new ControlGroupBox(controller->groups[i], parent, eventsink); wxStaticBoxSizer *control_group = - new wxStaticBoxSizer(wxVERTICAL, parent, WXTSTR_FROM_CSTR(controller->groups[i]->name)); + new wxStaticBoxSizer(wxVERTICAL, parent, StrToWxStr(controller->groups[i]->name)); control_group->Add(control_group_box); const size_t grp_size = controller->groups[i]->controls.size() + controller->groups[i]->settings.size(); @@ -955,7 +952,7 @@ GamepadPage::GamepadPage(wxWindow* parent, InputPlugin& plugin, const unsigned i InputConfigDialog::InputConfigDialog(wxWindow* const parent, InputPlugin& plugin, const std::string& name, const int tab_num) - : wxDialog(parent, wxID_ANY, WXTSTR_FROM_CSTR(name.c_str()), wxPoint(128,-1), wxDefaultSize) + : wxDialog(parent, wxID_ANY, StrToWxStr(name), wxPoint(128,-1), wxDefaultSize) , m_plugin(plugin) { m_pad_notebook = new wxNotebook(this, -1, wxDefaultPosition, wxDefaultSize, wxNB_DEFAULT); @@ -963,7 +960,7 @@ InputConfigDialog::InputConfigDialog(wxWindow* const parent, InputPlugin& plugin { GamepadPage* gp = new GamepadPage(m_pad_notebook, m_plugin, i, this); m_padpages.push_back(gp); - m_pad_notebook->AddPage(gp, wxString::Format(wxT("%s %u"), WXTSTR_FROM_CSTR(m_plugin.gui_name), 1+i)); + m_pad_notebook->AddPage(gp, wxString::Format(wxT("%s %u"), StrToWxStr(m_plugin.gui_name), 1+i)); } m_pad_notebook->SetSelection(tab_num); diff --git a/Source/Core/DolphinWX/Src/InputConfigDiagBitmaps.cpp b/Source/Core/DolphinWX/Src/InputConfigDiagBitmaps.cpp index ff5ed3b9cd..efb7db59af 100644 --- a/Source/Core/DolphinWX/Src/InputConfigDiagBitmaps.cpp +++ b/Source/Core/DolphinWX/Src/InputConfigDiagBitmaps.cpp @@ -16,6 +16,7 @@ // http://code.google.com/p/dolphin-emu/ #include "InputConfigDiag.h" +#include "WxUtils.h" void InputConfigDialog::UpdateBitmaps(wxTimerEvent& WXUNUSED(event)) { @@ -48,7 +49,7 @@ void InputConfigDialog::UpdateBitmaps(wxTimerEvent& WXUNUSED(event)) // label for sticks and stuff if (64 == bitmap.GetHeight()) - dc.DrawText(wxString::FromAscii((*g)->control_group->name).Upper(), 4, 2); + dc.DrawText(StrToWxStr((*g)->control_group->name).Upper(), 4, 2); switch ( (*g)->control_group->type ) { @@ -227,7 +228,7 @@ void InputConfigDialog::UpdateBitmaps(wxTimerEvent& WXUNUSED(event)) // text const char* const name = (*g)->control_group->controls[n]->name; // bit of hax so ZL, ZR show up as L, R - dc.DrawText(wxString::FromAscii((name[1] && name[1] < 'a') ? name[1] : name[0]), n*12 + 2, 1); + dc.DrawText(StrToWxStr(std::string(1, (name[1] && name[1] < 'a') ? name[1] : name[0])), n*12 + 2, 1); } delete[] bitmasks; @@ -263,7 +264,7 @@ void InputConfigDialog::UpdateBitmaps(wxTimerEvent& WXUNUSED(event)) dc.DrawRectangle(0, n*12, trigs[n], 14); // text - dc.DrawText(wxString::FromAscii((*g)->control_group->controls[n]->name), 3, n*12 + 1); + dc.DrawText(StrToWxStr((*g)->control_group->controls[n]->name), 3, n*12 + 1); } delete[] trigs; @@ -298,8 +299,8 @@ void InputConfigDialog::UpdateBitmaps(wxTimerEvent& WXUNUSED(event)) dc.DrawRectangle(64, n*12, 32, 14); // text - dc.DrawText(wxString::FromAscii((*g)->control_group->controls[n+trigger_count]->name), 3, n*12 + 1); - dc.DrawText(wxString::FromAscii((*g)->control_group->controls[n]->name[0]), 64 + 3, n*12 + 1); + dc.DrawText(StrToWxStr((*g)->control_group->controls[n+trigger_count]->name), 3, n*12 + 1); + dc.DrawText(StrToWxStr(std::string(1, (*g)->control_group->controls[n]->name[0])), 64 + 3, n*12 + 1); } // threshold box diff --git a/Source/Core/DolphinWX/Src/LogConfigWindow.cpp b/Source/Core/DolphinWX/Src/LogConfigWindow.cpp index 162647c64d..a4a5fa647a 100644 --- a/Source/Core/DolphinWX/Src/LogConfigWindow.cpp +++ b/Source/Core/DolphinWX/Src/LogConfigWindow.cpp @@ -20,6 +20,7 @@ #include "ConsoleListener.h" #include "LogWindow.h" #include "FileUtil.h" +#include "WxUtils.h" LogConfigWindow::LogConfigWindow(wxWindow* parent, CLogWindow *log_window, wxWindowID id) : wxPanel(parent, id, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL, _("Log Configuration")) @@ -74,7 +75,7 @@ void LogConfigWindow::CreateGUIControls() m_checks = new wxCheckListBox(this, wxID_ANY); m_checks->Bind(wxEVT_COMMAND_CHECKLISTBOX_TOGGLED, &LogConfigWindow::OnLogCheck, this); for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; i++) - m_checks->Append(wxString::FromAscii(m_LogManager->GetFullName((LogTypes::LOG_TYPE)i))); + m_checks->Append(StrToWxStr(m_LogManager->GetFullName((LogTypes::LOG_TYPE)i))); // Sizers wxStaticBoxSizer* sbOutputs = new wxStaticBoxSizer(wxVERTICAL, this, _("Logger Outputs")); diff --git a/Source/Core/DolphinWX/Src/LogWindow.cpp b/Source/Core/DolphinWX/Src/LogWindow.cpp index 4c9c495713..27e5856410 100644 --- a/Source/Core/DolphinWX/Src/LogWindow.cpp +++ b/Source/Core/DolphinWX/Src/LogWindow.cpp @@ -21,6 +21,8 @@ #include "IniFile.h" #include "FileUtil.h" #include "Debugger/DebuggerUIUtil.h" +#include "WxUtils.h" + #include // Milliseconds between msgQueue flushes to wxTextCtrl @@ -41,25 +43,7 @@ CLogWindow::CLogWindow(CFrame *parent, wxWindowID id, const wxPoint& pos, , x(0), y(0), winpos(0) , Parent(parent), m_ignoreLogTimer(false), m_LogAccess(true) , m_Log(NULL), m_cmdline(NULL), m_FontChoice(NULL) - , m_SJISConv(wxT("")) { -#ifdef _WIN32 - static bool validCP932 = ::IsValidCodePage(932) != 0; - if (validCP932) - { - m_SJISConv = wxCSConv(wxFontMapper::GetEncodingName(wxFONTENCODING_SHIFT_JIS)); - } - else - { - WARN_LOG(COMMON, "Cannot Convert from Charset Windows Japanese cp 932"); - m_SJISConv = *(wxCSConv*)wxConvCurrent; - } -#else - // on linux the wrong string is returned from wxFontMapper::GetEncodingName(wxFONTENCODING_SHIFT_JIS) - // it returns CP-932, in order to use iconv we need to use CP932 - m_SJISConv = wxCSConv(wxT("CP932")); -#endif - m_LogManager = LogManager::GetInstance(); CreateGUIControls(); @@ -208,7 +192,7 @@ void CLogWindow::SaveSettings() void CLogWindow::OnSubmit(wxCommandEvent& WXUNUSED (event)) { if (!m_cmdline) return; - Console_Submit(m_cmdline->GetValue().To8BitData()); + Console_Submit(WxStrToStr(m_cmdline->GetValue()).c_str()); m_cmdline->SetValue(wxEmptyString); } @@ -247,7 +231,7 @@ wxTextCtrl* CLogWindow::CreateTextCtrl(wxPanel* parent, wxWindowID id, long Styl #else TC->SetBackgroundColour(*wxBLACK); #endif - if (m_FontChoice && m_FontChoice->GetSelection() < (int)LogFont.size()) + if (m_FontChoice && m_FontChoice->GetSelection() < (int)LogFont.size() && m_FontChoice->GetSelection() >= 0) TC->SetDefaultStyle(wxTextAttr(wxNullColour, wxNullColour, LogFont[m_FontChoice->GetSelection()])); return TC; @@ -370,5 +354,6 @@ void CLogWindow::Log(LogTypes::LOG_LEVELS level, const char *text) if (msgQueue.size() >= 100) msgQueue.pop(); - msgQueue.push(std::pair((u8)level, wxString(text, m_SJISConv))); + + msgQueue.push(std::make_pair(u8(level), StrToWxStr(text))); } diff --git a/Source/Core/DolphinWX/Src/LogWindow.h b/Source/Core/DolphinWX/Src/LogWindow.h index 86fd1d3b4f..54a59c4d91 100644 --- a/Source/Core/DolphinWX/Src/LogWindow.h +++ b/Source/Core/DolphinWX/Src/LogWindow.h @@ -75,8 +75,6 @@ private: std::mutex m_LogSection; - wxCSConv m_SJISConv; - DECLARE_EVENT_TABLE() wxTextCtrl * CreateTextCtrl(wxPanel* parent, wxWindowID id = wxID_ANY, long Style = NULL); diff --git a/Source/Core/DolphinWX/Src/Main.cpp b/Source/Core/DolphinWX/Src/Main.cpp index 338ed59547..37311c84bf 100644 --- a/Source/Core/DolphinWX/Src/Main.cpp +++ b/Source/Core/DolphinWX/Src/Main.cpp @@ -32,6 +32,7 @@ #include "Host.h" // Core #include "HW/Wiimote.h" +#include "WxUtils.h" #include "Globals.h" // Local #include "Main.h" #include "ConfigManager.h" @@ -201,6 +202,7 @@ bool DolphinApp::OnInit() wxHandleFatalExceptions(true); #endif +#ifndef _M_ARM // TODO: if First Boot if (!cpu_info.bSSE2) { @@ -209,9 +211,10 @@ bool DolphinApp::OnInit() "Sayonara!\n"); return false; } +#endif #ifdef _WIN32 - if (!wxSetWorkingDirectory(wxString(File::GetExeDirectory().c_str(), *wxConvCurrent))) + if (!wxSetWorkingDirectory(StrToWxStr(File::GetExeDirectory()))) { INFO_LOG(CONSOLE, "set working directory failed"); } @@ -246,7 +249,7 @@ bool DolphinApp::OnInit() if (selectVideoBackend && videoBackendName != wxEmptyString) SConfig::GetInstance().m_LocalCoreStartupParameter.m_strVideoBackend = - std::string(videoBackendName.mb_str()); + WxStrToStr(videoBackendName); if (selectAudioEmulation) { @@ -296,7 +299,7 @@ bool DolphinApp::OnInit() #endif main_frame = new CFrame((wxFrame*)NULL, wxID_ANY, - wxString::FromAscii(scm_rev_str), + StrToWxStr(scm_rev_str), wxPoint(x, y), wxSize(w, h), UseDebugger, BatchMode, UseLogger); SetTopWindow(main_frame); @@ -317,7 +320,7 @@ void DolphinApp::MacOpenFile(const wxString &fileName) LoadFile = true; if (m_afterinit == NULL) - main_frame->BootGame(std::string(FileToLoad.mb_str())); + main_frame->BootGame(WxStrToStr(FileToLoad)); } void DolphinApp::AfterInit(wxTimerEvent& WXUNUSED(event)) @@ -331,7 +334,7 @@ void DolphinApp::AfterInit(wxTimerEvent& WXUNUSED(event)) // First check if we have an exec command line. if (LoadFile && FileToLoad != wxEmptyString) { - main_frame->BootGame(std::string(FileToLoad.mb_str())); + main_frame->BootGame(WxStrToStr(FileToLoad)); } // If we have selected Automatic Start, start the default ISO, // or if no default ISO exists, start the last loaded ISO @@ -390,10 +393,6 @@ void DolphinApp::InitLanguageSupport() int DolphinApp::OnExit() { WiimoteReal::Shutdown(); -#ifdef _WIN32 - if (SConfig::GetInstance().m_WiiAutoUnpair) - WiimoteReal::UnPair(); -#endif VideoBackend::ClearList(); SConfig::Shutdown(); LogManager::Shutdown(); @@ -422,7 +421,7 @@ void Host_SysMessage(const char *fmt, ...) va_end(list); if (msg[strlen(msg)-1] == '\n') msg[strlen(msg)-1] = 0; - //wxMessageBox(wxString::FromAscii(msg)); + //wxMessageBox(StrToWxStr(msg)); PanicAlert("%s", msg); } @@ -431,14 +430,13 @@ bool wxMsgAlert(const char* caption, const char* text, bool yes_no, int /*Style* #ifdef __WXGTK__ if (wxIsMainThread()) #endif - return wxYES == wxMessageBox(wxString::FromUTF8(text), - wxString::FromUTF8(caption), + return wxYES == wxMessageBox(StrToWxStr(text), StrToWxStr(caption), (yes_no) ? wxYES_NO : wxOK, wxGetActiveWindow()); #ifdef __WXGTK__ else { wxCommandEvent event(wxEVT_HOST_COMMAND, IDM_PANIC); - event.SetString(wxString::FromUTF8(caption) + wxT(":") + wxString::FromUTF8(text)); + event.SetString(StrToWxStr(caption) + wxT(":") + StrToWxStr(text)); event.SetInt(yes_no); main_frame->GetEventHandler()->AddPendingEvent(event); main_frame->panic_event.Wait(); @@ -449,7 +447,7 @@ bool wxMsgAlert(const char* caption, const char* text, bool yes_no, int /*Style* std::string wxStringTranslator(const char *text) { - return (const char *)wxString(wxGetTranslation(wxString::From8BitData(text))).ToUTF8(); + return WxStrToStr(wxGetTranslation(wxString::FromUTF8(text))); } // Accessor for the main window class @@ -540,7 +538,7 @@ void Host_UpdateMainFrame() void Host_UpdateTitle(const char* title) { wxCommandEvent event(wxEVT_HOST_COMMAND, IDM_UPDATETITLE); - event.SetString(wxString::FromAscii(title)); + event.SetString(StrToWxStr(title)); main_frame->GetEventHandler()->AddPendingEvent(event); } @@ -607,7 +605,7 @@ void Host_UpdateStatusBar(const char* _pText, int Field) { wxCommandEvent event(wxEVT_HOST_COMMAND, IDM_UPDATESTATUSBAR); // Set the event string - event.SetString(wxString::FromAscii(_pText)); + event.SetString(StrToWxStr(_pText)); // Update statusbar field event.SetInt(Field); // Post message diff --git a/Source/Core/DolphinWX/Src/MainAndroid.cpp b/Source/Core/DolphinWX/Src/MainAndroid.cpp new file mode 100644 index 0000000000..ca2119921d --- /dev/null +++ b/Source/Core/DolphinWX/Src/MainAndroid.cpp @@ -0,0 +1,149 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ +#include +#include +#include + +#include "Common.h" +#include "FileUtil.h" + +#include "Core.h" +#include "Host.h" +#include "CPUDetect.h" +#include "Thread.h" + +#include "PowerPC/PowerPC.h" +#include "HW/Wiimote.h" + +#include "VideoBackendBase.h" +#include "ConfigManager.h" +#include "LogManager.h" +#include "BootManager.h" + +#include +#include +#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "Dolphinemu", __VA_ARGS__)) + +bool rendererHasFocus = true; +bool running = true; + +void Host_NotifyMapLoaded() {} +void Host_RefreshDSPDebuggerWindow() {} + +void Host_ShowJitResults(unsigned int address){} + +Common::Event updateMainFrameEvent; +void Host_Message(int Id) +{ +} + +void* Host_GetRenderHandle() +{ + return NULL; +} + +void* Host_GetInstance() { return NULL; } + +void Host_UpdateTitle(const char* title){}; + +void Host_UpdateLogDisplay(){} + +void Host_UpdateDisasmDialog(){} + +void Host_UpdateMainFrame() +{ +} + +void Host_UpdateBreakPointView(){} + +bool Host_GetKeyState(int keycode) +{ + return false; +} + +void Host_GetRenderWindowSize(int& x, int& y, int& width, int& height) +{ + x = SConfig::GetInstance().m_LocalCoreStartupParameter.iRenderWindowXPos; + y = SConfig::GetInstance().m_LocalCoreStartupParameter.iRenderWindowYPos; + width = SConfig::GetInstance().m_LocalCoreStartupParameter.iRenderWindowWidth; + height = SConfig::GetInstance().m_LocalCoreStartupParameter.iRenderWindowHeight; +} + +void Host_RequestRenderWindowSize(int width, int height) {} +void Host_SetStartupDebuggingParameters() +{ +} + +bool Host_RendererHasFocus() +{ + return true; +} + +void Host_ConnectWiimote(int wm_idx, bool connect) {} + +void Host_SetWaitCursor(bool enable){} + +void Host_UpdateStatusBar(const char* _pText, int Filed){} + +void Host_SysMessage(const char *fmt, ...) +{ + va_list list; + char msg[512]; + + va_start(list, fmt); + vsprintf(msg, fmt, list); + va_end(list); + + size_t len = strlen(msg); + if (msg[len - 1] != '\n') { + msg[len - 1] = '\n'; + msg[len] = '\0'; + } + LOGI(msg); +} + +void Host_SetWiiMoteConnectionState(int _State) {} + +#ifdef __cplusplus +extern "C" +{ +#endif +JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_dolphinemuactivity_main(JNIEnv *env, jobject obj) +{ + LogManager::Init(); + SConfig::Init(); + VideoBackend::PopulateList(); + VideoBackend::ActivateBackend(SConfig::GetInstance(). + m_LocalCoreStartupParameter.m_strVideoBackend); + WiimoteReal::LoadSettings(); + + // No use running the loop when booting fails + if (BootManager::BootCore("")) + { + while (PowerPC::GetState() != PowerPC::CPU_POWERDOWN) + updateMainFrameEvent.Wait(); + } + + WiimoteReal::Shutdown(); + VideoBackend::ClearList(); + SConfig::Shutdown(); + LogManager::Shutdown(); +} + +#ifdef __cplusplus +} +#endif diff --git a/Source/Core/DolphinWX/Src/MemcardManager.cpp b/Source/Core/DolphinWX/Src/MemcardManager.cpp index b3a7ab22b8..0bbbbd0a7b 100644 --- a/Source/Core/DolphinWX/Src/MemcardManager.cpp +++ b/Source/Core/DolphinWX/Src/MemcardManager.cpp @@ -17,6 +17,8 @@ #include "MemcardManager.h" #include "Common.h" + +#include "WxUtils.h" #include "wx/mstream.h" #define ARROWS slot ? _T("") : ARROW[slot], slot ? ARROW[slot] : _T("") @@ -212,7 +214,7 @@ void CMemcardManager::CreateGUIControls() sPages->Add(m_NextPage[slot], 0, wxEXPAND|wxALL, 1); m_MemcardPath[slot] = new wxFilePickerCtrl(this, ID_MEMCARDPATH_A + slot, - wxString::From8BitData(File::GetUserPath(D_GCUSER_IDX).c_str()), _("Choose a memory card:"), + StrToWxStr(File::GetUserPath(D_GCUSER_IDX)), _("Choose a memory card:"), _("Gamecube Memory Cards (*.raw,*.gcp)") + wxString(wxT("|*.raw;*.gcp")), wxDefaultPosition, wxDefaultSize, wxFLP_USE_TEXTCTRL|wxFLP_OPEN); m_MemcardList[slot] = new CMemcardListCtrl(this, ID_MEMCARDLIST_A + slot, wxDefaultPosition, wxSize(350,400), @@ -263,7 +265,7 @@ void CMemcardManager::CreateGUIControls() m_Delete[i]->Disable(); if (DefaultMemcard[i].length()) { - m_MemcardPath[i]->SetPath(wxString::From8BitData(DefaultMemcard[i].c_str())); + m_MemcardPath[i]->SetPath(StrToWxStr(DefaultMemcard[i])); ChangePath(i); } } @@ -290,7 +292,7 @@ void CMemcardManager::ChangePath(int slot) } else { - if (m_MemcardPath[slot]->GetPath().length() && ReloadMemcard(m_MemcardPath[slot]->GetPath().mb_str(), slot)) + if (m_MemcardPath[slot]->GetPath().length() && ReloadMemcard(WxStrToStr(m_MemcardPath[slot]->GetPath()).c_str(), slot)) { if (memoryCard[slot2]) { @@ -345,7 +347,7 @@ void CMemcardManager::OnPageChange(wxCommandEvent& event) m_NextPage[slot]->Disable(); m_MemcardList[slot]->nextPage = false; } - ReloadMemcard(m_MemcardPath[slot]->GetPath().mb_str(), slot); + ReloadMemcard(WxStrToStr(m_MemcardPath[slot]->GetPath()).c_str(), slot); break; case ID_PREVPAGE_A: slot = SLOT_A; @@ -361,7 +363,7 @@ void CMemcardManager::OnPageChange(wxCommandEvent& event) m_PrevPage[slot]->Disable(); m_MemcardList[slot]->prevPage = false; } - ReloadMemcard(m_MemcardPath[slot]->GetPath().mb_str(), slot); + ReloadMemcard(WxStrToStr(m_MemcardPath[slot]->GetPath()).c_str(), slot); break; } } @@ -373,7 +375,7 @@ void CMemcardManager::OnMenuChange(wxCommandEvent& event) { case ID_MEMCARDPATH_A: case ID_MEMCARDPATH_B: - DefaultMemcard[_id - ID_MEMCARDPATH_A] = m_MemcardPath[_id - ID_MEMCARDPATH_A]->GetPath().mb_str(); + DefaultMemcard[_id - ID_MEMCARDPATH_A] = WxStrToStr(m_MemcardPath[_id - ID_MEMCARDPATH_A]->GetPath()); return; case ID_USEPAGES: mcmSettings.usePages = !mcmSettings.usePages; @@ -400,8 +402,8 @@ void CMemcardManager::OnMenuChange(wxCommandEvent& event) break; } - if (memoryCard[SLOT_A]) ReloadMemcard(m_MemcardPath[SLOT_A]->GetPath().mb_str(), SLOT_A); - if (memoryCard[SLOT_B]) ReloadMemcard(m_MemcardPath[SLOT_B]->GetPath().mb_str(), SLOT_B); + if (memoryCard[SLOT_A]) ReloadMemcard(WxStrToStr(m_MemcardPath[SLOT_A]->GetPath()).c_str(), SLOT_A); + if (memoryCard[SLOT_B]) ReloadMemcard(WxStrToStr(m_MemcardPath[SLOT_B]->GetPath()).c_str(), SLOT_B); } bool CMemcardManager::CopyDeleteSwitch(u32 error, int slot) { @@ -416,7 +418,7 @@ bool CMemcardManager::CopyDeleteSwitch(u32 error, int slot) memoryCard[slot]->FixChecksums(); if (!memoryCard[slot]->Save()) PanicAlert(E_SAVEFAILED); page[slot] = FIRSTPAGE; - ReloadMemcard(m_MemcardPath[slot]->GetPath().mb_str(), slot); + ReloadMemcard(WxStrToStr(m_MemcardPath[slot]->GetPath()).c_str(), slot); } break; case NOMEMCARD: @@ -517,8 +519,8 @@ void CMemcardManager::CopyDeleteClick(wxCommandEvent& event) wxString fileName = wxFileSelector( _("Select a save file to import"), (strcmp(DefaultIOPath.c_str(), "/Users/GC") == 0) - ? wxString::FromAscii("") - : wxString::From8BitData(DefaultIOPath.c_str()), + ? StrToWxStr("") + : StrToWxStr(DefaultIOPath), wxEmptyString, wxEmptyString, _("GameCube Savegame files(*.gci;*.gcs;*.sav)") + wxString(wxT("|*.gci;*.gcs;*.sav|")) + _("Native GCI files(*.gci)") + wxString(wxT("|*.gci|")) + @@ -532,11 +534,11 @@ void CMemcardManager::CopyDeleteClick(wxCommandEvent& event) _("GCI File(*.gci)") + wxString(_T("|*.gci")), wxFD_OVERWRITE_PROMPT|wxFD_SAVE, this); if (temp2.empty()) break; - fileName2 = temp2.mb_str(); + fileName2 = WxStrToStr(temp2); } if (fileName.length() > 0) { - CopyDeleteSwitch(memoryCard[slot]->ImportGci(fileName.mb_str(), fileName2), slot); + CopyDeleteSwitch(memoryCard[slot]->ImportGci(WxStrToStr(fileName).c_str(), fileName2), slot); } } break; @@ -555,8 +557,8 @@ void CMemcardManager::CopyDeleteClick(wxCommandEvent& event) } wxString fileName = wxFileSelector( _("Export save as..."), - wxString::From8BitData(DefaultIOPath.c_str()), - wxString::From8BitData(gciFilename.c_str()), wxT(".gci"), + StrToWxStr(DefaultIOPath), + StrToWxStr(gciFilename), wxT(".gci"), _("Native GCI files(*.gci)") + wxString(wxT("|*.gci|")) + _("MadCatz Gameshark files(*.gcs)") + wxString(wxT("|*.gcs|")) + _("Datel MaxDrive/Pro files(*.sav)") + wxString(wxT("|*.sav")), @@ -564,9 +566,9 @@ void CMemcardManager::CopyDeleteClick(wxCommandEvent& event) if (fileName.length() > 0) { - if (!CopyDeleteSwitch(memoryCard[slot]->ExportGci(index, fileName.mb_str(), ""), -1)) + if (!CopyDeleteSwitch(memoryCard[slot]->ExportGci(index, WxStrToStr(fileName).c_str(), ""), -1)) { - File::Delete(std::string(fileName.mb_str())); + File::Delete(WxStrToStr(fileName)); } } } @@ -576,7 +578,7 @@ void CMemcardManager::CopyDeleteClick(wxCommandEvent& event) case ID_EXPORTALL_B: { std::string path1, path2, mpath; - mpath = m_MemcardPath[slot]->GetPath().mb_str(); + mpath = WxStrToStr(m_MemcardPath[slot]->GetPath()); SplitPath(mpath, &path1, &path2, NULL); path1 += path2; File::CreateDir(path1); @@ -702,26 +704,11 @@ bool CMemcardManager::ReloadMemcard(const char *fileName, int card) std::string title = memoryCard[card]->GetSaveComment1(fileIndex); std::string comment = memoryCard[card]->GetSaveComment2(fileIndex); - bool ascii = memoryCard[card]->IsAsciiEncoding(); - -#ifdef _WIN32 - wxCSConv SJISConv(*(wxCSConv*)wxConvCurrent); - static bool validCP932 = ::IsValidCodePage(932) != 0; - if (validCP932) - { - SJISConv = wxCSConv(wxFontMapper::GetEncodingName(wxFONTENCODING_SHIFT_JIS)); - } - else - { - WARN_LOG(COMMON, "Cannot Convert from Charset Windows Japanese cp 932"); - } -#else - // on linux the wrong string is returned from wxFontMapper::GetEncodingName(wxFONTENCODING_SHIFT_JIS) - // it returns CP-932, in order to use iconv we need to use CP932 - wxCSConv SJISConv(wxT("CP932")); -#endif - wxTitle = wxString(title.c_str(), ascii ? *wxConvCurrent : SJISConv); - wxComment = wxString(comment.c_str(), ascii ? *wxConvCurrent : SJISConv); + auto const string_decoder = memoryCard[card]->IsAsciiEncoding() ? + CP1252ToUTF8 : SHIFTJISToUTF8; + + wxTitle = StrToWxStr(string_decoder(title)); + wxComment = StrToWxStr(string_decoder(comment)); m_MemcardList[card]->SetItem(index, COLUMN_TITLE, wxTitle); m_MemcardList[card]->SetItem(index, COLUMN_COMMENT, wxComment); diff --git a/Source/Core/DolphinWX/Src/NetWindow.cpp b/Source/Core/DolphinWX/Src/NetWindow.cpp index 142a7ea00c..76bb76881b 100644 --- a/Source/Core/DolphinWX/Src/NetWindow.cpp +++ b/Source/Core/DolphinWX/Src/NetWindow.cpp @@ -18,11 +18,13 @@ #include #include +#include "WxUtils.h" #include "NetPlay.h" #include "NetWindow.h" #include "Frame.h" #include +#include #define NETPLAY_TITLEBAR "Dolphin NetPlay" @@ -34,6 +36,24 @@ static NetPlay* netplay_ptr = NULL; extern CFrame* main_frame; NetPlayDiag *NetPlayDiag::npd = NULL; +std::string BuildGameName(const GameListItem& game) +{ + // Lang needs to be consistent + auto const lang = 0; + + std::string name(game.GetBannerName(lang)); + if (name.empty()) + name = game.GetVolumeName(lang); + + return name + " (" + game.GetUniqueID() + ")"; +} + +void FillWithGameNames(wxListBox* game_lbox, const CGameListCtrl& game_list) +{ + for (u32 i = 0 ; auto game = game_list.GetISO(i); ++i) + game_lbox->Append(StrToWxStr(BuildGameName(*game))); +} + NetPlaySetupDiag::NetPlaySetupDiag(wxWindow* const parent, const CGameListCtrl* const game_list) : wxFrame(parent, wxID_ANY, wxT(NETPLAY_TITLEBAR), wxDefaultPosition, wxDefaultSize) , m_game_list(game_list) @@ -50,7 +70,7 @@ NetPlaySetupDiag::NetPlaySetupDiag(wxWindow* const parent, const CGameListCtrl* std::string nickname; netplay_section.Get("Nickname", &nickname, "Player"); - m_nickname_text = new wxTextCtrl(panel, wxID_ANY, wxString::From8BitData(nickname.c_str())); + m_nickname_text = new wxTextCtrl(panel, wxID_ANY, StrToWxStr(nickname)); wxBoxSizer* const nick_szr = new wxBoxSizer(wxHORIZONTAL); nick_szr->Add(nick_lbl, 0, wxCENTER); @@ -72,7 +92,7 @@ NetPlaySetupDiag::NetPlaySetupDiag(wxWindow* const parent, const CGameListCtrl* std::string address; netplay_section.Get("Address", &address, "localhost"); - m_connect_ip_text = new wxTextCtrl(connect_tab, wxID_ANY, wxString::FromAscii(address.c_str())); + m_connect_ip_text = new wxTextCtrl(connect_tab, wxID_ANY, StrToWxStr(address)); wxStaticText* const port_lbl = new wxStaticText(connect_tab, wxID_ANY, _("Port :"), wxDefaultPosition, wxDefaultSize); @@ -80,7 +100,7 @@ NetPlaySetupDiag::NetPlaySetupDiag(wxWindow* const parent, const CGameListCtrl* // string? w/e std::string port; netplay_section.Get("ConnectPort", &port, "2626"); - m_connect_port_text = new wxTextCtrl(connect_tab, wxID_ANY, wxString::FromAscii(port.c_str())); + m_connect_port_text = new wxTextCtrl(connect_tab, wxID_ANY, StrToWxStr(port)); wxButton* const connect_btn = new wxButton(connect_tab, wxID_ANY, _("Connect")); connect_btn->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &NetPlaySetupDiag::OnJoin, this); @@ -113,18 +133,15 @@ NetPlaySetupDiag::NetPlaySetupDiag(wxWindow* const parent, const CGameListCtrl* // string? w/e std::string port; netplay_section.Get("HostPort", &port, "2626"); - m_host_port_text = new wxTextCtrl(host_tab, wxID_ANY, wxString::FromAscii(port.c_str())); + m_host_port_text = new wxTextCtrl(host_tab, wxID_ANY, StrToWxStr(port)); wxButton* const host_btn = new wxButton(host_tab, wxID_ANY, _("Host")); host_btn->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &NetPlaySetupDiag::OnHost, this); m_game_lbox = new wxListBox(host_tab, wxID_ANY); m_game_lbox->Bind(wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, &NetPlaySetupDiag::OnHost, this); - - std::istringstream ss(game_list->GetGameNames()); - std::string game; - while (std::getline(ss,game)) - m_game_lbox->Append(wxString(game.c_str(), *wxConvCurrent)); + + FillWithGameNames(m_game_lbox, *game_list); wxBoxSizer* const top_szr = new wxBoxSizer(wxHORIZONTAL); top_szr->Add(port_lbl, 0, wxCENTER | wxRIGHT, 5); @@ -167,10 +184,10 @@ NetPlaySetupDiag::~NetPlaySetupDiag() inifile.Load(dolphin_ini); IniFile::Section& netplay_section = *inifile.GetOrCreateSection("NetPlay"); - netplay_section.Set("Nickname", m_nickname_text->GetValue().mb_str()); - netplay_section.Set("Address", m_connect_ip_text->GetValue().mb_str()); - netplay_section.Set("ConnectPort", m_connect_port_text->GetValue().mb_str()); - netplay_section.Set("HostPort", m_host_port_text->GetValue().mb_str()); + netplay_section.Set("Nickname", WxStrToStr(m_nickname_text->GetValue())); + netplay_section.Set("Address", WxStrToStr(m_connect_ip_text->GetValue())); + netplay_section.Set("ConnectPort", WxStrToStr(m_connect_port_text->GetValue())); + netplay_section.Set("HostPort", WxStrToStr(m_host_port_text->GetValue())); inifile.Save(dolphin_ini); main_frame->g_NetPlaySetupDiag = NULL; @@ -191,13 +208,13 @@ void NetPlaySetupDiag::OnHost(wxCommandEvent&) return; } - std::string game(m_game_lbox->GetStringSelection().mb_str()); + std::string game(WxStrToStr(m_game_lbox->GetStringSelection())); npd = new NetPlayDiag(m_parent, m_game_list, game, true); unsigned long port = 0; m_host_port_text->GetValue().ToULong(&port); netplay_ptr = new NetPlayServer(u16(port) - , std::string(m_nickname_text->GetValue().mb_str()), npd, game); + , WxStrToStr(m_nickname_text->GetValue()), npd, game); if (netplay_ptr->is_connected) { npd->Show(); @@ -222,8 +239,8 @@ void NetPlaySetupDiag::OnJoin(wxCommandEvent&) npd = new NetPlayDiag(m_parent, m_game_list, ""); unsigned long port = 0; m_connect_port_text->GetValue().ToULong(&port); - netplay_ptr = new NetPlayClient(std::string(m_connect_ip_text->GetValue().mb_str()) - , (u16)port, npd, std::string(m_nickname_text->GetValue().mb_str())); + netplay_ptr = new NetPlayClient(WxStrToStr(m_connect_ip_text->GetValue()) + , (u16)port, npd, WxStrToStr(m_nickname_text->GetValue())); if (netplay_ptr->is_connected) { npd->Show(); @@ -250,7 +267,7 @@ NetPlayDiag::NetPlayDiag(wxWindow* const parent, const CGameListCtrl* const game // top crap m_game_btn = new wxButton(panel, wxID_ANY, - wxString(m_selected_game.c_str(), *wxConvCurrent).Prepend(_(" Game : ")), + StrToWxStr(m_selected_game).Prepend(_(" Game : ")), wxDefaultPosition, wxDefaultSize, wxBU_LEFT); if (is_hosting) @@ -351,7 +368,7 @@ void NetPlayDiag::OnChat(wxCommandEvent&) if (s.Length()) { - netplay_ptr->SendChatMessage(std::string(s.mb_str())); + netplay_ptr->SendChatMessage(WxStrToStr(s)); m_chat_text->AppendText(s.Prepend(wxT(" >> ")).Append(wxT('\n'))); m_chat_msg_text->Clear(); } @@ -359,24 +376,17 @@ void NetPlayDiag::OnChat(wxCommandEvent&) void NetPlayDiag::OnStart(wxCommandEvent&) { - // find path for selected game - std::string ntmp, ptmp, path; - std::istringstream nss(m_game_list->GetGameNames()), pss(m_game_list->GetGamePaths()); - - while(std::getline(nss,ntmp)) + // find path for selected game, sloppy.. + for (u32 i = 0 ; auto game = m_game_list->GetISO(i); ++i) { - std::getline(pss,ptmp); - if (m_selected_game == ntmp) + if (m_selected_game == BuildGameName(*game)) { - path = ptmp; - break; + netplay_ptr->StartGame(game->GetFileName()); + return; } } - - if (path.length()) - netplay_ptr->StartGame(path); - else - PanicAlertT("Game not found!!"); + + PanicAlertT("Game not found!"); } void NetPlayDiag::OnStop(wxCommandEvent&) @@ -412,7 +422,7 @@ void NetPlayDiag::OnMsgChangeGame(const std::string& filename) { wxCommandEvent evt(wxEVT_THREAD, NP_GUI_EVT_CHANGE_GAME); // TODO: using a wxString in AddPendingEvent from another thread is unsafe i guess? - evt.SetString(wxString(filename.c_str(), *wxConvCurrent)); + evt.SetString(StrToWxStr(filename)); GetEventHandler()->AddPendingEvent(evt); } @@ -436,7 +446,7 @@ void NetPlayDiag::OnPadBuffHelp(wxCommandEvent&) << time * (60.0f/1000) << "(60fps) / " << time * (50.0f/1000) << "(50fps) >\n"; - m_chat_text->AppendText(wxString(ss.str().c_str(), *wxConvCurrent)); + m_chat_text->AppendText(StrToWxStr(ss.str())); } void NetPlayDiag::OnAdjustBuffer(wxCommandEvent& event) @@ -447,7 +457,7 @@ void NetPlayDiag::OnAdjustBuffer(wxCommandEvent& event) std::ostringstream ss; ss << "< Pad Buffer: " << val << " >"; netplay_ptr->SendChatMessage(ss.str()); - m_chat_text->AppendText(wxString(ss.str().c_str(), *wxConvCurrent).Append(wxT('\n'))); + m_chat_text->AppendText(StrToWxStr(ss.str()).Append(wxT('\n'))); } void NetPlayDiag::OnQuit(wxCommandEvent&) @@ -468,7 +478,7 @@ void NetPlayDiag::OnThread(wxCommandEvent& event) m_player_lbox->Clear(); std::istringstream ss(tmps); while (std::getline(ss, tmps)) - m_player_lbox->Append(wxString(tmps.c_str(), *wxConvCurrent)); + m_player_lbox->Append(StrToWxStr(tmps)); m_player_lbox->SetSelection(selection); @@ -477,7 +487,7 @@ void NetPlayDiag::OnThread(wxCommandEvent& event) case NP_GUI_EVT_CHANGE_GAME : // update selected game :/ { - m_selected_game.assign(event.GetString().mb_str()); + m_selected_game.assign(WxStrToStr(event.GetString())); m_game_btn->SetLabel(event.GetString().Prepend(_(" Game : "))); } break; @@ -503,7 +513,7 @@ void NetPlayDiag::OnThread(wxCommandEvent& event) std::string s; chat_msgs.Pop(s); //PanicAlert("message: %s", s.c_str()); - m_chat_text->AppendText(wxString(s.c_str(), *wxConvCurrent).Append(wxT('\n'))); + m_chat_text->AppendText(StrToWxStr(s).Append(wxT('\n'))); } } @@ -515,7 +525,7 @@ void NetPlayDiag::OnChangeGame(wxCommandEvent&) if (game_name.length()) { - m_selected_game = std::string(game_name.mb_str()); + m_selected_game = WxStrToStr(game_name); netplay_ptr->ChangeGame(m_selected_game); m_game_btn->SetLabel(game_name.Prepend(_(" Game : "))); } @@ -549,11 +559,7 @@ ChangeGameDiag::ChangeGameDiag(wxWindow* const parent, const CGameListCtrl* cons m_game_lbox = new wxListBox(this, wxID_ANY); m_game_lbox->Bind(wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, &ChangeGameDiag::OnPick, this); - // fill list with games - std::istringstream ss(game_list->GetGameNames()); - std::string game; - while (std::getline(ss,game)) - m_game_lbox->Append(wxString(game.c_str(), *wxConvCurrent)); + FillWithGameNames(m_game_lbox, *game_list); wxButton* const ok_btn = new wxButton(this, wxID_OK, _("Change")); ok_btn->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &ChangeGameDiag::OnPick, this); diff --git a/Source/Core/DolphinWX/Src/PHackSettings.cpp b/Source/Core/DolphinWX/Src/PHackSettings.cpp index 83f08d9cb7..dcfa1a8501 100644 --- a/Source/Core/DolphinWX/Src/PHackSettings.cpp +++ b/Source/Core/DolphinWX/Src/PHackSettings.cpp @@ -17,6 +17,7 @@ #include "PHackSettings.h" #include "ConfigManager.h" +#include "WxUtils.h" extern PHackData PHack_Data; @@ -97,8 +98,8 @@ void CPHackSettings::LoadPHackData() if (sTemp.empty()) sTemp = wxString(_("(UNKNOWN)")).char_str(); if (i == 0) - PHackChoice->Append(wxString("-------------", *wxConvCurrent)); - PHackChoice->Append(wxString(sTemp.c_str(), *wxConvCurrent)); + PHackChoice->Append(StrToWxStr("-------------")); + PHackChoice->Append(StrToWxStr(sTemp)); } PHackChoice->Select(0); @@ -106,8 +107,8 @@ void CPHackSettings::LoadPHackData() PHackSZFar->Set3StateValue((wxCheckBoxState)PHack_Data.PHackSZFar); PHackExP->Set3StateValue((wxCheckBoxState)PHack_Data.PHackExP); - PHackZNear->SetValue(wxString(PHack_Data.PHZNear.c_str(), *wxConvCurrent)); - PHackZFar->SetValue(wxString(PHack_Data.PHZFar.c_str(), *wxConvCurrent)); + PHackZNear->SetValue(StrToWxStr(PHack_Data.PHZNear)); + PHackZFar->SetValue(StrToWxStr(PHack_Data.PHZFar)); } void CPHackSettings::SetRefresh(wxCommandEvent& event) @@ -128,9 +129,9 @@ void CPHackSettings::SetRefresh(wxCommandEvent& event) PHPresetsIni.Get(sIndex, "PH_ExtraParam", &bTemp); PHackExP->Set3StateValue((wxCheckBoxState)bTemp); PHPresetsIni.Get(sIndex, "PH_ZNear", &sTemp); - PHackZNear->SetValue(wxString(sTemp.c_str(), *wxConvCurrent)); + PHackZNear->SetValue(StrToWxStr(sTemp)); PHPresetsIni.Get(sIndex, "PH_ZFar", &sTemp); - PHackZFar->SetValue(wxString(sTemp.c_str(), *wxConvCurrent)); + PHackZFar->SetValue(StrToWxStr(sTemp)); } } diff --git a/Source/Core/DolphinWX/Src/PatchAddEdit.cpp b/Source/Core/DolphinWX/Src/PatchAddEdit.cpp index 7d521006d3..ead7918d34 100644 --- a/Source/Core/DolphinWX/Src/PatchAddEdit.cpp +++ b/Source/Core/DolphinWX/Src/PatchAddEdit.cpp @@ -16,6 +16,7 @@ // http://code.google.com/p/dolphin-emu/ #include "PatchAddEdit.h" +#include "WxUtils.h" extern std::vector onFrame; @@ -48,7 +49,7 @@ void CPatchAddEdit::CreateGUIControls(int _selection) } else { - currentName = wxString(onFrame.at(_selection).name.c_str(), *wxConvCurrent); + currentName = StrToWxStr(onFrame.at(_selection).name); tempEntries = onFrame.at(_selection).entries; } @@ -66,7 +67,7 @@ void CPatchAddEdit::CreateGUIControls(int _selection) EntrySelection->SetValue((int)tempEntries.size()-1); wxArrayString wxArrayStringFor_EditPatchType; for (int i = 0; i < 3; ++i) - wxArrayStringFor_EditPatchType.Add(wxString::FromAscii(PatchEngine::PatchTypeStrings[i])); + wxArrayStringFor_EditPatchType.Add(StrToWxStr(PatchEngine::PatchTypeStrings[i])); EditPatchType = new wxRadioBox(this, ID_EDITPATCH_TYPE, _("Type"), wxDefaultPosition, wxDefaultSize, wxArrayStringFor_EditPatchType, 3, wxRA_SPECIFY_COLS); EditPatchType->SetSelection((int)tempEntries.at(0).type); wxStaticText* EditPatchValueText = new wxStaticText(this, ID_EDITPATCH_VALUE_TEXT, _("Value:")); @@ -121,7 +122,7 @@ void CPatchAddEdit::SavePatchData(wxCommandEvent& event) if (selection == -1) { PatchEngine::Patch newPatch; - newPatch.name = std::string(EditPatchName->GetValue().mb_str()); + newPatch.name = WxStrToStr(EditPatchName->GetValue()); newPatch.entries = tempEntries; newPatch.active = true; @@ -129,7 +130,7 @@ void CPatchAddEdit::SavePatchData(wxCommandEvent& event) } else { - onFrame.at(selection).name = std::string(EditPatchName->GetValue().mb_str()); + onFrame.at(selection).name = WxStrToStr(EditPatchName->GetValue()); onFrame.at(selection).entries = tempEntries; } diff --git a/Source/Core/DolphinWX/Src/UDPConfigDiag.cpp b/Source/Core/DolphinWX/Src/UDPConfigDiag.cpp index 2f31311495..9619f38dee 100644 --- a/Source/Core/DolphinWX/Src/UDPConfigDiag.cpp +++ b/Source/Core/DolphinWX/Src/UDPConfigDiag.cpp @@ -4,6 +4,8 @@ #include "Common.h" #include "ControllerEmu.h" #include "IniFile.h" +#include "WxUtils.h" + #include UDPConfigDiag::UDPConfigDiag(wxWindow * const parent, UDPWrapper * _wrp) : @@ -26,7 +28,7 @@ UDPConfigDiag::UDPConfigDiag(wxWindow * const parent, UDPWrapper * _wrp) : wxBoxSizer *const port_sizer = new wxBoxSizer(wxHORIZONTAL); port_sizer->Add(new wxStaticText(this, wxID_ANY, _("UDP Port:")), 0, wxALIGN_CENTER); - port_tbox = new wxTextCtrl(this, wxID_ANY, wxString::FromUTF8(wrp->port.c_str())); + port_tbox = new wxTextCtrl(this, wxID_ANY, StrToWxStr(wrp->port)); port_sizer->Add(port_tbox, 1, wxLEFT | wxEXPAND, 5); enable->Bind(wxEVT_COMMAND_CHECKBOX_CLICKED, &UDPConfigDiag::ChangeState, this); @@ -71,7 +73,7 @@ void UDPConfigDiag::ChangeUpdateFlags(wxCommandEvent & WXUNUSED(event)) void UDPConfigDiag::ChangeState(wxCommandEvent & WXUNUSED(event)) { - wrp->udpEn=enable->GetValue(); - wrp->port=port_tbox->GetValue().mb_str(wxConvUTF8); + wrp->udpEn = enable->GetValue(); + wrp->port = WxStrToStr(port_tbox->GetValue()); wrp->Refresh(); } diff --git a/Source/Core/DolphinWX/Src/VideoConfigDiag.cpp b/Source/Core/DolphinWX/Src/VideoConfigDiag.cpp index 8cd59b7c67..b2fe32cb65 100644 --- a/Source/Core/DolphinWX/Src/VideoConfigDiag.cpp +++ b/Source/Core/DolphinWX/Src/VideoConfigDiag.cpp @@ -142,7 +142,7 @@ wxArrayString GetListOfResolutions() if (std::find(resos.begin(), resos.end(), strRes) == resos.end()) { resos.push_back(strRes); - retlist.Add(wxString::FromAscii(res)); + retlist.Add(StrToWxStr(res)); } ZeroMemory(&dmi, sizeof(dmi)); } @@ -181,8 +181,7 @@ wxArrayString GetListOfResolutions() VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string &title, const std::string& _ininame) : wxDialog(parent, -1, - wxString::Format(_("Dolphin %s Graphics Configuration"), - wxGetTranslation(wxString::From8BitData(title.c_str()))), + wxString::Format(_("Dolphin %s Graphics Configuration"), wxGetTranslation(StrToWxStr(title))), wxDefaultPosition, wxDefaultSize) , vconfig(g_Config) , ininame(_ininame) @@ -213,9 +212,9 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string &title, con it = g_available_video_backends.begin(), itend = g_available_video_backends.end(); for (; it != itend; ++it) - choice_backend->AppendString(wxGetTranslation(wxString::FromAscii((*it)->GetName().c_str()))); + choice_backend->AppendString(wxGetTranslation(StrToWxStr((*it)->GetName()))); - choice_backend->SetStringSelection(wxGetTranslation(wxString::FromAscii(g_video_backend->GetName().c_str()))); + choice_backend->SetStringSelection(wxGetTranslation(StrToWxStr(g_video_backend->GetName()))); choice_backend->Bind(wxEVT_COMMAND_CHOICE_SELECTED, &VideoConfigDiag::Event_Backend, this); szr_basic->Add(label_backend, 1, wxALIGN_CENTER_VERTICAL, 5); @@ -237,7 +236,7 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string &title, con it = vconfig.backend_info.Adapters.begin(), itend = vconfig.backend_info.Adapters.end(); for (; it != itend; ++it) - choice_adapter->AppendString(wxString::FromAscii(it->c_str())); + choice_adapter->AppendString(StrToWxStr(*it)); choice_adapter->Select(vconfig.iAdapter); @@ -260,7 +259,7 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string &title, con RegisterControl(choice_display_resolution, wxGetTranslation(display_res_desc)); choice_display_resolution->Bind(wxEVT_COMMAND_CHOICE_SELECTED, &VideoConfigDiag::Event_DisplayResolution, this); - choice_display_resolution->SetStringSelection(wxString::FromAscii(SConfig::GetInstance().m_LocalCoreStartupParameter.strFullscreenResolution.c_str())); + choice_display_resolution->SetStringSelection(StrToWxStr(SConfig::GetInstance().m_LocalCoreStartupParameter.strFullscreenResolution)); szr_display->Add(label_display_resolution, 1, wxALIGN_CENTER_VERTICAL, 0); szr_display->Add(choice_display_resolution); @@ -356,7 +355,7 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string &title, con it = vconfig.backend_info.AAModes.begin(), itend = vconfig.backend_info.AAModes.end(); for (; it != itend; ++it) - choice_aamode->AppendString(wxGetTranslation(wxString::FromAscii(it->c_str()))); + choice_aamode->AppendString(wxGetTranslation(StrToWxStr(*it))); choice_aamode->Select(vconfig.iMultisampleMode); szr_enh->Add(text_aamode, 1, wxALIGN_CENTER_VERTICAL, 0); @@ -381,12 +380,12 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string &title, con it = vconfig.backend_info.PPShaders.begin(), itend = vconfig.backend_info.PPShaders.end(); for (; it != itend; ++it) - choice_ppshader->AppendString(wxString::FromAscii(it->c_str())); + choice_ppshader->AppendString(StrToWxStr(*it)); if (vconfig.sPostProcessingShader.empty()) choice_ppshader->Select(0); else - choice_ppshader->SetStringSelection(wxString::FromAscii(vconfig.sPostProcessingShader.c_str())); + choice_ppshader->SetStringSelection(StrToWxStr(vconfig.sPostProcessingShader)); choice_ppshader->Bind(wxEVT_COMMAND_CHOICE_SELECTED, &VideoConfigDiag::Event_PPShader, this); @@ -599,7 +598,7 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string &title, con void VideoConfigDiag::Event_DisplayResolution(wxCommandEvent &ev) { SConfig::GetInstance().m_LocalCoreStartupParameter.strFullscreenResolution = - choice_display_resolution->GetStringSelection().mb_str(); + WxStrToStr(choice_display_resolution->GetStringSelection()); #if defined(HAVE_XRANDR) && HAVE_XRANDR main_frame->m_XRRConfig->Update(); #endif diff --git a/Source/Core/DolphinWX/Src/VideoConfigDiag.h b/Source/Core/DolphinWX/Src/VideoConfigDiag.h index c7a19c6cb8..90a42c34a1 100644 --- a/Source/Core/DolphinWX/Src/VideoConfigDiag.h +++ b/Source/Core/DolphinWX/Src/VideoConfigDiag.h @@ -20,6 +20,7 @@ #include #include "MsgHandler.h" +#include "WxUtils.h" template class BoolSetting : public W @@ -99,7 +100,7 @@ protected: else { // Select current backend again - choice_backend->SetStringSelection(wxString::FromAscii(g_video_backend->GetName().c_str())); + choice_backend->SetStringSelection(StrToWxStr(g_video_backend->GetName())); } } @@ -129,7 +130,7 @@ protected: { const int sel = ev.GetInt(); if (sel) - vconfig.sPostProcessingShader = ev.GetString().mb_str(); + vconfig.sPostProcessingShader = WxStrToStr(ev.GetString()); else vconfig.sPostProcessingShader.clear(); diff --git a/Source/Core/DolphinWX/Src/WiimoteConfigDiag.cpp b/Source/Core/DolphinWX/Src/WiimoteConfigDiag.cpp index ea23e532e7..475718ed2e 100644 --- a/Source/Core/DolphinWX/Src/WiimoteConfigDiag.cpp +++ b/Source/Core/DolphinWX/Src/WiimoteConfigDiag.cpp @@ -4,13 +4,6 @@ #include "HW/WiimoteReal/WiimoteReal.h" #include "Frame.h" -const wxString& ConnectedWiimotesString() -{ - static wxString str; - str.Printf(_("%i connected"), WiimoteReal::Initialize()); - return str; -} - WiimoteConfigDiag::WiimoteConfigDiag(wxWindow* const parent, InputPlugin& plugin) : wxDialog(parent, -1, _("Dolphin Wiimote Configuration"), wxDefaultPosition, wxDefaultSize) , m_plugin(plugin) @@ -64,27 +57,31 @@ WiimoteConfigDiag::WiimoteConfigDiag(wxWindow* const parent, InputPlugin& plugin // "Real wiimotes" controls - connected_wiimotes_txt = new wxStaticText(this, -1, ConnectedWiimotesString()); - wxButton* const refresh_btn = new wxButton(this, -1, _("Refresh"), wxDefaultPosition); refresh_btn->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &WiimoteConfigDiag::RefreshRealWiimotes, this); -#ifdef _WIN32 - wxButton* const pairup_btn = new wxButton(this, -1, _("Pair Up"), wxDefaultPosition); - pairup_btn->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &WiimoteConfigDiag::PairUpRealWiimotes, this); -#endif + wxStaticBoxSizer* const real_wiimotes_group = new wxStaticBoxSizer(wxVERTICAL, this, _("Real Wiimotes")); + + wxBoxSizer* const real_wiimotes_sizer = new wxBoxSizer(wxHORIZONTAL); + + if (!WiimoteReal::g_wiimote_scanner.IsReady()) + real_wiimotes_group->Add(new wxStaticText(this, -1, _("A supported bluetooth device could not be found.\n" + "You must manually connect your wiimotes.")), 0, wxALIGN_CENTER | wxALL, 5); + + wxCheckBox* const continuous_scanning = new wxCheckBox(this, wxID_ANY, _("Continuous Scanning")); + continuous_scanning->Bind(wxEVT_COMMAND_CHECKBOX_CLICKED, &WiimoteConfigDiag::OnContinuousScanning, this); + continuous_scanning->SetValue(SConfig::GetInstance().m_WiimoteContinuousScanning); + auto wiimote_speaker = new wxCheckBox(this, wxID_ANY, _("Enable Speaker Data")); + wiimote_speaker->Bind(wxEVT_COMMAND_CHECKBOX_CLICKED, &WiimoteConfigDiag::OnEnableSpeaker, this); + wiimote_speaker->SetValue(SConfig::GetInstance().m_WiimoteEnableSpeaker); + + real_wiimotes_sizer->Add(continuous_scanning, 0, wxALIGN_CENTER_VERTICAL); + real_wiimotes_sizer->AddStretchSpacer(1); + real_wiimotes_sizer->Add(refresh_btn, 0, wxALL | wxALIGN_CENTER, 5); - // "Real wiimotes" layout - wxStaticBoxSizer* const real_wiimotes_group = new wxStaticBoxSizer(wxHORIZONTAL, this, _("Real Wiimotes")); - wxFlexGridSizer* const real_wiimotes_sizer = new wxFlexGridSizer(3, 5, 5); - real_wiimotes_sizer->Add(connected_wiimotes_txt, 0, wxALIGN_CENTER_VERTICAL); -#ifdef _WIN32 - real_wiimotes_sizer->Add(pairup_btn); -#endif - real_wiimotes_sizer->Add(refresh_btn); - real_wiimotes_group->Add(real_wiimotes_sizer, 1, wxALL, 5); - + real_wiimotes_group->Add(wiimote_speaker, 0); + real_wiimotes_group->Add(real_wiimotes_sizer, 0, wxEXPAND); // "General Settings" controls const wxString str[] = { _("Bottom"), _("Top") }; @@ -188,33 +185,9 @@ void WiimoteConfigDiag::ConfigEmulatedWiimote(wxCommandEvent& ev) m_emu_config_diag->Destroy(); } -void WiimoteConfigDiag::UpdateGUI() -{ - connected_wiimotes_txt->SetLabel(ConnectedWiimotesString()); -} - -#ifdef _WIN32 -void WiimoteConfigDiag::PairUpRealWiimotes(wxCommandEvent&) -{ - const int paired = WiimoteReal::PairUp(); - - if (paired > 0) - { - // TODO: Maybe add a label of newly paired up wiimotes? - WiimoteReal::Refresh(); - UpdateGUI(); - } - else if (paired < 0) - PanicAlertT("A supported bluetooth device could not be found!\n" - "If you are not using Microsoft's bluetooth stack " - "you must manually pair your wiimotes and use only the \"Refresh\" button."); -} -#endif - void WiimoteConfigDiag::RefreshRealWiimotes(wxCommandEvent&) { WiimoteReal::Refresh(); - UpdateGUI(); } void WiimoteConfigDiag::SelectSource(wxCommandEvent& event) @@ -222,30 +195,15 @@ void WiimoteConfigDiag::SelectSource(wxCommandEvent& event) // This needs to be changed now in order for refresh to work right. // Revert if the dialog is canceled. int index = m_wiimote_index_from_ctrl_id[event.GetId()]; - g_wiimote_sources[index] = event.GetInt(); + + WiimoteReal::ChangeWiimoteSource(index, event.GetInt()); + if (g_wiimote_sources[index] != WIIMOTE_SRC_EMU && g_wiimote_sources[index] != WIIMOTE_SRC_HYBRID) wiimote_configure_bt[index]->Disable(); else wiimote_configure_bt[index]->Enable(); } -void WiimoteConfigDiag::UpdateWiimoteStatus() -{ - for (int index = 0; index < 4; ++index) - { - if (m_orig_wiimote_sources[index] != g_wiimote_sources[index]) - { - // Disconnect first, otherwise the new source doesn't seem to work - CFrame::ConnectWiimote(index, false); - // Connect wiimotes - if (WIIMOTE_SRC_EMU & g_wiimote_sources[index]) - CFrame::ConnectWiimote(index, true); - else if (WIIMOTE_SRC_REAL & g_wiimote_sources[index] && WiimoteReal::g_wiimotes[index]) - CFrame::ConnectWiimote(index, WiimoteReal::g_wiimotes[index]->IsConnected()); - } - } -} - void WiimoteConfigDiag::RevertSource() { for (int i = 0; i < 4; ++i) @@ -267,7 +225,6 @@ void WiimoteConfigDiag::Save(wxCommandEvent& event) sec.Set("Source", (int)g_wiimote_sources[i]); } - UpdateWiimoteStatus(); inifile.Save(ini_filename); diff --git a/Source/Core/DolphinWX/Src/WiimoteConfigDiag.h b/Source/Core/DolphinWX/Src/WiimoteConfigDiag.h index 2b2e60de4a..4c33661ca2 100644 --- a/Source/Core/DolphinWX/Src/WiimoteConfigDiag.h +++ b/Source/Core/DolphinWX/Src/WiimoteConfigDiag.h @@ -24,20 +24,13 @@ class WiimoteConfigDiag : public wxDialog public: WiimoteConfigDiag(wxWindow* const parent, InputPlugin& plugin); -#ifdef _WIN32 - void PairUpRealWiimotes(wxCommandEvent& event); -#endif void RefreshRealWiimotes(wxCommandEvent& event); - void SelectSource(wxCommandEvent& event); - void UpdateWiimoteStatus(); void RevertSource(); - void ConfigEmulatedWiimote(wxCommandEvent& event); void Save(wxCommandEvent& event); - void UpdateGUI(); void OnSensorBarPos(wxCommandEvent& event) { @@ -64,6 +57,17 @@ public: SConfig::GetInstance().m_WiimoteReconnectOnLoad = event.IsChecked(); event.Skip(); } + void OnContinuousScanning(wxCommandEvent& event) + { + SConfig::GetInstance().m_WiimoteContinuousScanning = event.IsChecked(); + WiimoteReal::Initialize(); + event.Skip(); + } + void OnEnableSpeaker(wxCommandEvent& event) + { + SConfig::GetInstance().m_WiimoteEnableSpeaker = event.IsChecked(); + event.Skip(); + } private: void Cancel(wxCommandEvent& event); @@ -76,8 +80,6 @@ private: wxButton* wiimote_configure_bt[4]; std::map m_wiimote_index_from_conf_bt_id; - - wxStaticText* connected_wiimotes_txt; }; diff --git a/Source/Core/DolphinWX/Src/WxUtils.cpp b/Source/Core/DolphinWX/Src/WxUtils.cpp index 22fa10b84d..6856c96481 100644 --- a/Source/Core/DolphinWX/Src/WxUtils.cpp +++ b/Source/Core/DolphinWX/Src/WxUtils.cpp @@ -20,12 +20,14 @@ #include #include +#include "WxUtils.h" + namespace WxUtils { // Launch a file according to its mime type void Launch(const char *filename) { - if (! ::wxLaunchDefaultBrowser(wxString(filename, *wxConvCurrent))) + if (! ::wxLaunchDefaultBrowser(StrToWxStr(filename))) { // WARN_LOG } @@ -34,7 +36,7 @@ void Launch(const char *filename) // Launch an file explorer window on a certain path void Explore(const char *path) { - wxString wxPath = wxString(path, *wxConvCurrent); + wxString wxPath = StrToWxStr(path); // Default to file if (! wxPath.Contains(wxT("://"))) { @@ -52,3 +54,14 @@ void Explore(const char *path) } } // namespace + +std::string WxStrToStr(const wxString& str) +{ + return str.ToUTF8().data(); +} + +wxString StrToWxStr(const std::string& str) +{ + //return wxString::FromUTF8Unchecked(str.c_str()); + return wxString::FromUTF8(str.c_str()); +} diff --git a/Source/Core/DolphinWX/Src/WxUtils.h b/Source/Core/DolphinWX/Src/WxUtils.h index 8e837e9e96..61a16b298e 100644 --- a/Source/Core/DolphinWX/Src/WxUtils.h +++ b/Source/Core/DolphinWX/Src/WxUtils.h @@ -18,7 +18,11 @@ #ifndef WXUTILS_H #define WXUTILS_H -namespace WxUtils { +#include +#include + +namespace WxUtils +{ // Launch a file according to its mime type void Launch(const char *filename); @@ -28,4 +32,7 @@ void Explore(const char *path); } // namespace +std::string WxStrToStr(const wxString& str); +wxString StrToWxStr(const std::string& str); + #endif // WXUTILS diff --git a/Source/Core/DolphinWX/Src/X11Utils.cpp b/Source/Core/DolphinWX/Src/X11Utils.cpp index f032f81e96..6c4282cceb 100644 --- a/Source/Core/DolphinWX/Src/X11Utils.cpp +++ b/Source/Core/DolphinWX/Src/X11Utils.cpp @@ -26,6 +26,7 @@ extern char **environ; #if defined(HAVE_WX) && HAVE_WX #include #include +#include "WxUtils.h" #endif namespace X11Utils @@ -350,7 +351,7 @@ void XRRConfiguration::AddResolutions(wxArrayString& arrayStringFor_FullscreenRe if (std::find(resos.begin(), resos.end(), strRes) == resos.end()) { resos.push_back(strRes); - arrayStringFor_FullscreenResolution.Add(wxString::FromUTF8(strRes.c_str())); + arrayStringFor_FullscreenResolution.Add(StrToWxStr(strRes)); } } } diff --git a/Source/Core/DolphinWX/resources/no_banner.cpp b/Source/Core/DolphinWX/resources/no_banner.cpp deleted file mode 100644 index df8d51d737..0000000000 --- a/Source/Core/DolphinWX/resources/no_banner.cpp +++ /dev/null @@ -1,28 +0,0 @@ -static const unsigned char no_banner_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, - 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x20, 0x04, 0x03, - 0x00, 0x00, 0x00, 0x1f, 0xee, 0x60, 0x67, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, - 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, 0x0b, 0x13, 0x01, 0x00, 0x9a, - 0x9c, 0x18, 0x00, 0x00, 0x00, 0x07, 0x74, 0x49, 0x4d, 0x45, 0x07, 0xdd, 0x02, - 0x09, 0x16, 0x39, 0x17, 0xf0, 0x40, 0x6e, 0x04, 0x00, 0x00, 0x00, 0x15, 0x50, - 0x4c, 0x54, 0x45, 0x66, 0x66, 0x66, 0x6a, 0x6a, 0x6a, 0x6b, 0x6b, 0x6b, 0x6d, - 0x6d, 0x6d, 0x70, 0x70, 0x70, 0x73, 0x73, 0x73, 0x80, 0x80, 0x80, 0xd1, 0x7d, - 0x40, 0x35, 0x00, 0x00, 0x00, 0xc6, 0x49, 0x44, 0x41, 0x54, 0x38, 0xcb, 0x8d, - 0xd4, 0x31, 0x0e, 0xc3, 0x20, 0x10, 0x44, 0xd1, 0x51, 0x64, 0xfa, 0x1c, 0x25, - 0x47, 0x48, 0x45, 0xed, 0xca, 0x07, 0xb0, 0x80, 0xfb, 0x1f, 0x21, 0x05, 0x60, - 0xd6, 0x30, 0xe3, 0xac, 0xbb, 0x95, 0xf8, 0x7a, 0xb2, 0x01, 0xa3, 0x98, 0x27, - 0x01, 0x00, 0x10, 0xfa, 0x9c, 0xeb, 0xbc, 0xd9, 0x35, 0xb0, 0x43, 0xf9, 0xd6, - 0x15, 0x47, 0x1b, 0xf7, 0x3a, 0x46, 0x1d, 0xdc, 0x09, 0x06, 0x4c, 0xc1, 0x9d, - 0x60, 0xc0, 0x1c, 0x58, 0x82, 0x02, 0x73, 0x60, 0x09, 0x0a, 0x2c, 0xc1, 0x20, - 0x38, 0xb0, 0x04, 0x83, 0xe0, 0xc0, 0x1a, 0x74, 0x42, 0x00, 0x6b, 0xd0, 0x89, - 0x0f, 0x07, 0x48, 0xd0, 0x08, 0x01, 0x90, 0xa0, 0x13, 0x1c, 0x60, 0x41, 0x7a, - 0x02, 0x58, 0x60, 0x88, 0xe8, 0x0b, 0xd2, 0x03, 0x40, 0x83, 0x8b, 0x88, 0xde, - 0xe0, 0xac, 0xeb, 0x5f, 0xc5, 0x1b, 0xb4, 0x4d, 0xbe, 0xee, 0xc5, 0xbf, 0x20, - 0xf7, 0x77, 0x08, 0xce, 0x60, 0xbf, 0xbe, 0xd2, 0xe1, 0x0a, 0xf2, 0xd8, 0x87, - 0xe0, 0x0a, 0x76, 0xb3, 0xd3, 0x87, 0x23, 0xc8, 0xf6, 0x2c, 0x05, 0x47, 0xd0, - 0x80, 0xb7, 0x20, 0x20, 0x80, 0x2d, 0x09, 0x02, 0x02, 0x88, 0xf3, 0x3f, 0x4a, - 0x05, 0xe3, 0xa2, 0x09, 0x02, 0x0a, 0x28, 0x82, 0x80, 0x02, 0x14, 0x01, 0x09, - 0x08, 0x02, 0x12, 0x10, 0x04, 0x34, 0xc0, 0x89, 0x1f, 0xe2, 0x9a, 0xca, 0x1c, - 0x5f, 0x12, 0x62, 0x57, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, - 0x42, 0x60, 0x82 -}; diff --git a/Source/Core/InputCommon/Src/ControllerInterface/DInput/DInput.cpp b/Source/Core/InputCommon/Src/ControllerInterface/DInput/DInput.cpp index c23e9df17e..01baf9cf1a 100644 --- a/Source/Core/InputCommon/Src/ControllerInterface/DInput/DInput.cpp +++ b/Source/Core/InputCommon/Src/ControllerInterface/DInput/DInput.cpp @@ -4,7 +4,7 @@ #include "DInput.h" -#include +#include "StringUtil.h" #ifdef CIFACE_USE_DINPUT_JOYSTICK #include "DInputJoystick.h" @@ -41,24 +41,18 @@ BOOL CALLBACK DIEnumDevicesCallback(LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef) std::string GetDeviceName(const LPDIRECTINPUTDEVICE8 device) { - std::string out; - - DIPROPSTRING str; - ZeroMemory(&str, sizeof(str)); + DIPROPSTRING str = {}; str.diph.dwSize = sizeof(str); str.diph.dwHeaderSize = sizeof(str.diph); str.diph.dwHow = DIPH_DEVICE; + std::string result; if (SUCCEEDED(device->GetProperty(DIPROP_PRODUCTNAME, &str.diph))) { - const int size = WideCharToMultiByte(CP_UTF8, 0, str.wsz, -1, NULL, 0, NULL, NULL); - char* const data = new char[size]; - if (size == WideCharToMultiByte(CP_UTF8, 0, str.wsz, -1, data, size, NULL, NULL)) - out.assign(data); - delete[] data; + result = StripSpaces(UTF16ToUTF8(str.wsz)); } - return StripSpaces(out); + return result; } void Init(std::vector& devices, HWND hwnd) diff --git a/Source/Core/InputCommon/Src/ControllerInterface/OSX/OSXKeyboard.mm b/Source/Core/InputCommon/Src/ControllerInterface/OSX/OSXKeyboard.mm index 56e360019a..c22e267044 100644 --- a/Source/Core/InputCommon/Src/ControllerInterface/OSX/OSXKeyboard.mm +++ b/Source/Core/InputCommon/Src/ControllerInterface/OSX/OSXKeyboard.mm @@ -69,6 +69,7 @@ bool Keyboard::UpdateInput() CGRectMakeWithDictionaryRepresentation(boundsDictionary, &bounds); } + CFRelease(windowDescriptions); CFRelease(windowArray); CGEventRef event = CGEventCreate(nil); diff --git a/Source/Core/VideoCommon/CMakeLists.txt b/Source/Core/VideoCommon/CMakeLists.txt index 6ed8e29c6b..89b6828281 100644 --- a/Source/Core/VideoCommon/CMakeLists.txt +++ b/Source/Core/VideoCommon/CMakeLists.txt @@ -3,7 +3,6 @@ set(SRCS Src/BPFunctions.cpp Src/BPStructs.cpp Src/CPMemory.cpp Src/CommandProcessor.cpp - Src/DLCache.cpp Src/Debugger.cpp Src/Fifo.cpp Src/FPSCounter.cpp @@ -17,6 +16,7 @@ set(SRCS Src/BPFunctions.cpp Src/OpcodeDecoding.cpp Src/OpenCL.cpp Src/OpenCL/OCLTextureDecoder.cpp + Src/PerfQueryBase.cpp Src/PixelEngine.cpp Src/PixelShaderGen.cpp Src/PixelShaderManager.cpp @@ -24,7 +24,6 @@ set(SRCS Src/BPFunctions.cpp Src/Statistics.cpp Src/TextureCacheBase.cpp Src/TextureConversionShader.cpp - Src/TextureDecoder.cpp Src/VertexLoader.cpp Src/VertexLoaderManager.cpp Src/VertexLoader_Color.cpp @@ -41,6 +40,14 @@ set(SRCS Src/BPFunctions.cpp Src/memcpy_amd.cpp) set(LIBS core) + +if(NOT _M_GENERIC) + set(SRCS ${SRCS} Src/x64TextureDecoder.cpp + Src/x64DLCache.cpp) +else() + set(SRCS ${SRCS} Src/GenericTextureDecoder.cpp + Src/GenericDLCache.cpp) +endif() if(NOT ${CL} STREQUAL CL-NOTFOUND) list(APPEND LIBS ${CL}) endif() diff --git a/Source/Core/VideoCommon/Src/AVIDump.cpp b/Source/Core/VideoCommon/Src/AVIDump.cpp index c172903b5d..fefb09fecb 100644 --- a/Source/Core/VideoCommon/Src/AVIDump.cpp +++ b/Source/Core/VideoCommon/Src/AVIDump.cpp @@ -157,9 +157,21 @@ void AVIDump::Stop() NOTICE_LOG(VIDEO, "Stop"); } -void AVIDump::AddFrame(char *data) +void AVIDump::AddFrame(const u8* data, int w, int h) { - AVIStreamWrite(m_streamCompressed, ++m_frameCount, 1, (LPVOID) data, m_bitmap.biSizeImage, AVIIF_KEYFRAME, NULL, &m_byteBuffer); + static bool shown_error = false; + if ((w != m_bitmap.biWidth || h != m_bitmap.biHeight) && !shown_error) + { + PanicAlert("You have resized the window while dumping frames.\n" + "Nothing sane can be done to handle this.\n" + "Your video will likely be broken."); + shown_error = true; + + m_bitmap.biWidth = w; + m_bitmap.biHeight = h; + } + + AVIStreamWrite(m_streamCompressed, ++m_frameCount, 1, const_cast(data), m_bitmap.biSizeImage, AVIIF_KEYFRAME, NULL, &m_byteBuffer); m_totalBytes += m_byteBuffer; // Close the recording if the file is more than 2gb // VfW can't properly save files over 2gb in size, but can keep writing to them up to 4gb. @@ -298,9 +310,9 @@ bool AVIDump::CreateFile() return true; } -void AVIDump::AddFrame(uint8_t *data, int width, int height) +void AVIDump::AddFrame(const u8* data, int width, int height) { - avpicture_fill((AVPicture *)s_BGRFrame, data, PIX_FMT_BGR24, width, height); + avpicture_fill((AVPicture *)s_BGRFrame, const_cast(data), PIX_FMT_BGR24, width, height); // Convert image from BGR24 to desired pixel format, and scale to initial // width and height diff --git a/Source/Core/VideoCommon/Src/AVIDump.h b/Source/Core/VideoCommon/Src/AVIDump.h index e74df05db4..08ab6be254 100644 --- a/Source/Core/VideoCommon/Src/AVIDump.h +++ b/Source/Core/VideoCommon/Src/AVIDump.h @@ -24,6 +24,8 @@ #include #endif +#include "CommonTypes.h" + class AVIDump { private: @@ -36,11 +38,11 @@ class AVIDump public: #ifdef _WIN32 static bool Start(HWND hWnd, int w, int h); - static void AddFrame(char *data); #else static bool Start(int w, int h); - static void AddFrame(uint8_t *data, int width, int height); #endif + static void AddFrame(const u8* data, int width, int height); + static void Stop(); }; diff --git a/Source/Core/VideoCommon/Src/BPMemory.h b/Source/Core/VideoCommon/Src/BPMemory.h index 85e95f4f8b..0ee00f911e 100644 --- a/Source/Core/VideoCommon/Src/BPMemory.h +++ b/Source/Core/VideoCommon/Src/BPMemory.h @@ -62,7 +62,7 @@ #define BPMEM_COPYFILTER1 0x54 #define BPMEM_CLEARBBOX1 0x55 #define BPMEM_CLEARBBOX2 0x56 -#define BPMEM_UNKNOWN_57 0x57 +#define BPMEM_CLEAR_PIXEL_PERF 0x57 #define BPMEM_REVBITS 0x58 #define BPMEM_SCISSOROFFSET 0x59 #define BPMEM_PRELOAD_ADDR 0x60 diff --git a/Source/Core/VideoCommon/Src/BPStructs.cpp b/Source/Core/VideoCommon/Src/BPStructs.cpp index c7159b8783..99a03487d6 100644 --- a/Source/Core/VideoCommon/Src/BPStructs.cpp +++ b/Source/Core/VideoCommon/Src/BPStructs.cpp @@ -31,6 +31,7 @@ #include "VertexShaderManager.h" #include "Thread.h" #include "HW/Memmap.h" +#include "PerfQueryBase.h" using namespace BPFunctions; @@ -62,7 +63,6 @@ void RenderToXFB(const BPCmd &bp, const EFBRectangle &rc, float yScale, float xf { Renderer::RenderToXFB(xfbAddr, dstWidth, dstHeight, rc, gamma); } - void BPWritten(const BPCmd& bp) { /* @@ -144,7 +144,8 @@ void BPWritten(const BPCmd& bp) || bp.address == BPMEM_LOADTLUT0 || bp.address == BPMEM_LOADTLUT1 || bp.address == BPMEM_TEXINVALIDATE - || bp.address == BPMEM_PRELOAD_MODE)) + || bp.address == BPMEM_PRELOAD_MODE + || bp.address == BPMEM_CLEAR_PIXEL_PERF)) { return; } @@ -488,9 +489,10 @@ void BPWritten(const BPCmd& bp) case BPMEM_IND_IMASK: // Index Mask ? case BPMEM_REVBITS: // Always set to 0x0F when GX_InitRevBits() is called. break; - - case BPMEM_UNKNOWN_57: // Sunshine alternates this register between values 0x000 and 0xAAA - DEBUG_LOG(VIDEO, "Unknown BP Reg 0x57: %08x", bp.newvalue); + + case BPMEM_CLEAR_PIXEL_PERF: + // GXClearPixMetric writes 0xAAA here, Sunshine alternates this register between values 0x000 and 0xAAA + g_perf_query->ResetQuery(); break; case BPMEM_PRELOAD_ADDR: diff --git a/Source/Core/VideoCommon/Src/DataReader.h b/Source/Core/VideoCommon/Src/DataReader.h index 06668f8bbc..03061229c0 100644 --- a/Source/Core/VideoCommon/Src/DataReader.h +++ b/Source/Core/VideoCommon/Src/DataReader.h @@ -20,6 +20,8 @@ #ifndef _DATAREADER_H #define _DATAREADER_H +#include "VertexManagerBase.h" + extern u8* g_pVideoData; #if _M_SSE >= 0x301 && !(defined __GNUC__ && !defined __SSSE3__) @@ -31,43 +33,63 @@ __forceinline void DataSkip(u32 skip) g_pVideoData += skip; } +// probably unnecessary +template +__forceinline void DataSkip() +{ + g_pVideoData += count; +} + +template +__forceinline T DataPeek(int _uOffset) +{ + auto const result = Common::FromBigEndian(*reinterpret_cast(g_pVideoData + _uOffset)); + return result; +} + +// TODO: kill these __forceinline u8 DataPeek8(int _uOffset) { - return g_pVideoData[_uOffset]; + return DataPeek(_uOffset); } __forceinline u16 DataPeek16(int _uOffset) { - return Common::swap16(*(u16*)&g_pVideoData[_uOffset]); + return DataPeek(_uOffset); } __forceinline u32 DataPeek32(int _uOffset) { - return Common::swap32(*(u32*)&g_pVideoData[_uOffset]); + return DataPeek(_uOffset); } +template +__forceinline T DataRead() +{ + auto const result = DataPeek(0); + DataSkip(); + return result; +} + +// TODO: kill these __forceinline u8 DataReadU8() { - return *g_pVideoData++; + return DataRead(); } __forceinline s8 DataReadS8() { - return (s8)(*g_pVideoData++); + return DataRead(); } __forceinline u16 DataReadU16() { - u16 tmp = Common::swap16(*(u16*)g_pVideoData); - g_pVideoData += 2; - return tmp; + return DataRead(); } __forceinline u32 DataReadU32() { - u32 tmp = Common::swap32(*(u32*)g_pVideoData); - g_pVideoData += 4; - return tmp; + return DataRead(); } typedef void (*DataReadU32xNfunc)(u32 *buf); @@ -120,58 +142,16 @@ __forceinline u32 DataReadU32Unswapped() return tmp; } -template -__forceinline T DataRead() -{ - T tmp = *(T*)g_pVideoData; - g_pVideoData += sizeof(T); - return tmp; -} - -template <> -__forceinline u16 DataRead() -{ - u16 tmp = Common::swap16(*(u16*)g_pVideoData); - g_pVideoData += 2; - return tmp; -} - -template <> -__forceinline s16 DataRead() -{ - s16 tmp = (s16)Common::swap16(*(u16*)g_pVideoData); - g_pVideoData += 2; - return tmp; -} - -template <> -__forceinline u32 DataRead() -{ - u32 tmp = (u32)Common::swap32(*(u32*)g_pVideoData); - g_pVideoData += 4; - return tmp; -} - -template <> -__forceinline s32 DataRead() -{ - s32 tmp = (s32)Common::swap32(*(u32*)g_pVideoData); - g_pVideoData += 4; - return tmp; -} - -__forceinline float DataReadF32() -{ - union {u32 i; float f;} temp; - temp.i = Common::swap32(*(u32*)g_pVideoData); - g_pVideoData += 4; - float tmp = temp.f; - return tmp; -} - __forceinline u8* DataGetPosition() { return g_pVideoData; } +template +__forceinline void DataWrite(T data) +{ + *(T*)VertexManager::s_pCurBufferPointer = data; + VertexManager::s_pCurBufferPointer += sizeof(T); +} + #endif diff --git a/Source/Core/VideoCommon/Src/EmuWindow.cpp b/Source/Core/VideoCommon/Src/EmuWindow.cpp index cbb0bc31ac..81227ba0ca 100644 --- a/Source/Core/VideoCommon/Src/EmuWindow.cpp +++ b/Source/Core/VideoCommon/Src/EmuWindow.cpp @@ -205,10 +205,6 @@ LRESULT CALLBACK WndProc( HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam ) OnKeyDown(lParam); FreeLookInput((u32)wParam, lParam); } - else if (wParam == WIIMOTE_DISCONNECT) - { - PostMessage(m_hParent, WM_USER, wParam, lParam); - } break; // Called when a screensaver wants to show up while this window is active diff --git a/Source/Core/VideoCommon/Src/Fifo.cpp b/Source/Core/VideoCommon/Src/Fifo.cpp index 50aa21ebbf..413b163ced 100644 --- a/Source/Core/VideoCommon/Src/Fifo.cpp +++ b/Source/Core/VideoCommon/Src/Fifo.cpp @@ -222,11 +222,11 @@ void RunGpu() { u8 *uData = Memory::GetPointer(fifo.CPReadPointer); - SaveSSEState(); - LoadDefaultSSEState(); + FPURoundMode::SaveSIMDState(); + FPURoundMode::LoadDefaultSIMDState(); ReadDataFromFifo(uData, 32); OpcodeDecoder_Run(g_bSkipCurrentFrame); - LoadSSEState(); + FPURoundMode::LoadSIMDState(); //DEBUG_LOG(COMMANDPROCESSOR, "Fifo wraps to base"); diff --git a/Source/Core/VideoCommon/Src/GenericDLCache.cpp b/Source/Core/VideoCommon/Src/GenericDLCache.cpp new file mode 100644 index 0000000000..5e27deb469 --- /dev/null +++ b/Source/Core/VideoCommon/Src/GenericDLCache.cpp @@ -0,0 +1,52 @@ +// Copyright (C) 2003-2009 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +// TODO: Handle cache-is-full condition :p + + +#include "Common.h" +#include "DLCache.h" + +namespace DLCache +{ + +void Init() +{ +} + +void Shutdown() +{ +} + +void Clear() +{ +} + +void ProgressiveCleanup() +{ +} +} // namespace + +// NOTE - outside the namespace on purpose. +bool HandleDisplayList(u32 address, u32 size) +{ + return false; +} + +void IncrementCheckContextId() +{ +} diff --git a/Source/Core/VideoCommon/Src/GenericTextureDecoder.cpp b/Source/Core/VideoCommon/Src/GenericTextureDecoder.cpp new file mode 100644 index 0000000000..7546511515 --- /dev/null +++ b/Source/Core/VideoCommon/Src/GenericTextureDecoder.cpp @@ -0,0 +1,2216 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "Common.h" +//#include "VideoCommon.h" // to get debug logs + +#include "CPUDetect.h" +#include "TextureDecoder.h" +#include "OpenCL.h" +#include "OpenCL/OCLTextureDecoder.h" +#include "VideoConfig.h" + +#include "LookUpTables.h" + +#include + + + +bool TexFmt_Overlay_Enable=false; +bool TexFmt_Overlay_Center=false; + +extern const char* texfmt[]; +extern const unsigned char sfont_map[]; +extern const unsigned char sfont_raw[][9*10]; + +// TRAM +// STATE_TO_SAVE + GC_ALIGNED16(u8 texMem[TMEM_SIZE]); + + +// Gamecube/Wii texture decoder + +// Decodes all known Gamecube/Wii texture formats. +// by ector + +int TexDecoder_GetTexelSizeInNibbles(int format) +{ + switch (format & 0x3f) { + case GX_TF_I4: return 1; + case GX_TF_I8: return 2; + case GX_TF_IA4: return 2; + case GX_TF_IA8: return 4; + case GX_TF_RGB565: return 4; + case GX_TF_RGB5A3: return 4; + case GX_TF_RGBA8: return 8; + case GX_TF_C4: return 1; + case GX_TF_C8: return 2; + case GX_TF_C14X2: return 4; + case GX_TF_CMPR: return 1; + case GX_CTF_R4: return 1; + case GX_CTF_RA4: return 2; + case GX_CTF_RA8: return 4; + case GX_CTF_YUVA8: return 8; + case GX_CTF_A8: return 2; + case GX_CTF_R8: return 2; + case GX_CTF_G8: return 2; + case GX_CTF_B8: return 2; + case GX_CTF_RG8: return 4; + case GX_CTF_GB8: return 4; + + case GX_TF_Z8: return 2; + case GX_TF_Z16: return 4; + case GX_TF_Z24X8: return 8; + + case GX_CTF_Z4: return 1; + case GX_CTF_Z8M: return 2; + case GX_CTF_Z8L: return 2; + case GX_CTF_Z16L: return 4; + default: return 1; + } +} + +int TexDecoder_GetTextureSizeInBytes(int width, int height, int format) +{ + return (width * height * TexDecoder_GetTexelSizeInNibbles(format)) / 2; +} + +int TexDecoder_GetBlockWidthInTexels(u32 format) +{ + switch (format) + { + case GX_TF_I4: return 8; + case GX_TF_I8: return 8; + case GX_TF_IA4: return 8; + case GX_TF_IA8: return 4; + case GX_TF_RGB565: return 4; + case GX_TF_RGB5A3: return 4; + case GX_TF_RGBA8: return 4; + case GX_TF_C4: return 8; + case GX_TF_C8: return 8; + case GX_TF_C14X2: return 4; + case GX_TF_CMPR: return 8; + case GX_CTF_R4: return 8; + case GX_CTF_RA4: return 8; + case GX_CTF_RA8: return 4; + case GX_CTF_A8: return 8; + case GX_CTF_R8: return 8; + case GX_CTF_G8: return 8; + case GX_CTF_B8: return 8; + case GX_CTF_RG8: return 4; + case GX_CTF_GB8: return 4; + case GX_TF_Z8: return 8; + case GX_TF_Z16: return 4; + case GX_TF_Z24X8: return 4; + case GX_CTF_Z4: return 8; + case GX_CTF_Z8M: return 8; + case GX_CTF_Z8L: return 8; + case GX_CTF_Z16L: return 4; + default: + ERROR_LOG(VIDEO, "Unsupported Texture Format (%08x)! (GetBlockWidthInTexels)", format); + return 8; + } +} + +int TexDecoder_GetBlockHeightInTexels(u32 format) +{ + switch (format) + { + case GX_TF_I4: return 8; + case GX_TF_I8: return 4; + case GX_TF_IA4: return 4; + case GX_TF_IA8: return 4; + case GX_TF_RGB565: return 4; + case GX_TF_RGB5A3: return 4; + case GX_TF_RGBA8: return 4; + case GX_TF_C4: return 8; + case GX_TF_C8: return 4; + case GX_TF_C14X2: return 4; + case GX_TF_CMPR: return 8; + case GX_CTF_R4: return 8; + case GX_CTF_RA4: return 4; + case GX_CTF_RA8: return 4; + case GX_CTF_A8: return 4; + case GX_CTF_R8: return 4; + case GX_CTF_G8: return 4; + case GX_CTF_B8: return 4; + case GX_CTF_RG8: return 4; + case GX_CTF_GB8: return 4; + case GX_TF_Z8: return 4; + case GX_TF_Z16: return 4; + case GX_TF_Z24X8: return 4; + case GX_CTF_Z4: return 8; + case GX_CTF_Z8M: return 4; + case GX_CTF_Z8L: return 4; + case GX_CTF_Z16L: return 4; + default: + ERROR_LOG(VIDEO, "Unsupported Texture Format (%08x)! (GetBlockHeightInTexels)", format); + return 4; + } +} + +//returns bytes +int TexDecoder_GetPaletteSize(int format) +{ + switch (format) + { + case GX_TF_C4: return 16 * 2; + case GX_TF_C8: return 256 * 2; + case GX_TF_C14X2: return 16384 * 2; + default: + return 0; + } +} + +static inline u32 decodeIA8(u16 val) +{ + int a = val >> 8; + int i = val & 0xFF; + return (a << 24) | (i << 16) | (i << 8) | i; +} + +static inline u32 decode5A3(u16 val) +{ + int r,g,b,a; + if ((val & 0x8000)) + { + a = 0xFF; + r = Convert5To8((val >> 10) & 0x1F); + g = Convert5To8((val >> 5) & 0x1F); + b = Convert5To8(val & 0x1F); + } + else + { + a = Convert3To8((val >> 12) & 0x7); + r = Convert4To8((val >> 8) & 0xF); + g = Convert4To8((val >> 4) & 0xF); + b = Convert4To8(val & 0xF); + } + return (a << 24) | (r << 16) | (g << 8) | b; +} + +static inline u32 decode5A3RGBA(u16 val) +{ + int r,g,b,a; + if ((val&0x8000)) + { + r=Convert5To8((val>>10) & 0x1f); + g=Convert5To8((val>>5 ) & 0x1f); + b=Convert5To8((val ) & 0x1f); + a=0xFF; + } + else + { + a=Convert3To8((val>>12) & 0x7); + r=Convert4To8((val>>8 ) & 0xf); + g=Convert4To8((val>>4 ) & 0xf); + b=Convert4To8((val ) & 0xf); + } + return r | (g<<8) | (b << 16) | (a << 24); +} + +static inline u32 decode565RGBA(u16 val) +{ + int r,g,b,a; + r=Convert5To8((val>>11) & 0x1f); + g=Convert6To8((val>>5 ) & 0x3f); + b=Convert5To8((val ) & 0x1f); + a=0xFF; + return r | (g<<8) | (b << 16) | (a << 24); +} + +static inline u32 decodeIA8Swapped(u16 val) +{ + int a = val & 0xFF; + int i = val >> 8; + return i | (i<<8) | (i<<16) | (a<<24); +} + + + +struct DXTBlock +{ + u16 color1; + u16 color2; + u8 lines[4]; +}; + +//inline void decodebytesC4(u32 *dst, const u8 *src, int numbytes, int tlutaddr, int tlutfmt) +inline void decodebytesC4_5A3_To_BGRA32(u32 *dst, const u8 *src, int tlutaddr) +{ + u16 *tlut = (u16*)(texMem + tlutaddr); + for (int x = 0; x < 4; x++) + { + u8 val = src[x]; + *dst++ = decode5A3(Common::swap16(tlut[val >> 4])); + *dst++ = decode5A3(Common::swap16(tlut[val & 0xF])); + } +} + +inline void decodebytesC4_5A3_To_rgba32(u32 *dst, const u8 *src, int tlutaddr) +{ + u16 *tlut = (u16*)(texMem + tlutaddr); + for (int x = 0; x < 4; x++) + { + u8 val = src[x]; + *dst++ = decode5A3RGBA(Common::swap16(tlut[val >> 4])); + *dst++ = decode5A3RGBA(Common::swap16(tlut[val & 0xF])); + } +} + +inline void decodebytesC4_To_Raw16(u16* dst, const u8* src, int tlutaddr) +{ + u16* tlut = (u16*)(texMem+tlutaddr); + for (int x = 0; x < 4; x++) + { + u8 val = src[x]; + *dst++ = Common::swap16(tlut[val >> 4]); + *dst++ = Common::swap16(tlut[val & 0xF]); + } +} + +inline void decodebytesC4IA8_To_RGBA(u32* dst, const u8* src, int tlutaddr) +{ + u16* tlut = (u16*)(texMem+tlutaddr); + for (int x = 0; x < 4; x++) + { + u8 val = src[x]; + *dst++ = decodeIA8Swapped(tlut[val >> 4]); + *dst++ = decodeIA8Swapped(tlut[val & 0xF]); + } +} + +inline void decodebytesC4RGB565_To_RGBA(u32* dst, const u8* src, int tlutaddr) +{ + u16* tlut = (u16*)(texMem+tlutaddr); + for (int x = 0; x < 4; x++) + { + u8 val = src[x]; + *dst++ = decode565RGBA(Common::swap16(tlut[val >> 4])); + *dst++ = decode565RGBA(Common::swap16(tlut[val & 0xF])); + } +} + +//inline void decodebytesC8(u32 *dst, const u8 *src, int numbytes, int tlutaddr, int tlutfmt) +inline void decodebytesC8_5A3_To_BGRA32(u32 *dst, const u8 *src, int tlutaddr) +{ + u16 *tlut = (u16*)(texMem + tlutaddr); + for (int x = 0; x < 8; x++) + { + u8 val = src[x]; + *dst++ = decode5A3(Common::swap16(tlut[val])); + } +} + +inline void decodebytesC8_5A3_To_RGBA32(u32 *dst, const u8 *src, int tlutaddr) +{ + u16 *tlut = (u16*)(texMem + tlutaddr); + for (int x = 0; x < 8; x++) + { + u8 val = src[x]; + *dst++ = decode5A3RGBA(Common::swap16(tlut[val])); + } +} + +inline void decodebytesC8_To_Raw16(u16* dst, const u8* src, int tlutaddr) +{ + u16* tlut = (u16*)(texMem + tlutaddr); + for (int x = 0; x < 8; x++) + { + u8 val = src[x]; + *dst++ = Common::swap16(tlut[val]); + } +} + +inline void decodebytesC8IA8_To_RGBA(u32* dst, const u8* src, int tlutaddr) +{ + u16* tlut = (u16*)(texMem + tlutaddr); + for (int x = 0; x < 8; x++) + { + *dst++ = decodeIA8Swapped(tlut[src[x]]); + } +} + +inline void decodebytesC8RGB565_To_RGBA(u32* dst, const u8* src, int tlutaddr) +{ + u16* tlut = (u16*)(texMem + tlutaddr); + for (int x = 0; x < 8; x++) + { + *dst++ = decode565RGBA(Common::swap16(tlut[src[x]])); + } +} + +inline void decodebytesC14X2_5A3_To_BGRA32(u32 *dst, const u16 *src, int tlutaddr) +{ + u16 *tlut = (u16*)(texMem + tlutaddr); + for (int x = 0; x < 4; x++) + { + u16 val = Common::swap16(src[x]); + *dst++ = decode5A3(Common::swap16(tlut[(val & 0x3FFF)])); + } +} + +inline void decodebytesC14X2_5A3_To_RGBA(u32 *dst, const u16 *src, int tlutaddr) +{ + u16 *tlut = (u16*)(texMem + tlutaddr); + for (int x = 0; x < 4; x++) + { + u16 val = Common::swap16(src[x]); + *dst++ = decode5A3RGBA(Common::swap16(tlut[(val & 0x3FFF)])); + } +} + +inline void decodebytesC14X2_To_Raw16(u16* dst, const u16* src, int tlutaddr) +{ + u16* tlut = (u16*)(texMem + tlutaddr); + for (int x = 0; x < 4; x++) + { + u16 val = Common::swap16(src[x]); + *dst++ = Common::swap16(tlut[(val & 0x3FFF)]); + } +} + +inline void decodebytesC14X2IA8_To_RGBA(u32* dst, const u16* src, int tlutaddr) +{ + u16* tlut = (u16*)(texMem + tlutaddr); + for (int x = 0; x < 4; x++) + { + u16 val = Common::swap16(src[x]); + *dst++ = decodeIA8Swapped(tlut[(val & 0x3FFF)]); + } +} + +inline void decodebytesC14X2rgb565_To_RGBA(u32* dst, const u16* src, int tlutaddr) +{ + u16* tlut = (u16*)(texMem + tlutaddr); + for (int x = 0; x < 4; x++) + { + u16 val = Common::swap16(src[x]); + *dst++ = decode565RGBA(Common::swap16(tlut[(val & 0x3FFF)])); + } +} + +// Needs more speed. +inline void decodebytesIA4(u16 *dst, const u8 *src) +{ + for (int x = 0; x < 8; x++) + { + const u8 val = src[x]; + u8 a = Convert4To8(val >> 4); + u8 l = Convert4To8(val & 0xF); + dst[x] = (a << 8) | l; + } +} + +inline void decodebytesIA4RGBA(u32 *dst, const u8 *src) +{ + for (int x = 0; x < 8; x++) + { + const u8 val = src[x]; + u8 a = Convert4To8(val >> 4); + u8 l = Convert4To8(val & 0xF); + dst[x] = (a << 24) | l << 16 | l << 8 | l; + } +} + +inline void decodebytesRGB5A3(u32 *dst, const u16 *src) +{ +#if 0 + for (int x = 0; x < 4; x++) + dst[x] = decode5A3(Common::swap16(src[x])); +#else + dst[0] = decode5A3(Common::swap16(src[0])); + dst[1] = decode5A3(Common::swap16(src[1])); + dst[2] = decode5A3(Common::swap16(src[2])); + dst[3] = decode5A3(Common::swap16(src[3])); +#endif +} + +inline void decodebytesRGB5A3rgba(u32 *dst, const u16 *src) +{ +#if 0 + for (int x = 0; x < 4; x++) + dst[x] = decode5A3RGBA(Common::swap16(src[x])); +#else + dst[0] = decode5A3RGBA(Common::swap16(src[0])); + dst[1] = decode5A3RGBA(Common::swap16(src[1])); + dst[2] = decode5A3RGBA(Common::swap16(src[2])); + dst[3] = decode5A3RGBA(Common::swap16(src[3])); +#endif +} + +// This one is used by many video formats. It'd therefore be good if it was fast. +// Needs more speed. +inline void decodebytesARGB8_4(u32 *dst, const u16 *src, const u16 *src2) +{ +#if 0 + for (int x = 0; x < 4; x++) + dst[x] = Common::swap32((src2[x] << 16) | src[x]); +#else + dst[0] = Common::swap32((src2[0] << 16) | src[0]); + dst[1] = Common::swap32((src2[1] << 16) | src[1]); + dst[2] = Common::swap32((src2[2] << 16) | src[2]); + dst[3] = Common::swap32((src2[3] << 16) | src[3]); +#endif + + // This can probably be done in a few SSE pack/unpack instructions + pshufb + // some unpack instruction x2: + // ABABABABABABABAB 1212121212121212 -> + // AB12AB12AB12AB12 AB12AB12AB12AB12 + // 2x pshufb-> + // 21BA21BA21BA21BA 21BA21BA21BA21BA + // and we are done. +} + +inline void decodebytesARGB8_4ToRgba(u32 *dst, const u16 *src, const u16 * src2) +{ +#if 0 + for (int x = 0; x < 4; x++) { + dst[x] = ((src[x] & 0xFF) << 24) | ((src[x] & 0xFF00)>>8) | (src2[x] << 8); + } +#else + dst[0] = ((src[0] & 0xFF) << 24) | ((src[0] & 0xFF00)>>8) | (src2[0] << 8); + dst[1] = ((src[1] & 0xFF) << 24) | ((src[1] & 0xFF00)>>8) | (src2[1] << 8); + dst[2] = ((src[2] & 0xFF) << 24) | ((src[2] & 0xFF00)>>8) | (src2[2] << 8); + dst[3] = ((src[3] & 0xFF) << 24) | ((src[3] & 0xFF00)>>8) | (src2[3] << 8); +#endif +} + +inline u32 makecol(int r, int g, int b, int a) +{ + return (a << 24)|(r << 16)|(g << 8)|b; +} + +inline u32 makeRGBA(int r, int g, int b, int a) +{ + return (a<<24)|(b<<16)|(g<<8)|r; +} + +void decodeDXTBlock(u32 *dst, const DXTBlock *src, int pitch) +{ + // S3TC Decoder (Note: GCN decodes differently from PC so we can't use native support) + // Needs more speed. + u16 c1 = Common::swap16(src->color1); + u16 c2 = Common::swap16(src->color2); + int blue1 = Convert5To8(c1 & 0x1F); + int blue2 = Convert5To8(c2 & 0x1F); + int green1 = Convert6To8((c1 >> 5) & 0x3F); + int green2 = Convert6To8((c2 >> 5) & 0x3F); + int red1 = Convert5To8((c1 >> 11) & 0x1F); + int red2 = Convert5To8((c2 >> 11) & 0x1F); + int colors[4]; + colors[0] = makecol(red1, green1, blue1, 255); + colors[1] = makecol(red2, green2, blue2, 255); + if (c1 > c2) + { + int blue3 = ((blue2 - blue1) >> 1) - ((blue2 - blue1) >> 3); + int green3 = ((green2 - green1) >> 1) - ((green2 - green1) >> 3); + int red3 = ((red2 - red1) >> 1) - ((red2 - red1) >> 3); + colors[2] = makecol(red1 + red3, green1 + green3, blue1 + blue3, 255); + colors[3] = makecol(red2 - red3, green2 - green3, blue2 - blue3, 255); + } + else + { + colors[2] = makecol((red1 + red2 + 1) / 2, // Average + (green1 + green2 + 1) / 2, + (blue1 + blue2 + 1) / 2, 255); + colors[3] = makecol(red2, green2, blue2, 0); // Color2 but transparent + } + + for (int y = 0; y < 4; y++) + { + int val = src->lines[y]; + for (int x = 0; x < 4; x++) + { + dst[x] = colors[(val >> 6) & 3]; + val <<= 2; + } + dst += pitch; + } +} + +void decodeDXTBlockRGBA(u32 *dst, const DXTBlock *src, int pitch) +{ + // S3TC Decoder (Note: GCN decodes differently from PC so we can't use native support) + // Needs more speed. + u16 c1 = Common::swap16(src->color1); + u16 c2 = Common::swap16(src->color2); + int blue1 = Convert5To8(c1 & 0x1F); + int blue2 = Convert5To8(c2 & 0x1F); + int green1 = Convert6To8((c1 >> 5) & 0x3F); + int green2 = Convert6To8((c2 >> 5) & 0x3F); + int red1 = Convert5To8((c1 >> 11) & 0x1F); + int red2 = Convert5To8((c2 >> 11) & 0x1F); + int colors[4]; + colors[0] = makeRGBA(red1, green1, blue1, 255); + colors[1] = makeRGBA(red2, green2, blue2, 255); + if (c1 > c2) + { + int blue3 = ((blue2 - blue1) >> 1) - ((blue2 - blue1) >> 3); + int green3 = ((green2 - green1) >> 1) - ((green2 - green1) >> 3); + int red3 = ((red2 - red1) >> 1) - ((red2 - red1) >> 3); + colors[2] = makeRGBA(red1 + red3, green1 + green3, blue1 + blue3, 255); + colors[3] = makeRGBA(red2 - red3, green2 - green3, blue2 - blue3, 255); + } + else + { + colors[2] = makeRGBA((red1 + red2 + 1) / 2, // Average + (green1 + green2 + 1) / 2, + (blue1 + blue2 + 1) / 2, 255); + colors[3] = makeRGBA(red2, green2, blue2, 0); // Color2 but transparent + } + + for (int y = 0; y < 4; y++) + { + int val = src->lines[y]; + for (int x = 0; x < 4; x++) + { + dst[x] = colors[(val >> 6) & 3]; + val <<= 2; + } + dst += pitch; + } +} + +#if 0 // TODO - currently does not handle transparency correctly and causes problems when texture dimensions are not multiples of 8 +static void copyDXTBlock(u8* dst, const u8* src) +{ + ((u16*)dst)[0] = Common::swap16(((u16*)src)[0]); + ((u16*)dst)[1] = Common::swap16(((u16*)src)[1]); + u32 pixels = ((u32*)src)[1]; + // A bit of trickiness here: the row are in the same order + // between the two formats, but the ordering within the rows + // is reversed. + pixels = ((pixels >> 4) & 0x0F0F0F0F) | ((pixels << 4) & 0xF0F0F0F0); + pixels = ((pixels >> 2) & 0x33333333) | ((pixels << 2) & 0xCCCCCCCC); + ((u32*)dst)[1] = pixels; +} +#endif + +static PC_TexFormat GetPCFormatFromTLUTFormat(int tlutfmt) +{ + switch (tlutfmt) + { + case 0: return PC_TEX_FMT_IA8; // IA8 + case 1: return PC_TEX_FMT_RGB565; // RGB565 + case 2: return PC_TEX_FMT_BGRA32; // RGB5A3: This TLUT format requires + // extra work to decode. + } + return PC_TEX_FMT_NONE; // Error +} + +PC_TexFormat GetPC_TexFormat(int texformat, int tlutfmt) +{ + switch (texformat) + { + case GX_TF_C4: + return GetPCFormatFromTLUTFormat(tlutfmt); + case GX_TF_I4: + return PC_TEX_FMT_IA8; + case GX_TF_I8: // speed critical + return PC_TEX_FMT_IA8; + case GX_TF_C8: + return GetPCFormatFromTLUTFormat(tlutfmt); + case GX_TF_IA4: + return PC_TEX_FMT_IA4_AS_IA8; + case GX_TF_IA8: + return PC_TEX_FMT_IA8; + case GX_TF_C14X2: + return GetPCFormatFromTLUTFormat(tlutfmt); + case GX_TF_RGB565: + return PC_TEX_FMT_RGB565; + case GX_TF_RGB5A3: + return PC_TEX_FMT_BGRA32; + case GX_TF_RGBA8: // speed critical + return PC_TEX_FMT_BGRA32; + case GX_TF_CMPR: // speed critical + // The metroid games use this format almost exclusively. + { + return PC_TEX_FMT_BGRA32; + } + } + + // The "copy" texture formats, too? + return PC_TEX_FMT_NONE; +} + + +//switch endianness, unswizzle +//TODO: to save memory, don't blindly convert everything to argb8888 +//also ARGB order needs to be swapped later, to accommodate modern hardware better +//need to add DXT support too +PC_TexFormat TexDecoder_Decode_real(u8 *dst, const u8 *src, int width, int height, int texformat, int tlutaddr, int tlutfmt) +{ + const int Wsteps4 = (width + 3) / 4; + const int Wsteps8 = (width + 7) / 8; + + switch (texformat) + { + case GX_TF_C4: + if (tlutfmt == 2) + { + // Special decoding is required for TLUT format 5A3 + for (int y = 0; y < height; y += 8) + for (int x = 0, yStep = (y / 8) * Wsteps8; x < width; x += 8, yStep++) + for (int iy = 0, xStep = yStep * 8; iy < 8; iy++, xStep++) + decodebytesC4_5A3_To_BGRA32((u32*)dst + (y + iy) * width + x, src + 4 * xStep, tlutaddr); + } + else + { + for (int y = 0; y < height; y += 8) + for (int x = 0, yStep = (y / 8) * Wsteps8; x < width; x += 8, yStep++) + for (int iy = 0, xStep = yStep * 8; iy < 8; iy++, xStep++) + decodebytesC4_To_Raw16((u16*)dst + (y + iy) * width + x, src + 4 * xStep, tlutaddr); + } + return GetPCFormatFromTLUTFormat(tlutfmt); + case GX_TF_I4: + { + for (int y = 0; y < height; y += 8) + for (int x = 0, yStep = (y / 8) * Wsteps8; x < width; x += 8, yStep++) + for (int iy = 0, xStep = yStep * 8 ; iy < 8; iy++,xStep++) + for (int ix = 0; ix < 4; ix++) + { + int val = src[4 * xStep + ix]; + dst[(y + iy) * width + x + ix * 2] = Convert4To8(val >> 4); + dst[(y + iy) * width + x + ix * 2 + 1] = Convert4To8(val & 0xF); + } + } + return PC_TEX_FMT_I4_AS_I8; + case GX_TF_I8: // speed critical + { + for (int y = 0; y < height; y += 4) + for (int x = 0, yStep = (y / 4) * Wsteps8; x < width; x += 8, yStep++) + for (int iy = 0, xStep = 4 * yStep; iy < 4; iy++, xStep++) + { + ((u64*)(dst + (y + iy) * width + x))[0] = ((u64*)(src + 8 * xStep))[0]; + } + } + return PC_TEX_FMT_I8; + case GX_TF_C8: + if (tlutfmt == 2) + { + // Special decoding is required for TLUT format 5A3 + for (int y = 0; y < height; y += 4) + for (int x = 0, yStep = (y / 4) * Wsteps8; x < width; x += 8, yStep++) + for (int iy = 0, xStep = 4 * yStep; iy < 4; iy++, xStep++) + decodebytesC8_5A3_To_BGRA32((u32*)dst + (y + iy) * width + x, src + 8 * xStep, tlutaddr); + } + else + { + + { + for (int y = 0; y < height; y += 4) + for (int x = 0, yStep = (y / 4) * Wsteps8; x < width; x += 8, yStep++) + for (int iy = 0, xStep = 4 * yStep; iy < 4; iy++, xStep++) + decodebytesC8_To_Raw16((u16*)dst + (y + iy) * width + x, src + 8 * xStep, tlutaddr); + } + } + return GetPCFormatFromTLUTFormat(tlutfmt); + case GX_TF_IA4: + { + for (int y = 0; y < height; y += 4) + for (int x = 0, yStep = (y / 4) * Wsteps8; x < width; x += 8, yStep++) + for (int iy = 0, xStep = 4 * yStep; iy < 4; iy++, xStep++) + decodebytesIA4((u16*)dst + (y + iy) * width + x, src + 8 * xStep); + } + return PC_TEX_FMT_IA4_AS_IA8; + case GX_TF_IA8: + { + for (int y = 0; y < height; y += 4) + for (int x = 0, yStep = (y / 4) * Wsteps4; x < width; x += 4, yStep++) + for (int iy = 0, xStep = yStep * 4; iy < 4; iy++, xStep++) + { + u16 *ptr = (u16 *)dst + (y + iy) * width + x; + u16 *s = (u16 *)(src + 8 * xStep); + for(int j = 0; j < 4; j++) + *ptr++ = Common::swap16(*s++); + } + + } + return PC_TEX_FMT_IA8; + case GX_TF_C14X2: + if (tlutfmt == 2) + { + // Special decoding is required for TLUT format 5A3 + for (int y = 0; y < height; y += 4) + for (int x = 0, yStep = (y / 4) * Wsteps4; x < width; x += 4, yStep++) + for (int iy = 0, xStep = 4 * yStep; iy < 4; iy++, xStep++) + decodebytesC14X2_5A3_To_BGRA32((u32*)dst + (y + iy) * width + x, (u16*)(src + 8 * xStep), tlutaddr); + } + else + { + for (int y = 0; y < height; y += 4) + for (int x = 0, yStep = (y / 4) * Wsteps4; x < width; x += 4, yStep++) + for (int iy = 0, xStep = 4 * yStep; iy < 4; iy++, xStep++) + decodebytesC14X2_To_Raw16((u16*)dst + (y + iy) * width + x,(u16*)(src + 8 * xStep), tlutaddr); + } + return GetPCFormatFromTLUTFormat(tlutfmt); + case GX_TF_RGB565: + { + for (int y = 0; y < height; y += 4) + for (int x = 0, yStep = (y / 4) * Wsteps4; x < width; x += 4, yStep++) + for (int iy = 0, xStep = 4 * yStep; iy < 4; iy++, xStep++) + { + u16 *ptr = (u16 *)dst + (y + iy) * width + x; + u16 *s = (u16 *)(src + 8 * xStep); + for(int j = 0; j < 4; j++) + *ptr++ = Common::swap16(*s++); + } + } + return PC_TEX_FMT_RGB565; + case GX_TF_RGB5A3: + { + for (int y = 0; y < height; y += 4) + for (int x = 0, yStep = (y / 4) * Wsteps4; x < width; x += 4, yStep++) + for (int iy = 0, xStep = 4 * yStep; iy < 4; iy++, xStep++) + //decodebytesRGB5A3((u32*)dst+(y+iy)*width+x, (u16*)src, 4); + decodebytesRGB5A3((u32*)dst+(y+iy)*width+x, (u16*)(src + 8 * xStep)); + } + return PC_TEX_FMT_BGRA32; + case GX_TF_RGBA8: // speed critical + { + + { + for (int y = 0; y < height; y += 4) + for (int x = 0, yStep = (y / 4) * Wsteps4; x < width; x += 4, yStep++) + { + const u8* src2 = src + 64 * yStep; + for (int iy = 0; iy < 4; iy++) + decodebytesARGB8_4((u32*)dst + (y+iy)*width + x, (u16*)src2 + 4 * iy, (u16*)src2 + 4 * iy + 16); + } + } + } + return PC_TEX_FMT_BGRA32; + case GX_TF_CMPR: // speed critical + // The metroid games use this format almost exclusively. + { +#if 0 // TODO - currently does not handle transparency correctly and causes problems when texture dimensions are not multiples of 8 + // 11111111 22222222 55555555 66666666 + // 33333333 44444444 77777777 88888888 + for (int y = 0; y < height; y += 8) + { + for (int x = 0; x < width; x += 8) + { + copyDXTBlock(dst+(y/2)*width+x*2, src); + src += 8; + copyDXTBlock(dst+(y/2)*width+x*2+8, src); + src += 8; + copyDXTBlock(dst+(y/2+2)*width+x*2, src); + src += 8; + copyDXTBlock(dst+(y/2+2)*width+x*2+8, src); + src += 8; + } + } + return PC_TEX_FMT_DXT1; +#else + for (int y = 0; y < height; y += 8) + { + for (int x = 0, yStep = (y / 8) * Wsteps8; x < width; x += 8, yStep++) + { + const u8* src2 = src + 4 * sizeof(DXTBlock) * yStep; + decodeDXTBlock((u32*)dst + y * width + x, (DXTBlock*)src2, width); + src2 += sizeof(DXTBlock); + decodeDXTBlock((u32*)dst + y * width + x + 4, (DXTBlock*)src2, width); + src2 += sizeof(DXTBlock); + decodeDXTBlock((u32*)dst + (y + 4) * width + x, (DXTBlock*)src2, width); + src2 += sizeof(DXTBlock); + decodeDXTBlock((u32*)dst + (y + 4) * width + x + 4, (DXTBlock*)src2, width); + } + } +#endif + return PC_TEX_FMT_BGRA32; + } + } + + // The "copy" texture formats, too? + return PC_TEX_FMT_NONE; +} + + + +// JSD 01/06/11: +// TODO: we really should ensure BOTH the source and destination addresses are aligned to 16-byte boundaries to +// squeeze out a little more performance. _mm_loadu_si128/_mm_storeu_si128 is slower than _mm_load_si128/_mm_store_si128 +// because they work on unaligned addresses. The processor is free to make the assumption that addresses are multiples +// of 16 in the aligned case. +// TODO: complete SSE2 optimization of less often used texture formats. +// TODO: refactor algorithms using _mm_loadl_epi64 unaligned loads to prefer 128-bit aligned loads. + +PC_TexFormat TexDecoder_Decode_RGBA(u32 * dst, const u8 * src, int width, int height, int texformat, int tlutaddr, int tlutfmt) +{ + + const int Wsteps4 = (width + 3) / 4; + const int Wsteps8 = (width + 7) / 8; + + switch (texformat) + { + case GX_TF_C4: + if (tlutfmt == 2) + { + // Special decoding is required for TLUT format 5A3 + for (int y = 0; y < height; y += 8) + for (int x = 0, yStep = (y / 8) * Wsteps8; x < width; x += 8,yStep++) + for (int iy = 0, xStep = 8 * yStep; iy < 8; iy++,xStep++) + decodebytesC4_5A3_To_rgba32(dst + (y + iy) * width + x, src + 4 * xStep, tlutaddr); + } + else if(tlutfmt == 0) + { + for (int y = 0; y < height; y += 8) + for (int x = 0, yStep = (y / 8) * Wsteps8; x < width; x += 8,yStep++) + for (int iy = 0, xStep = 8 * yStep; iy < 8; iy++,xStep++) + decodebytesC4IA8_To_RGBA(dst + (y + iy) * width + x, src + 4 * xStep, tlutaddr); + + } + else + { + for (int y = 0; y < height; y += 8) + for (int x = 0, yStep = (y / 8) * Wsteps8; x < width; x += 8,yStep++) + for (int iy = 0, xStep = 8 * yStep; iy < 8; iy++,xStep++) + decodebytesC4RGB565_To_RGBA(dst + (y + iy) * width + x, src + 4 * xStep, tlutaddr); + } + break; + case GX_TF_I4: + { + // Reference C implementation: + for (int y = 0; y < height; y += 8) + for (int x = 0; x < width; x += 8) + for (int iy = 0; iy < 8; iy++, src += 4) + for (int ix = 0; ix < 4; ix++) + { + int val = src[ix]; + u8 i1 = Convert4To8(val >> 4); + u8 i2 = Convert4To8(val & 0xF); + memset(dst+(y + iy) * width + x + ix * 2 , i1,4); + memset(dst+(y + iy) * width + x + ix * 2 + 1 , i2,4); + } + } + break; + case GX_TF_I8: // speed critical + { + // Reference C implementation + for (int y = 0; y < height; y += 4) + for (int x = 0; x < width; x += 8) + for (int iy = 0; iy < 4; ++iy, src += 8) + { + u32 * newdst = dst + (y + iy)*width+x; + const u8 * newsrc = src; + u8 srcval; + + srcval = (newsrc++)[0]; (newdst++)[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24); + srcval = (newsrc++)[0]; (newdst++)[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24); + srcval = (newsrc++)[0]; (newdst++)[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24); + srcval = (newsrc++)[0]; (newdst++)[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24); + srcval = (newsrc++)[0]; (newdst++)[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24); + srcval = (newsrc++)[0]; (newdst++)[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24); + srcval = (newsrc++)[0]; (newdst++)[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24); + srcval = newsrc[0]; newdst[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24); + } + } + break; + case GX_TF_C8: + if (tlutfmt == 2) + { + // Special decoding is required for TLUT format 5A3 + for (int y = 0; y < height; y += 4) + for (int x = 0, yStep = (y / 4) * Wsteps8; x < width; x += 8, yStep++) + for (int iy = 0, xStep = 4 * yStep; iy < 4; iy++, xStep++) + decodebytesC8_5A3_To_RGBA32((u32*)dst + (y + iy) * width + x, src + 8 * xStep, tlutaddr); + } + else if(tlutfmt == 0) + { + for (int y = 0; y < height; y += 4) + for (int x = 0, yStep = (y / 4) * Wsteps8; x < width; x += 8, yStep++) + for (int iy = 0, xStep = 4 * yStep; iy < 4; iy++, xStep++) + decodebytesC8IA8_To_RGBA(dst + (y + iy) * width + x, src + 8 * xStep, tlutaddr); + + } + else + { + for (int y = 0; y < height; y += 4) + for (int x = 0, yStep = (y / 4) * Wsteps8; x < width; x += 8, yStep++) + for (int iy = 0, xStep = 4 * yStep; iy < 4; iy++, xStep++) + decodebytesC8RGB565_To_RGBA(dst + (y + iy) * width + x, src + 8 * xStep, tlutaddr); + + } + break; + case GX_TF_IA4: + { + for (int y = 0; y < height; y += 4) + for (int x = 0, yStep = (y / 4) * Wsteps8; x < width; x += 8, yStep++) + for (int iy = 0, xStep = 4 * yStep; iy < 4; iy++, xStep++) + decodebytesIA4RGBA(dst + (y + iy) * width + x, src + 8 * xStep); + } + break; + case GX_TF_IA8: + { + // Reference C implementation: + for (int y = 0; y < height; y += 4) + for (int x = 0; x < width; x += 4) + for (int iy = 0; iy < 4; iy++, src += 8) + { + u32 *ptr = dst + (y + iy) * width + x; + u16 *s = (u16 *)src; + ptr[0] = decodeIA8Swapped(s[0]); + ptr[1] = decodeIA8Swapped(s[1]); + ptr[2] = decodeIA8Swapped(s[2]); + ptr[3] = decodeIA8Swapped(s[3]); + } + } + break; + case GX_TF_C14X2: + if (tlutfmt == 2) + { + // Special decoding is required for TLUT format 5A3 + for (int y = 0; y < height; y += 4) + for (int x = 0, yStep = (y / 4) * Wsteps4; x < width; x += 4, yStep++) + for (int iy = 0, xStep = 4 * yStep; iy < 4; iy++, xStep++) + decodebytesC14X2_5A3_To_BGRA32(dst + (y + iy) * width + x, (u16*)(src + 8 * xStep), tlutaddr); + } + else if (tlutfmt == 0) + { + for (int y = 0; y < height; y += 4) + for (int x = 0, yStep = (y / 4) * Wsteps4; x < width; x += 4, yStep++) + for (int iy = 0, xStep = 4 * yStep; iy < 4; iy++, xStep++) + decodebytesC14X2IA8_To_RGBA(dst + (y + iy) * width + x, (u16*)(src + 8 * xStep), tlutaddr); + } + else + { + for (int y = 0; y < height; y += 4) + for (int x = 0, yStep = (y / 4) * Wsteps4; x < width; x += 4, yStep++) + for (int iy = 0, xStep = 4 * yStep; iy < 4; iy++, xStep++) + decodebytesC14X2rgb565_To_RGBA(dst + (y + iy) * width + x, (u16*)(src + 8 * xStep), tlutaddr); + } + break; + case GX_TF_RGB565: + { + // Reference C implementation. + for (int y = 0; y < height; y += 4) + for (int x = 0; x < width; x += 4) + for (int iy = 0; iy < 4; iy++, src += 8) + { + u32 *ptr = dst + (y + iy) * width + x; + u16 *s = (u16 *)src; + for(int j = 0; j < 4; j++) + *ptr++ = decode565RGBA(Common::swap16(*s++)); + } + } + break; + case GX_TF_RGB5A3: + { + // Reference C implementation: + for (int y = 0; y < height; y += 4) + for (int x = 0; x < width; x += 4) + for (int iy = 0; iy < 4; iy++, src += 8) + decodebytesRGB5A3rgba(dst+(y+iy)*width+x, (u16*)src); + } + break; + case GX_TF_RGBA8: // speed critical + { + // Reference C implementation. + for (int y = 0; y < height; y += 4) + for (int x = 0; x < width; x += 4) + { + for (int iy = 0; iy < 4; iy++) + decodebytesARGB8_4ToRgba(dst + (y+iy)*width + x, (u16*)src + 4 * iy, (u16*)src + 4 * iy + 16); + src += 64; + } + } + break; + case GX_TF_CMPR: // speed critical + // The metroid games use this format almost exclusively. + { + for (int y = 0; y < height; y += 8) + { + for (int x = 0; x < width; x += 8) + { + decodeDXTBlockRGBA((u32*)dst + y * width + x, (DXTBlock*)src, width); + src += sizeof(DXTBlock); + decodeDXTBlockRGBA((u32*)dst + y * width + x + 4, (DXTBlock*)src, width); + src += sizeof(DXTBlock); + decodeDXTBlockRGBA((u32*)dst + (y + 4) * width + x, (DXTBlock*)src, width); + src += sizeof(DXTBlock); + decodeDXTBlockRGBA((u32*)dst + (y + 4) * width + x + 4, (DXTBlock*)src, width); + src += sizeof(DXTBlock); + } + } + break; + } + } + + // The "copy" texture formats, too? + return PC_TEX_FMT_RGBA32; +} + + + + +void TexDecoder_SetTexFmtOverlayOptions(bool enable, bool center) +{ + TexFmt_Overlay_Enable = enable; + TexFmt_Overlay_Center = center; +} + +PC_TexFormat TexDecoder_Decode(u8 *dst, const u8 *src, int width, int height, int texformat, int tlutaddr, int tlutfmt,bool rgbaOnly) +{ + PC_TexFormat retval = TexDecoder_Decode_OpenCL(dst, src, + width, height, texformat, tlutaddr, tlutfmt, rgbaOnly); + if (retval == PC_TEX_FMT_NONE) + retval = rgbaOnly ? TexDecoder_Decode_RGBA((u32*)dst, src, + width, height, texformat, tlutaddr, tlutfmt) + : TexDecoder_Decode_real(dst, src, + width, height, texformat, tlutaddr, tlutfmt); + + if ((!TexFmt_Overlay_Enable)|| (retval == PC_TEX_FMT_NONE)) + return retval; + + int w = min(width, 40); + int h = min(height, 10); + + int xoff = (width - w) >> 1; + int yoff = (height - h) >> 1; + + if (!TexFmt_Overlay_Center) + { + xoff=0; + yoff=0; + } + + const char* fmt = texfmt[texformat&15]; + while (*fmt) + { + int xcnt = 0; + int nchar = sfont_map[(int)*fmt]; + + const unsigned char *ptr = sfont_raw[nchar]; // each char is up to 9x10 + + for (int x = 0; x < 9;x++) + { + if (ptr[x] == 0x78) + break; + xcnt++; + } + + for (int y=0; y < 10; y++) + { + for (int x=0; x < xcnt; x++) + { + switch(retval) + { + case PC_TEX_FMT_I8: + { + // TODO: Is this an acceptable way to draw in I8? + u8 *dtp = (u8*)dst; + dtp[(y + yoff) * width + x + xoff] = ptr[x] ? 0xFF : 0x88; + break; + } + case PC_TEX_FMT_IA8: + case PC_TEX_FMT_IA4_AS_IA8: + { + u16 *dtp = (u16*)dst; + dtp[(y + yoff) * width + x + xoff] = ptr[x] ? 0xFFFF : 0xFF00; + break; + } + case PC_TEX_FMT_RGB565: + { + u16 *dtp = (u16*)dst; + dtp[(y + yoff)*width + x + xoff] = ptr[x] ? 0xFFFF : 0x0000; + break; + } + default: + case PC_TEX_FMT_BGRA32: + { + int *dtp = (int*)dst; + dtp[(y + yoff) * width + x + xoff] = ptr[x] ? 0xFFFFFFFF : 0xFF000000; + break; + } + } + } + ptr += 9; + } + xoff += xcnt; + fmt++; + } + + return retval; +} + + + +void TexDecoder_DecodeTexel(u8 *dst, const u8 *src, int s, int t, int imageWidth, int texformat, int tlutaddr, int tlutfmt) +{ + /* General formula for computing texture offset + // + u16 sBlk = s / blockWidth; + u16 tBlk = t / blockHeight; + u16 widthBlks = (width / blockWidth) + 1; + u32 base = (tBlk * widthBlks + sBlk) * blockWidth * blockHeight; + u16 blkS = s & (blockWidth - 1); + u16 blkT = t & (blockHeight - 1); + u32 blkOff = blkT * blockWidth + blkS; + */ + + switch (texformat) + { + case GX_TF_C4: + { + u16 sBlk = s >> 3; + u16 tBlk = t >> 3; + u16 widthBlks = (imageWidth >> 3) + 1; + u32 base = (tBlk * widthBlks + sBlk) << 5; + u16 blkS = s & 7; + u16 blkT = t & 7; + u32 blkOff = (blkT << 3) + blkS; + + int rs = (blkOff & 1)?0:4; + u32 offset = base + (blkOff >> 1); + + u8 val = (*(src + offset) >> rs) & 0xF; + u16 *tlut = (u16*)(texMem + tlutaddr); + + switch (tlutfmt) + { + case 0: + *((u32*)dst) = decodeIA8Swapped(tlut[val]); + break; + case 1: + *((u32*)dst) = decode565RGBA(Common::swap16(tlut[val])); + break; + case 2: + *((u32*)dst) = decode5A3RGBA(Common::swap16(tlut[val])); + break; + } + } + break; + case GX_TF_I4: + { + u16 sBlk = s >> 3; + u16 tBlk = t >> 3; + u16 widthBlks = (imageWidth >> 3) + 1; + u32 base = (tBlk * widthBlks + sBlk) << 5; + u16 blkS = s & 7; + u16 blkT = t & 7; + u32 blkOff = (blkT << 3) + blkS; + + int rs = (blkOff & 1)?0:4; + u32 offset = base + (blkOff >> 1); + + u8 val = (*(src + offset) >> rs) & 0xF; + val = Convert4To8(val); + dst[0] = val; + dst[1] = val; + dst[2] = val; + dst[3] = val; + } + break; + case GX_TF_I8: + { + u16 sBlk = s >> 3; + u16 tBlk = t >> 2; + u16 widthBlks = (imageWidth >> 3) + 1; + u32 base = (tBlk * widthBlks + sBlk) << 5; + u16 blkS = s & 7; + u16 blkT = t & 3; + u32 blkOff = (blkT << 3) + blkS; + + u8 val = *(src + base + blkOff); + dst[0] = val; + dst[1] = val; + dst[2] = val; + dst[3] = val; + } + break; + case GX_TF_C8: + { + u16 sBlk = s >> 3; + u16 tBlk = t >> 2; + u16 widthBlks = (imageWidth >> 3) + 1; + u32 base = (tBlk * widthBlks + sBlk) << 5; + u16 blkS = s & 7; + u16 blkT = t & 3; + u32 blkOff = (blkT << 3) + blkS; + + u8 val = *(src + base + blkOff); + u16 *tlut = (u16*)(texMem + tlutaddr); + + switch (tlutfmt) + { + case 0: + *((u32*)dst) = decodeIA8Swapped(tlut[val]); + break; + case 1: + *((u32*)dst) = decode565RGBA(Common::swap16(tlut[val])); + break; + case 2: + *((u32*)dst) = decode5A3RGBA(Common::swap16(tlut[val])); + break; + } + } + break; + case GX_TF_IA4: + { + u16 sBlk = s >> 3; + u16 tBlk = t >> 2; + u16 widthBlks = (imageWidth >> 3) + 1; + u32 base = (tBlk * widthBlks + sBlk) << 5; + u16 blkS = s & 7; + u16 blkT = t & 3; + u32 blkOff = (blkT << 3) + blkS; + + u8 val = *(src + base + blkOff); + const u8 a = Convert4To8(val>>4); + const u8 l = Convert4To8(val&0xF); + dst[0] = l; + dst[1] = l; + dst[2] = l; + dst[3] = a; + } + break; + case GX_TF_IA8: + { + u16 sBlk = s >> 2; + u16 tBlk = t >> 2; + u16 widthBlks = (imageWidth >> 2) + 1; + u32 base = (tBlk * widthBlks + sBlk) << 4; + u16 blkS = s & 3; + u16 blkT = t & 3; + u32 blkOff = (blkT << 2) + blkS; + + u32 offset = (base + blkOff) << 1; + const u16* valAddr = (u16*)(src + offset); + + *((u32*)dst) = decodeIA8Swapped(*valAddr); + } + break; + case GX_TF_C14X2: + { + u16 sBlk = s >> 2; + u16 tBlk = t >> 2; + u16 widthBlks = (imageWidth >> 2) + 1; + u32 base = (tBlk * widthBlks + sBlk) << 4; + u16 blkS = s & 3; + u16 blkT = t & 3; + u32 blkOff = (blkT << 2) + blkS; + + u32 offset = (base + blkOff) << 1; + const u16* valAddr = (u16*)(src + offset); + + u16 val = Common::swap16(*valAddr) & 0x3FFF; + u16 *tlut = (u16*)(texMem + tlutaddr); + + switch (tlutfmt) + { + case 0: + *((u32*)dst) = decodeIA8Swapped(tlut[val]); + break; + case 1: + *((u32*)dst) = decode565RGBA(Common::swap16(tlut[val])); + break; + case 2: + *((u32*)dst) = decode5A3RGBA(Common::swap16(tlut[val])); + break; + } + } + break; + case GX_TF_RGB565: + { + u16 sBlk = s >> 2; + u16 tBlk = t >> 2; + u16 widthBlks = (imageWidth >> 2) + 1; + u32 base = (tBlk * widthBlks + sBlk) << 4; + u16 blkS = s & 3; + u16 blkT = t & 3; + u32 blkOff = (blkT << 2) + blkS; + + u32 offset = (base + blkOff) << 1; + const u16* valAddr = (u16*)(src + offset); + + *((u32*)dst) = decode565RGBA(Common::swap16(*valAddr)); + } + break; + case GX_TF_RGB5A3: + { + u16 sBlk = s >> 2; + u16 tBlk = t >> 2; + u16 widthBlks = (imageWidth >> 2) + 1; + u32 base = (tBlk * widthBlks + sBlk) << 4; + u16 blkS = s & 3; + u16 blkT = t & 3; + u32 blkOff = (blkT << 2) + blkS; + + u32 offset = (base + blkOff) << 1; + const u16* valAddr = (u16*)(src + offset); + + *((u32*)dst) = decode5A3RGBA(Common::swap16(*valAddr)); + } + break; + case GX_TF_RGBA8: + { + u16 sBlk = s >> 2; + u16 tBlk = t >> 2; + u16 widthBlks = (imageWidth >> 2) + 1; + u32 base = (tBlk * widthBlks + sBlk) << 5; // shift by 5 is correct + u16 blkS = s & 3; + u16 blkT = t & 3; + u32 blkOff = (blkT << 2) + blkS; + + u32 offset = (base + blkOff) << 1 ; + const u8* valAddr = src + offset; + + dst[3] = valAddr[0]; + dst[0] = valAddr[1]; + dst[1] = valAddr[32]; + dst[2] = valAddr[33]; + } + break; + case GX_TF_CMPR: + { + u16 sDxt = s >> 2; + u16 tDxt = t >> 2; + + u16 sBlk = sDxt >> 1; + u16 tBlk = tDxt >> 1; + u16 widthBlks = (imageWidth >> 3) + 1; + u32 base = (tBlk * widthBlks + sBlk) << 2; + u16 blkS = sDxt & 1; + u16 blkT = tDxt & 1; + u32 blkOff = (blkT << 1) + blkS; + + u32 offset = (base + blkOff) << 3; + + const DXTBlock* dxtBlock = (const DXTBlock*)(src + offset); + + u16 c1 = Common::swap16(dxtBlock->color1); + u16 c2 = Common::swap16(dxtBlock->color2); + int blue1 = Convert5To8(c1 & 0x1F); + int blue2 = Convert5To8(c2 & 0x1F); + int green1 = Convert6To8((c1 >> 5) & 0x3F); + int green2 = Convert6To8((c2 >> 5) & 0x3F); + int red1 = Convert5To8((c1 >> 11) & 0x1F); + int red2 = Convert5To8((c2 >> 11) & 0x1F); + + u16 ss = s & 3; + u16 tt = t & 3; + + int colorSel = dxtBlock->lines[tt]; + int rs = 6 - (ss << 1); + colorSel = (colorSel >> rs) & 3; + colorSel |= c1 > c2?0:4; + + u32 color = 0; + + switch (colorSel) + { + case 0: + case 4: + color = makeRGBA(red1, green1, blue1, 255); + break; + case 1: + case 5: + color = makeRGBA(red2, green2, blue2, 255); + break; + case 2: + color = makeRGBA(red1+(red2-red1)/3, green1+(green2-green1)/3, blue1+(blue2-blue1)/3, 255); + break; + case 3: + color = makeRGBA(red2+(red1-red2)/3, green2+(green1-green2)/3, blue2+(blue1-blue2)/3, 255); + break; + case 6: + color = makeRGBA((int)ceil((float)(red1+red2)/2), (int)ceil((float)(green1+green2)/2), (int)ceil((float)(blue1+blue2)/2), 255); + break; + case 7: + color = makeRGBA(red2, green2, blue2, 0); + break; + } + + *((u32*)dst) = color; + } + break; + } +} + +void TexDecoder_DecodeTexelRGBA8FromTmem(u8 *dst, const u8 *src_ar, const u8* src_gb, int s, int t, int imageWidth) +{ + u16 sBlk = s >> 2; + u16 tBlk = t >> 2; + u16 widthBlks = (imageWidth >> 2) + 1; // TODO: Looks wrong. Shouldn't this be ((imageWidth-1)>>2)+1 ? + u32 base_ar = (tBlk * widthBlks + sBlk) << 4; + u32 base_gb = (tBlk * widthBlks + sBlk) << 4; + u16 blkS = s & 3; + u16 blkT = t & 3; + u32 blk_off = (blkT << 2) + blkS; + + u32 offset_ar = (base_ar + blk_off) << 1; + u32 offset_gb = (base_gb + blk_off) << 1; + const u8* val_addr_ar = src_ar + offset_ar; + const u8* val_addr_gb = src_gb + offset_gb; + + dst[3] = val_addr_ar[0]; // A + dst[0] = val_addr_ar[1]; // R + dst[1] = val_addr_gb[0]; // G + dst[2] = val_addr_gb[1]; // B +} + +PC_TexFormat TexDecoder_DecodeRGBA8FromTmem(u8* dst, const u8 *src_ar, const u8 *src_gb, int width, int height) +{ + // TODO for someone who cares: Make this less slow! + for (int y = 0; y < height; ++y) + for (int x = 0; x < width; ++x) + { + TexDecoder_DecodeTexelRGBA8FromTmem(dst, src_ar, src_gb, x, y, width-1); + dst += 4; + } + + return PC_TEX_FMT_RGBA32; +} + +const char* texfmt[] = { + // pixel + "I4", "I8", "IA4", "IA8", + "RGB565", "RGB5A3", "RGBA8", "0x07", + "C4", "C8", "C14X2", "0x0B", + "0x0C", "0x0D", "CMPR", "0x0F", + // Z-buffer + "0x10", "Z8", "0x12", "Z16", + "0x14", "0x15", "Z24X8", "0x17", + "0x18", "0x19", "0x1A", "0x1B", + "0x1C", "0x1D", "0x1E", "0x1F", + // pixel + copy + "CR4", "0x21", "CRA4", "CRA8", + "0x24", "0x25", "CYUVA8", "CA8", + "CR8", "CG8", "CB8", "CRG8", + "CGB8", "0x2D", "0x2E", "0x2F", + // Z + copy + "CZ4", "0x31", "0x32", "0x33", + "0x34", "0x35", "0x36", "0x37", + "0x38", "CZ8M", "CZ8L", "0x3B", + "CZ16L", "0x3D", "0x3E", "0x3F", +}; + +const unsigned char sfont_map[] = { + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,10,10,10,10,10, + 10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25, + 26,27,28,29,30,31,32,33,34,35,36,10,10,10,10,10, + 10,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51, + 52,53,54,55,56,57,58,59,60,61,62,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, +}; + +const unsigned char sfont_raw[][9*10] = { + { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, + 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, + 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, + 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, + 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, + 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, + 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0x00, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + },{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x78, 0x78, 0x78, + }, +}; diff --git a/Source/Core/VideoCommon/Src/ImageWrite.cpp b/Source/Core/VideoCommon/Src/ImageWrite.cpp index 23b0e73427..482b4dad25 100644 --- a/Source/Core/VideoCommon/Src/ImageWrite.cpp +++ b/Source/Core/VideoCommon/Src/ImageWrite.cpp @@ -69,7 +69,8 @@ bool SaveTGA(const char* filename, int width, int height, void* pdata) bool SaveData(const char* filename, const char* data) { - std::ofstream f(filename, std::ios::binary); + std::ofstream f; + OpenFStream(f, filename, std::ios::binary); f << data; return true; diff --git a/Source/Core/VideoCommon/Src/IndexGenerator.cpp b/Source/Core/VideoCommon/Src/IndexGenerator.cpp index 8053114fae..f2d23a7fce 100644 --- a/Source/Core/VideoCommon/Src/IndexGenerator.cpp +++ b/Source/Core/VideoCommon/Src/IndexGenerator.cpp @@ -15,6 +15,9 @@ // Official SVN repository and contact information can be found at // http://code.google.com/p/dolphin-emu/ +#include + +#include "Common.h" #include "IndexGenerator.h" /* @@ -27,24 +30,18 @@ QUAD simulator */ //Init -u16 *IndexGenerator::Tptr = 0; -u16 *IndexGenerator::BASETptr = 0; -u16 *IndexGenerator::Lptr = 0; -u16 *IndexGenerator::BASELptr = 0; -u16 *IndexGenerator::Pptr = 0; -u16 *IndexGenerator::BASEPptr = 0; -int IndexGenerator::numT = 0; -int IndexGenerator::numL = 0; -int IndexGenerator::numP = 0; -int IndexGenerator::index = 0; -int IndexGenerator::Tadds = 0; -int IndexGenerator::Ladds = 0; -int IndexGenerator::Padds = 0; -IndexGenerator::IndexPrimitiveType IndexGenerator::LastTPrimitive = Prim_None; -IndexGenerator::IndexPrimitiveType IndexGenerator::LastLPrimitive = Prim_None; -bool IndexGenerator::used = false; +u16 *IndexGenerator::Tptr; +u16 *IndexGenerator::BASETptr; +u16 *IndexGenerator::Lptr; +u16 *IndexGenerator::BASELptr; +u16 *IndexGenerator::Pptr; +u16 *IndexGenerator::BASEPptr; +u32 IndexGenerator::numT; +u32 IndexGenerator::numL; +u32 IndexGenerator::numP; +u32 IndexGenerator::index; -void IndexGenerator::Start(u16 *Triangleptr,u16 *Lineptr,u16 *Pointptr) +void IndexGenerator::Start(u16* Triangleptr, u16* Lineptr, u16* Pointptr) { Tptr = Triangleptr; Lptr = Lineptr; @@ -56,288 +53,116 @@ void IndexGenerator::Start(u16 *Triangleptr,u16 *Lineptr,u16 *Pointptr) numT = 0; numL = 0; numP = 0; - Tadds = 0; - Ladds = 0; - Padds = 0; - LastTPrimitive = Prim_None; - LastLPrimitive = Prim_None; } + +void IndexGenerator::AddIndices(int primitive, u32 numVerts) +{ + //switch (primitive) + //{ + //case GX_DRAW_QUADS: IndexGenerator::AddQuads(numVerts); break; + //case GX_DRAW_TRIANGLES: IndexGenerator::AddList(numVerts); break; + //case GX_DRAW_TRIANGLE_STRIP: IndexGenerator::AddStrip(numVerts); break; + //case GX_DRAW_TRIANGLE_FAN: IndexGenerator::AddFan(numVerts); break; + //case GX_DRAW_LINES: IndexGenerator::AddLineList(numVerts); break; + //case GX_DRAW_LINE_STRIP: IndexGenerator::AddLineStrip(numVerts); break; + //case GX_DRAW_POINTS: IndexGenerator::AddPoints(numVerts); break; + //} + + static void (*const primitive_table[])(u32) = + { + IndexGenerator::AddQuads, + NULL, + IndexGenerator::AddList, + IndexGenerator::AddStrip, + IndexGenerator::AddFan, + IndexGenerator::AddLineList, + IndexGenerator::AddLineStrip, + IndexGenerator::AddPoints, + }; + + primitive_table[primitive](numVerts); + index += numVerts; +} + // Triangles -void IndexGenerator::AddList(int numVerts) +__forceinline void IndexGenerator::WriteTriangle(u32 index1, u32 index2, u32 index3) { - //if we have no vertices return - if(numVerts <= 0) return; - int numTris = numVerts / 3; - if (!numTris) - { - //if we have less than 3 verts - if(numVerts == 1) - { - // discard - index++; - return; - } - else - { - //we have two verts render a degenerated triangle - numTris = 1; - *Tptr++ = index; - *Tptr++ = index+1; - *Tptr++ = index; - } - } - else - { - for (int i = 0; i < numTris; i++) - { - *Tptr++ = index+i*3; - *Tptr++ = index+i*3+1; - *Tptr++ = index+i*3+2; - } - int baseRemainingverts = numVerts - numVerts % 3; - switch (numVerts % 3) - { - case 2: - //whe have 2 remaining verts use strip method - *Tptr++ = index + baseRemainingverts - 1; - *Tptr++ = index + baseRemainingverts; - *Tptr++ = index + baseRemainingverts + 1; - numTris++; - break; - case 1: - //whe have 1 remaining verts use strip method this is only a conjeture - *Tptr++ = index + baseRemainingverts - 2; - *Tptr++ = index + baseRemainingverts - 1; - *Tptr++ = index + baseRemainingverts; - numTris++; - break; - default: - break; - }; - } - index += numVerts; - numT += numTris; - Tadds++; - LastTPrimitive = Prim_List; + *Tptr++ = index1; + *Tptr++ = index2; + *Tptr++ = index3; + + ++numT; } -void IndexGenerator::AddStrip(int numVerts) +void IndexGenerator::AddList(u32 const numVerts) { - if(numVerts <= 0) return; - int numTris = numVerts - 2; - if (numTris < 1) + auto const numTris = numVerts / 3; + for (u32 i = 0; i != numTris; ++i) { - //if we have less than 3 verts - if(numVerts == 1) - { - // discard - index++; - return; - } - else - { - //we have two verts render a degenerated triangle - numTris = 1; - *Tptr++ = index; - *Tptr++ = index+1; - *Tptr++ = index; - } + WriteTriangle(index + i * 3, index + i * 3 + 1, index + i * 3 + 2); } - else - { - bool wind = false; - for (int i = 0; i < numTris; i++) - { - *Tptr++ = index+i; - *Tptr++ = index+i+(wind?2:1); - *Tptr++ = index+i+(wind?1:2); - wind = !wind; - } - } - index += numVerts; - numT += numTris; - Tadds++; - LastTPrimitive = Prim_Strip; -} -void IndexGenerator::AddFan(int numVerts) -{ - if(numVerts <= 0) return; - int numTris = numVerts - 2; - if (numTris < 1) - { - //if we have less than 3 verts - if(numVerts == 1) - { - //Discard - index++; - return; - } - else - { - //we have two verts render a degenerated triangle - numTris = 1; - *Tptr++ = index; - *Tptr++ = index+1; - *Tptr++ = index; - } - } - else - { - for (int i = 0; i < numTris; i++) - { - *Tptr++ = index; - *Tptr++ = index+i+1; - *Tptr++ = index+i+2; - } - } - index += numVerts; - numT += numTris; - Tadds++; - LastTPrimitive = Prim_Fan; } -void IndexGenerator::AddQuads(int numVerts) +void IndexGenerator::AddStrip(u32 const numVerts) { - if(numVerts <= 0) return; - int numTris = (numVerts/4)*2; - if (numTris == 0) + bool wind = false; + for (u32 i = 2; i < numVerts; ++i) { - //if we have less than 3 verts - if(numVerts == 1) - { - //discard - index++; - return; - } - else - { - if(numVerts == 2) - { - //we have two verts render a degenerated triangle - numTris = 1; - *Tptr++ = index; - *Tptr++ = index + 1; - *Tptr++ = index; - } - else - { - //we have 3 verts render a full triangle - numTris = 1; - *Tptr++ = index; - *Tptr++ = index + 1; - *Tptr++ = index + 2; - } - } + WriteTriangle( + index + i - 2, + index + i - !wind, + index + i - wind); + + wind ^= true; } - else - { - for (int i = 0; i < numTris / 2; i++) - { - *Tptr++ = index+i*4; - *Tptr++ = index+i*4+1; - *Tptr++ = index+i*4+2; - *Tptr++ = index+i*4; - *Tptr++ = index+i*4+2; - *Tptr++ = index+i*4+3; - } - int baseRemainingverts = numVerts - numVerts % 4; - switch (numVerts % 4) - { - case 3: - //whe have 3 remaining verts use strip method - *Tptr++ = index + baseRemainingverts; - *Tptr++ = index + baseRemainingverts + 1; - *Tptr++ = index + baseRemainingverts + 2; - numTris++; - break; - case 2: - //whe have 2 remaining verts use strip method - *Tptr++ = index + baseRemainingverts - 1; - *Tptr++ = index + baseRemainingverts; - *Tptr++ = index + baseRemainingverts + 1; - numTris++; - break; - case 1: - //whe have 1 remaining verts use strip method this is only a conjeture - *Tptr++ = index + baseRemainingverts - 2; - *Tptr++ = index + baseRemainingverts - 1; - *Tptr++ = index + baseRemainingverts; - numTris++; - break; - default: - break; - }; - } - index += numVerts; - numT += numTris; - Tadds++; - LastTPrimitive = Prim_List; } - -//Lines -void IndexGenerator::AddLineList(int numVerts) +void IndexGenerator::AddFan(u32 numVerts) { - if(numVerts <= 0) return; - int numLines = numVerts / 2; - if (!numLines) + for (u32 i = 2; i < numVerts; ++i) { - //Discard - index++; - return; + WriteTriangle(index, index + i - 1, index + i); } - else - { - for (int i = 0; i < numLines; i++) - { - *Lptr++ = index+i*2; - *Lptr++ = index+i*2+1; - } - if((numVerts & 1) != 0) - { - //use line strip for remaining vert - *Lptr++ = index + numLines * 2 - 1; - *Lptr++ = index + numLines * 2; - } - } - index += numVerts; - numL += numLines; - Ladds++; - LastLPrimitive = Prim_List; } -void IndexGenerator::AddLineStrip(int numVerts) +void IndexGenerator::AddQuads(u32 numVerts) { - int numLines = numVerts - 1; - if (numLines <= 0) + auto const numQuads = numVerts / 4; + for (u32 i = 0; i != numQuads; ++i) { - if(numVerts == 1) - { - index++; - } - return; + WriteTriangle(index + i * 4, index + i * 4 + 1, index + i * 4 + 2); + WriteTriangle(index + i * 4, index + i * 4 + 2, index + i * 4 + 3); } - for (int i = 0; i < numLines; i++) - { - *Lptr++ = index+i; - *Lptr++ = index+i+1; - } - index += numVerts; - numL += numLines; - Ladds++; - LastLPrimitive = Prim_Strip; } - - -//Points -void IndexGenerator::AddPoints(int numVerts) +// Lines +void IndexGenerator::AddLineList(u32 numVerts) { - for (int i = 0; i < numVerts; i++) + auto const numLines = numVerts / 2; + for (u32 i = 0; i != numLines; ++i) { - *Pptr++ = index+i; + *Lptr++ = index + i * 2; + *Lptr++ = index + i * 2 + 1; + ++numL; + } +} + +void IndexGenerator::AddLineStrip(u32 numVerts) +{ + for (u32 i = 1; i < numVerts; ++i) + { + *Lptr++ = index + i - 1; + *Lptr++ = index + i; + ++numL; + } +} + +// Points +void IndexGenerator::AddPoints(u32 numVerts) +{ + for (u32 i = 0; i != numVerts; ++i) + { + *Pptr++ = index + i; + ++numP; } - index += numVerts; - numP += numVerts; - Padds++; } diff --git a/Source/Core/VideoCommon/Src/IndexGenerator.h b/Source/Core/VideoCommon/Src/IndexGenerator.h index d1ed143d98..400d252bf8 100644 --- a/Source/Core/VideoCommon/Src/IndexGenerator.h +++ b/Source/Core/VideoCommon/Src/IndexGenerator.h @@ -25,53 +25,58 @@ class IndexGenerator { public: - //Init + // Init static void Start(u16 *Triangleptr,u16 *Lineptr,u16 *Pointptr); - //Triangles - static void AddList(int numVerts); - static void AddStrip(int numVerts); - static void AddFan(int numVerts); - static void AddQuads(int numVerts); - //Lines - static void AddLineList(int numVerts); - static void AddLineStrip(int numVerts); - //Points - static void AddPoints(int numVerts); - //Interface - static int GetNumTriangles() {used = true; return numT;} - static int GetNumLines() {used = true;return numL;} - static int GetNumPoints() {used = true;return numP;} - static int GetNumVerts() {return index;} //returns numprimitives - static int GetNumAdds() {return Tadds + Ladds + Padds;} - static int GetTriangleindexLen() {return (int)(Tptr - BASETptr);} - static int GetLineindexLen() {return (int)(Lptr - BASELptr);} - static int GetPointindexLen() {return (int)(Pptr - BASEPptr);} - + + static void AddIndices(int primitive, u32 numVertices); + + // Interface + static u32 GetNumTriangles() {return numT;} + static u32 GetNumLines() {return numL;} + static u32 GetNumPoints() {return numP;} + + // returns numprimitives + static u32 GetNumVerts() {return index;} + + static u32 GetTriangleindexLen() {return (u32)(Tptr - BASETptr);} + static u32 GetLineindexLen() {return (u32)(Lptr - BASELptr);} + static u32 GetPointindexLen() {return (u32)(Pptr - BASEPptr);} +/* enum IndexPrimitiveType { Prim_None = 0, Prim_List, Prim_Strip, Prim_Fan - } ; + }; +*/ private: + // Triangles + static void AddList(u32 numVerts); + static void AddStrip(u32 numVerts); + static void AddFan(u32 numVerts); + static void AddQuads(u32 numVerts); + + // Lines + static void AddLineList(u32 numVerts); + static void AddLineStrip(u32 numVerts); + + // Points + static void AddPoints(u32 numVerts); + + static void WriteTriangle(u32 index1, u32 index2, u32 index3); + static u16 *Tptr; static u16 *BASETptr; static u16 *Lptr; static u16 *BASELptr; static u16 *Pptr; static u16 *BASEPptr; - static int numT; - static int numL; - static int numP; - static int index; - static int Tadds; - static int Ladds; - static int Padds; - static IndexPrimitiveType LastTPrimitive; - static IndexPrimitiveType LastLPrimitive; - static bool used; - + // TODO: redundant variables + static u32 numT; + static u32 numL; + static u32 numP; + static u32 index; }; #endif // _INDEXGENERATOR_H diff --git a/Source/Core/VideoCommon/Src/MainBase.cpp b/Source/Core/VideoCommon/Src/MainBase.cpp index 726ef71b38..1472367f21 100644 --- a/Source/Core/VideoCommon/Src/MainBase.cpp +++ b/Source/Core/VideoCommon/Src/MainBase.cpp @@ -21,6 +21,10 @@ volatile u32 s_swapRequested = false; u32 s_efbAccessRequested = false; volatile u32 s_FifoShuttingDown = false; +std::condition_variable s_perf_query_cond; +std::mutex s_perf_query_lock; +static volatile bool s_perf_query_requested; + static volatile struct { u32 xfbAddr; @@ -169,6 +173,43 @@ u32 VideoBackendHardware::Video_AccessEFB(EFBAccessType type, u32 x, u32 y, u32 return 0; } +static bool QueryResultIsReady() +{ + return !s_perf_query_requested || s_FifoShuttingDown; +} + +void VideoFifo_CheckPerfQueryRequest() +{ + if (s_perf_query_requested) + { + g_perf_query->FlushResults(); + + { + std::lock_guard lk(s_perf_query_lock); + s_perf_query_requested = false; + } + + s_perf_query_cond.notify_one(); + } +} + +u32 VideoBackendHardware::Video_GetQueryResult(PerfQueryType type) +{ + // TODO: Is this check sane? + if (!g_perf_query->IsFlushed()) + { + if (SConfig::GetInstance().m_LocalCoreStartupParameter.bCPUThread) + { + s_perf_query_requested = true; + std::unique_lock lk(s_perf_query_lock); + s_perf_query_cond.wait(lk, QueryResultIsReady); + } + else + g_perf_query->FlushResults(); + } + + return g_perf_query->GetQueryResult(type); +} void VideoBackendHardware::InitializeShared() { @@ -176,6 +217,7 @@ void VideoBackendHardware::InitializeShared() s_swapRequested = 0; s_efbAccessRequested = 0; + s_perf_query_requested = false; s_FifoShuttingDown = 0; memset((void*)&s_beginFieldArgs, 0, sizeof(s_beginFieldArgs)); memset(&s_accessEFBArgs, 0, sizeof(s_accessEFBArgs)); @@ -186,6 +228,11 @@ void VideoBackendHardware::InitializeShared() // Run from the CPU thread void VideoBackendHardware::DoState(PointerWrap& p) { + bool software = false; + p.Do(software); + if (p.GetMode() == PointerWrap::MODE_READ && software == true) + // change mode to abort load of incompatible save state. + p.SetMode(PointerWrap::MODE_VERIFY); VideoCommon_DoState(p); p.DoMarker("VideoCommon"); @@ -233,6 +280,7 @@ void VideoFifo_CheckAsyncRequest() { VideoFifo_CheckSwapRequest(); VideoFifo_CheckEFBAccess(); + VideoFifo_CheckPerfQueryRequest(); } void VideoBackendHardware::Video_GatherPipeBursted() diff --git a/Source/Core/VideoCommon/Src/OnScreenDisplay.h b/Source/Core/VideoCommon/Src/OnScreenDisplay.h index 3777e2b5d3..80187b8ac3 100644 --- a/Source/Core/VideoCommon/Src/OnScreenDisplay.h +++ b/Source/Core/VideoCommon/Src/OnScreenDisplay.h @@ -22,7 +22,7 @@ namespace OSD { // On-screen message display -void AddMessage(const char* str, u32 ms); +void AddMessage(const char* str, u32 ms = 2000); void DrawMessages(); // draw the current messages on the screen. Only call once per frame. void ClearMessages(); diff --git a/Source/Core/VideoCommon/Src/PerfQueryBase.cpp b/Source/Core/VideoCommon/Src/PerfQueryBase.cpp new file mode 100644 index 0000000000..c537d176f6 --- /dev/null +++ b/Source/Core/VideoCommon/Src/PerfQueryBase.cpp @@ -0,0 +1,3 @@ +#include "PerfQueryBase.h" + +PerfQueryBase* g_perf_query = 0; diff --git a/Source/Core/VideoCommon/Src/PerfQueryBase.h b/Source/Core/VideoCommon/Src/PerfQueryBase.h new file mode 100644 index 0000000000..b979449edb --- /dev/null +++ b/Source/Core/VideoCommon/Src/PerfQueryBase.h @@ -0,0 +1,54 @@ +#ifndef _PERFQUERY_BASE_H_ +#define _PERFQUERY_BASE_H_ + +#include "CommonTypes.h" + +enum PerfQueryType +{ + PQ_ZCOMP_INPUT_ZCOMPLOC = 0, + PQ_ZCOMP_OUTPUT_ZCOMPLOC, + PQ_ZCOMP_INPUT, + PQ_ZCOMP_OUTPUT, + PQ_BLEND_INPUT, + PQ_EFB_COPY_CLOCKS, + PQ_NUM_MEMBERS +}; + +enum PerfQueryGroup +{ + PQG_ZCOMP_ZCOMPLOC, + PQG_ZCOMP, + PQG_EFB_COPY_CLOCKS, + PQG_NUM_MEMBERS, +}; + +class PerfQueryBase +{ +public: + PerfQueryBase() {}; + virtual ~PerfQueryBase() {} + + // Begin querying the specified value for the following host GPU commands + virtual void EnableQuery(PerfQueryGroup type) {} + + // Stop querying the specified value for the following host GPU commands + virtual void DisableQuery(PerfQueryGroup type) {} + + // Reset query counters to zero and drop any pending queries + virtual void ResetQuery() {} + + // Return the measured value for the specified query type + // NOTE: Called from CPU thread + virtual u32 GetQueryResult(PerfQueryType type) { return 0; } + + // Request the value of any pending queries - causes a pipeline flush and thus should be used carefully! + virtual void FlushResults() {} + + // True if there are no further pending query results + // NOTE: Called from CPU thread + virtual bool IsFlushed() const { return true; } +}; + +extern PerfQueryBase* g_perf_query; + +#endif // _PERFQUERY_H_ diff --git a/Source/Core/VideoCommon/Src/PixelEngine.cpp b/Source/Core/VideoCommon/Src/PixelEngine.cpp index a488e52b42..e5ba554678 100644 --- a/Source/Core/VideoCommon/Src/PixelEngine.cpp +++ b/Source/Core/VideoCommon/Src/PixelEngine.cpp @@ -28,10 +28,13 @@ #include "ConfigManager.h" #include "PixelEngine.h" +#include "RenderBase.h" #include "CommandProcessor.h" #include "HW/ProcessorInterface.h" #include "DLCache.h" #include "State.h" +#include "PerfQueryBase.h" + namespace PixelEngine { @@ -255,23 +258,59 @@ void Read16(u16& _uReturnValue, const u32 _iAddress) break; } - case PE_PERF_0L: - case PE_PERF_0H: - case PE_PERF_1L: - case PE_PERF_1H: - case PE_PERF_2L: - case PE_PERF_2H: - case PE_PERF_3L: - case PE_PERF_3H: - case PE_PERF_4L: - case PE_PERF_4H: - case PE_PERF_5L: - case PE_PERF_5H: - INFO_LOG(PIXELENGINE, "(r16) perf counter @ %08x", _iAddress); - // git r90a2096a24f4 (svn r3663) added the PE_PERF cases, without setting - // _uReturnValue to anything, this reverts to the previous behaviour which allows - // The timer in SMS:Scrubbing Serena Beach to countdown correctly - _uReturnValue = 1; + // NOTE(neobrain): only PE_PERF_ZCOMP_OUTPUT is implemented in D3D11, but the other values shouldn't be contradictionary to the value of that register (i.e. INPUT registers should always be greater or equal to their corresponding OUTPUT registers). + case PE_PERF_ZCOMP_INPUT_ZCOMPLOC_L: + _uReturnValue = g_video_backend->Video_GetQueryResult(PQ_ZCOMP_INPUT_ZCOMPLOC) & 0xFFFF; + break; + + case PE_PERF_ZCOMP_INPUT_ZCOMPLOC_H: + _uReturnValue = g_video_backend->Video_GetQueryResult(PQ_ZCOMP_INPUT_ZCOMPLOC) >> 16; + break; + + case PE_PERF_ZCOMP_OUTPUT_ZCOMPLOC_L: + _uReturnValue = g_video_backend->Video_GetQueryResult(PQ_ZCOMP_OUTPUT_ZCOMPLOC) & 0xFFFF; + break; + + case PE_PERF_ZCOMP_OUTPUT_ZCOMPLOC_H: + _uReturnValue = g_video_backend->Video_GetQueryResult(PQ_ZCOMP_OUTPUT_ZCOMPLOC) >> 16; + break; + + case PE_PERF_ZCOMP_INPUT_L: + _uReturnValue = g_video_backend->Video_GetQueryResult(PQ_ZCOMP_INPUT) & 0xFFFF; + break; + + case PE_PERF_ZCOMP_INPUT_H: + _uReturnValue = g_video_backend->Video_GetQueryResult(PQ_ZCOMP_INPUT) >> 16; + break; + + case PE_PERF_ZCOMP_OUTPUT_L: + _uReturnValue = g_video_backend->Video_GetQueryResult(PQ_ZCOMP_OUTPUT) & 0xFFFF; + break; + + case PE_PERF_ZCOMP_OUTPUT_H: + _uReturnValue = g_video_backend->Video_GetQueryResult(PQ_ZCOMP_OUTPUT) >> 16; + break; + + case PE_PERF_BLEND_INPUT_L: + // Super Mario Sunshine uses this register in episode 6 of Sirena Beach: + // The amount of remaining goop is determined by checking how many pixels reach the blending stage. + // Once this register falls below a particular value (around 0x90), the game regards the challenge finished. + // In very old builds, Dolphin only returned 0. That caused the challenge to be immediately finished without any goop being cleaned (the timer just didn't even start counting from 3:00:00). + // Later builds returned 1 for the high register. That caused the timer to actually count down, but made the challenge unbeatable because the game always thought you didn't clear any goop at all. + // Note that currently this functionality is only implemented in the D3D11 backend. + _uReturnValue = g_video_backend->Video_GetQueryResult(PQ_BLEND_INPUT) & 0xFFFF; + break; + + case PE_PERF_BLEND_INPUT_H: + _uReturnValue = g_video_backend->Video_GetQueryResult(PQ_BLEND_INPUT) >> 16; + break; + + case PE_PERF_EFB_COPY_CLOCKS_L: + _uReturnValue = g_video_backend->Video_GetQueryResult(PQ_EFB_COPY_CLOCKS) & 0xFFFF; + break; + + case PE_PERF_EFB_COPY_CLOCKS_H: + _uReturnValue = g_video_backend->Video_GetQueryResult(PQ_EFB_COPY_CLOCKS) >> 16; break; default: diff --git a/Source/Core/VideoCommon/Src/PixelEngine.h b/Source/Core/VideoCommon/Src/PixelEngine.h index 64f959009f..eaf55f0031 100644 --- a/Source/Core/VideoCommon/Src/PixelEngine.h +++ b/Source/Core/VideoCommon/Src/PixelEngine.h @@ -36,19 +36,20 @@ enum PE_BBOX_TOP = 0x14, // Flip Top PE_BBOX_BOTTOM = 0x16, // Flip Bottom - // These have not yet been RE:d. They are the perf counters. - PE_PERF_0L = 0x18, - PE_PERF_0H = 0x1a, - PE_PERF_1L = 0x1c, - PE_PERF_1H = 0x1e, - PE_PERF_2L = 0x20, - PE_PERF_2H = 0x22, - PE_PERF_3L = 0x24, - PE_PERF_3H = 0x26, - PE_PERF_4L = 0x28, - PE_PERF_4H = 0x2a, - PE_PERF_5L = 0x2c, - PE_PERF_5H = 0x2e, + // NOTE: Order not verified + // These indicate the number of quads that are being used as input/output for each particular stage + PE_PERF_ZCOMP_INPUT_ZCOMPLOC_L = 0x18, + PE_PERF_ZCOMP_INPUT_ZCOMPLOC_H = 0x1a, + PE_PERF_ZCOMP_OUTPUT_ZCOMPLOC_L = 0x1c, + PE_PERF_ZCOMP_OUTPUT_ZCOMPLOC_H = 0x1e, + PE_PERF_ZCOMP_INPUT_L = 0x20, + PE_PERF_ZCOMP_INPUT_H = 0x22, + PE_PERF_ZCOMP_OUTPUT_L = 0x24, + PE_PERF_ZCOMP_OUTPUT_H = 0x26, + PE_PERF_BLEND_INPUT_L = 0x28, + PE_PERF_BLEND_INPUT_H = 0x2a, + PE_PERF_EFB_COPY_CLOCKS_L = 0x2c, + PE_PERF_EFB_COPY_CLOCKS_H = 0x2e, }; namespace PixelEngine diff --git a/Source/Core/VideoCommon/Src/PixelShaderGen.cpp b/Source/Core/VideoCommon/Src/PixelShaderGen.cpp index b05157aa43..7d7fcf1135 100644 --- a/Source/Core/VideoCommon/Src/PixelShaderGen.cpp +++ b/Source/Core/VideoCommon/Src/PixelShaderGen.cpp @@ -252,7 +252,8 @@ void ValidatePixelShaderIDs(API_TYPE api, PIXELSHADERUIDSAFE old_id, const std:: static int num_failures = 0; char szTemp[MAX_PATH]; sprintf(szTemp, "%spsuid_mismatch_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), num_failures++); - std::ofstream file(szTemp); + std::ofstream file; + OpenFStream(file, szTemp, std::ios_base::out); file << msg; file << "\n\nOld shader code:\n" << old_code; file << "\n\nNew shader code:\n" << new_code; @@ -275,7 +276,7 @@ void ValidatePixelShaderIDs(API_TYPE api, PIXELSHADERUIDSAFE old_id, const std:: static void WriteStage(char *&p, int n, API_TYPE ApiType); static void SampleTexture(char *&p, const char *destination, const char *texcoords, const char *texswap, int texmap, API_TYPE ApiType); // static void WriteAlphaCompare(char *&p, int num, int comp); -static void WriteAlphaTest(char *&p, API_TYPE ApiType,DSTALPHA_MODE dstAlphaMode); +static void WriteAlphaTest(char *&p, API_TYPE ApiType,DSTALPHA_MODE dstAlphaMode, bool depthTextureEnable); static void WriteFog(char *&p); static const char *tevKSelTableC[] = // KCSEL @@ -510,6 +511,8 @@ const char *GeneratePixelShaderCode(DSTALPHA_MODE dstAlphaMode, API_TYPE ApiType BuildSwapModeTable(); // Needed for WriteStage int numStages = bpmem.genMode.numtevstages + 1; int numTexgen = bpmem.genMode.numtexgens; + + bool depthTextureEnable = bpmem.ztex2.op != ZTEXTURE_DISABLE && !bpmem.zcontrol.early_ztest && bpmem.zmode.testenable; char *p = text; WRITE(p, "//Pixel Shader for TEV stages\n"); @@ -599,7 +602,8 @@ const char *GeneratePixelShaderCode(DSTALPHA_MODE dstAlphaMode, API_TYPE ApiType if (dstAlphaMode == DSTALPHA_DUAL_SOURCE_BLEND) WRITE(p, "out float4 ocol1;\n"); - WRITE(p, "float depth;\n"); + if (depthTextureEnable) + WRITE(p, "#define depth gl_FragDepth\n"); WRITE(p, "float4 rawpos = gl_FragCoord;\n"); WRITE(p, "VARYIN float4 colors_02;\n"); @@ -654,14 +658,14 @@ const char *GeneratePixelShaderCode(DSTALPHA_MODE dstAlphaMode, API_TYPE ApiType { WRITE(p, " out float4 ocol0 : COLOR0,%s%s\n in float4 rawpos : %s,\n", dstAlphaMode == DSTALPHA_DUAL_SOURCE_BLEND ? "\n out float4 ocol1 : COLOR1," : "", - "\n out float depth : DEPTH,", + depthTextureEnable ? "\n out float depth : DEPTH," : "", ApiType & API_D3D9_SM20 ? "POSITION" : "VPOS"); } else { WRITE(p, " out float4 ocol0 : SV_Target0,%s%s\n in float4 rawpos : SV_Position,\n", dstAlphaMode == DSTALPHA_DUAL_SOURCE_BLEND ? "\n out float4 ocol1 : SV_Target1," : "", - "\n out float depth : SV_Depth,"); + depthTextureEnable ? "\n out float depth : SV_Depth," : ""); } WRITE(p, " in float4 colors_0 : COLOR0,\n"); @@ -804,13 +808,18 @@ const char *GeneratePixelShaderCode(DSTALPHA_MODE dstAlphaMode, API_TYPE ApiType AlphaTest::TEST_RESULT Pretest = bpmem.alpha_test.TestResult(); if (Pretest == AlphaTest::UNDETERMINED) - WriteAlphaTest(p, ApiType, dstAlphaMode); + WriteAlphaTest(p, ApiType, dstAlphaMode, depthTextureEnable); + // the screen space depth value = far z + (clip z / clip w) * z range - WRITE(p, "float zCoord = " I_ZBIAS"[1].x + (clipPos.z / clipPos.w) * " I_ZBIAS"[1].y;\n"); - + if(ApiType == API_OPENGL || ApiType == API_D3D11) + WRITE(p, "float zCoord = rawpos.z;\n"); + else + // dx9 doesn't support 4 component position, so we have to calculate it again + WRITE(p, "float zCoord = " I_ZBIAS"[1].x + (clipPos.z / clipPos.w) * " I_ZBIAS"[1].y;\n"); + // Note: depth textures are disabled if early depth test is enabled - if (bpmem.ztex2.op != ZTEXTURE_DISABLE && !bpmem.zcontrol.early_ztest && bpmem.zmode.testenable) + if (depthTextureEnable) { // use the texture input of the last texture stage (textemp), hopefully this has been read and is in correct format... WRITE(p, "zCoord = dot(" I_ZBIAS"[0].xyzw, textemp.xyzw) + " I_ZBIAS"[1].w %s;\n", @@ -820,8 +829,9 @@ const char *GeneratePixelShaderCode(DSTALPHA_MODE dstAlphaMode, API_TYPE ApiType WRITE(p, "zCoord = zCoord * (16777215.0f/16777216.0f);\n"); WRITE(p, "zCoord = frac(zCoord);\n"); WRITE(p, "zCoord = zCoord * (16777216.0f/16777215.0f);\n"); + + WRITE(p, "depth = zCoord;\n"); } - WRITE(p, "depth = zCoord;\n"); if (dstAlphaMode == DSTALPHA_ALPHA_PASS) WRITE(p, "\tocol0 = float4(prev.rgb, " I_ALPHA"[0].a);\n"); @@ -841,10 +851,6 @@ const char *GeneratePixelShaderCode(DSTALPHA_MODE dstAlphaMode, API_TYPE ApiType WRITE(p, "\tocol0.a = " I_ALPHA"[0].a;\n"); } - if (ApiType == API_OPENGL) - { - WRITE(p, "\tgl_FragDepth = depth;\n"); - } WRITE(p, "}\n"); if (text[sizeof(text) - 1] != 0x7C) PanicAlert("PixelShader generator - buffer too small, canary has been eaten!"); @@ -1236,7 +1242,7 @@ static const char *tevAlphaFunclogicTable[] = " == " // xnor }; -static void WriteAlphaTest(char *&p, API_TYPE ApiType,DSTALPHA_MODE dstAlphaMode) +static void WriteAlphaTest(char *&p, API_TYPE ApiType,DSTALPHA_MODE dstAlphaMode, bool depthTextureEnable) { static const char *alphaRef[2] = { @@ -1260,7 +1266,8 @@ static void WriteAlphaTest(char *&p, API_TYPE ApiType,DSTALPHA_MODE dstAlphaMode WRITE(p, "\t\tocol0 = float4(0.0f, 0.0f, 0.0f, 0.0f);\n"); if (dstAlphaMode == DSTALPHA_DUAL_SOURCE_BLEND) WRITE(p, "\t\tocol1 = float4(0.0f, 0.0f, 0.0f, 0.0f);\n"); - WRITE(p, "depth = 1.f;\n"); + if(depthTextureEnable) + WRITE(p, "depth = 1.f;\n"); // HAXX: zcomploc (aka early_ztest) is a way to control whether depth test is done before // or after texturing and alpha test. PC GPUs have no way to support this diff --git a/Source/Core/VideoCommon/Src/RenderBase.cpp b/Source/Core/VideoCommon/Src/RenderBase.cpp index 8e1d012fa2..90a09aec43 100644 --- a/Source/Core/VideoCommon/Src/RenderBase.cpp +++ b/Source/Core/VideoCommon/Src/RenderBase.cpp @@ -83,7 +83,9 @@ unsigned int Renderer::efb_scale_denominatorY = 1; unsigned int Renderer::ssaa_multiplier = 1; -Renderer::Renderer() : frame_data(NULL), bLastFrameDumped(false) +Renderer::Renderer() + : frame_data() + , bLastFrameDumped(false) { UpdateActiveConfig(); TextureCache::OnConfigChanged(g_ActiveConfig); @@ -110,7 +112,6 @@ Renderer::~Renderer() if (pFrameDump.IsOpen()) pFrameDump.Close(); #endif - delete[] frame_data; } void Renderer::RenderToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc, float Gamma) diff --git a/Source/Core/VideoCommon/Src/RenderBase.h b/Source/Core/VideoCommon/Src/RenderBase.h index 5376577cbd..55678f3f5a 100644 --- a/Source/Core/VideoCommon/Src/RenderBase.h +++ b/Source/Core/VideoCommon/Src/RenderBase.h @@ -52,6 +52,15 @@ public: Renderer(); virtual ~Renderer(); + enum PixelPerfQuery { + PP_ZCOMP_INPUT_ZCOMPLOC, + PP_ZCOMP_OUTPUT_ZCOMPLOC, + PP_ZCOMP_INPUT, + PP_ZCOMP_OUTPUT, + PP_BLEND_INPUT, + PP_EFB_COPY_CLOCKS + }; + virtual void SetColorMask() = 0; virtual void SetBlendMode(bool forceUpdate) = 0; virtual void SetScissorRect(const TargetRectangle& rc) = 0; @@ -147,7 +156,7 @@ protected: #else File::IOFile pFrameDump; #endif - char* frame_data; + std::vector frame_data; bool bLastFrameDumped; // The framebuffer size diff --git a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp index 8ce7b48b4d..c9c455b874 100644 --- a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp @@ -129,7 +129,10 @@ void TextureCache::Cleanup() TexCache::iterator tcend = textures.end(); while (iter != tcend) { - if (frameCount > TEXTURE_KILL_THRESHOLD + iter->second->frameCount) // TODO: Deleting EFB copies might not be a good idea here... + if ( frameCount > TEXTURE_KILL_THRESHOLD + iter->second->frameCount + + // EFB copies living on the host GPU are unrecoverable and thus shouldn't be deleted + && ! iter->second->IsEfbCopy() ) { delete iter->second; textures.erase(iter++); @@ -318,7 +321,7 @@ static TextureCache::TCacheEntryBase* ReturnEntry(unsigned int stage, TextureCac TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int const stage, u32 const address, unsigned int width, unsigned int height, int const texformat, - unsigned int const tlutaddr, int const tlutfmt, bool const use_mipmaps, unsigned int const maxlevel, bool const from_tmem) + unsigned int const tlutaddr, int const tlutfmt, bool const use_mipmaps, unsigned int maxlevel, bool const from_tmem) { if (0 == address) return NULL; @@ -345,7 +348,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int const stage, full_format = texformat | (tlutfmt << 16); const u32 texture_size = TexDecoder_GetTextureSizeInBytes(expandedWidth, expandedHeight, texformat); - + const u8* src_data; if (from_tmem) src_data = &texMem[bpmem.tex[stage / 4].texImage1[stage % 4].tmem_even * TMEM_LINE_SIZE]; @@ -372,6 +375,11 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int const stage, tex_hash ^= tlut_hash; } + // D3D doesn't like when the specified mipmap count would require more than one 1x1-sized LOD in the mipmap chain + // e.g. 64x64 with 7 LODs would have the mipmap chain 64x64,32x32,16x16,8x8,4x4,2x2,1x1,1x1, so we limit the mipmap count to 6 there + while (g_ActiveConfig.backend_info.bUseMinimalMipCount && max(expandedWidth, expandedHeight) >> maxlevel == 0) + --maxlevel; + TCacheEntryBase *entry = textures[texID]; if (entry) { @@ -456,7 +464,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int const stage, const bool using_custom_lods = using_custom_texture && CheckForCustomTextureLODs(tex_hash, texformat, texLevels); // Only load native mips if their dimensions fit to our virtual texture dimensions const bool use_native_mips = use_mipmaps && !using_custom_lods && (width == nativeW && height == nativeH); - texLevels = (use_native_mips || using_custom_lods) ? texLevels : 1; + texLevels = (use_native_mips || using_custom_lods) ? texLevels : 1; // TODO: Should be forced to 1 for non-pow2 textures (e.g. efb copies with automatically adjusted IR) // create the entry/texture if (NULL == entry) @@ -476,15 +484,20 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int const stage, GFX_DEBUGGER_PAUSE_AT(NEXT_NEW_TEXTURE, true); } + else + { + // load texture (CreateTexture also loads level 0) + entry->Load(width, height, expandedWidth, 0); + } entry->SetGeneralParameters(address, texture_size, full_format, entry->num_mipmaps); entry->SetDimensions(nativeW, nativeH, width, height); entry->hash = tex_hash; - if (entry->IsEfbCopy() && !g_ActiveConfig.bCopyEFBToTexture) entry->type = TCET_EC_DYNAMIC; - else entry->type = TCET_NORMAL; - - // load texture - entry->Load(stage, width, height, expandedWidth, 0); + + if (entry->IsEfbCopy() && !g_ActiveConfig.bCopyEFBToTexture) + entry->type = TCET_EC_DYNAMIC; + else + entry->type = TCET_NORMAL; if (g_ActiveConfig.bDumpTextures && !using_custom_texture) DumpTexture(entry, 0); @@ -518,7 +531,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int const stage, TexDecoder_Decode(temp, mip_src_data, expanded_mip_width, expanded_mip_height, texformat, tlutaddr, tlutfmt, g_ActiveConfig.backend_info.bUseRGBATextures); mip_src_data += TexDecoder_GetTextureSizeInBytes(expanded_mip_width, expanded_mip_height, texformat); - entry->Load(stage, mip_width, mip_height, expanded_mip_width, level); + entry->Load(mip_width, mip_height, expanded_mip_width, level); if (g_ActiveConfig.bDumpTextures) DumpTexture(entry, level); @@ -532,7 +545,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int const stage, unsigned int mip_height = CalculateLevelSize(height, level); LoadCustomTexture(tex_hash, texformat, level, mip_width, mip_height); - entry->Load(stage, mip_width, mip_height, mip_width, level); + entry->Load(mip_width, mip_height, mip_width, level); } } } diff --git a/Source/Core/VideoCommon/Src/TextureCacheBase.h b/Source/Core/VideoCommon/Src/TextureCacheBase.h index 950caad67d..40441c2d70 100644 --- a/Source/Core/VideoCommon/Src/TextureCacheBase.h +++ b/Source/Core/VideoCommon/Src/TextureCacheBase.h @@ -88,7 +88,7 @@ public: virtual void Bind(unsigned int stage) = 0; virtual bool Save(const char filename[], unsigned int level) = 0; - virtual void Load(unsigned int stage, unsigned int width, unsigned int height, + virtual void Load(unsigned int width, unsigned int height, unsigned int expanded_width, unsigned int level) = 0; virtual void FromRenderTarget(u32 dstAddr, unsigned int dstFormat, unsigned int srcFormat, const EFBRectangle& srcRect, diff --git a/Source/Core/VideoCommon/Src/VertexLoader.cpp b/Source/Core/VideoCommon/Src/VertexLoader.cpp index 5bffab8ee7..6c85324ba8 100644 --- a/Source/Core/VideoCommon/Src/VertexLoader.cpp +++ b/Source/Core/VideoCommon/Src/VertexLoader.cpp @@ -23,7 +23,7 @@ #include "MemoryUtil.h" #include "StringUtil.h" #include "x64Emitter.h" -#include "ABI.h" +#include "x64ABI.h" #include "PixelEngine.h" #include "Host.h" @@ -43,8 +43,9 @@ //BBox #include "XFMemory.h" extern float GC_ALIGNED16(g_fProjectionMatrix[16]); - +#ifndef _M_GENERIC #define USE_JIT +#endif #define COMPILED_CODE_SIZE 4096 @@ -72,6 +73,10 @@ int colElements[2]; float posScale; float tcScale[8]; +// bbox must read vertex position, so convert it to this buffer +static float s_bbox_vertex_buffer[3]; +static u8 *s_bbox_pCurBufferPointer_orig; + static const float fractionTable[32] = { 1.0f / (1U << 0), 1.0f / (1U << 1), 1.0f / (1U << 2), 1.0f / (1U << 3), 1.0f / (1U << 4), 1.0f / (1U << 5), 1.0f / (1U << 6), 1.0f / (1U << 7), @@ -82,8 +87,9 @@ static const float fractionTable[32] = { 1.0f / (1U << 24), 1.0f / (1U << 25), 1.0f / (1U << 26), 1.0f / (1U << 27), 1.0f / (1U << 28), 1.0f / (1U << 29), 1.0f / (1U << 30), 1.0f / (1U << 31), }; - +#ifdef USE_JIT using namespace Gen; +#endif void LOADERDECL PosMtx_ReadDirect_UByte() { @@ -93,23 +99,38 @@ void LOADERDECL PosMtx_ReadDirect_UByte() void LOADERDECL PosMtx_Write() { - *VertexManager::s_pCurBufferPointer++ = s_curposmtx; - *VertexManager::s_pCurBufferPointer++ = 0; - *VertexManager::s_pCurBufferPointer++ = 0; - *VertexManager::s_pCurBufferPointer++ = 0; + DataWrite(s_curposmtx); + DataWrite(0); + DataWrite(0); + DataWrite(0); +} + +void LOADERDECL UpdateBoundingBoxPrepare() +{ + if (!PixelEngine::bbox_active) + return; + + // set our buffer as videodata buffer, so we will get a copy of the vertex positions + // this is a big hack, but so we can use the same converting function then without bbox + s_bbox_pCurBufferPointer_orig = VertexManager::s_pCurBufferPointer; + VertexManager::s_pCurBufferPointer = (u8*)s_bbox_vertex_buffer; } void LOADERDECL UpdateBoundingBox() { if (!PixelEngine::bbox_active) return; + + // reset videodata pointer + VertexManager::s_pCurBufferPointer = s_bbox_pCurBufferPointer_orig; + + // copy vertex pointers + memcpy(VertexManager::s_pCurBufferPointer, s_bbox_vertex_buffer, 12); + VertexManager::s_pCurBufferPointer += 12; - // Truly evil hack, reading backwards from the write pointer. If we were writing to write-only - // memory like we might have been with a D3D vertex buffer, this would have been a bad idea. - float *data = (float *)(VertexManager::s_pCurBufferPointer - 12); // We must transform the just loaded point by the current world and projection matrix - in software. // Then convert to screen space and update the bounding box. - float p[3] = {data[0], data[1], data[2]}; + float p[3] = {s_bbox_vertex_buffer[0], s_bbox_vertex_buffer[1], s_bbox_vertex_buffer[2]}; const float *world_matrix = (float*)xfmem + MatrixIndexA.PosNormalMtxIdx * 4; const float *proj_matrix = &g_fProjectionMatrix[0]; @@ -147,24 +168,22 @@ void LOADERDECL TexMtx_ReadDirect_UByte() void LOADERDECL TexMtx_Write_Float() { - *(float*)VertexManager::s_pCurBufferPointer = (float)s_curtexmtx[s_texmtxwrite++]; - VertexManager::s_pCurBufferPointer += 4; + DataWrite(float(s_curtexmtx[s_texmtxwrite++])); } void LOADERDECL TexMtx_Write_Float2() { - ((float*)VertexManager::s_pCurBufferPointer)[0] = 0; - ((float*)VertexManager::s_pCurBufferPointer)[1] = (float)s_curtexmtx[s_texmtxwrite++]; - VertexManager::s_pCurBufferPointer += 8; + DataWrite(0.f); + DataWrite(float(s_curtexmtx[s_texmtxwrite++])); } void LOADERDECL TexMtx_Write_Float4() { - ((float*)VertexManager::s_pCurBufferPointer)[0] = 0; - ((float*)VertexManager::s_pCurBufferPointer)[1] = 0; - ((float*)VertexManager::s_pCurBufferPointer)[2] = s_curtexmtx[s_texmtxwrite++]; - ((float*)VertexManager::s_pCurBufferPointer)[3] = 0; // Just to fill out with 0. - VertexManager::s_pCurBufferPointer += 16; + DataWrite(0.f); + DataWrite(0.f); + DataWrite(float(s_curtexmtx[s_texmtxwrite++])); + // Just to fill out with 0. + DataWrite(0.f); } VertexLoader::VertexLoader(const TVtxDesc &vtx_desc, const VAT &vtx_attr) @@ -182,14 +201,19 @@ VertexLoader::VertexLoader(const TVtxDesc &vtx_desc, const VAT &vtx_attr) m_VtxDesc = vtx_desc; SetVAT(vtx_attr.g0.Hex, vtx_attr.g1.Hex, vtx_attr.g2.Hex); + #ifdef USE_JIT AllocCodeSpace(COMPILED_CODE_SIZE); CompileVertexTranslator(); WriteProtect(); + #endif + } VertexLoader::~VertexLoader() { + #ifdef USE_JIT FreeCodeSpace(); + #endif delete m_NativeFmt; } @@ -267,15 +291,16 @@ void VertexLoader::CompileVertexTranslator() if (m_VtxDesc.Tex7MatIdx) {m_VertexSize += 1; m_NativeFmt->m_components |= VB_HAS_TEXMTXIDX7; WriteCall(TexMtx_ReadDirect_UByte); } // Write vertex position loader - WriteCall(VertexLoader_Position::GetFunction(m_VtxDesc.Position, m_VtxAttr.PosFormat, m_VtxAttr.PosElements)); + if(g_ActiveConfig.bUseBBox) { + WriteCall(UpdateBoundingBoxPrepare); + WriteCall(VertexLoader_Position::GetFunction(m_VtxDesc.Position, m_VtxAttr.PosFormat, m_VtxAttr.PosElements)); + WriteCall(UpdateBoundingBox); + } else { + WriteCall(VertexLoader_Position::GetFunction(m_VtxDesc.Position, m_VtxAttr.PosFormat, m_VtxAttr.PosElements)); + } m_VertexSize += VertexLoader_Position::GetSize(m_VtxDesc.Position, m_VtxAttr.PosFormat, m_VtxAttr.PosElements); nat_offset += 12; - // OK, so we just got a point. Let's go back and read it for the bounding box. - - if(g_ActiveConfig.bUseBBox) - WriteCall(UpdateBoundingBox); - // Normals vtx_decl.num_normals = 0; if (m_VtxDesc.Normal != NOT_PRESENT) @@ -474,7 +499,8 @@ void VertexLoader::WriteCall(TPipelineFunction func) m_PipelineStages[m_numPipelineStages++] = func; #endif } - +// ARMTODO: This should be done in a better way +#ifndef _M_GENERIC void VertexLoader::WriteGetVariable(int bits, OpArg dest, void *address) { #ifdef USE_JIT @@ -498,8 +524,9 @@ void VertexLoader::WriteSetVariable(int bits, void *address, OpArg value) #endif #endif } +#endif -void VertexLoader::RunVertices(int vtx_attr_group, int primitive, int count) +int VertexLoader::SetupRunVertices(int vtx_attr_group, int primitive, int const count) { m_numLoadedVertices += count; @@ -518,7 +545,7 @@ void VertexLoader::RunVertices(int vtx_attr_group, int primitive, int count) { // if cull mode is none, ignore triangles and quads DataSkip(count * m_VertexSize); - return; + return 0; } m_NativeFmt->EnableComponents(m_NativeFmt->m_components); @@ -542,157 +569,48 @@ void VertexLoader::RunVertices(int vtx_attr_group, int primitive, int count) for (int i = 0; i < 2; i++) colElements[i] = m_VtxAttr.color[i].Elements; - // if strips or fans, make sure all vertices can fit in buffer, otherwise flush - int granularity = 1; - switch (primitive) { - case 3: // strip .. hm, weird - case 4: // fan - if (VertexManager::GetRemainingSize() < 3 * native_stride) - VertexManager::Flush(); - break; - case 6: // line strip - if (VertexManager::GetRemainingSize() < 2 * native_stride) - VertexManager::Flush(); - break; - case 0: granularity = 4; break; // quads - case 2: granularity = 3; break; // tris - case 5: granularity = 2; break; // lines - } - - int startv = 0, extraverts = 0; - int v = 0; - - //int remainingVerts2 = VertexManager::GetRemainingVertices(primitive); - while (v < count) - { - int remainingVerts = VertexManager::GetRemainingSize() / native_stride; - //if (remainingVerts2 - v + startv < remainingVerts) - //remainingVerts = remainingVerts2 - v + startv; - if (remainingVerts < granularity) { - INCSTAT(stats.thisFrame.numBufferSplits); - // This buffer full - break current primitive and flush, to switch to the next buffer. - u8* plastptr = VertexManager::s_pCurBufferPointer; - if (v - startv > 0) - VertexManager::AddVertices(primitive, v - startv + extraverts); - VertexManager::Flush(); - //remainingVerts2 = VertexManager::GetRemainingVertices(primitive); - // Why does this need to be so complicated? - switch (primitive) { - case 3: // triangle strip, copy last two vertices - // a little trick since we have to keep track of signs - if (v & 1) { - memcpy_gc(VertexManager::s_pCurBufferPointer, plastptr-2*native_stride, native_stride); - memcpy_gc(VertexManager::s_pCurBufferPointer+native_stride, plastptr-native_stride*2, 2*native_stride); - VertexManager::s_pCurBufferPointer += native_stride*3; - extraverts = 3; - } - else { - memcpy_gc(VertexManager::s_pCurBufferPointer, plastptr-native_stride*2, native_stride*2); - VertexManager::s_pCurBufferPointer += native_stride*2; - extraverts = 2; - } - break; - case 4: // tri fan, copy first and last vert - memcpy_gc(VertexManager::s_pCurBufferPointer, plastptr-native_stride*(v-startv+extraverts), native_stride); - VertexManager::s_pCurBufferPointer += native_stride; - memcpy_gc(VertexManager::s_pCurBufferPointer, plastptr-native_stride, native_stride); - VertexManager::s_pCurBufferPointer += native_stride; - extraverts = 2; - break; - case 6: // line strip - memcpy_gc(VertexManager::s_pCurBufferPointer, plastptr-native_stride, native_stride); - VertexManager::s_pCurBufferPointer += native_stride; - extraverts = 1; - break; - default: - extraverts = 0; - break; - } - startv = v; - } - int remainingPrims = remainingVerts / granularity; - remainingVerts = remainingPrims * granularity; - if (count - v < remainingVerts) - remainingVerts = count - v; - - #ifdef USE_JIT - if (remainingVerts > 0) { - loop_counter = remainingVerts; - ((void (*)())(void*)m_compiledCode)(); - } - #else - for (int s = 0; s < remainingVerts; s++) - { - tcIndex = 0; - colIndex = 0; - s_texmtxwrite = s_texmtxread = 0; - for (int i = 0; i < m_numPipelineStages; i++) - m_PipelineStages[i](); - PRIM_LOG("\n"); - } - #endif - v += remainingVerts; - } - - if (startv < count) - VertexManager::AddVertices(primitive, count - startv + extraverts); + VertexManager::PrepareForAdditionalData(primitive, count, native_stride); + + return count; } - - - -void VertexLoader::RunCompiledVertices(int vtx_attr_group, int primitive, int count, u8* Data) +void VertexLoader::RunVertices(int vtx_attr_group, int primitive, int const count) { - m_numLoadedVertices += count; - - // Flush if our vertex format is different from the currently set. - if (g_nativeVertexFmt != NULL && g_nativeVertexFmt != m_NativeFmt) - { - // We really must flush here. It's possible that the native representations - // of the two vtx formats are the same, but we have no way to easily check that - // now. - VertexManager::Flush(); - // Also move the Set() here? - } - g_nativeVertexFmt = m_NativeFmt; - - if (bpmem.genMode.cullmode == 3 && primitive < 5) - { - // if cull mode is none, ignore triangles and quads - DataSkip(count * m_VertexSize); - return; - } - - m_NativeFmt->EnableComponents(m_NativeFmt->m_components); - - // Load position and texcoord scale factors. - m_VtxAttr.PosFrac = g_VtxAttr[vtx_attr_group].g0.PosFrac; - m_VtxAttr.texCoord[0].Frac = g_VtxAttr[vtx_attr_group].g0.Tex0Frac; - m_VtxAttr.texCoord[1].Frac = g_VtxAttr[vtx_attr_group].g1.Tex1Frac; - m_VtxAttr.texCoord[2].Frac = g_VtxAttr[vtx_attr_group].g1.Tex2Frac; - m_VtxAttr.texCoord[3].Frac = g_VtxAttr[vtx_attr_group].g1.Tex3Frac; - m_VtxAttr.texCoord[4].Frac = g_VtxAttr[vtx_attr_group].g2.Tex4Frac; - m_VtxAttr.texCoord[5].Frac = g_VtxAttr[vtx_attr_group].g2.Tex5Frac; - m_VtxAttr.texCoord[6].Frac = g_VtxAttr[vtx_attr_group].g2.Tex6Frac; - m_VtxAttr.texCoord[7].Frac = g_VtxAttr[vtx_attr_group].g2.Tex7Frac; - - pVtxAttr = &m_VtxAttr; - posScale = fractionTable[m_VtxAttr.PosFrac]; - if (m_NativeFmt->m_components & VB_HAS_UVALL) - for (int i = 0; i < 8; i++) - tcScale[i] = fractionTable[m_VtxAttr.texCoord[i].Frac]; - for (int i = 0; i < 2; i++) - colElements[i] = m_VtxAttr.color[i].Elements; - - if(VertexManager::GetRemainingSize() < native_stride * count) - VertexManager::Flush(); - memcpy_gc(VertexManager::s_pCurBufferPointer, Data, native_stride * count); - VertexManager::s_pCurBufferPointer += native_stride * count; - DataSkip(count * m_VertexSize); - VertexManager::AddVertices(primitive, count); + auto const new_count = SetupRunVertices(vtx_attr_group, primitive, count); + ConvertVertices(new_count); + VertexManager::AddVertices(primitive, new_count); } +void VertexLoader::ConvertVertices ( int count ) +{ +#ifdef USE_JIT + if (count > 0) { + loop_counter = count; + ((void (*)())(void*)m_compiledCode)(); + } +#else + for (int s = 0; s < count; s++) + { + tcIndex = 0; + colIndex = 0; + s_texmtxwrite = s_texmtxread = 0; + for (int i = 0; i < m_numPipelineStages; i++) + m_PipelineStages[i](); + PRIM_LOG("\n"); + } +#endif +} +void VertexLoader::RunCompiledVertices(int vtx_attr_group, int primitive, int const count, u8* Data) +{ + auto const new_count = SetupRunVertices(vtx_attr_group, primitive, count); + + memcpy_gc(VertexManager::s_pCurBufferPointer, Data, native_stride * new_count); + VertexManager::s_pCurBufferPointer += native_stride * new_count; + DataSkip(new_count * m_VertexSize); + + VertexManager::AddVertices(primitive, new_count); +} void VertexLoader::SetVAT(u32 _group0, u32 _group1, u32 _group2) { diff --git a/Source/Core/VideoCommon/Src/VertexLoader.h b/Source/Core/VideoCommon/Src/VertexLoader.h index 98a57cb9ff..c107b6b184 100644 --- a/Source/Core/VideoCommon/Src/VertexLoader.h +++ b/Source/Core/VideoCommon/Src/VertexLoader.h @@ -76,13 +76,20 @@ private: } }; +// ARMTODO: This should be done in a better way +#ifndef _M_GENERIC class VertexLoader : public Gen::XCodeBlock, NonCopyable +#else +class VertexLoader +#endif { public: VertexLoader(const TVtxDesc &vtx_desc, const VAT &vtx_attr); ~VertexLoader(); int GetVertexSize() const {return m_VertexSize;} + + int SetupRunVertices(int vtx_attr_group, int primitive, int const count); void RunVertices(int vtx_attr_group, int primitive, int count); void RunCompiledVertices(int vtx_attr_group, int primitive, int count, u8* Data); @@ -119,11 +126,14 @@ private: void SetVAT(u32 _group0, u32 _group1, u32 _group2); void CompileVertexTranslator(); + void ConvertVertices(int count); void WriteCall(TPipelineFunction); +#ifndef _M_GENERIC void WriteGetVariable(int bits, Gen::OpArg dest, void *address); void WriteSetVariable(int bits, void *address, Gen::OpArg dest); +#endif }; #endif diff --git a/Source/Core/VideoCommon/Src/VertexLoader_Color.cpp b/Source/Core/VideoCommon/Src/VertexLoader_Color.cpp index 9cfa5efc31..fa1ecbe973 100644 --- a/Source/Core/VideoCommon/Src/VertexLoader_Color.cpp +++ b/Source/Core/VideoCommon/Src/VertexLoader_Color.cpp @@ -15,9 +15,6 @@ // Official SVN repository and contact information can be found at // http://code.google.com/p/dolphin-emu/ -#ifndef _VERTEXLOADERCOLOR_H -#define _VERTEXLOADERCOLOR_H - #include "Common.h" #include "VideoCommon.h" #include "LookUpTables.h" @@ -37,8 +34,7 @@ extern int colElements[2]; __forceinline void _SetCol(u32 val) { - *(u32*)VertexManager::s_pCurBufferPointer = val; - VertexManager::s_pCurBufferPointer += 4; + DataWrite(val); colIndex++; } @@ -132,80 +128,65 @@ void LOADERDECL Color_ReadDirect_32b_8888() _SetCol(col); } - - -void LOADERDECL Color_ReadIndex8_16b_565() +template +void Color_ReadIndex_16b_565() { - u8 Index = DataReadU8(); + auto const Index = DataRead(); u16 val = Common::swap16(*(const u16 *)(cached_arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex]))); _SetCol565(val); } -void LOADERDECL Color_ReadIndex8_24b_888() + +template +void Color_ReadIndex_24b_888() { - u8 Index = DataReadU8(); + auto const Index = DataRead(); const u8 *iAddress = cached_arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex]); _SetCol(_Read24(iAddress)); } -void LOADERDECL Color_ReadIndex8_32b_888x() + +template +void Color_ReadIndex_32b_888x() { - u8 Index = DataReadU8(); + auto const Index = DataRead(); const u8 *iAddress = cached_arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex]); _SetCol(_Read24(iAddress)); } -void LOADERDECL Color_ReadIndex8_16b_4444() + +template +void Color_ReadIndex_16b_4444() { - u8 Index = DataReadU8(); + auto const Index = DataRead(); u16 val = *(const u16 *)(cached_arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex])); _SetCol4444(val); } -void LOADERDECL Color_ReadIndex8_24b_6666() + +template +void Color_ReadIndex_24b_6666() { - u8 Index = DataReadU8(); + auto const Index = DataRead(); const u8* pData = cached_arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex]) - 1; u32 val = Common::swap32(pData); _SetCol6666(val); } -void LOADERDECL Color_ReadIndex8_32b_8888() + +template +void Color_ReadIndex_32b_8888() { - u8 Index = DataReadU8(); + auto const Index = DataRead(); const u8 *iAddress = cached_arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex]); _SetCol(_Read32(iAddress)); } -void LOADERDECL Color_ReadIndex16_16b_565() -{ - u16 Index = DataReadU16(); - u16 val = Common::swap16(*(const u16 *)(cached_arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex]))); - _SetCol565(val); -} -void LOADERDECL Color_ReadIndex16_24b_888() -{ - u16 Index = DataReadU16(); - const u8 *iAddress = cached_arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex]); - _SetCol(_Read24(iAddress)); -} -void LOADERDECL Color_ReadIndex16_32b_888x() -{ - u16 Index = DataReadU16(); - const u8 *iAddress = cached_arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex]); - _SetCol(_Read24(iAddress)); -} -void LOADERDECL Color_ReadIndex16_16b_4444() -{ - u16 Index = DataReadU16(); - u16 val = *(const u16 *)(cached_arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex])); - _SetCol4444(val); -} -void LOADERDECL Color_ReadIndex16_24b_6666() -{ - u16 Index = DataReadU16(); - const u8 *pData = cached_arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex]) - 1; - u32 val = Common::swap32(pData); - _SetCol6666(val); -} -void LOADERDECL Color_ReadIndex16_32b_8888() -{ - u16 Index = DataReadU16(); - const u8 *iAddress = cached_arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex]); - _SetCol(_Read32(iAddress)); -} -#endif + +void LOADERDECL Color_ReadIndex8_16b_565() { Color_ReadIndex_16b_565(); } +void LOADERDECL Color_ReadIndex8_24b_888() { Color_ReadIndex_24b_888(); } +void LOADERDECL Color_ReadIndex8_32b_888x() { Color_ReadIndex_32b_888x(); } +void LOADERDECL Color_ReadIndex8_16b_4444() { Color_ReadIndex_16b_4444(); } +void LOADERDECL Color_ReadIndex8_24b_6666() { Color_ReadIndex_24b_6666(); } +void LOADERDECL Color_ReadIndex8_32b_8888() { Color_ReadIndex_32b_8888(); } + +void LOADERDECL Color_ReadIndex16_16b_565() { Color_ReadIndex_16b_565(); } +void LOADERDECL Color_ReadIndex16_24b_888() { Color_ReadIndex_24b_888(); } +void LOADERDECL Color_ReadIndex16_32b_888x() { Color_ReadIndex_32b_888x(); } +void LOADERDECL Color_ReadIndex16_16b_4444() { Color_ReadIndex_16b_4444(); } +void LOADERDECL Color_ReadIndex16_24b_6666() { Color_ReadIndex_24b_6666(); } +void LOADERDECL Color_ReadIndex16_32b_8888() { Color_ReadIndex_32b_8888(); } diff --git a/Source/Core/VideoCommon/Src/VertexLoader_Normal.cpp b/Source/Core/VideoCommon/Src/VertexLoader_Normal.cpp index 830bd3de13..7e016828be 100644 --- a/Source/Core/VideoCommon/Src/VertexLoader_Normal.cpp +++ b/Source/Core/VideoCommon/Src/VertexLoader_Normal.cpp @@ -22,6 +22,7 @@ #include "VertexManagerBase.h" #include "CPUDetect.h" #include +#include #if _M_SSE >= 0x401 #include @@ -30,78 +31,163 @@ #include #endif +// warning: mapping buffer should be disabled to use this #define LOG_NORM() // PRIM_LOG("norm: %f %f %f, ", ((float*)VertexManager::s_pCurBufferPointer)[-3], ((float*)VertexManager::s_pCurBufferPointer)[-2], ((float*)VertexManager::s_pCurBufferPointer)[-1]); VertexLoader_Normal::Set VertexLoader_Normal::m_Table[NUM_NRM_TYPE][NUM_NRM_INDICES][NUM_NRM_ELEMENTS][NUM_NRM_FORMAT]; +namespace +{ + +template +__forceinline float FracAdjust(T val) +{ + //auto const S8FRAC = 1.f / (1u << 6); + //auto const U8FRAC = 1.f / (1u << 7); + //auto const S16FRAC = 1.f / (1u << 14); + //auto const U16FRAC = 1.f / (1u << 15); + + // TODO: is this right? + return val / float(1u << (sizeof(T) * 8 - std::numeric_limits::is_signed - 1)); +} + +template <> +__forceinline float FracAdjust(float val) +{ return val; } + +template +__forceinline void ReadIndirect(const T* data) +{ + static_assert(3 == N || 9 == N, "N is only sane as 3 or 9!"); + + for (int i = 0; i != N; ++i) + { + DataWrite(FracAdjust(Common::FromBigEndian(data[i]))); + } + + LOG_NORM(); +} + +template +struct Normal_Direct +{ + static void LOADERDECL function() + { + auto const source = reinterpret_cast(DataGetPosition()); + ReadIndirect(source); + DataSkip(); + } + + static const int size = sizeof(T) * N * 3; +}; + +template +__forceinline void Normal_Index_Offset() +{ + static_assert(!std::numeric_limits::is_signed, "Only unsigned I is sane!"); + + auto const index = DataRead(); + auto const data = reinterpret_cast(cached_arraybases[ARRAY_NORMAL] + + (index * arraystrides[ARRAY_NORMAL]) + sizeof(T) * 3 * Offset); + ReadIndirect(data); +} + +template +struct Normal_Index +{ + static void LOADERDECL function() + { + Normal_Index_Offset(); + } + + static const int size = sizeof(I); +}; + +template +struct Normal_Index_Indices3 +{ + static void LOADERDECL function() + { + Normal_Index_Offset(); + Normal_Index_Offset(); + Normal_Index_Offset(); + } + + static const int size = sizeof(I) * 3; +}; + +} + void VertexLoader_Normal::Init(void) { - // HACK is for signed instead of unsigned to prevent crashes. - m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT] [FORMAT_UBYTE] = Set(3, Normal_DirectByte); //HACK - m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT] [FORMAT_BYTE] = Set(3, Normal_DirectByte); - m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT] [FORMAT_USHORT] = Set(6, Normal_DirectShort); //HACK - m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT] [FORMAT_SHORT] = Set(6, Normal_DirectShort); - m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT] [FORMAT_FLOAT] = Set(12, Normal_DirectFloat); - m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT3][FORMAT_UBYTE] = Set(9, Normal_DirectByte3); //HACK - m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT3][FORMAT_BYTE] = Set(9, Normal_DirectByte3); - m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT3][FORMAT_USHORT] = Set(18, Normal_DirectShort3); //HACK - m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT3][FORMAT_SHORT] = Set(18, Normal_DirectShort3); - m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT3][FORMAT_FLOAT] = Set(36, Normal_DirectFloat3); - - m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT] [FORMAT_UBYTE] = Set(3, Normal_DirectByte); //HACK - m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT] [FORMAT_BYTE] = Set(3, Normal_DirectByte); - m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT] [FORMAT_USHORT] = Set(6, Normal_DirectShort); //HACK - m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT] [FORMAT_SHORT] = Set(6, Normal_DirectShort); - m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT] [FORMAT_FLOAT] = Set(12, Normal_DirectFloat); - m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT3][FORMAT_UBYTE] = Set(9, Normal_DirectByte3); //HACK - m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT3][FORMAT_BYTE] = Set(9, Normal_DirectByte3); - m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT3][FORMAT_USHORT] = Set(18, Normal_DirectShort3); //HACK - m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT3][FORMAT_SHORT] = Set(18, Normal_DirectShort3); - m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT3][FORMAT_FLOAT] = Set(36, Normal_DirectFloat3); - - m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT] [FORMAT_UBYTE] = Set(1, Normal_Index8_Byte); //HACK - m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT] [FORMAT_BYTE] = Set(1, Normal_Index8_Byte); - m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT] [FORMAT_USHORT] = Set(1, Normal_Index8_Short); //HACK - m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT] [FORMAT_SHORT] = Set(1, Normal_Index8_Short); - m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT] [FORMAT_FLOAT] = Set(1, Normal_Index8_Float); - m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT3][FORMAT_UBYTE] = Set(1, Normal_Index8_Byte3_Indices1); //HACK - m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT3][FORMAT_BYTE] = Set(1, Normal_Index8_Byte3_Indices1); - m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT3][FORMAT_USHORT] = Set(1, Normal_Index8_Short3_Indices1); //HACK - m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT3][FORMAT_SHORT] = Set(1, Normal_Index8_Short3_Indices1); - m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT3][FORMAT_FLOAT] = Set(1, Normal_Index8_Float3_Indices1); - - m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT] [FORMAT_UBYTE] = Set(1, Normal_Index8_Byte); //HACK - m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT] [FORMAT_BYTE] = Set(1, Normal_Index8_Byte); - m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT] [FORMAT_USHORT] = Set(1, Normal_Index8_Short); //HACK - m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT] [FORMAT_SHORT] = Set(1, Normal_Index8_Short); - m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT] [FORMAT_FLOAT] = Set(1, Normal_Index8_Float); - m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT3][FORMAT_UBYTE] = Set(3, Normal_Index8_Byte3_Indices3); //HACK - m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT3][FORMAT_BYTE] = Set(3, Normal_Index8_Byte3_Indices3); - m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT3][FORMAT_USHORT] = Set(3, Normal_Index8_Short3_Indices3); //HACK - m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT3][FORMAT_SHORT] = Set(3, Normal_Index8_Short3_Indices3); - m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT3][FORMAT_FLOAT] = Set(3, Normal_Index8_Float3_Indices3); - - m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT] [FORMAT_UBYTE] = Set(2, Normal_Index16_Byte); //HACK - m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT] [FORMAT_BYTE] = Set(2, Normal_Index16_Byte); - m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT] [FORMAT_USHORT] = Set(2, Normal_Index16_Short); //HACK - m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT] [FORMAT_SHORT] = Set(2, Normal_Index16_Short); - m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT] [FORMAT_FLOAT] = Set(2, Normal_Index16_Float); - m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT3][FORMAT_UBYTE] = Set(2, Normal_Index16_Byte3_Indices1); //HACK - m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT3][FORMAT_BYTE] = Set(2, Normal_Index16_Byte3_Indices1); - m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT3][FORMAT_USHORT] = Set(2, Normal_Index16_Short3_Indices1); //HACK - m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT3][FORMAT_SHORT] = Set(2, Normal_Index16_Short3_Indices1); - m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT3][FORMAT_FLOAT] = Set(2, Normal_Index16_Float3_Indices1); - - m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT] [FORMAT_UBYTE] = Set(2, Normal_Index16_Byte); //HACK - m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT] [FORMAT_BYTE] = Set(2, Normal_Index16_Byte); - m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT] [FORMAT_USHORT] = Set(2, Normal_Index16_Short); //HACK - m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT] [FORMAT_SHORT] = Set(2, Normal_Index16_Short); - m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT] [FORMAT_FLOAT] = Set(2, Normal_Index16_Float); - m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT3][FORMAT_UBYTE] = Set(6, Normal_Index16_Byte3_Indices3); //HACK - m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT3][FORMAT_BYTE] = Set(6, Normal_Index16_Byte3_Indices3); - m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT3][FORMAT_USHORT] = Set(6, Normal_Index16_Short3_Indices3); //HACK - m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT3][FORMAT_SHORT] = Set(6, Normal_Index16_Short3_Indices3); - m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT3][FORMAT_FLOAT] = Set(6, Normal_Index16_Float3_Indices3); + m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT] [FORMAT_UBYTE] = Normal_Direct(); + m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT] [FORMAT_BYTE] = Normal_Direct(); + m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT] [FORMAT_USHORT] = Normal_Direct(); + m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT] [FORMAT_SHORT] = Normal_Direct(); + m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT] [FORMAT_FLOAT] = Normal_Direct(); + m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT3][FORMAT_UBYTE] = Normal_Direct(); + m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT3][FORMAT_BYTE] = Normal_Direct(); + m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT3][FORMAT_USHORT] = Normal_Direct(); + m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT3][FORMAT_SHORT] = Normal_Direct(); + m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT3][FORMAT_FLOAT] = Normal_Direct(); + + // Same as above + m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT] [FORMAT_UBYTE] = Normal_Direct(); + m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT] [FORMAT_BYTE] = Normal_Direct(); + m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT] [FORMAT_USHORT] = Normal_Direct(); + m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT] [FORMAT_SHORT] = Normal_Direct(); + m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT] [FORMAT_FLOAT] = Normal_Direct(); + m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT3][FORMAT_UBYTE] = Normal_Direct(); + m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT3][FORMAT_BYTE] = Normal_Direct(); + m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT3][FORMAT_USHORT] = Normal_Direct(); + m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT3][FORMAT_SHORT] = Normal_Direct(); + m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT3][FORMAT_FLOAT] = Normal_Direct(); + + m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT] [FORMAT_UBYTE] = Normal_Index(); + m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT] [FORMAT_BYTE] = Normal_Index(); + m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT] [FORMAT_USHORT] = Normal_Index(); + m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT] [FORMAT_SHORT] = Normal_Index(); + m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT] [FORMAT_FLOAT] = Normal_Index(); + m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT3][FORMAT_UBYTE] = Normal_Index(); + m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT3][FORMAT_BYTE] = Normal_Index(); + m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT3][FORMAT_USHORT] = Normal_Index(); + m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT3][FORMAT_SHORT] = Normal_Index(); + m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT3][FORMAT_FLOAT] = Normal_Index(); + + // Same as above for NRM_NBT + m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT] [FORMAT_UBYTE] = Normal_Index(); + m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT] [FORMAT_BYTE] = Normal_Index(); + m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT] [FORMAT_USHORT] = Normal_Index(); + m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT] [FORMAT_SHORT] = Normal_Index(); + m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT] [FORMAT_FLOAT] = Normal_Index(); + m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT3][FORMAT_UBYTE] = Normal_Index_Indices3(); + m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT3][FORMAT_BYTE] = Normal_Index_Indices3(); + m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT3][FORMAT_USHORT] = Normal_Index_Indices3(); + m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT3][FORMAT_SHORT] = Normal_Index_Indices3(); + m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT3][FORMAT_FLOAT] = Normal_Index_Indices3(); + + m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT] [FORMAT_UBYTE] = Normal_Index(); + m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT] [FORMAT_BYTE] = Normal_Index(); + m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT] [FORMAT_USHORT] = Normal_Index(); + m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT] [FORMAT_SHORT] = Normal_Index(); + m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT] [FORMAT_FLOAT] = Normal_Index(); + m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT3][FORMAT_UBYTE] = Normal_Index(); + m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT3][FORMAT_BYTE] = Normal_Index(); + m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT3][FORMAT_USHORT] = Normal_Index(); + m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT3][FORMAT_SHORT] = Normal_Index(); + m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT3][FORMAT_FLOAT] = Normal_Index(); + + // Same as above for NRM_NBT + m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT] [FORMAT_UBYTE] = Normal_Index(); + m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT] [FORMAT_BYTE] = Normal_Index(); + m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT] [FORMAT_USHORT] = Normal_Index(); + m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT] [FORMAT_SHORT] = Normal_Index(); + m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT] [FORMAT_FLOAT] = Normal_Index(); + m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT3][FORMAT_UBYTE] = Normal_Index_Indices3(); + m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT3][FORMAT_BYTE] = Normal_Index_Indices3(); + m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT3][FORMAT_USHORT] = Normal_Index_Indices3(); + m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT3][FORMAT_SHORT] = Normal_Index_Indices3(); + m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT3][FORMAT_FLOAT] = Normal_Index_Indices3(); } unsigned int VertexLoader_Normal::GetSize(unsigned int _type, @@ -116,312 +202,3 @@ TPipelineFunction VertexLoader_Normal::GetFunction(unsigned int _type, TPipelineFunction pFunc = m_Table[_type][_index3][_elements][_format].function; return pFunc; } - -// This fracs are fixed acording to format -#define S8FRAC 0.015625f; // 1.0f / (1U << 6) -#define S16FRAC 0.00006103515625f; // 1.0f / (1U << 14) -// --- Direct --- - -inline void ReadIndirectS8x3(const s8* pData) -{ - ((float*)VertexManager::s_pCurBufferPointer)[0] = pData[0] * S8FRAC; - ((float*)VertexManager::s_pCurBufferPointer)[1] = pData[1] * S8FRAC; - ((float*)VertexManager::s_pCurBufferPointer)[2] = pData[2] * S8FRAC; - VertexManager::s_pCurBufferPointer += 12; - LOG_NORM(); -} - -inline void ReadIndirectS8x9(const s8* pData) -{ - ((float*)VertexManager::s_pCurBufferPointer)[0] = pData[0] * S8FRAC; - ((float*)VertexManager::s_pCurBufferPointer)[1] = pData[1] * S8FRAC; - ((float*)VertexManager::s_pCurBufferPointer)[2] = pData[2] * S8FRAC; - LOG_NORM(); - ((float*)VertexManager::s_pCurBufferPointer)[3] = pData[3] * S8FRAC; - ((float*)VertexManager::s_pCurBufferPointer)[4] = pData[4] * S8FRAC; - ((float*)VertexManager::s_pCurBufferPointer)[5] = pData[5] * S8FRAC; - LOG_NORM(); - ((float*)VertexManager::s_pCurBufferPointer)[6] = pData[6] * S8FRAC; - ((float*)VertexManager::s_pCurBufferPointer)[7] = pData[7] * S8FRAC; - ((float*)VertexManager::s_pCurBufferPointer)[8] = pData[8] * S8FRAC; - LOG_NORM(); - VertexManager::s_pCurBufferPointer += 36; -} - -inline void ReadIndirectS16x3(const u16* pData) -{ - ((float*)VertexManager::s_pCurBufferPointer)[0] = ((s16)Common::swap16(pData[0])) * S16FRAC; - ((float*)VertexManager::s_pCurBufferPointer)[1] = ((s16)Common::swap16(pData[1])) * S16FRAC; - ((float*)VertexManager::s_pCurBufferPointer)[2] = ((s16)Common::swap16(pData[2])) * S16FRAC; - VertexManager::s_pCurBufferPointer += 12; - LOG_NORM() -} - -inline void ReadIndirectS16x9(const u16* pData) -{ - ((float*)VertexManager::s_pCurBufferPointer)[0] = ((s16)Common::swap16(pData[0])) * S16FRAC; - ((float*)VertexManager::s_pCurBufferPointer)[1] = ((s16)Common::swap16(pData[1])) * S16FRAC; - ((float*)VertexManager::s_pCurBufferPointer)[2] = ((s16)Common::swap16(pData[2])) * S16FRAC; - LOG_NORM() - ((float*)VertexManager::s_pCurBufferPointer)[3] = ((s16)Common::swap16(pData[3])) * S16FRAC; - ((float*)VertexManager::s_pCurBufferPointer)[4] = ((s16)Common::swap16(pData[4])) * S16FRAC; - ((float*)VertexManager::s_pCurBufferPointer)[5] = ((s16)Common::swap16(pData[5])) * S16FRAC; - LOG_NORM() - ((float*)VertexManager::s_pCurBufferPointer)[6] = ((s16)Common::swap16(pData[6])) * S16FRAC; - ((float*)VertexManager::s_pCurBufferPointer)[7] = ((s16)Common::swap16(pData[7])) * S16FRAC; - ((float*)VertexManager::s_pCurBufferPointer)[8] = ((s16)Common::swap16(pData[8])) * S16FRAC; - LOG_NORM() - VertexManager::s_pCurBufferPointer += 36; -} - -inline void ReadIndirectFloatx3(const u32* pData) -{ - ((u32*)VertexManager::s_pCurBufferPointer)[0] = Common::swap32(pData[0]); - ((u32*)VertexManager::s_pCurBufferPointer)[1] = Common::swap32(pData[1]); - ((u32*)VertexManager::s_pCurBufferPointer)[2] = Common::swap32(pData[2]); - VertexManager::s_pCurBufferPointer += 12; - LOG_NORM(); -} - -inline void ReadIndirectFloatx9(const u32* pData) -{ - ((u32*)VertexManager::s_pCurBufferPointer)[0] = Common::swap32(pData[0]); - ((u32*)VertexManager::s_pCurBufferPointer)[1] = Common::swap32(pData[1]); - ((u32*)VertexManager::s_pCurBufferPointer)[2] = Common::swap32(pData[2]); - LOG_NORM(); - ((u32*)VertexManager::s_pCurBufferPointer)[3] = Common::swap32(pData[3]); - ((u32*)VertexManager::s_pCurBufferPointer)[4] = Common::swap32(pData[4]); - ((u32*)VertexManager::s_pCurBufferPointer)[5] = Common::swap32(pData[5]); - LOG_NORM(); - ((u32*)VertexManager::s_pCurBufferPointer)[6] = Common::swap32(pData[6]); - ((u32*)VertexManager::s_pCurBufferPointer)[7] = Common::swap32(pData[7]); - ((u32*)VertexManager::s_pCurBufferPointer)[8] = Common::swap32(pData[8]); - LOG_NORM(); - VertexManager::s_pCurBufferPointer += 36; -} - -inline void ReadDirectS8x3() -{ - const s8* Source = (const s8*)DataGetPosition(); - ReadIndirectS8x3(Source); - DataSkip(3); -} - -inline void ReadDirectS8x9() -{ - const s8* Source = (const s8*)DataGetPosition(); - ReadIndirectS8x9(Source); - DataSkip(9); -} - -inline void ReadDirectS16x3() -{ - const u16* Source = (const u16*)DataGetPosition(); - ReadIndirectS16x3(Source); - DataSkip(6); -} - -inline void ReadDirectS16x9() -{ - const u16* Source = (const u16*)DataGetPosition(); - ReadIndirectS16x9(Source); - DataSkip(18); -} - -inline void ReadDirectFloatx3() -{ - const u32* Source = (const u32*)DataGetPosition(); - ReadIndirectFloatx3(Source); - DataSkip(12); -} - -inline void ReadDirectFloatx9() -{ - const u32* Source = (const u32*)DataGetPosition(); - ReadIndirectFloatx9(Source); - DataSkip(36); -} - - - -void LOADERDECL VertexLoader_Normal::Normal_DirectByte() -{ - ReadDirectS8x3(); -} - -void LOADERDECL VertexLoader_Normal::Normal_DirectShort() -{ - ReadDirectS16x3(); -} - -void LOADERDECL VertexLoader_Normal::Normal_DirectFloat() -{ - ReadDirectFloatx3(); -} - -void LOADERDECL VertexLoader_Normal::Normal_DirectByte3() -{ - ReadDirectS8x9(); -} - -void LOADERDECL VertexLoader_Normal::Normal_DirectShort3() -{ - ReadDirectS16x9(); -} - -void LOADERDECL VertexLoader_Normal::Normal_DirectFloat3() -{ - ReadDirectFloatx9(); -} - - -// --- Index8 --- - -void LOADERDECL VertexLoader_Normal::Normal_Index8_Byte() -{ - u8 Index = DataReadU8(); - const s8* pData = (const s8 *)(cached_arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL])); - ReadIndirectS8x3(pData); -} - -void LOADERDECL VertexLoader_Normal::Normal_Index8_Short() -{ - u8 Index = DataReadU8(); - const u16* pData = (const u16 *)(cached_arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL])); - ReadIndirectS16x3(pData); -} - -void LOADERDECL VertexLoader_Normal::Normal_Index8_Float() -{ - u8 Index = DataReadU8(); - const u32* pData = (const u32 *)(cached_arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL])); - ReadIndirectFloatx3(pData); -} - -void LOADERDECL VertexLoader_Normal::Normal_Index8_Byte3_Indices1() -{ - u8 Index = DataReadU8(); - const s8* pData = (const s8 *)(cached_arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL])); - ReadIndirectS8x9(pData); -} - -void LOADERDECL VertexLoader_Normal::Normal_Index8_Short3_Indices1() -{ - u8 Index = DataReadU8(); - const u16* pData = (const u16 *)(cached_arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL])); - ReadIndirectS16x9(pData); -} - -void LOADERDECL VertexLoader_Normal::Normal_Index8_Float3_Indices1() -{ - u8 Index = DataReadU8(); - const u32* pData = (const u32 *)(cached_arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL])); - ReadIndirectFloatx9(pData); -} - -void LOADERDECL VertexLoader_Normal::Normal_Index8_Byte3_Indices3() -{ - for (int i = 0; i < 3; i++) - { - u8 Index = DataReadU8(); - const s8* pData = (const s8*)(cached_arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 1*3*i); - ReadIndirectS8x3(pData); - } -} - - -void LOADERDECL VertexLoader_Normal::Normal_Index8_Short3_Indices3() -{ - for (int i = 0; i < 3; i++) - { - u8 Index = DataReadU8(); - const u16* pData = (const u16 *)(cached_arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 2*3*i); - ReadIndirectS16x3(pData); - } -} - -void LOADERDECL VertexLoader_Normal::Normal_Index8_Float3_Indices3() -{ - for (int i = 0; i < 3; i++) - { - u8 Index = DataReadU8(); - const u32* pData = (const u32 *)(cached_arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 4*3*i); - ReadIndirectFloatx3(pData); - } -} - - -// --- Index16 --- - - -void LOADERDECL VertexLoader_Normal::Normal_Index16_Byte() -{ - u16 Index = DataReadU16(); - const s8* pData = (const s8 *)(cached_arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL])); - ReadIndirectS8x3(pData); -} - -void LOADERDECL VertexLoader_Normal::Normal_Index16_Short() -{ - u16 Index = DataReadU16(); - const u16* pData = (const u16 *)(cached_arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL])); - ReadIndirectS16x3(pData); -} - -void LOADERDECL VertexLoader_Normal::Normal_Index16_Float() -{ - u16 Index = DataReadU16(); - const u32* pData = (const u32 *)(cached_arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL])); - ReadIndirectFloatx3(pData); -} - -void LOADERDECL VertexLoader_Normal::Normal_Index16_Byte3_Indices1() -{ - u16 Index = DataReadU16(); - const s8* pData = (const s8 *)(cached_arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL])); - ReadIndirectS8x9(pData); -} - -void LOADERDECL VertexLoader_Normal::Normal_Index16_Short3_Indices1() -{ - u16 Index = DataReadU16(); - const u16* pData = (const u16 *)(cached_arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL])); - ReadIndirectS16x9(pData); -} - -void LOADERDECL VertexLoader_Normal::Normal_Index16_Float3_Indices1() -{ - u16 Index = DataReadU16(); - const u32* pData = (const u32 *)(cached_arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL])); - ReadIndirectFloatx9(pData); -} - -void LOADERDECL VertexLoader_Normal::Normal_Index16_Byte3_Indices3() -{ - for (int i = 0; i < 3; i++) - { - u16 Index = DataReadU16(); - const s8* pData = (const s8*)(cached_arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 1*3*i); - ReadIndirectS8x3(pData); - } -} - -void LOADERDECL VertexLoader_Normal::Normal_Index16_Short3_Indices3() -{ - for (int i = 0; i < 3; i++) - { - u16 Index = DataReadU16(); - const u16* pData = (const u16 *)(cached_arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 2*3*i); - ReadIndirectS16x3(pData); - } -} - -void LOADERDECL VertexLoader_Normal::Normal_Index16_Float3_Indices3() -{ - for (int i = 0; i < 3; i++) - { - u16 Index = DataReadU16(); - const u32* pData = (const u32 *)(cached_arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 4*3*i); - ReadIndirectFloatx3(pData); - } -} diff --git a/Source/Core/VideoCommon/Src/VertexLoader_Normal.h b/Source/Core/VideoCommon/Src/VertexLoader_Normal.h index 934cd1ec43..d538b2a72e 100644 --- a/Source/Core/VideoCommon/Src/VertexLoader_Normal.h +++ b/Source/Core/VideoCommon/Src/VertexLoader_Normal.h @@ -70,45 +70,20 @@ private: NUM_NRM_INDICES }; - struct Set { - Set() {} - Set(int gc_size_, TPipelineFunction function_) : gc_size(gc_size_), function(function_) {} + struct Set + { + template + void operator=(const T&) + { + gc_size = T::size; + function = T::function; + } + int gc_size; TPipelineFunction function; -// int pc_size; }; static Set m_Table[NUM_NRM_TYPE][NUM_NRM_INDICES][NUM_NRM_ELEMENTS][NUM_NRM_FORMAT]; - - // direct - static void LOADERDECL Normal_DirectByte(); - static void LOADERDECL Normal_DirectShort(); - static void LOADERDECL Normal_DirectFloat(); - static void LOADERDECL Normal_DirectByte3(); - static void LOADERDECL Normal_DirectShort3(); - static void LOADERDECL Normal_DirectFloat3(); - - // index8 - static void LOADERDECL Normal_Index8_Byte(); - static void LOADERDECL Normal_Index8_Short(); - static void LOADERDECL Normal_Index8_Float(); - static void LOADERDECL Normal_Index8_Byte3_Indices1(); - static void LOADERDECL Normal_Index8_Short3_Indices1(); - static void LOADERDECL Normal_Index8_Float3_Indices1(); - static void LOADERDECL Normal_Index8_Byte3_Indices3(); - static void LOADERDECL Normal_Index8_Short3_Indices3(); - static void LOADERDECL Normal_Index8_Float3_Indices3(); - - // index16 - static void LOADERDECL Normal_Index16_Byte(); - static void LOADERDECL Normal_Index16_Short(); - static void LOADERDECL Normal_Index16_Float(); - static void LOADERDECL Normal_Index16_Byte3_Indices1(); - static void LOADERDECL Normal_Index16_Short3_Indices1(); - static void LOADERDECL Normal_Index16_Float3_Indices1(); - static void LOADERDECL Normal_Index16_Byte3_Indices3(); - static void LOADERDECL Normal_Index16_Short3_Indices3(); - static void LOADERDECL Normal_Index16_Float3_Indices3(); }; #endif diff --git a/Source/Core/VideoCommon/Src/VertexLoader_Position.cpp b/Source/Core/VideoCommon/Src/VertexLoader_Position.cpp index 06481f9ddf..ce7a38b8c3 100644 --- a/Source/Core/VideoCommon/Src/VertexLoader_Position.cpp +++ b/Source/Core/VideoCommon/Src/VertexLoader_Position.cpp @@ -15,6 +15,8 @@ // Official SVN repository and contact information can be found at // http://code.google.com/p/dolphin-emu/ +#include + #include "Common.h" #include "VideoCommon.h" #include "VertexLoader.h" @@ -71,101 +73,42 @@ MOVUPS(MOffset(EDI, 0), XMM0); */ -// ============================================================================== -// Direct -// ============================================================================== - -template -void Pos_ReadDirect() +template +float PosScale(T val) { - ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(T)DataRead() * posScale; - ((float*)VertexManager::s_pCurBufferPointer)[1] = (float)(T)DataRead() * posScale; - if (three) - ((float*)VertexManager::s_pCurBufferPointer)[2] = (float)(T)DataRead() * posScale; - else - ((float*)VertexManager::s_pCurBufferPointer)[2] = 0.0f; + return val * posScale; +} + +template <> +float PosScale(float val) +{ return val; } + +template +void LOADERDECL Pos_ReadDirect() +{ + static_assert(N <= 3, "N > 3 is not sane!"); + + for (int i = 0; i < 3; ++i) + DataWrite(i()) : 0.f); + LOG_VTX(); - VertexManager::s_pCurBufferPointer += 12; } -void LOADERDECL Pos_ReadDirect_UByte3() { Pos_ReadDirect(); } -void LOADERDECL Pos_ReadDirect_Byte3() { Pos_ReadDirect(); } -void LOADERDECL Pos_ReadDirect_UShort3() { Pos_ReadDirect(); } -void LOADERDECL Pos_ReadDirect_Short3() { Pos_ReadDirect(); } -void LOADERDECL Pos_ReadDirect_UByte2() { Pos_ReadDirect(); } -void LOADERDECL Pos_ReadDirect_Byte2() { Pos_ReadDirect(); } -void LOADERDECL Pos_ReadDirect_UShort2() { Pos_ReadDirect(); } -void LOADERDECL Pos_ReadDirect_Short2() { Pos_ReadDirect(); } - -void LOADERDECL Pos_ReadDirect_Float3() +template +void LOADERDECL Pos_ReadIndex() { - // No need to use floating point here. - ((u32 *)VertexManager::s_pCurBufferPointer)[0] = DataReadU32(); - ((u32 *)VertexManager::s_pCurBufferPointer)[1] = DataReadU32(); - ((u32 *)VertexManager::s_pCurBufferPointer)[2] = DataReadU32(); - LOG_VTX(); - VertexManager::s_pCurBufferPointer += 12; -} - -void LOADERDECL Pos_ReadDirect_Float2() -{ - // No need to use floating point here. - ((u32 *)VertexManager::s_pCurBufferPointer)[0] = DataReadU32(); - ((u32 *)VertexManager::s_pCurBufferPointer)[1] = DataReadU32(); - ((u32 *)VertexManager::s_pCurBufferPointer)[2] = 0; - LOG_VTX(); - VertexManager::s_pCurBufferPointer += 12; -} - - -template -inline void Pos_ReadIndex_Byte(int Index) -{ - if(Index < MaxSize) + static_assert(!std::numeric_limits::is_signed, "Only unsigned I is sane!"); + static_assert(N <= 3, "N > 3 is not sane!"); + + auto const index = DataRead(); + if (index < std::numeric_limits::max()) { - const u8* pData = cached_arraybases[ARRAY_POSITION] + ((u32)Index * arraystrides[ARRAY_POSITION]); - ((float*)VertexManager::s_pCurBufferPointer)[0] = ((float)(T)(pData[0])) * posScale; - ((float*)VertexManager::s_pCurBufferPointer)[1] = ((float)(T)(pData[1])) * posScale; - if (three) - ((float*)VertexManager::s_pCurBufferPointer)[2] = ((float)(T)(pData[2])) * posScale; - else - ((float*)VertexManager::s_pCurBufferPointer)[2] = 0.0f; + auto const data = reinterpret_cast(cached_arraybases[ARRAY_POSITION] + (index * arraystrides[ARRAY_POSITION])); + + for (int i = 0; i < 3; ++i) + DataWrite(i -inline void Pos_ReadIndex_Short(int Index) -{ - if(Index < MaxSize) - { - const u16* pData = (const u16 *)(cached_arraybases[ARRAY_POSITION] + ((u32)Index * arraystrides[ARRAY_POSITION])); - ((float*)VertexManager::s_pCurBufferPointer)[0] = ((float)(T)Common::swap16(pData[0])) * posScale; - ((float*)VertexManager::s_pCurBufferPointer)[1] = ((float)(T)Common::swap16(pData[1])) * posScale; - if (three) - ((float*)VertexManager::s_pCurBufferPointer)[2] = ((float)(T)Common::swap16(pData[2])) * posScale; - else - ((float*)VertexManager::s_pCurBufferPointer)[2] = 0.0f; - LOG_VTX(); - VertexManager::s_pCurBufferPointer += 12; - } -} - -template -void Pos_ReadIndex_Float(int Index) -{ - if(Index < MaxSize) - { - const u32* pData = (const u32 *)(cached_arraybases[ARRAY_POSITION] + (Index * arraystrides[ARRAY_POSITION])); - ((u32*)VertexManager::s_pCurBufferPointer)[0] = Common::swap32(pData[0]); - ((u32*)VertexManager::s_pCurBufferPointer)[1] = Common::swap32(pData[1]); - if (three) - ((u32*)VertexManager::s_pCurBufferPointer)[2] = Common::swap32(pData[2]); - else - ((float*)VertexManager::s_pCurBufferPointer)[2] = 0.0f; - LOG_VTX(); - VertexManager::s_pCurBufferPointer += 12; } } @@ -173,87 +116,22 @@ void Pos_ReadIndex_Float(int Index) static const __m128i kMaskSwap32_3 = _mm_set_epi32(0xFFFFFFFFL, 0x08090A0BL, 0x04050607L, 0x00010203L); static const __m128i kMaskSwap32_2 = _mm_set_epi32(0xFFFFFFFFL, 0xFFFFFFFFL, 0x04050607L, 0x00010203L); -template -void Pos_ReadIndex_Float_SSSE3(int Index) +template +void LOADERDECL Pos_ReadIndex_Float_SSSE3() { - if(Index < MaxSize) + auto const index = DataRead(); + if (index < std::numeric_limits::max()) { - const u32* pData = (const u32 *)(cached_arraybases[ARRAY_POSITION] + (Index * arraystrides[ARRAY_POSITION])); + const u32* pData = (const u32 *)(cached_arraybases[ARRAY_POSITION] + (index * arraystrides[ARRAY_POSITION])); GC_ALIGNED128(const __m128i a = _mm_loadu_si128((__m128i*)pData)); GC_ALIGNED128(__m128i b = _mm_shuffle_epi8(a, three ? kMaskSwap32_3 : kMaskSwap32_2)); _mm_storeu_si128((__m128i*)VertexManager::s_pCurBufferPointer, b); + VertexManager::s_pCurBufferPointer += sizeof(float) * 3; LOG_VTX(); - VertexManager::s_pCurBufferPointer += 12; } } #endif -// Explicitly instantiate these functions to decrease the possibility of -// symbol binding problems when (only) calling them from JIT compiled code. -template void Pos_ReadDirect(); -template void Pos_ReadDirect(); -template void Pos_ReadDirect(); -template void Pos_ReadDirect(); -template void Pos_ReadDirect(); -template void Pos_ReadDirect(); -template void Pos_ReadDirect(); -template void Pos_ReadDirect(); -template void Pos_ReadIndex_Byte(int Index); -template void Pos_ReadIndex_Byte(int Index); -template void Pos_ReadIndex_Short(int Index); -template void Pos_ReadIndex_Short(int Index); -template void Pos_ReadIndex_Float(int Index); -template void Pos_ReadIndex_Byte(int Index); -template void Pos_ReadIndex_Byte(int Index); -template void Pos_ReadIndex_Short(int Index); -template void Pos_ReadIndex_Short(int Index); -template void Pos_ReadIndex_Float(int Index); -template void Pos_ReadIndex_Byte(int Index); -template void Pos_ReadIndex_Byte(int Index); -template void Pos_ReadIndex_Short(int Index); -template void Pos_ReadIndex_Short(int Index); -template void Pos_ReadIndex_Float(int Index); -template void Pos_ReadIndex_Byte(int Index); -template void Pos_ReadIndex_Byte(int Index); -template void Pos_ReadIndex_Short(int Index); -template void Pos_ReadIndex_Short(int Index); -template void Pos_ReadIndex_Float(int Index); - -// ============================================================================== -// Index 8 -// ============================================================================== -void LOADERDECL Pos_ReadIndex8_UByte3() {Pos_ReadIndex_Byte (DataReadU8());} -void LOADERDECL Pos_ReadIndex8_Byte3() {Pos_ReadIndex_Byte (DataReadU8());} -void LOADERDECL Pos_ReadIndex8_UShort3() {Pos_ReadIndex_Short (DataReadU8());} -void LOADERDECL Pos_ReadIndex8_Short3() {Pos_ReadIndex_Short (DataReadU8());} -void LOADERDECL Pos_ReadIndex8_Float3() {Pos_ReadIndex_Float (DataReadU8());} -void LOADERDECL Pos_ReadIndex8_UByte2() {Pos_ReadIndex_Byte(DataReadU8());} -void LOADERDECL Pos_ReadIndex8_Byte2() {Pos_ReadIndex_Byte(DataReadU8());} -void LOADERDECL Pos_ReadIndex8_UShort2() {Pos_ReadIndex_Short(DataReadU8());} -void LOADERDECL Pos_ReadIndex8_Short2() {Pos_ReadIndex_Short(DataReadU8());} -void LOADERDECL Pos_ReadIndex8_Float2() {Pos_ReadIndex_Float (DataReadU8());} - -// ============================================================================== -// Index 16 -// ============================================================================== -void LOADERDECL Pos_ReadIndex16_UByte3() {Pos_ReadIndex_Byte (DataReadU16());} -void LOADERDECL Pos_ReadIndex16_Byte3() {Pos_ReadIndex_Byte (DataReadU16());} -void LOADERDECL Pos_ReadIndex16_UShort3() {Pos_ReadIndex_Short (DataReadU16());} -void LOADERDECL Pos_ReadIndex16_Short3() {Pos_ReadIndex_Short (DataReadU16());} -void LOADERDECL Pos_ReadIndex16_Float3() {Pos_ReadIndex_Float (DataReadU16());} -void LOADERDECL Pos_ReadIndex16_UByte2() {Pos_ReadIndex_Byte(DataReadU16());} -void LOADERDECL Pos_ReadIndex16_Byte2() {Pos_ReadIndex_Byte(DataReadU16());} -void LOADERDECL Pos_ReadIndex16_UShort2() {Pos_ReadIndex_Short(DataReadU16());} -void LOADERDECL Pos_ReadIndex16_Short2() {Pos_ReadIndex_Short(DataReadU16());} -void LOADERDECL Pos_ReadIndex16_Float2() {Pos_ReadIndex_Float (DataReadU16());} - -#if _M_SSE >= 0x301 -void LOADERDECL Pos_ReadIndex8_Float3_SSSE3() {Pos_ReadIndex_Float_SSSE3 (DataReadU8());} -void LOADERDECL Pos_ReadIndex8_Float2_SSSE3() {Pos_ReadIndex_Float_SSSE3 (DataReadU8());} -void LOADERDECL Pos_ReadIndex16_Float3_SSSE3() {Pos_ReadIndex_Float_SSSE3 (DataReadU16());} -void LOADERDECL Pos_ReadIndex16_Float2_SSSE3() {Pos_ReadIndex_Float_SSSE3 (DataReadU16());} -#endif - static TPipelineFunction tableReadPosition[4][8][2] = { { {NULL, NULL,}, @@ -263,56 +141,40 @@ static TPipelineFunction tableReadPosition[4][8][2] = { {NULL, NULL,}, }, { - {Pos_ReadDirect_UByte2, Pos_ReadDirect_UByte3,}, - {Pos_ReadDirect_Byte2, Pos_ReadDirect_Byte3,}, - {Pos_ReadDirect_UShort2, Pos_ReadDirect_UShort3,}, - {Pos_ReadDirect_Short2, Pos_ReadDirect_Short3,}, - {Pos_ReadDirect_Float2, Pos_ReadDirect_Float3,}, + {Pos_ReadDirect, Pos_ReadDirect,}, + {Pos_ReadDirect, Pos_ReadDirect,}, + {Pos_ReadDirect, Pos_ReadDirect,}, + {Pos_ReadDirect, Pos_ReadDirect,}, + {Pos_ReadDirect, Pos_ReadDirect,}, }, { - {Pos_ReadIndex8_UByte2, Pos_ReadIndex8_UByte3,}, - {Pos_ReadIndex8_Byte2, Pos_ReadIndex8_Byte3,}, - {Pos_ReadIndex8_UShort2, Pos_ReadIndex8_UShort3,}, - {Pos_ReadIndex8_Short2, Pos_ReadIndex8_Short3,}, - {Pos_ReadIndex8_Float2, Pos_ReadIndex8_Float3,}, + {Pos_ReadIndex, Pos_ReadIndex,}, + {Pos_ReadIndex, Pos_ReadIndex,}, + {Pos_ReadIndex, Pos_ReadIndex,}, + {Pos_ReadIndex, Pos_ReadIndex,}, + {Pos_ReadIndex, Pos_ReadIndex,}, }, { - {Pos_ReadIndex16_UByte2, Pos_ReadIndex16_UByte3,}, - {Pos_ReadIndex16_Byte2, Pos_ReadIndex16_Byte3,}, - {Pos_ReadIndex16_UShort2, Pos_ReadIndex16_UShort3,}, - {Pos_ReadIndex16_Short2, Pos_ReadIndex16_Short3,}, - {Pos_ReadIndex16_Float2, Pos_ReadIndex16_Float3,}, + {Pos_ReadIndex, Pos_ReadIndex,}, + {Pos_ReadIndex, Pos_ReadIndex,}, + {Pos_ReadIndex, Pos_ReadIndex,}, + {Pos_ReadIndex, Pos_ReadIndex,}, + {Pos_ReadIndex, Pos_ReadIndex,}, }, }; static int tableReadPositionVertexSize[4][8][2] = { { - {0, 0,}, - {0, 0,}, - {0, 0,}, - {0, 0,}, - {0, 0,}, + {0, 0,}, {0, 0,}, {0, 0,}, {0, 0,}, {0, 0,}, }, { - {2, 3,}, - {2, 3,}, - {4, 6,}, - {4, 6,}, - {8, 12,}, + {2, 3,}, {2, 3,}, {4, 6,}, {4, 6,}, {8, 12,}, }, { - {1, 1,}, - {1, 1,}, - {1, 1,}, - {1, 1,}, - {1, 1,}, + {1, 1,}, {1, 1,}, {1, 1,}, {1, 1,}, {1, 1,}, }, { - {2, 2,}, - {2, 2,}, - {2, 2,}, - {2, 2,}, - {2, 2,}, + {2, 2,}, {2, 2,}, {2, 2,}, {2, 2,}, {2, 2,}, }, }; @@ -322,10 +184,10 @@ void VertexLoader_Position::Init(void) { #if _M_SSE >= 0x301 if (cpu_info.bSSSE3) { - tableReadPosition[2][4][0] = Pos_ReadIndex8_Float2_SSSE3; - tableReadPosition[2][4][1] = Pos_ReadIndex8_Float3_SSSE3; - tableReadPosition[3][4][0] = Pos_ReadIndex16_Float2_SSSE3; - tableReadPosition[3][4][1] = Pos_ReadIndex16_Float3_SSSE3; + tableReadPosition[2][4][0] = Pos_ReadIndex_Float_SSSE3; + tableReadPosition[2][4][1] = Pos_ReadIndex_Float_SSSE3; + tableReadPosition[3][4][0] = Pos_ReadIndex_Float_SSSE3; + tableReadPosition[3][4][1] = Pos_ReadIndex_Float_SSSE3; } #endif diff --git a/Source/Core/VideoCommon/Src/VertexLoader_TextCoord.cpp b/Source/Core/VideoCommon/Src/VertexLoader_TextCoord.cpp index ba3bb73f43..4be24640b3 100644 --- a/Source/Core/VideoCommon/Src/VertexLoader_TextCoord.cpp +++ b/Source/Core/VideoCommon/Src/VertexLoader_TextCoord.cpp @@ -28,8 +28,22 @@ #include #endif -#define LOG_TEX1() // PRIM_LOG("tex: %f, ", ((float*)VertexManager::s_pCurBufferPointer)[0]); -#define LOG_TEX2() // PRIM_LOG("tex: %f %f, ", ((float*)VertexManager::s_pCurBufferPointer)[0], ((float*)VertexManager::s_pCurBufferPointer)[1]); +template +void LOG_TEX(); + +template <> +__forceinline void LOG_TEX<1>() +{ + // warning: mapping buffer should be disabled to use this + // PRIM_LOG("tex: %f, ", ((float*)VertexManager::s_pCurBufferPointer)[-1]); +} + +template <> +__forceinline void LOG_TEX<2>() +{ + // warning: mapping buffer should be disabled to use this + // PRIM_LOG("tex: %f %f, ", ((float*)VertexManager::s_pCurBufferPointer)[-2], ((float*)VertexManager::s_pCurBufferPointer)[-1]); +} extern int tcIndex; extern float tcScale[8]; @@ -39,279 +53,54 @@ void LOADERDECL TexCoord_Read_Dummy() tcIndex++; } -void LOADERDECL TexCoord_ReadDirect_UByte1() +template +float TCScale(T val) { - ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)DataReadU8() * tcScale[tcIndex]; - LOG_TEX1(); - VertexManager::s_pCurBufferPointer += 4; - tcIndex++; -} -void LOADERDECL TexCoord_ReadDirect_UByte2() -{ - ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)DataReadU8() * tcScale[tcIndex]; - ((float*)VertexManager::s_pCurBufferPointer)[1] = (float)DataReadU8() * tcScale[tcIndex]; - LOG_TEX2(); - VertexManager::s_pCurBufferPointer += 8; - tcIndex++; + return val * tcScale[tcIndex]; } -void LOADERDECL TexCoord_ReadDirect_Byte1() +template <> +float TCScale(float val) +{ return val; } + +template +void LOADERDECL TexCoord_ReadDirect() { - ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(s8)DataReadU8() * tcScale[tcIndex]; - LOG_TEX1(); - VertexManager::s_pCurBufferPointer += 4; - tcIndex++; -} -void LOADERDECL TexCoord_ReadDirect_Byte2() -{ - ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(s8)DataReadU8() * tcScale[tcIndex]; - ((float*)VertexManager::s_pCurBufferPointer)[1] = (float)(s8)DataReadU8() * tcScale[tcIndex]; - LOG_TEX2(); - VertexManager::s_pCurBufferPointer += 8; - tcIndex++; + for (int i = 0; i != N; ++i) + DataWrite(TCScale(DataRead())); + + LOG_TEX(); + + ++tcIndex; } -void LOADERDECL TexCoord_ReadDirect_UShort1() +template +void LOADERDECL TexCoord_ReadIndex() { - ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)DataReadU16() * tcScale[tcIndex]; - LOG_TEX1(); - VertexManager::s_pCurBufferPointer += 4; - tcIndex++; -} -void LOADERDECL TexCoord_ReadDirect_UShort2() -{ - ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)DataReadU16() * tcScale[tcIndex]; - ((float*)VertexManager::s_pCurBufferPointer)[1] = (float)DataReadU16() * tcScale[tcIndex]; - LOG_TEX2(); - VertexManager::s_pCurBufferPointer += 8; - tcIndex++; -} - -void LOADERDECL TexCoord_ReadDirect_Short1() -{ - ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(s16)DataReadU16() * tcScale[tcIndex]; - LOG_TEX1(); - VertexManager::s_pCurBufferPointer += 4; - tcIndex++; -} -void LOADERDECL TexCoord_ReadDirect_Short2() -{ - ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(s16)DataReadU16() * tcScale[tcIndex]; - ((float*)VertexManager::s_pCurBufferPointer)[1] = (float)(s16)DataReadU16() * tcScale[tcIndex]; - LOG_TEX2(); - VertexManager::s_pCurBufferPointer += 8; - tcIndex++; -} - -void LOADERDECL TexCoord_ReadDirect_Float1() -{ - ((u32*)VertexManager::s_pCurBufferPointer)[0] = DataReadU32(); - LOG_TEX1(); - VertexManager::s_pCurBufferPointer += 4; - tcIndex++; -} -void LOADERDECL TexCoord_ReadDirect_Float2() -{ - ((u32*)VertexManager::s_pCurBufferPointer)[0] = DataReadU32(); - ((u32*)VertexManager::s_pCurBufferPointer)[1] = DataReadU32(); - LOG_TEX2(); - VertexManager::s_pCurBufferPointer += 8; - tcIndex++; -} - -// ================================================================================== -void LOADERDECL TexCoord_ReadIndex8_UByte1() -{ - u8 Index = DataReadU8(); - const u8 *pData = cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]); - ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(*pData) * tcScale[tcIndex]; - LOG_TEX1(); - VertexManager::s_pCurBufferPointer += 4; - tcIndex++; -} -void LOADERDECL TexCoord_ReadIndex8_UByte2() -{ - u8 Index = DataReadU8(); - const u8 *pData = cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]); - ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(u8)(pData[0]) * tcScale[tcIndex]; - ((float*)VertexManager::s_pCurBufferPointer)[1] = (float)(u8)(pData[1]) * tcScale[tcIndex]; - LOG_TEX2(); - VertexManager::s_pCurBufferPointer += 8; - tcIndex++; -} - -void LOADERDECL TexCoord_ReadIndex8_Byte1() -{ - u8 Index = DataReadU8(); - const u8 *pData = cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]); - - ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(s8)(*pData) * tcScale[tcIndex]; - LOG_TEX1(); - VertexManager::s_pCurBufferPointer += 4; - tcIndex++; -} -void LOADERDECL TexCoord_ReadIndex8_Byte2() -{ - u8 Index = DataReadU8(); - const u8 *pData = cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]); - ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(s8)(pData[0]) * tcScale[tcIndex]; - ((float*)VertexManager::s_pCurBufferPointer)[1] = (float)(s8)(pData[1]) * tcScale[tcIndex]; - LOG_TEX2(); - VertexManager::s_pCurBufferPointer += 8; - tcIndex++; -} - -void LOADERDECL TexCoord_ReadIndex8_UShort1() -{ - u8 Index = DataReadU8(); - const u16 *pData = (const u16 *)(cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex])); - ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(u16)Common::swap16(*pData) * tcScale[tcIndex]; - LOG_TEX1(); - VertexManager::s_pCurBufferPointer += 4; - tcIndex++; -} -void LOADERDECL TexCoord_ReadIndex8_UShort2() -{ - u8 Index = DataReadU8(); - const u16 *pData = (const u16 *)(cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex])); - ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(u16)Common::swap16(pData[0]) * tcScale[tcIndex]; - ((float*)VertexManager::s_pCurBufferPointer)[1] = (float)(u16)Common::swap16(pData[1]) * tcScale[tcIndex]; - LOG_TEX2(); - VertexManager::s_pCurBufferPointer += 8; - tcIndex++; -} - -void LOADERDECL TexCoord_ReadIndex8_Short1() -{ - u8 Index = DataReadU8(); - const u16 *pData = (const u16 *)(cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex])); - ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(s16)Common::swap16(pData[0]) * tcScale[tcIndex]; - LOG_TEX1(); - VertexManager::s_pCurBufferPointer += 4; - tcIndex++; -} -void LOADERDECL TexCoord_ReadIndex8_Short2() -{ - u8 Index = DataReadU8(); - const u16 *pData = (const u16 *)(cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex])); - ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(s16)Common::swap16(pData[0]) * tcScale[tcIndex]; - ((float*)VertexManager::s_pCurBufferPointer)[1] = (float)(s16)Common::swap16(pData[1]) * tcScale[tcIndex]; - LOG_TEX2(); - VertexManager::s_pCurBufferPointer += 8; - tcIndex++; -} - -void LOADERDECL TexCoord_ReadIndex8_Float1() -{ - u16 Index = DataReadU8(); - const u32 *pData = (const u32 *)(cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex])); - ((u32*)VertexManager::s_pCurBufferPointer)[0] = Common::swap32(pData[0]); - LOG_TEX1(); - VertexManager::s_pCurBufferPointer += 4; - tcIndex++; -} -void LOADERDECL TexCoord_ReadIndex8_Float2() -{ - u16 Index = DataReadU8(); - const u32 *pData = (const u32 *)(cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex])); - ((u32*)VertexManager::s_pCurBufferPointer)[0] = Common::swap32(pData[0]); - ((u32*)VertexManager::s_pCurBufferPointer)[1] = Common::swap32(pData[1]); - LOG_TEX2(); - VertexManager::s_pCurBufferPointer += 8; - tcIndex++; -} - -// ================================================================================== -void LOADERDECL TexCoord_ReadIndex16_UByte1() -{ - u16 Index = DataReadU16(); - const u8 *pData = cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]); - ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(u8)(pData[0]) * tcScale[tcIndex]; - LOG_TEX1(); - VertexManager::s_pCurBufferPointer += 4; - tcIndex++; -} -void LOADERDECL TexCoord_ReadIndex16_UByte2() -{ - u16 Index = DataReadU16(); - const u8 *pData = cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]); - ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(u8)(pData[0]) * tcScale[tcIndex]; - ((float*)VertexManager::s_pCurBufferPointer)[1] = (float)(u8)(pData[1]) * tcScale[tcIndex]; - LOG_TEX2(); - VertexManager::s_pCurBufferPointer += 8; - tcIndex++; -} - -void LOADERDECL TexCoord_ReadIndex16_Byte1() -{ - u16 Index = DataReadU16(); - const u8 *pData = cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]); - ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(s8)(pData[0]) * tcScale[tcIndex]; - LOG_TEX1(); - VertexManager::s_pCurBufferPointer += 4; - tcIndex++; -} -void LOADERDECL TexCoord_ReadIndex16_Byte2() -{ - u16 Index = DataReadU16(); - const u8 *pData = cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]); - ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(s8)(pData[0]) * tcScale[tcIndex]; - ((float*)VertexManager::s_pCurBufferPointer)[1] = (float)(s8)(pData[1]) * tcScale[tcIndex]; - LOG_TEX2(); - VertexManager::s_pCurBufferPointer += 8; - tcIndex++; -} - -void LOADERDECL TexCoord_ReadIndex16_UShort1() -{ - u16 Index = DataReadU16(); - const u16* pData = (const u16 *)(cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex])); - ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(u16)Common::swap16(pData[0]) * tcScale[tcIndex]; - LOG_TEX1(); - VertexManager::s_pCurBufferPointer += 4; - tcIndex++; -} -void LOADERDECL TexCoord_ReadIndex16_UShort2() -{ - u16 Index = DataReadU16(); - const u16* pData = (const u16 *)(cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex])); - ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(u16)Common::swap16(pData[0]) * tcScale[tcIndex]; - ((float*)VertexManager::s_pCurBufferPointer)[1] = (float)(u16)Common::swap16(pData[1]) * tcScale[tcIndex]; - LOG_TEX2(); - VertexManager::s_pCurBufferPointer += 8; - tcIndex++; -} - -void LOADERDECL TexCoord_ReadIndex16_Short1() -{ - u16 Index = DataReadU16(); - const u16 *pData = (const u16 *)(cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex])); - ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(s16)Common::swap16(*pData) * tcScale[tcIndex]; - LOG_TEX1(); - VertexManager::s_pCurBufferPointer += 4; - tcIndex++; -} - -void LOADERDECL TexCoord_ReadIndex16_Short2() -{ - // Heavy in ZWW - u16 Index = DataReadU16(); - const u16 *pData = (const u16 *)(cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex])); - ((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(s16)Common::swap16(pData[0]) * tcScale[tcIndex]; - ((float*)VertexManager::s_pCurBufferPointer)[1] = (float)(s16)Common::swap16(pData[1]) * tcScale[tcIndex]; - LOG_TEX2(); - VertexManager::s_pCurBufferPointer += 8; - tcIndex++; + static_assert(!std::numeric_limits::is_signed, "Only unsigned I is sane!"); + + auto const index = DataRead(); + auto const data = reinterpret_cast(cached_arraybases[ARRAY_TEXCOORD0 + tcIndex] + + (index * arraystrides[ARRAY_TEXCOORD0 + tcIndex])); + + for (int i = 0; i != N; ++i) + DataWrite(TCScale(Common::FromBigEndian(data[i]))); + + LOG_TEX(); + ++tcIndex; } #if _M_SSE >= 0x401 static const __m128i kMaskSwap16_2 = _mm_set_epi32(0xFFFFFFFFL, 0xFFFFFFFFL, 0xFFFFFFFFL, 0x02030001L); -void LOADERDECL TexCoord_ReadIndex16_Short2_SSE4() +template +void LOADERDECL TexCoord_ReadIndex_Short2_SSE4() { + static_assert(!std::numeric_limits::is_signed, "Only unsigned I is sane!"); + // Heavy in ZWW - u16 Index = DataReadU16(); - const s32 *pData = (const s32*)(cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex])); + auto const index = DataRead(); + const s32 *pData = (const s32*)(cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (index * arraystrides[ARRAY_TEXCOORD0+tcIndex])); const __m128i a = _mm_cvtsi32_si128(*pData); const __m128i b = _mm_shuffle_epi8(a, kMaskSwap16_2); const __m128i c = _mm_cvtepi16_epi32(b); @@ -319,47 +108,27 @@ void LOADERDECL TexCoord_ReadIndex16_Short2_SSE4() const __m128 e = _mm_load1_ps(&tcScale[tcIndex]); const __m128 f = _mm_mul_ps(d, e); _mm_storeu_ps((float*)VertexManager::s_pCurBufferPointer, f); - LOG_TEX2(); - VertexManager::s_pCurBufferPointer += 8; + VertexManager::s_pCurBufferPointer += sizeof(float) * 2; + LOG_TEX<2>(); tcIndex++; } #endif -void LOADERDECL TexCoord_ReadIndex16_Float1() -{ - u16 Index = DataReadU16(); - const u32 *pData = (const u32 *)(cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex])); - ((u32*)VertexManager::s_pCurBufferPointer)[0] = Common::swap32(pData[0]); - LOG_TEX1(); - VertexManager::s_pCurBufferPointer += 4; - tcIndex++; -} - -void LOADERDECL TexCoord_ReadIndex16_Float2() -{ - u16 Index = DataReadU16(); - const u32 *pData = (const u32 *)(cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex])); - ((u32*)VertexManager::s_pCurBufferPointer)[0] = Common::swap32(pData[0]); - ((u32*)VertexManager::s_pCurBufferPointer)[1] = Common::swap32(pData[1]); - LOG_TEX2(); - VertexManager::s_pCurBufferPointer += 8; - tcIndex++; -} - #if _M_SSE >= 0x301 static const __m128i kMaskSwap32 = _mm_set_epi32(0xFFFFFFFFL, 0xFFFFFFFFL, 0x04050607L, 0x00010203L); -void LOADERDECL TexCoord_ReadIndex16_Float2_SSSE3() +template +void LOADERDECL TexCoord_ReadIndex_Float2_SSSE3() { - u16 Index = DataReadU16(); - const u32 *pData = (const u32 *)(cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex])); + static_assert(!std::numeric_limits::is_signed, "Only unsigned I is sane!"); + + auto const index = DataRead(); + const u32 *pData = (const u32 *)(cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (index * arraystrides[ARRAY_TEXCOORD0+tcIndex])); GC_ALIGNED128(const __m128i a = _mm_loadl_epi64((__m128i*)pData)); GC_ALIGNED128(const __m128i b = _mm_shuffle_epi8(a, kMaskSwap32)); - u8* p = VertexManager::s_pCurBufferPointer; - _mm_storel_epi64((__m128i*)p, b); - LOG_TEX2(); - p += 8; - VertexManager::s_pCurBufferPointer = p; + _mm_storel_epi64((__m128i*)VertexManager::s_pCurBufferPointer, b); + VertexManager::s_pCurBufferPointer += sizeof(float) * 2; + LOG_TEX<2>(); tcIndex++; } #endif @@ -373,56 +142,40 @@ static TPipelineFunction tableReadTexCoord[4][8][2] = { {NULL, NULL,}, }, { - {TexCoord_ReadDirect_UByte1, TexCoord_ReadDirect_UByte2,}, - {TexCoord_ReadDirect_Byte1, TexCoord_ReadDirect_Byte2,}, - {TexCoord_ReadDirect_UShort1, TexCoord_ReadDirect_UShort2,}, - {TexCoord_ReadDirect_Short1, TexCoord_ReadDirect_Short2,}, - {TexCoord_ReadDirect_Float1, TexCoord_ReadDirect_Float2,}, + {TexCoord_ReadDirect, TexCoord_ReadDirect,}, + {TexCoord_ReadDirect, TexCoord_ReadDirect,}, + {TexCoord_ReadDirect, TexCoord_ReadDirect,}, + {TexCoord_ReadDirect, TexCoord_ReadDirect,}, + {TexCoord_ReadDirect, TexCoord_ReadDirect,}, }, { - {TexCoord_ReadIndex8_UByte1, TexCoord_ReadIndex8_UByte2,}, - {TexCoord_ReadIndex8_Byte1, TexCoord_ReadIndex8_Byte2,}, - {TexCoord_ReadIndex8_UShort1, TexCoord_ReadIndex8_UShort2,}, - {TexCoord_ReadIndex8_Short1, TexCoord_ReadIndex8_Short2,}, - {TexCoord_ReadIndex8_Float1, TexCoord_ReadIndex8_Float2,}, + {TexCoord_ReadIndex, TexCoord_ReadIndex,}, + {TexCoord_ReadIndex, TexCoord_ReadIndex,}, + {TexCoord_ReadIndex, TexCoord_ReadIndex,}, + {TexCoord_ReadIndex, TexCoord_ReadIndex,}, + {TexCoord_ReadIndex, TexCoord_ReadIndex,}, }, { - {TexCoord_ReadIndex16_UByte1, TexCoord_ReadIndex16_UByte2,}, - {TexCoord_ReadIndex16_Byte1, TexCoord_ReadIndex16_Byte2,}, - {TexCoord_ReadIndex16_UShort1, TexCoord_ReadIndex16_UShort2,}, - {TexCoord_ReadIndex16_Short1, TexCoord_ReadIndex16_Short2,}, - {TexCoord_ReadIndex16_Float1, TexCoord_ReadIndex16_Float2,}, + {TexCoord_ReadIndex, TexCoord_ReadIndex,}, + {TexCoord_ReadIndex, TexCoord_ReadIndex,}, + {TexCoord_ReadIndex, TexCoord_ReadIndex,}, + {TexCoord_ReadIndex, TexCoord_ReadIndex,}, + {TexCoord_ReadIndex, TexCoord_ReadIndex,}, }, }; static int tableReadTexCoordVertexSize[4][8][2] = { { - {0, 0,}, - {0, 0,}, - {0, 0,}, - {0, 0,}, - {0, 0,}, + {0, 0,}, {0, 0,}, {0, 0,}, {0, 0,}, {0, 0,}, }, { - {1, 2,}, - {1, 2,}, - {2, 4,}, - {2, 4,}, - {4, 8,}, + {1, 2,}, {1, 2,}, {2, 4,}, {2, 4,}, {4, 8,}, }, { - {1, 1,}, - {1, 1,}, - {1, 1,}, - {1, 1,}, - {1, 1,}, + {1, 1,}, {1, 1,}, {1, 1,}, {1, 1,}, {1, 1,}, }, { - {2, 2,}, - {2, 2,}, - {2, 2,}, - {2, 2,}, - {2, 2,}, + {2, 2,}, {2, 2,}, {2, 2,}, {2, 2,}, {2, 2,}, }, }; @@ -430,16 +183,20 @@ void VertexLoader_TextCoord::Init(void) { #if _M_SSE >= 0x301 - if (cpu_info.bSSSE3) { - tableReadTexCoord[3][4][1] = TexCoord_ReadIndex16_Float2_SSSE3; + if (cpu_info.bSSSE3) + { + tableReadTexCoord[2][4][1] = TexCoord_ReadIndex_Float2_SSSE3; + tableReadTexCoord[3][4][1] = TexCoord_ReadIndex_Float2_SSSE3; } #endif #if _M_SSE >= 0x401 - if (cpu_info.bSSE4_1) { - tableReadTexCoord[3][3][1] = TexCoord_ReadIndex16_Short2_SSE4; + if (cpu_info.bSSE4_1) + { + tableReadTexCoord[2][3][1] = TexCoord_ReadIndex_Short2_SSE4; + tableReadTexCoord[3][3][1] = TexCoord_ReadIndex_Short2_SSE4; } #endif diff --git a/Source/Core/VideoCommon/Src/VertexManagerBase.cpp b/Source/Core/VideoCommon/Src/VertexManagerBase.cpp index bae5711e14..54830bcbea 100644 --- a/Source/Core/VideoCommon/Src/VertexManagerBase.cpp +++ b/Source/Core/VideoCommon/Src/VertexManagerBase.cpp @@ -12,174 +12,120 @@ #include "BPStructs.h" #include "VertexManagerBase.h" +#include "MainBase.h" #include "VideoConfig.h" VertexManager *g_vertex_manager; u8 *VertexManager::s_pCurBufferPointer; u8 *VertexManager::s_pBaseBufferPointer; - -u8 *VertexManager::LocalVBuffer; -u16 *VertexManager::TIBuffer; -u16 *VertexManager::LIBuffer; -u16 *VertexManager::PIBuffer; - -bool VertexManager::Flushed; +u8 *VertexManager::s_pEndBufferPointer; VertexManager::VertexManager() { - Flushed = false; + LocalVBuffer.resize(MAXVBUFFERSIZE); + s_pCurBufferPointer = s_pBaseBufferPointer = &LocalVBuffer[0]; + s_pEndBufferPointer = s_pBaseBufferPointer + LocalVBuffer.size(); - LocalVBuffer = new u8[MAXVBUFFERSIZE]; - s_pCurBufferPointer = s_pBaseBufferPointer = LocalVBuffer; + TIBuffer.resize(MAXIBUFFERSIZE); + LIBuffer.resize(MAXIBUFFERSIZE); + PIBuffer.resize(MAXIBUFFERSIZE); - TIBuffer = new u16[MAXIBUFFERSIZE]; - LIBuffer = new u16[MAXIBUFFERSIZE]; - PIBuffer = new u16[MAXIBUFFERSIZE]; - - IndexGenerator::Start(TIBuffer, LIBuffer, PIBuffer); -} - -void VertexManager::ResetBuffer() -{ - s_pCurBufferPointer = LocalVBuffer; -} - -VertexManager::~VertexManager() -{ - delete[] LocalVBuffer; - - delete[] TIBuffer; - delete[] LIBuffer; - delete[] PIBuffer; - - // TODO: necessary?? ResetBuffer(); } -void VertexManager::AddIndices(int primitive, int numVertices) -{ - //switch (primitive) - //{ - //case GX_DRAW_QUADS: IndexGenerator::AddQuads(numVertices); break; - //case GX_DRAW_TRIANGLES: IndexGenerator::AddList(numVertices); break; - //case GX_DRAW_TRIANGLE_STRIP: IndexGenerator::AddStrip(numVertices); break; - //case GX_DRAW_TRIANGLE_FAN: IndexGenerator::AddFan(numVertices); break; - //case GX_DRAW_LINES: IndexGenerator::AddLineList(numVertices); break; - //case GX_DRAW_LINE_STRIP: IndexGenerator::AddLineStrip(numVertices); break; - //case GX_DRAW_POINTS: IndexGenerator::AddPoints(numVertices); break; - //} +VertexManager::~VertexManager() +{} - static void (*const primitive_table[])(int) = +void VertexManager::ResetBuffer() +{ + s_pCurBufferPointer = s_pBaseBufferPointer; + IndexGenerator::Start(GetTriangleIndexBuffer(), GetLineIndexBuffer(), GetPointIndexBuffer()); +} + +u32 VertexManager::GetRemainingSize() +{ + return (u32)(s_pEndBufferPointer - s_pCurBufferPointer); +} + +void VertexManager::PrepareForAdditionalData(int primitive, u32 count, u32 stride) +{ + u32 const needed_vertex_bytes = count * stride; + + if (needed_vertex_bytes > GetRemainingSize() || count > GetRemainingIndices(primitive)) { - IndexGenerator::AddQuads, - NULL, - IndexGenerator::AddList, - IndexGenerator::AddStrip, - IndexGenerator::AddFan, - IndexGenerator::AddLineList, - IndexGenerator::AddLineStrip, - IndexGenerator::AddPoints, - }; - - primitive_table[primitive](numVertices); + Flush(); + + if (needed_vertex_bytes > GetRemainingSize()) + ERROR_LOG(VIDEO, "VertexManager: Buffer not large enough for all vertices! " + "Increase MAXVBUFFERSIZE or we need primitive breaking afterall."); + if (count > GetRemainingIndices(primitive)) + ERROR_LOG(VIDEO, "VertexManager: Buffer not large enough for all indices! " + "Increase MAXIBUFFERSIZE or we need primitive breaking afterall."); + } } -int VertexManager::GetRemainingSize() +bool VertexManager::IsFlushed() const { - return MAXVBUFFERSIZE - (int)(s_pCurBufferPointer - LocalVBuffer); + return s_pBaseBufferPointer == s_pCurBufferPointer; } -int VertexManager::GetRemainingVertices(int primitive) +u32 VertexManager::GetRemainingIndices(int primitive) { switch (primitive) { case GX_DRAW_QUADS: + return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()) / 6 * 4; case GX_DRAW_TRIANGLES: + return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()); case GX_DRAW_TRIANGLE_STRIP: + return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()) / 3 + 2; case GX_DRAW_TRIANGLE_FAN: - return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()) / 3; - break; + return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()) / 3 + 2; case GX_DRAW_LINES: + return (MAXIBUFFERSIZE - IndexGenerator::GetLineindexLen()); case GX_DRAW_LINE_STRIP: - return (MAXIBUFFERSIZE - IndexGenerator::GetLineindexLen()) / 2; - break; + return (MAXIBUFFERSIZE - IndexGenerator::GetLineindexLen()) / 2 + 1; case GX_DRAW_POINTS: return (MAXIBUFFERSIZE - IndexGenerator::GetPointindexLen()); - break; default: return 0; - break; } } -void VertexManager::AddVertices(int primitive, int numVertices) +void VertexManager::AddVertices(int primitive, u32 numVertices) { if (numVertices <= 0) return; - switch (primitive) - { - case GX_DRAW_QUADS: - case GX_DRAW_TRIANGLES: - case GX_DRAW_TRIANGLE_STRIP: - case GX_DRAW_TRIANGLE_FAN: - if (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen() < 3 * numVertices) - Flush(); - break; - - case GX_DRAW_LINES: - case GX_DRAW_LINE_STRIP: - if (MAXIBUFFERSIZE - IndexGenerator::GetLineindexLen() < 2 * numVertices) - Flush(); - break; - - case GX_DRAW_POINTS: - if (MAXIBUFFERSIZE - IndexGenerator::GetPointindexLen() < numVertices) - Flush(); - break; - - default: - return; - break; - } - - if (Flushed) - { - IndexGenerator::Start(TIBuffer, LIBuffer, PIBuffer); - Flushed = false; - } - ADDSTAT(stats.thisFrame.numPrims, numVertices); INCSTAT(stats.thisFrame.numPrimitiveJoins); - AddIndices(primitive, numVertices); + + IndexGenerator::AddIndices(primitive, numVertices); } void VertexManager::Flush() { + if (g_vertex_manager->IsFlushed()) + return; + // loading a state will invalidate BP, so check for it g_video_backend->CheckInvalidState(); - if (LocalVBuffer == s_pCurBufferPointer) return; - if (Flushed) return; - Flushed = true; + VideoFifo_CheckEFBAccess(); + g_vertex_manager->vFlush(); + + g_vertex_manager->ResetBuffer(); } // TODO: need to merge more stuff into VideoCommon to use this #if (0) void VertexManager::Flush() { - if (LocalVBuffer == s_pCurBufferPointer || Flushed) - return; - - Flushed = true; - - VideoFifo_CheckEFBAccess(); - #if defined(_DEBUG) || defined(DEBUGFAST) PRIM_LOG("frame%d:\n texgen=%d, numchan=%d, dualtex=%d, ztex=%d, cole=%d, alpe=%d, ze=%d", g_ActiveConfig.iSaveTargetId, xfregs.numTexGens, xfregs.nNumChans, (int)xfregs.bEnableDualTexTransform, bpmem.ztex2.op, @@ -252,21 +198,23 @@ void VertexManager::Flush() // finally bind if (false == PixelShaderCache::SetShader(false, g_nativeVertexFmt->m_components)) - goto shader_fail; + return; if (false == VertexShaderCache::SetShader(g_nativeVertexFmt->m_components)) - goto shader_fail; + return; const int stride = g_nativeVertexFmt->GetVertexStride(); //if (g_nativeVertexFmt) g_nativeVertexFmt->SetupVertexPointers(); + g_renderer->ResumePixelPerf(false); g_vertex_manager->Draw(stride, false); + g_renderer->PausePixelPerf(false); // run through vertex groups again to set alpha if (false == g_ActiveConfig.bDstAlphaPass && bpmem.dstalpha.enable && bpmem.blendmode.alphaupdate) { if (false == PixelShaderCache::SetShader(true, g_nativeVertexFmt->m_components)) - goto shader_fail; + return; g_vertex_manager->Draw(stride, true); } @@ -280,10 +228,12 @@ void VertexManager::Flush() // save the shaders char strfile[255]; sprintf(strfile, "%sps%.3d.txt", File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), g_ActiveConfig.iSaveTargetId); - std::ofstream fps(strfile); + std::ofstream fps; + OpenFStream(fps, strfile, std::ios_base::out); fps << ps->strprog.c_str(); sprintf(strfile, "%svs%.3d.txt", File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), g_ActiveConfig.iSaveTargetId); - std::ofstream fvs(strfile); + std::ofstream fvs; + OpenFStream(fvs, strfile, std::ios_base::out); fvs << vs->strprog.c_str(); } @@ -300,9 +250,6 @@ void VertexManager::Flush() } #endif ++g_Config.iSaveTargetId; - -shader_fail: - ResetBuffer(); } #endif @@ -313,12 +260,16 @@ void VertexManager::DoState(PointerWrap& p) void VertexManager::DoStateShared(PointerWrap& p) { - p.DoPointer(s_pCurBufferPointer, LocalVBuffer); - p.DoArray(LocalVBuffer, MAXVBUFFERSIZE); - p.DoArray(TIBuffer, MAXIBUFFERSIZE); - p.DoArray(LIBuffer, MAXIBUFFERSIZE); - p.DoArray(PIBuffer, MAXIBUFFERSIZE); - - if (p.GetMode() == PointerWrap::MODE_READ) - Flushed = false; + // It seems we half-assume to be flushed here + // We update s_pCurBufferPointer yet don't worry about IndexGenerator's outdated pointers + // and maybe other things are overlooked + + p.Do(LocalVBuffer); + p.Do(TIBuffer); + p.Do(LIBuffer); + p.Do(PIBuffer); + + s_pBaseBufferPointer = &LocalVBuffer[0]; + s_pEndBufferPointer = s_pBaseBufferPointer + LocalVBuffer.size(); + p.DoPointer(s_pCurBufferPointer, s_pBaseBufferPointer); } diff --git a/Source/Core/VideoCommon/Src/VertexManagerBase.h b/Source/Core/VideoCommon/Src/VertexManagerBase.h index f3a4aa72e3..2690ffc03e 100644 --- a/Source/Core/VideoCommon/Src/VertexManagerBase.h +++ b/Source/Core/VideoCommon/Src/VertexManagerBase.h @@ -2,72 +2,70 @@ #ifndef _VERTEXMANAGERBASE_H #define _VERTEXMANAGERBASE_H +#include + class NativeVertexFormat; class PointerWrap; class VertexManager { +private: + // What are the actual values? + static const u32 SMALLEST_POSSIBLE_VERTEX = 1; + static const u32 LARGEST_POSSIBLE_VERTEX = 188; + + static const u32 MAX_PRIMITIVES_PER_COMMAND = (u16)-1; + public: - - enum - { - // values from OGL backend - //MAXVBUFFERSIZE = 0x1FFFF, - //MAXIBUFFERSIZE = 0xFFFF, - - // values from DX9 backend - //MAXVBUFFERSIZE = 0x50000, - //MAXIBUFFERSIZE = 0xFFFF, - - // values from DX11 backend - MAXVBUFFERSIZE = 0x50000, - MAXIBUFFERSIZE = 0xFFFF, - }; + static const u32 MAXVBUFFERSIZE = MAX_PRIMITIVES_PER_COMMAND * LARGEST_POSSIBLE_VERTEX; + + // We may convert triangle-fans to triangle-lists, almost 3x as many indices. + static const u32 MAXIBUFFERSIZE = MAX_PRIMITIVES_PER_COMMAND * 3; VertexManager(); - virtual ~VertexManager(); // needs to be virtual for DX11's dtor + // needs to be virtual for DX11's dtor + virtual ~VertexManager(); - static void AddVertices(int _primitive, int _numVertices); + static void AddVertices(int _primitive, u32 _numVertices); - // TODO: protected? static u8 *s_pCurBufferPointer; static u8 *s_pBaseBufferPointer; + static u8 *s_pEndBufferPointer; - static int GetRemainingSize(); - static int GetRemainingVertices(int primitive); + static u32 GetRemainingSize(); + static void PrepareForAdditionalData(int primitive, u32 count, u32 stride); + static u32 GetRemainingIndices(int primitive); static void Flush(); virtual ::NativeVertexFormat* CreateNativeVertexFormat() = 0; - static u16* GetTriangleIndexBuffer() { return TIBuffer; } - static u16* GetLineIndexBuffer() { return LIBuffer; } - static u16* GetPointIndexBuffer() { return PIBuffer; } - static u8* GetVertexBuffer() { return LocalVBuffer; } - static void DoState(PointerWrap& p); virtual void CreateDeviceObjects(){}; virtual void DestroyDeviceObjects(){}; + protected: - // TODO: make private after Flush() is merged - static void ResetBuffer(); - - static u8 *LocalVBuffer; - static u16 *TIBuffer; - static u16 *LIBuffer; - static u16 *PIBuffer; - - static bool Flushed; + u16* GetTriangleIndexBuffer() { return &TIBuffer[0]; } + u16* GetLineIndexBuffer() { return &LIBuffer[0]; } + u16* GetPointIndexBuffer() { return &PIBuffer[0]; } + u8* GetVertexBuffer() { return &s_pBaseBufferPointer[0]; } virtual void vDoState(PointerWrap& p) { DoStateShared(p); } void DoStateShared(PointerWrap& p); private: - static void AddIndices(int primitive, int numVertices); + bool IsFlushed() const; + + void ResetBuffer(); + //virtual void Draw(u32 stride, bool alphapass) = 0; // temp virtual void vFlush() = 0; - + + std::vector LocalVBuffer; + std::vector TIBuffer; + std::vector LIBuffer; + std::vector PIBuffer; }; extern VertexManager *g_vertex_manager; diff --git a/Source/Core/VideoCommon/Src/VertexShaderGen.cpp b/Source/Core/VideoCommon/Src/VertexShaderGen.cpp index a657a68b2d..4b9dba4f7a 100644 --- a/Source/Core/VideoCommon/Src/VertexShaderGen.cpp +++ b/Source/Core/VideoCommon/Src/VertexShaderGen.cpp @@ -114,7 +114,8 @@ void ValidateVertexShaderIDs(API_TYPE api, VERTEXSHADERUIDSAFE old_id, const std static int num_failures = 0; char szTemp[MAX_PATH]; sprintf(szTemp, "%svsuid_mismatch_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), num_failures++); - std::ofstream file(szTemp); + std::ofstream file; + OpenFStream(file, szTemp, std::ios_base::out); file << msg; file << "\n\nOld shader code:\n" << old_code; file << "\n\nNew shader code:\n" << new_code; @@ -515,7 +516,6 @@ const char *GenerateVertexShaderCode(u32 components, API_TYPE ApiType) //write the true depth value, if the game uses depth textures pixel shaders will override with the correct values //if not early z culling will improve speed - // TODO: Can probably be dropped? if (is_d3d) { WRITE(p, "o.pos.z = " I_DEPTHPARAMS".x * o.pos.w + o.pos.z * " I_DEPTHPARAMS".y;\n"); diff --git a/Source/Core/VideoCommon/Src/VideoCommon.h b/Source/Core/VideoCommon/Src/VideoCommon.h index a1b72c9284..bf83235591 100644 --- a/Source/Core/VideoCommon/Src/VideoCommon.h +++ b/Source/Core/VideoCommon/Src/VideoCommon.h @@ -90,8 +90,8 @@ struct TargetRectangle : public MathUtil::Rectangle #define PRIM_LOG(...) DEBUG_LOG(VIDEO, ##__VA_ARGS__) #endif - -// #define LOG_VTX() DEBUG_LOG(VIDEO, "vtx: %f %f %f, ", ((float*)VertexManager::s_pCurBufferPointer)[0], ((float*)VertexManager::s_pCurBufferPointer)[1], ((float*)VertexManager::s_pCurBufferPointer)[2]); +// warning: mapping buffer should be disabled to use this +// #define LOG_VTX() DEBUG_LOG(VIDEO, "vtx: %f %f %f, ", ((float*)VertexManager::s_pCurBufferPointer)[-3], ((float*)VertexManager::s_pCurBufferPointer)[-2], ((float*)VertexManager::s_pCurBufferPointer)[-1]); #define LOG_VTX() diff --git a/Source/Core/VideoCommon/Src/VideoConfig.cpp b/Source/Core/VideoCommon/Src/VideoConfig.cpp index 157b4a547e..3606d6944b 100644 --- a/Source/Core/VideoCommon/Src/VideoConfig.cpp +++ b/Source/Core/VideoCommon/Src/VideoConfig.cpp @@ -42,6 +42,7 @@ VideoConfig::VideoConfig() // disable all features by default backend_info.APIType = API_NONE; backend_info.bUseRGBATextures = false; + backend_info.bUseMinimalMipCount = false; backend_info.bSupports3DVision = false; } diff --git a/Source/Core/VideoCommon/Src/VideoConfig.h b/Source/Core/VideoCommon/Src/VideoConfig.h index 4b739fa222..d99e8c974e 100644 --- a/Source/Core/VideoCommon/Src/VideoConfig.h +++ b/Source/Core/VideoCommon/Src/VideoConfig.h @@ -115,7 +115,7 @@ struct VideoConfig int iAnaglyphStereoSeparation; int iAnaglyphFocalAngle; bool b3DVision; - + // Hacks bool bEFBAccessEnable; bool bDlistCachingEnable; @@ -158,6 +158,7 @@ struct VideoConfig std::vector PPShaders; // post-processing shaders bool bUseRGBATextures; // used for D3D11 in TextureCache + bool bUseMinimalMipCount; bool bSupports3DVision; bool bSupportsDualSourceBlend; // only supported by D3D11 and OpenGL bool bSupportsFormatReinterpretation; diff --git a/Source/Core/VideoCommon/Src/DLCache.cpp b/Source/Core/VideoCommon/Src/x64DLCache.cpp similarity index 99% rename from Source/Core/VideoCommon/Src/DLCache.cpp rename to Source/Core/VideoCommon/Src/x64DLCache.cpp index c828ea3a03..6033981759 100644 --- a/Source/Core/VideoCommon/Src/DLCache.cpp +++ b/Source/Core/VideoCommon/Src/x64DLCache.cpp @@ -35,7 +35,7 @@ #include "VertexLoaderManager.h" #include "VertexManagerBase.h" #include "x64Emitter.h" -#include "ABI.h" +#include "x64ABI.h" #include "DLCache.h" #include "VideoConfig.h" @@ -550,8 +550,7 @@ void CompileAndRunDisplayList(u32 address, u32 size, CachedDisplayList *dl) cmd_byte & GX_VAT_MASK, // Vertex loader index (0 - 7) (cmd_byte & GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT, numVertices); - u8* EndAddress = VertexManager::s_pCurBufferPointer; - u32 Vdatasize = (u32)(EndAddress - StartAddress); + u32 Vdatasize = (u32)(VertexManager::s_pCurBufferPointer - StartAddress); if (Vdatasize > 0) { // Compile diff --git a/Source/Core/VideoCommon/Src/TextureDecoder.cpp b/Source/Core/VideoCommon/Src/x64TextureDecoder.cpp similarity index 97% rename from Source/Core/VideoCommon/Src/TextureDecoder.cpp rename to Source/Core/VideoCommon/Src/x64TextureDecoder.cpp index 30df817902..6c474920cd 100644 --- a/Source/Core/VideoCommon/Src/TextureDecoder.cpp +++ b/Source/Core/VideoCommon/Src/x64TextureDecoder.cpp @@ -1119,20 +1119,6 @@ PC_TexFormat TexDecoder_Decode_RGBA(u32 * dst, const u8 * src, int width, int he _mm_storeu_si128( (__m128i*)( dst+(y + iy+1) * width + x + 4 ), o4 ); } } -#if 0 - // Reference C implementation: - for (int y = 0; y < height; y += 8) - for (int x = 0; x < width; x += 8) - for (int iy = 0; iy < 8; iy++, src += 4) - for (int ix = 0; ix < 4; ix++) - { - int val = src[ix]; - u8 i1 = Convert4To8(val >> 4); - u8 i2 = Convert4To8(val & 0xF); - memset(dst+(y + iy) * width + x + ix * 2 , i1,4); - memset(dst+(y + iy) * width + x + ix * 2 + 1 , i2,4); - } -#endif } break; case GX_TF_I8: // speed critical @@ -1248,26 +1234,6 @@ PC_TexFormat TexDecoder_Decode_RGBA(u32 * dst, const u8 * src, int width, int he } } -#if 0 - // Reference C implementation - for (int y = 0; y < height; y += 4) - for (int x = 0; x < width; x += 8) - for (int iy = 0; iy < 4; ++iy, src += 8) - { - u32 * newdst = dst + (y + iy)*width+x; - const u8 * newsrc = src; - u8 srcval; - - srcval = (newsrc++)[0]; (newdst++)[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24); - srcval = (newsrc++)[0]; (newdst++)[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24); - srcval = (newsrc++)[0]; (newdst++)[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24); - srcval = (newsrc++)[0]; (newdst++)[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24); - srcval = (newsrc++)[0]; (newdst++)[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24); - srcval = (newsrc++)[0]; (newdst++)[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24); - srcval = (newsrc++)[0]; (newdst++)[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24); - srcval = newsrc[0]; newdst[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24); - } -#endif } break; case GX_TF_C8: @@ -1380,20 +1346,6 @@ PC_TexFormat TexDecoder_Decode_RGBA(u32 * dst, const u8 * src, int width, int he _mm_storeu_si128( (__m128i*)(dst + (y + iy) * width + x), r1 ); } } -#if 0 - // Reference C implementation: - for (int y = 0; y < height; y += 4) - for (int x = 0; x < width; x += 4) - for (int iy = 0; iy < 4; iy++, src += 8) - { - u32 *ptr = dst + (y + iy) * width + x; - u16 *s = (u16 *)src; - ptr[0] = decodeIA8Swapped(s[0]); - ptr[1] = decodeIA8Swapped(s[1]); - ptr[2] = decodeIA8Swapped(s[2]); - ptr[3] = decodeIA8Swapped(s[3]); - } -#endif } break; case GX_TF_C14X2: @@ -1493,18 +1445,6 @@ PC_TexFormat TexDecoder_Decode_RGBA(u32 * dst, const u8 * src, int width, int he __m128i *ptr = (__m128i *)(dst + (y + iy) * width + x); _mm_storeu_si128(ptr, abgr888x4); } -#if 0 - // Reference C implementation. - for (int y = 0; y < height; y += 4) - for (int x = 0; x < width; x += 4) - for (int iy = 0; iy < 4; iy++, src += 8) - { - u32 *ptr = dst + (y + iy) * width + x; - u16 *s = (u16 *)src; - for(int j = 0; j < 4; j++) - *ptr++ = decode565RGBA(Common::swap16(*s++)); - } -#endif } break; case GX_TF_RGB5A3: @@ -1718,13 +1658,6 @@ PC_TexFormat TexDecoder_Decode_RGBA(u32 * dst, const u8 * src, int width, int he } } } -#if 0 - // Reference C implementation: - for (int y = 0; y < height; y += 4) - for (int x = 0; x < width; x += 4) - for (int iy = 0; iy < 4; iy++, src += 8) - decodebytesRGB5A3rgba(dst+(y+iy)*width+x, (u16*)src); -#endif } break; case GX_TF_RGBA8: // speed critical @@ -1860,16 +1793,6 @@ PC_TexFormat TexDecoder_Decode_RGBA(u32 * dst, const u8 * src, int width, int he _mm_storeu_si128(dst128, rgba11); } } -#if 0 - // Reference C implementation. - for (int y = 0; y < height; y += 4) - for (int x = 0; x < width; x += 4) - { - for (int iy = 0; iy < 4; iy++) - decodebytesARGB8_4ToRgba(dst + (y+iy)*width + x, (u16*)src + 4 * iy, (u16*)src + 4 * iy + 16); - src += 64; - } -#endif } break; case GX_TF_CMPR: // speed critical @@ -2104,22 +2027,6 @@ PC_TexFormat TexDecoder_Decode_RGBA(u32 * dst, const u8 * src, int width, int he } } } -#if 0 - for (int y = 0; y < height; y += 8) - { - for (int x = 0; x < width; x += 8) - { - decodeDXTBlockRGBA((u32*)dst + y * width + x, (DXTBlock*)src, width); - src += sizeof(DXTBlock); - decodeDXTBlockRGBA((u32*)dst + y * width + x + 4, (DXTBlock*)src, width); - src += sizeof(DXTBlock); - decodeDXTBlockRGBA((u32*)dst + (y + 4) * width + x, (DXTBlock*)src, width); - src += sizeof(DXTBlock); - decodeDXTBlockRGBA((u32*)dst + (y + 4) * width + x + 4, (DXTBlock*)src, width); - src += sizeof(DXTBlock); - } - } -#endif break; } } diff --git a/Source/Core/VideoCommon/VideoCommon.vcxproj b/Source/Core/VideoCommon/VideoCommon.vcxproj index bf9122e6b5..f785cb5c84 100644 --- a/Source/Core/VideoCommon/VideoCommon.vcxproj +++ b/Source/Core/VideoCommon/VideoCommon.vcxproj @@ -111,8 +111,8 @@ ..\Common\Src;..\Core\Src;..\..\..\Externals\SOIL;..\..\..\Externals\CLRun\include;%(AdditionalIncludeDirectories) - false - + false + true @@ -143,7 +143,7 @@ ..\Common\Src;..\Core\Src;..\..\..\Externals\SOIL;..\..\..\Externals\CLRun\include;%(AdditionalIncludeDirectories) false - + true true @@ -182,7 +182,6 @@ - @@ -197,6 +196,7 @@ + @@ -204,7 +204,6 @@ - @@ -216,6 +215,8 @@ + + @@ -244,6 +245,7 @@ + diff --git a/Source/Core/VideoCommon/VideoCommon.vcxproj.filters b/Source/Core/VideoCommon/VideoCommon.vcxproj.filters index e7019f17ed..330b23d370 100644 --- a/Source/Core/VideoCommon/VideoCommon.vcxproj.filters +++ b/Source/Core/VideoCommon/VideoCommon.vcxproj.filters @@ -5,9 +5,6 @@ - - Vertex Loading - Vertex Loading @@ -92,9 +89,6 @@ Decoding - - Decoding - Base @@ -107,6 +101,9 @@ Base + + Base + Base @@ -122,6 +119,12 @@ Util + + Decoding + + + Vertex Loading + @@ -237,6 +240,9 @@ Base + + Base + Base @@ -285,4 +291,4 @@ {e2a527a2-ccc8-4ab8-a93e-dd2628c0f3b6} - \ No newline at end of file + diff --git a/Source/Plugins/Plugin_VideoDX11/Plugin_VideoDX11.vcxproj b/Source/Plugins/Plugin_VideoDX11/Plugin_VideoDX11.vcxproj index 52d1c37aed..aab9345ef7 100644 --- a/Source/Plugins/Plugin_VideoDX11/Plugin_VideoDX11.vcxproj +++ b/Source/Plugins/Plugin_VideoDX11/Plugin_VideoDX11.vcxproj @@ -199,6 +199,7 @@ + @@ -228,6 +229,7 @@ + diff --git a/Source/Plugins/Plugin_VideoDX11/Plugin_VideoDX11.vcxproj.filters b/Source/Plugins/Plugin_VideoDX11/Plugin_VideoDX11.vcxproj.filters index 6492e887ca..4b8efac92b 100644 --- a/Source/Plugins/Plugin_VideoDX11/Plugin_VideoDX11.vcxproj.filters +++ b/Source/Plugins/Plugin_VideoDX11/Plugin_VideoDX11.vcxproj.filters @@ -57,6 +57,9 @@ Render + + Render + @@ -117,6 +120,9 @@ Render + + Render + diff --git a/Source/Plugins/Plugin_VideoDX11/Src/D3DShader.cpp b/Source/Plugins/Plugin_VideoDX11/Src/D3DShader.cpp index 41e5423990..c688228945 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/D3DShader.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/D3DShader.cpp @@ -64,7 +64,8 @@ bool CompileVertexShader(const char* code, unsigned int len, D3DBlob** blob) static int num_failures = 0; char szTemp[MAX_PATH]; sprintf(szTemp, "%sbad_vs_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), num_failures++); - std::ofstream file(szTemp); + std::ofstream file; + OpenFStream(file, szTemp, std::ios_base::out); file << code; file.close(); @@ -121,7 +122,8 @@ bool CompileGeometryShader(const char* code, unsigned int len, D3DBlob** blob, static int num_failures = 0; char szTemp[MAX_PATH]; sprintf(szTemp, "%sbad_gs_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), num_failures++); - std::ofstream file(szTemp); + std::ofstream file; + OpenFStream(file, szTemp, std::ios_base::out); file << code; file.close(); @@ -180,7 +182,8 @@ bool CompilePixelShader(const char* code, unsigned int len, D3DBlob** blob, static int num_failures = 0; char szTemp[MAX_PATH]; sprintf(szTemp, "%sbad_ps_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), num_failures++); - std::ofstream file(szTemp); + std::ofstream file; + OpenFStream(file, szTemp, std::ios_base::out); file << code; file.close(); diff --git a/Source/Plugins/Plugin_VideoDX11/Src/PerfQuery.cpp b/Source/Plugins/Plugin_VideoDX11/Src/PerfQuery.cpp new file mode 100644 index 0000000000..b859d50ec6 --- /dev/null +++ b/Source/Plugins/Plugin_VideoDX11/Src/PerfQuery.cpp @@ -0,0 +1,150 @@ +#include "RenderBase.h" + +#include "D3DBase.h" +#include "PerfQuery.h" + +namespace DX11 { + +PerfQuery::PerfQuery() + : m_query_read_pos() + , m_query_count() +{ + for (int i = 0; i != ARRAYSIZE(m_query_buffer); ++i) + { + D3D11_QUERY_DESC qdesc = CD3D11_QUERY_DESC(D3D11_QUERY_OCCLUSION, 0); + D3D::device->CreateQuery(&qdesc, &m_query_buffer[i].query); + } + ResetQuery(); +} + +PerfQuery::~PerfQuery() +{ + for (int i = 0; i != ARRAYSIZE(m_query_buffer); ++i) + { + // TODO: EndQuery? + m_query_buffer[i].query->Release(); + } +} + +void PerfQuery::EnableQuery(PerfQueryGroup type) +{ + // Is this sane? + if (m_query_count > ARRAYSIZE(m_query_buffer) / 2) + WeakFlush(); + + if (ARRAYSIZE(m_query_buffer) == m_query_count) + { + // TODO + FlushOne(); + ERROR_LOG(VIDEO, "flushed query buffer early!"); + } + + // start query + if (type == PQG_ZCOMP_ZCOMPLOC || type == PQG_ZCOMP) + { + auto& entry = m_query_buffer[(m_query_read_pos + m_query_count) % ARRAYSIZE(m_query_buffer)]; + + D3D::context->Begin(entry.query); + entry.query_type = type; + + ++m_query_count; + } +} + +void PerfQuery::DisableQuery(PerfQueryGroup type) +{ + // stop query + if (type == PQG_ZCOMP_ZCOMPLOC || type == PQG_ZCOMP) + { + auto& entry = m_query_buffer[(m_query_read_pos + m_query_count + ARRAYSIZE(m_query_buffer)-1) % ARRAYSIZE(m_query_buffer)]; + D3D::context->End(entry.query); + } +} + +void PerfQuery::ResetQuery() +{ + m_query_count = 0; + std::fill_n(m_results, ARRAYSIZE(m_results), 0); +} + +u32 PerfQuery::GetQueryResult(PerfQueryType type) +{ + u32 result = 0; + + if (type == PQ_ZCOMP_INPUT_ZCOMPLOC || type == PQ_ZCOMP_OUTPUT_ZCOMPLOC) + { + result = m_results[PQG_ZCOMP_ZCOMPLOC]; + } + else if (type == PQ_ZCOMP_INPUT || type == PQ_ZCOMP_OUTPUT) + { + result = m_results[PQG_ZCOMP]; + } + else if (type == PQ_BLEND_INPUT) + { + result = m_results[PQG_ZCOMP] + m_results[PQG_ZCOMP_ZCOMPLOC]; + } + else if (type == PQ_EFB_COPY_CLOCKS) + { + result = m_results[PQG_EFB_COPY_CLOCKS]; + } + + return result / 4; +} + +void PerfQuery::FlushOne() +{ + auto& entry = m_query_buffer[m_query_read_pos]; + + UINT64 result = 0; + HRESULT hr = S_FALSE; + while (hr != S_OK) + { + // TODO: Might cause us to be stuck in an infinite loop! + hr = D3D::context->GetData(entry.query, &result, sizeof(result), 0); + } + + // NOTE: Reported pixel metrics should be referenced to native resolution + m_results[entry.query_type] += (u64)result * EFB_WIDTH / g_renderer->GetTargetWidth() * EFB_HEIGHT / g_renderer->GetTargetHeight(); + + m_query_read_pos = (m_query_read_pos + 1) % ARRAYSIZE(m_query_buffer); + --m_query_count; +} + +// TODO: could selectively flush things, but I don't think that will do much +void PerfQuery::FlushResults() +{ + while (!IsFlushed()) + FlushOne(); +} + +void PerfQuery::WeakFlush() +{ + while (!IsFlushed()) + { + auto& entry = m_query_buffer[m_query_read_pos]; + + UINT64 result = 0; + HRESULT hr = D3D::context->GetData(entry.query, &result, sizeof(result), D3D11_ASYNC_GETDATA_DONOTFLUSH); + + if (hr == S_OK) + { + // NOTE: Reported pixel metrics should be referenced to native resolution + m_results[entry.query_type] += (u64)result * EFB_WIDTH / g_renderer->GetTargetWidth() * EFB_HEIGHT / g_renderer->GetTargetHeight(); + + m_query_read_pos = (m_query_read_pos + 1) % ARRAYSIZE(m_query_buffer); + --m_query_count; + } + else + { + break; + } + } +} + +bool PerfQuery::IsFlushed() const +{ + return 0 == m_query_count; +} + + +} // namespace diff --git a/Source/Plugins/Plugin_VideoDX11/Src/PerfQuery.h b/Source/Plugins/Plugin_VideoDX11/Src/PerfQuery.h new file mode 100644 index 0000000000..b3709d1013 --- /dev/null +++ b/Source/Plugins/Plugin_VideoDX11/Src/PerfQuery.h @@ -0,0 +1,46 @@ +#ifndef _PERFQUERY_H_ +#define _PERFQUERY_H_ + +#include "PerfQueryBase.h" + +namespace DX11 { + +class PerfQuery : public PerfQueryBase +{ +public: + PerfQuery(); + ~PerfQuery(); + + void EnableQuery(PerfQueryGroup type); + void DisableQuery(PerfQueryGroup type); + void ResetQuery(); + u32 GetQueryResult(PerfQueryType type); + void FlushResults(); + bool IsFlushed() const; + +private: + struct ActiveQuery + { + ID3D11Query* query; + PerfQueryGroup query_type; + }; + + void WeakFlush(); + + // Only use when non-empty + void FlushOne(); + + // when testing in SMS: 64 was too small, 128 was ok + static const int PERF_QUERY_BUFFER_SIZE = 512; + + ActiveQuery m_query_buffer[PERF_QUERY_BUFFER_SIZE]; + int m_query_read_pos; + + // TODO: sloppy + volatile int m_query_count; + volatile u32 m_results[PQG_NUM_MEMBERS]; +}; + +} // namespace + +#endif // _PERFQUERY_H_ diff --git a/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp b/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp index a6cb52c40f..2dcfcd041c 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp @@ -65,6 +65,7 @@ ID3D11RasterizerState* resetraststate = NULL; static ID3D11Texture2D* s_screenshot_texture = NULL; + // GX pipeline state struct { @@ -761,11 +762,11 @@ bool Renderer::SaveScreenshot(const std::string &filename, const TargetRectangle return SUCCEEDED(hr); } -void formatBufferDump(const char *in, char *out, int w, int h, int p) +void formatBufferDump(const u8* in, u8* out, int w, int h, int p) { for (int y = 0; y < h; ++y) { - const u8 *line = (u8*)(in + (h - y - 1) * p); + auto line = (in + (h - y - 1) * p); for (int x = 0; x < w; ++x) { out[0] = line[2]; @@ -782,8 +783,8 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons { if (g_bSkipCurrentFrame || (!XFBWrited && !g_ActiveConfig.RealXFBEnabled()) || !fbWidth || !fbHeight) { - if (g_ActiveConfig.bDumpFrames && frame_data) - AVIDump::AddFrame(frame_data); + if (g_ActiveConfig.bDumpFrames && !frame_data.empty()) + AVIDump::AddFrame(&frame_data[0], fbWidth, fbHeight); Core::Callback_VideoCopiedToXFB(false); return; @@ -794,8 +795,8 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons const XFBSourceBase* const* xfbSourceList = FramebufferManager::GetXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount); if ((!xfbSourceList || xfbCount == 0) && g_ActiveConfig.bUseXFB && !g_ActiveConfig.bUseRealXFB) { - if (g_ActiveConfig.bDumpFrames && frame_data) - AVIDump::AddFrame(frame_data); + if (g_ActiveConfig.bDumpFrames && !frame_data.empty()) + AVIDump::AddFrame(&frame_data[0], fbWidth, fbHeight); Core::Callback_VideoCopiedToXFB(false); return; @@ -934,16 +935,15 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons D3D11_MAPPED_SUBRESOURCE map; D3D::context->Map(s_screenshot_texture, 0, D3D11_MAP_READ, 0, &map); - if (!frame_data || w != s_recordWidth || h != s_recordHeight) + if (frame_data.empty() || w != s_recordWidth || h != s_recordHeight) { - delete[] frame_data; - frame_data = new char[3 * s_recordWidth * s_recordHeight]; + frame_data.resize(3 * s_recordWidth * s_recordHeight); w = s_recordWidth; h = s_recordHeight; } - char* source_ptr = (char*)map.pData + GetTargetRectangle().left*4 + GetTargetRectangle().top*map.RowPitch; - formatBufferDump(source_ptr, frame_data, s_recordWidth, s_recordHeight, map.RowPitch); - AVIDump::AddFrame(frame_data); + auto source_ptr = (const u8*)map.pData + GetTargetRectangle().left*4 + GetTargetRectangle().top*map.RowPitch; + formatBufferDump(source_ptr, &frame_data[0], s_recordWidth, s_recordHeight, map.RowPitch); + AVIDump::AddFrame(&frame_data[0], fbWidth, fbHeight); D3D::context->Unmap(s_screenshot_texture, 0); } bLastFrameDumped = true; @@ -952,7 +952,7 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons { if (bLastFrameDumped && bAVIDumping) { - SAFE_DELETE_ARRAY(frame_data); + std::vector().swap(frame_data); w = h = 0; AVIDump::Stop(); diff --git a/Source/Plugins/Plugin_VideoDX11/Src/TextureCache.cpp b/Source/Plugins/Plugin_VideoDX11/Src/TextureCache.cpp index 6b22e1bd13..c0474e5c67 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/TextureCache.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/TextureCache.cpp @@ -58,7 +58,7 @@ bool TextureCache::TCacheEntry::Save(const char filename[], unsigned int level) return SUCCEEDED(PD3DX11SaveTextureToFileA(D3D::context, texture->GetTex(), D3DX11_IFF_PNG, filename)); } -void TextureCache::TCacheEntry::Load(unsigned int stage, unsigned int width, unsigned int height, +void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height, unsigned int expanded_width, unsigned int level) { D3D::ReplaceRGBATexture2D(texture->GetTex(), TextureCache::temp, width, height, expanded_width, level, usage); @@ -98,6 +98,9 @@ TextureCache::TCacheEntryBase* TextureCache::CreateTexture(unsigned int width, D3D::SetDebugObjectName((ID3D11DeviceChild*)entry->texture->GetSRV(), "shader resource view of a texture of the TextureCache"); SAFE_RELEASE(pTexture); + + if (tex_levels != 1) + entry->Load(width, height, expanded_width, 0); return entry; } diff --git a/Source/Plugins/Plugin_VideoDX11/Src/TextureCache.h b/Source/Plugins/Plugin_VideoDX11/Src/TextureCache.h index 5d3d9b5582..7876cb79ee 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/TextureCache.h +++ b/Source/Plugins/Plugin_VideoDX11/Src/TextureCache.h @@ -40,7 +40,7 @@ private: TCacheEntry(D3DTexture2D *_tex) : texture(_tex) {} ~TCacheEntry(); - void Load(unsigned int stage, unsigned int width, unsigned int height, + void Load(unsigned int width, unsigned int height, unsigned int expanded_width, unsigned int levels); void FromRenderTarget(u32 dstAddr, unsigned int dstFormat, diff --git a/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp b/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp index b42099c1a1..aa6ddf3b11 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp @@ -104,7 +104,7 @@ void VertexManager::PrepareDrawBuffers() { D3D11_MAPPED_SUBRESOURCE map; - UINT vSize = UINT(s_pCurBufferPointer - LocalVBuffer); + UINT vSize = UINT(s_pCurBufferPointer - s_pBaseBufferPointer); D3D11_MAP MapType = D3D11_MAP_WRITE_NO_OVERWRITE; if (m_vertex_buffer_cursor + vSize >= VBUFFER_SIZE) { @@ -116,7 +116,7 @@ void VertexManager::PrepareDrawBuffers() D3D::context->Map(m_vertex_buffers[m_current_vertex_buffer], 0, MapType, 0, &map); - memcpy((u8*)map.pData + m_vertex_buffer_cursor, LocalVBuffer, vSize); + memcpy((u8*)map.pData + m_vertex_buffer_cursor, s_pBaseBufferPointer, vSize); D3D::context->Unmap(m_vertex_buffers[m_current_vertex_buffer], 0); m_vertex_draw_offset = m_vertex_buffer_cursor; m_vertex_buffer_cursor += vSize; @@ -136,9 +136,9 @@ void VertexManager::PrepareDrawBuffers() m_triangle_draw_index = m_index_buffer_cursor; m_line_draw_index = m_triangle_draw_index + IndexGenerator::GetTriangleindexLen(); m_point_draw_index = m_line_draw_index + IndexGenerator::GetLineindexLen(); - memcpy((u16*)map.pData + m_triangle_draw_index, TIBuffer, sizeof(u16) * IndexGenerator::GetTriangleindexLen()); - memcpy((u16*)map.pData + m_line_draw_index, LIBuffer, sizeof(u16) * IndexGenerator::GetLineindexLen()); - memcpy((u16*)map.pData + m_point_draw_index, PIBuffer, sizeof(u16) * IndexGenerator::GetPointindexLen()); + memcpy((u16*)map.pData + m_triangle_draw_index, GetTriangleIndexBuffer(), sizeof(u16) * IndexGenerator::GetTriangleindexLen()); + memcpy((u16*)map.pData + m_line_draw_index, GetLineIndexBuffer(), sizeof(u16) * IndexGenerator::GetLineindexLen()); + memcpy((u16*)map.pData + m_point_draw_index, GetPointIndexBuffer(), sizeof(u16) * IndexGenerator::GetPointindexLen()); D3D::context->Unmap(m_index_buffers[m_current_index_buffer], 0); m_index_buffer_cursor += iCount; } @@ -211,8 +211,6 @@ void VertexManager::Draw(UINT stride) void VertexManager::vFlush() { - VideoFifo_CheckEFBAccess(); - u32 usedtextures = 0; for (u32 i = 0; i < (u32)bpmem.genMode.numtevstages + 1; ++i) if (bpmem.tevorders[i / 2].getEnable(i & 1)) @@ -260,26 +258,25 @@ void VertexManager::vFlush() g_nativeVertexFmt->m_components)) { GFX_DEBUGGER_PAUSE_LOG_AT(NEXT_ERROR,true,{printf("Fail to set pixel shader\n");}); - goto shader_fail; + return; } if (!VertexShaderCache::SetShader(g_nativeVertexFmt->m_components)) { GFX_DEBUGGER_PAUSE_LOG_AT(NEXT_ERROR,true,{printf("Fail to set pixel shader\n");}); - goto shader_fail; + return; } PrepareDrawBuffers(); unsigned int stride = g_nativeVertexFmt->GetVertexStride(); g_nativeVertexFmt->SetupVertexPointers(); g_renderer->ApplyState(useDstAlpha); - + + g_perf_query->EnableQuery(bpmem.zcontrol.early_ztest ? PQG_ZCOMP_ZCOMPLOC : PQG_ZCOMP); Draw(stride); + g_perf_query->DisableQuery(bpmem.zcontrol.early_ztest ? PQG_ZCOMP_ZCOMPLOC : PQG_ZCOMP); GFX_DEBUGGER_PAUSE_AT(NEXT_FLUSH, true); g_renderer->RestoreState(); - -shader_fail: - ResetBuffer(); } } // namespace diff --git a/Source/Plugins/Plugin_VideoDX11/Src/main.cpp b/Source/Plugins/Plugin_VideoDX11/Src/main.cpp index 37b2e24fea..17bbdcf33c 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/main.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/main.cpp @@ -42,6 +42,7 @@ #include "D3DUtil.h" #include "D3DBase.h" +#include "PerfQuery.h" #include "PixelShaderCache.h" #include "TextureCache.h" #include "VertexManager.h" @@ -90,6 +91,7 @@ void InitBackendInfo() g_Config.backend_info.APIType = API_D3D11; g_Config.backend_info.bUseRGBATextures = true; // the GX formats barely match any D3D11 formats + g_Config.backend_info.bUseMinimalMipCount = true; g_Config.backend_info.bSupports3DVision = false; g_Config.backend_info.bSupportsDualSourceBlend = true; g_Config.backend_info.bSupportsFormatReinterpretation = true; @@ -101,15 +103,13 @@ void InitBackendInfo() if (FAILED(hr)) PanicAlert("Failed to create IDXGIFactory object"); - char tmpstr[512] = {}; - DXGI_ADAPTER_DESC desc; // adapters g_Config.backend_info.Adapters.clear(); g_Config.backend_info.AAModes.clear(); while (factory->EnumAdapters((UINT)g_Config.backend_info.Adapters.size(), &ad) != DXGI_ERROR_NOT_FOUND) { + DXGI_ADAPTER_DESC desc; ad->GetDesc(&desc); - WideCharToMultiByte(/*CP_UTF8*/CP_ACP, 0, desc.Description, -1, tmpstr, 512, 0, false); // TODO: These don't get updated on adapter change, yet if (g_Config.backend_info.Adapters.size() == g_Config.iAdapter) @@ -126,7 +126,7 @@ void InitBackendInfo() } } - g_Config.backend_info.Adapters.push_back(tmpstr); + g_Config.backend_info.Adapters.push_back(UTF16ToUTF8(desc.Description)); ad->Release(); } @@ -184,6 +184,7 @@ void VideoBackend::Video_Prepare() g_renderer = new Renderer; g_texture_cache = new TextureCache; g_vertex_manager = new VertexManager; + g_perf_query = new PerfQuery; VertexShaderCache::Init(); PixelShaderCache::Init(); D3D::InitUtils(); @@ -227,6 +228,7 @@ void VideoBackend::Shutdown() D3D::ShutdownUtils(); PixelShaderCache::Shutdown(); VertexShaderCache::Shutdown(); + delete g_perf_query; delete g_vertex_manager; delete g_texture_cache; delete g_renderer; diff --git a/Source/Plugins/Plugin_VideoDX9/Src/D3DShader.cpp b/Source/Plugins/Plugin_VideoDX9/Src/D3DShader.cpp index 9c17c3df8c..c7c4cf266a 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/D3DShader.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/D3DShader.cpp @@ -50,7 +50,8 @@ bool CompileVertexShader(const char *code, int len, u8 **bytecode, int *bytecode static int num_failures = 0; char szTemp[MAX_PATH]; sprintf(szTemp, "%sbad_vs_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), num_failures++); - std::ofstream file(szTemp); + std::ofstream file; + OpenFStream(file, szTemp, std::ios_base::out); file << code; file.close(); @@ -105,7 +106,8 @@ bool CompilePixelShader(const char *code, int len, u8 **bytecode, int *bytecodel static int num_failures = 0; char szTemp[MAX_PATH]; sprintf(szTemp, "%sbad_ps_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), num_failures++); - std::ofstream file(szTemp); + std::ofstream file; + OpenFStream(file, szTemp, std::ios_base::out); file << code; file.close(); diff --git a/Source/Plugins/Plugin_VideoDX9/Src/NativeVertexFormat.cpp b/Source/Plugins/Plugin_VideoDX9/Src/NativeVertexFormat.cpp index bfaf21ec7e..d68228273c 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/NativeVertexFormat.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/NativeVertexFormat.cpp @@ -19,7 +19,7 @@ #include "D3DBase.h" #include "x64Emitter.h" -#include "ABI.h" +#include "x64ABI.h" #include "MemoryUtil.h" #include "VertexShaderGen.h" diff --git a/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp b/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp index 26b1fc4f57..7a175fd443 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp @@ -220,11 +220,11 @@ TargetRectangle Renderer::ConvertEFBRectangle(const EFBRectangle& rc) } -void formatBufferDump(const char *in, char *out, int w, int h, int p) +void formatBufferDump(const u8* in, u8* out, int w, int h, int p) { for (int y = 0; y < h; y++) { - const char *line = in + (h - y - 1) * p; + auto line = in + (h - y - 1) * p; for (int x = 0; x < w; x++) { memcpy(out, line, 3); @@ -729,8 +729,8 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons { if (g_bSkipCurrentFrame || (!XFBWrited && !g_ActiveConfig.RealXFBEnabled()) || !fbWidth || !fbHeight) { - if (g_ActiveConfig.bDumpFrames && frame_data) - AVIDump::AddFrame(frame_data); + if (g_ActiveConfig.bDumpFrames && !frame_data.empty()) + AVIDump::AddFrame(&frame_data[0], fbWidth, fbHeight); Core::Callback_VideoCopiedToXFB(false); return; @@ -741,8 +741,8 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons const XFBSourceBase* const* xfbSourceList = FramebufferManager::GetXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount); if ((!xfbSourceList || xfbCount == 0) && g_ActiveConfig.bUseXFB && !g_ActiveConfig.bUseRealXFB) { - if (g_ActiveConfig.bDumpFrames && frame_data) - AVIDump::AddFrame(frame_data); + if (g_ActiveConfig.bDumpFrames && !frame_data.empty()) + AVIDump::AddFrame(&frame_data[0], fbWidth, fbHeight); Core::Callback_VideoCopiedToXFB(false); return; @@ -939,15 +939,14 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons D3DLOCKED_RECT rect; if (SUCCEEDED(ScreenShootMEMSurface->LockRect(&rect, GetTargetRectangle().AsRECT(), D3DLOCK_NO_DIRTY_UPDATE | D3DLOCK_NOSYSLOCK | D3DLOCK_READONLY))) { - if (!frame_data || w != s_recordWidth || h != s_recordHeight) + if (frame_data.empty() || w != s_recordWidth || h != s_recordHeight) { - delete[] frame_data; - frame_data = new char[3 * s_recordWidth * s_recordHeight]; + frame_data.resize(3 * s_recordWidth * s_recordHeight); w = s_recordWidth; h = s_recordHeight; } - formatBufferDump((const char*)rect.pBits, frame_data, s_recordWidth, s_recordHeight, rect.Pitch); - AVIDump::AddFrame(frame_data); + formatBufferDump((const u8*)rect.pBits, &frame_data[0], s_recordWidth, s_recordHeight, rect.Pitch); + AVIDump::AddFrame(&frame_data[0], fbWidth, fbHeight); ScreenShootMEMSurface->UnlockRect(); } } @@ -957,12 +956,8 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons { if (bLastFrameDumped && bAVIDumping) { - if (frame_data) - { - delete[] frame_data; - frame_data = 0; - w = h = 0; - } + std::vector().swap(frame_data); + w = h = 0; AVIDump::Stop(); bAVIDumping = false; OSD::AddMessage("Stop dumping frames to AVI", 2000); diff --git a/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp b/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp index 6feacc74ad..0e7d82cf7a 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp @@ -71,7 +71,7 @@ bool TextureCache::TCacheEntry::Save(const char filename[], unsigned int level) return SUCCEEDED(hr); } -void TextureCache::TCacheEntry::Load(unsigned int stage, unsigned int width, unsigned int height, +void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height, unsigned int expanded_width, unsigned int level) { D3D::ReplaceTexture2D(texture, temp, width, height, expanded_width, d3d_fmt, swap_r_b, level); @@ -230,6 +230,8 @@ TextureCache::TCacheEntryBase* TextureCache::CreateTexture(unsigned int width, u TCacheEntry* entry = new TCacheEntry(D3D::CreateTexture2D(temp, width, height, expanded_width, d3d_fmt, swap_r_b, tex_levels)); entry->swap_r_b = swap_r_b; entry->d3d_fmt = d3d_fmt; + + entry->Load(width, height, expanded_width, 0); return entry; } diff --git a/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.h b/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.h index bad6b0fb95..fc338e623f 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.h +++ b/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.h @@ -43,7 +43,7 @@ private: TCacheEntry(LPDIRECT3DTEXTURE9 _tex) : texture(_tex) {} ~TCacheEntry(); - void Load(unsigned int stage, unsigned int width, unsigned int height, + void Load(unsigned int width, unsigned int height, unsigned int expanded_width, unsigned int levels); void FromRenderTarget(u32 dstAddr, unsigned int dstFormat, diff --git a/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp b/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp index 776d52f89e..fb3378c896 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp @@ -173,7 +173,7 @@ void VertexManager::PrepareDrawBuffers(u32 stride) DestroyDeviceObjects(); return; } - memcpy(pVertices, LocalVBuffer, datasize); + memcpy(pVertices, s_pBaseBufferPointer,, datasize); m_vertex_buffers[m_current_vertex_buffer]->Unlock(); LockMode = D3DLOCK_NOOVERWRITE; @@ -191,12 +191,12 @@ void VertexManager::PrepareDrawBuffers(u32 stride) } if(TdataSize) { - memcpy(pIndices, TIBuffer, TdataSize * sizeof(u16)); + memcpy(pIndices, GetTriangleIndexBuffer(), TdataSize * sizeof(u16)); pIndices += TdataSize; } if(LDataSize) { - memcpy(pIndices, LIBuffer, LDataSize * sizeof(u16)); + memcpy(pIndices, GetLineIndexBuffer(), LDataSize * sizeof(u16)); pIndices += LDataSize; } m_index_buffers[m_current_index_buffer]->Unlock(); @@ -280,10 +280,15 @@ void VertexManager::DrawVertexArray(int stride) { if (FAILED(D3D::dev->DrawIndexedPrimitiveUP( D3DPT_TRIANGLELIST, +<<<<<<< HEAD 0, numverts, triangles, TIBuffer, +======= + 0, IndexGenerator::GetNumVerts(), IndexGenerator::GetNumTriangles(), + GetTriangleIndexBuffer(), +>>>>>>> master D3DFMT_INDEX16, - LocalVBuffer, + s_pBaseBufferPointer, stride))) { DumpBadShaders(); @@ -294,10 +299,15 @@ void VertexManager::DrawVertexArray(int stride) { if (FAILED(D3D::dev->DrawIndexedPrimitiveUP( D3DPT_LINELIST, +<<<<<<< HEAD 0, numverts, lines, LIBuffer, +======= + 0, IndexGenerator::GetNumVerts(), IndexGenerator::GetNumLines(), + GetLineIndexBuffer(), +>>>>>>> master D3DFMT_INDEX16, - LocalVBuffer, + s_pBaseBufferPointer, stride))) { DumpBadShaders(); @@ -308,10 +318,15 @@ void VertexManager::DrawVertexArray(int stride) { if (FAILED(D3D::dev->DrawIndexedPrimitiveUP( D3DPT_POINTLIST, +<<<<<<< HEAD 0, numverts, points, PIBuffer, +======= + 0, IndexGenerator::GetNumVerts(), IndexGenerator::GetNumPoints(), + GetPointIndexBuffer(), +>>>>>>> master D3DFMT_INDEX16, - LocalVBuffer, + s_pBaseBufferPointer, stride))) { DumpBadShaders(); @@ -322,7 +337,10 @@ void VertexManager::DrawVertexArray(int stride) void VertexManager::vFlush() { +<<<<<<< HEAD VideoFifo_CheckEFBAccess(); +======= +>>>>>>> master u32 usedtextures = 0; for (u32 i = 0; i < (u32)bpmem.genMode.numtevstages + 1; ++i) if (bpmem.tevorders[i / 2].getEnable(i & 1)) @@ -413,7 +431,6 @@ shader_fail: m_index_buffer_cursor += IndexGenerator::GetTriangleindexLen() + IndexGenerator::GetLineindexLen() + IndexGenerator::GetPointindexLen(); m_vertex_buffer_cursor += IndexGenerator::GetNumVerts() * stride; } - ResetBuffer(); } } diff --git a/Source/Plugins/Plugin_VideoDX9/Src/main.cpp b/Source/Plugins/Plugin_VideoDX9/Src/main.cpp index d488747a5a..04ea2077fc 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/main.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/main.cpp @@ -57,6 +57,7 @@ #include "ConfigManager.h" #include "VideoBackend.h" +#include "PerfQueryBase.h" namespace DX9 { @@ -93,11 +94,10 @@ void InitBackendInfo() const int maxConstants = (shaderModel < 3) ? 32 : ((shaderModel < 4) ? 224 : 65536); g_Config.backend_info.APIType = shaderModel < 3 ? API_D3D9_SM20 :API_D3D9_SM30; g_Config.backend_info.bUseRGBATextures = false; + g_Config.backend_info.bUseMinimalMipCount = true; g_Config.backend_info.bSupports3DVision = true; g_Config.backend_info.bSupportsDualSourceBlend = false; g_Config.backend_info.bSupportsFormatReinterpretation = true; - - g_Config.backend_info.bSupportsPixelLighting = C_PLIGHTS + 40 <= maxConstants && C_PMATERIALS + 4 <= maxConstants; // adapters @@ -171,6 +171,7 @@ void VideoBackend::Video_Prepare() g_vertex_manager = new VertexManager; g_renderer = new Renderer; g_texture_cache = new TextureCache; + g_perf_query = new PerfQueryBase; // VideoCommon BPInit(); Fifo_Init(); @@ -209,6 +210,7 @@ void VideoBackend::Shutdown() // internal interfaces PixelShaderCache::Shutdown(); VertexShaderCache::Shutdown(); + delete g_perf_query; delete g_texture_cache; delete g_renderer; delete g_vertex_manager; diff --git a/Source/Plugins/Plugin_VideoOGL/CMakeLists.txt b/Source/Plugins/Plugin_VideoOGL/CMakeLists.txt index 7f34f9e355..3d4e225932 100644 --- a/Source/Plugins/Plugin_VideoOGL/CMakeLists.txt +++ b/Source/Plugins/Plugin_VideoOGL/CMakeLists.txt @@ -2,6 +2,7 @@ set(SRCS Src/FramebufferManager.cpp Src/GLUtil.cpp Src/main.cpp Src/NativeVertexFormat.cpp + Src/PerfQuery.cpp Src/PixelShaderCache.cpp Src/PostProcessing.cpp Src/ProgramShaderCache.cpp diff --git a/Source/Plugins/Plugin_VideoOGL/Plugin_VideoOGL.vcxproj b/Source/Plugins/Plugin_VideoOGL/Plugin_VideoOGL.vcxproj index dadfb18b61..403aac2c30 100644 --- a/Source/Plugins/Plugin_VideoOGL/Plugin_VideoOGL.vcxproj +++ b/Source/Plugins/Plugin_VideoOGL/Plugin_VideoOGL.vcxproj @@ -200,6 +200,7 @@ + @@ -225,6 +226,7 @@ + diff --git a/Source/Plugins/Plugin_VideoOGL/Plugin_VideoOGL.vcxproj.filters b/Source/Plugins/Plugin_VideoOGL/Plugin_VideoOGL.vcxproj.filters index 27bb563c52..a8b79d85ad 100644 --- a/Source/Plugins/Plugin_VideoOGL/Plugin_VideoOGL.vcxproj.filters +++ b/Source/Plugins/Plugin_VideoOGL/Plugin_VideoOGL.vcxproj.filters @@ -42,6 +42,9 @@ Render + + Render + @@ -75,6 +78,9 @@ Render + + Render + @@ -93,4 +99,4 @@ {aaa16061-dca9-4155-be44-f77538e839fc} - \ No newline at end of file + diff --git a/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp b/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp index 55b1d6e52a..4f71fb4a7d 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp @@ -51,7 +51,9 @@ void VideoBackend::UpdateFPSDisplay(const char *text) } void InitInterface() { - #if defined(USE_EGL) && USE_EGL + #ifdef ANDROID + GLInterface = new cInterfaceBase; + #elif defined(USE_EGL) && USE_EGL GLInterface = new cInterfaceEGL; #elif defined(__APPLE__) GLInterface = new cInterfaceAGL; diff --git a/Source/Plugins/Plugin_VideoOGL/Src/NativeVertexFormat.cpp b/Source/Plugins/Plugin_VideoOGL/Src/NativeVertexFormat.cpp index b2058cf089..acfdb7ee2e 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/NativeVertexFormat.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/NativeVertexFormat.cpp @@ -17,7 +17,7 @@ #include "GLUtil.h" #include "x64Emitter.h" -#include "ABI.h" +#include "x64ABI.h" #include "MemoryUtil.h" #include "ProgramShaderCache.h" #include "VertexShaderGen.h" diff --git a/Source/Plugins/Plugin_VideoOGL/Src/PerfQuery.cpp b/Source/Plugins/Plugin_VideoOGL/Src/PerfQuery.cpp new file mode 100644 index 0000000000..db47217655 --- /dev/null +++ b/Source/Plugins/Plugin_VideoOGL/Src/PerfQuery.cpp @@ -0,0 +1,133 @@ +#include "RenderBase.h" +#include "GLUtil.h" +#include "PerfQuery.h" + +namespace OGL +{ + +PerfQuery::PerfQuery() + : m_query_read_pos() + , m_query_count() +{ + for (u32 i = 0; i != ARRAYSIZE(m_query_buffer); ++i) + glGenQueries(1, &m_query_buffer[i].query_id); + + ResetQuery(); +} + +PerfQuery::~PerfQuery() +{ + for (u32 i = 0; i != ARRAYSIZE(m_query_buffer); ++i) + glDeleteQueries(1, &m_query_buffer[i].query_id); +} + +void PerfQuery::EnableQuery(PerfQueryGroup type) +{ + // Is this sane? + if (m_query_count > ARRAYSIZE(m_query_buffer) / 2) + WeakFlush(); + + if (ARRAYSIZE(m_query_buffer) == m_query_count) + { + FlushOne(); + //ERROR_LOG(VIDEO, "flushed query buffer early!"); + } + + // start query + if (type == PQG_ZCOMP_ZCOMPLOC || type == PQG_ZCOMP) + { + auto& entry = m_query_buffer[(m_query_read_pos + m_query_count) % ARRAYSIZE(m_query_buffer)]; + + glBeginQuery(GL_SAMPLES_PASSED, entry.query_id); + entry.query_type = type; + + ++m_query_count; + } +} + +void PerfQuery::DisableQuery(PerfQueryGroup type) +{ + // stop query + if (type == PQG_ZCOMP_ZCOMPLOC || type == PQG_ZCOMP) + { + glEndQuery(GL_SAMPLES_PASSED); + } +} + +bool PerfQuery::IsFlushed() const +{ + return 0 == m_query_count; +} + +void PerfQuery::FlushOne() +{ + auto& entry = m_query_buffer[m_query_read_pos]; + + GLuint result = 0; + glGetQueryObjectuiv(entry.query_id, GL_QUERY_RESULT, &result); + + // NOTE: Reported pixel metrics should be referenced to native resolution + m_results[entry.query_type] += (u64)result * EFB_WIDTH / g_renderer->GetTargetWidth() * EFB_HEIGHT / g_renderer->GetTargetHeight(); + + m_query_read_pos = (m_query_read_pos + 1) % ARRAYSIZE(m_query_buffer); + --m_query_count; +} + +// TODO: could selectively flush things, but I don't think that will do much +void PerfQuery::FlushResults() +{ + while (!IsFlushed()) + FlushOne(); +} + +void PerfQuery::WeakFlush() +{ + while (!IsFlushed()) + { + auto& entry = m_query_buffer[m_query_read_pos]; + + GLuint result = GL_FALSE; + glGetQueryObjectuiv(entry.query_id, GL_QUERY_RESULT_AVAILABLE, &result); + + if (GL_TRUE == result) + { + FlushOne(); + } + else + { + break; + } + } +} + +void PerfQuery::ResetQuery() +{ + m_query_count = 0; + std::fill_n(m_results, ARRAYSIZE(m_results), 0); +} + +u32 PerfQuery::GetQueryResult(PerfQueryType type) +{ + u32 result = 0; + + if (type == PQ_ZCOMP_INPUT_ZCOMPLOC || type == PQ_ZCOMP_OUTPUT_ZCOMPLOC) + { + result = m_results[PQG_ZCOMP_ZCOMPLOC]; + } + else if (type == PQ_ZCOMP_INPUT || type == PQ_ZCOMP_OUTPUT) + { + result = m_results[PQG_ZCOMP]; + } + else if (type == PQ_BLEND_INPUT) + { + result = m_results[PQG_ZCOMP] + m_results[PQG_ZCOMP_ZCOMPLOC]; + } + else if (type == PQ_EFB_COPY_CLOCKS) + { + result = m_results[PQG_EFB_COPY_CLOCKS]; + } + + return result / 4; +} + +} // namespace diff --git a/Source/Plugins/Plugin_VideoOGL/Src/PerfQuery.h b/Source/Plugins/Plugin_VideoOGL/Src/PerfQuery.h new file mode 100644 index 0000000000..b96fe7a4a0 --- /dev/null +++ b/Source/Plugins/Plugin_VideoOGL/Src/PerfQuery.h @@ -0,0 +1,46 @@ +#ifndef _PERFQUERY_H_ +#define _PERFQUERY_H_ + +#include "PerfQueryBase.h" + +namespace OGL { + +class PerfQuery : public PerfQueryBase +{ +public: + PerfQuery(); + ~PerfQuery(); + + void EnableQuery(PerfQueryGroup type); + void DisableQuery(PerfQueryGroup type); + void ResetQuery(); + u32 GetQueryResult(PerfQueryType type); + void FlushResults(); + bool IsFlushed() const; + +private: + struct ActiveQuery + { + GLuint query_id; + PerfQueryGroup query_type; + }; + + // when testing in SMS: 64 was too small, 128 was ok + static const u32 PERF_QUERY_BUFFER_SIZE = 512; + + void WeakFlush(); + // Only use when non-empty + void FlushOne(); + + // This contains gl query objects with unretrieved results. + ActiveQuery m_query_buffer[PERF_QUERY_BUFFER_SIZE]; + u32 m_query_read_pos; + + // TODO: sloppy + volatile u32 m_query_count; + volatile u32 m_results[PQG_NUM_MEMBERS]; +}; + +} // namespace + +#endif // _PERFQUERY_H_ diff --git a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp index 77f5c2323b..c72bcaa096 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp @@ -24,6 +24,7 @@ #include #include "GLUtil.h" +#include "WxUtils.h" #include "FileUtil.h" @@ -962,20 +963,23 @@ void Renderer::SetBlendMode(bool forceUpdate) s_blendMode = newval; } +void DumpFrame(const std::vector& data, int w, int h) +{ +#if defined(HAVE_LIBAV) || defined(_WIN32) + if (g_ActiveConfig.bDumpFrames && !data.empty()) + { + AVIDump::AddFrame(&data[0], w, h); + } +#endif +} + // This function has the final picture. We adjust the aspect ratio here. void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,const EFBRectangle& rc,float Gamma) { static int w = 0, h = 0; if (g_bSkipCurrentFrame || (!XFBWrited && !g_ActiveConfig.RealXFBEnabled()) || !fbWidth || !fbHeight) { - if (g_ActiveConfig.bDumpFrames && frame_data) - { -#ifdef _WIN32 - AVIDump::AddFrame(frame_data); -#elif defined HAVE_LIBAV - AVIDump::AddFrame((u8*)frame_data, w, h); -#endif - } + DumpFrame(frame_data, w, h); Core::Callback_VideoCopiedToXFB(false); return; } @@ -985,14 +989,7 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons const XFBSourceBase* const* xfbSourceList = FramebufferManager::GetXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount); if (g_ActiveConfig.VirtualXFBEnabled() && (!xfbSourceList || xfbCount == 0)) { - if (g_ActiveConfig.bDumpFrames && frame_data) - { -#ifdef _WIN32 - AVIDump::AddFrame(frame_data); -#elif defined HAVE_LIBAV - AVIDump::AddFrame((u8*)frame_data, w, h); -#endif - } + DumpFrame(frame_data, w, h); Core::Callback_VideoCopiedToXFB(false); return; } @@ -1117,16 +1114,15 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons if (g_ActiveConfig.bDumpFrames) { std::lock_guard lk(s_criticalScreenshot); - if (!frame_data || w != flipped_trc.GetWidth() || + if (frame_data.empty() || w != flipped_trc.GetWidth() || h != flipped_trc.GetHeight()) { - if (frame_data) delete[] frame_data; w = flipped_trc.GetWidth(); h = flipped_trc.GetHeight(); - frame_data = new char[3 * w * h]; + frame_data.resize(3 * w * h); } glPixelStorei(GL_PACK_ALIGNMENT, 1); - glReadPixels(flipped_trc.left, flipped_trc.bottom, w, h, GL_BGR, GL_UNSIGNED_BYTE, frame_data); + glReadPixels(flipped_trc.left, flipped_trc.bottom, w, h, GL_BGR, GL_UNSIGNED_BYTE, &frame_data[0]); if (GL_REPORT_ERROR() == GL_NO_ERROR && w > 0 && h > 0) { if (!bLastFrameDumped) @@ -1147,12 +1143,11 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons } if (bAVIDumping) { - #ifdef _WIN32 - AVIDump::AddFrame(frame_data); - #else - FlipImageData((u8*)frame_data, w, h); - AVIDump::AddFrame((u8*)frame_data, w, h); + #ifndef _WIN32 + FlipImageData(&frame_data[0], w, h); #endif + + AVIDump::AddFrame(&frame_data[0], w, h); } bLastFrameDumped = true; @@ -1164,12 +1159,8 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons { if (bLastFrameDumped && bAVIDumping) { - if (frame_data) - { - delete[] frame_data; - frame_data = NULL; - w = h = 0; - } + std::vector().swap(frame_data); + w = h = 0; AVIDump::Stop(); bAVIDumping = false; OSD::AddMessage("Stop dumping frames", 2000); @@ -1183,9 +1174,9 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons std::string movie_file_name; w = GetTargetRectangle().GetWidth(); h = GetTargetRectangle().GetHeight(); - frame_data = new char[3 * w * h]; + frame_data.resize(3 * w * h); glPixelStorei(GL_PACK_ALIGNMENT, 1); - glReadPixels(GetTargetRectangle().left, GetTargetRectangle().bottom, w, h, GL_BGR, GL_UNSIGNED_BYTE, frame_data); + glReadPixels(GetTargetRectangle().left, GetTargetRectangle().bottom, w, h, GL_BGR, GL_UNSIGNED_BYTE, &frame_data[0]); if (GL_REPORT_ERROR() == GL_NO_ERROR) { if (!bLastFrameDumped) @@ -1196,21 +1187,17 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons OSD::AddMessage("Error opening framedump.raw for writing.", 2000); else { - char msg [255]; - sprintf(msg, "Dumping Frames to \"%s\" (%dx%d RGB24)", movie_file_name.c_str(), w, h); - OSD::AddMessage(msg, 2000); + OSD::AddMessage(StringFromFormat("Dumping Frames to \"%s\" (%dx%d RGB24)", movie_file_name.c_str(), w, h).c_str(), 2000); } } if (pFrameDump) { - FlipImageData((u8*)frame_data, w, h); - pFrameDump.WriteBytes(frame_data, w * 3 * h); + FlipImageData(&frame_data[0], w, h); + pFrameDump.WriteBytes(&frame_data[0], w * 3 * h); pFrameDump.Flush(); } bLastFrameDumped = true; } - - delete[] frame_data; } else { @@ -1399,6 +1386,7 @@ void Renderer::SetDepthMode() else { // if the test is disabled write is disabled too + // TODO: When PE performance metrics are being emulated via occlusion queries, we should (probably?) enable depth test with depth function ALWAYS here glDisable(GL_DEPTH_TEST); glDepthMask(GL_FALSE); } @@ -1522,7 +1510,7 @@ void TakeScreenshot(ScrStrct* threadStruct) // 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(wxString::FromAscii(threadStruct->filename.c_str()), + threadStruct->img->SaveFile(StrToWxStr(threadStruct->filename), wxBITMAP_TYPE_PNG); threadStruct->img->Destroy(); diff --git a/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.cpp b/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.cpp index 7bb877f8e3..1a1fee21a0 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.cpp @@ -65,6 +65,7 @@ static u32 s_DepthCbufid; static u32 s_Textures[8]; static u32 s_ActiveTexture; +static u32 s_NextStage; struct VBOCache { GLuint vbo; @@ -204,23 +205,25 @@ TextureCache::TCacheEntryBase* TextureCache::CreateTexture(unsigned int width, entry.pcfmt = pcfmt; entry.m_tex_levels = tex_levels; + + entry.Load(width, height, expanded_width, 0); return &entry; } -void TextureCache::TCacheEntry::Load(unsigned int stage, unsigned int width, unsigned int height, +void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height, unsigned int expanded_width, unsigned int level) { - if (s_ActiveTexture != stage) + if (s_ActiveTexture != s_NextStage) { - glActiveTexture(GL_TEXTURE0 + stage); - s_ActiveTexture = stage; + glActiveTexture(GL_TEXTURE0 + s_NextStage); + s_ActiveTexture = s_NextStage; } - if (s_Textures[stage] != texture) + if (s_Textures[s_NextStage] != texture) { glBindTexture(GL_TEXTURE_2D, texture); - s_Textures[stage] = texture; + s_Textures[s_NextStage] = texture; } // TODO: sloppy, just do this on creation? @@ -458,6 +461,7 @@ TextureCache::TextureCache() s_DepthCbufid = -1; s_ActiveTexture = -1; + s_NextStage = -1; for(int i=0; i<8; i++) s_Textures[i] = -1; } @@ -490,5 +494,11 @@ void TextureCache::SetStage () glActiveTexture(GL_TEXTURE0 + s_ActiveTexture); } +void TextureCache::SetNextStage ( unsigned int stage ) +{ + s_NextStage = stage; +} + + } diff --git a/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.h b/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.h index f91a6ed0e4..a41c86e0b3 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.h +++ b/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.h @@ -35,6 +35,7 @@ public: TextureCache(); static void DisableStage(unsigned int stage); static void SetStage(); + static void SetNextStage(unsigned int stage); private: struct TCacheEntry : TCacheEntryBase @@ -55,7 +56,7 @@ private: TCacheEntry(); ~TCacheEntry(); - void Load(unsigned int stage, unsigned int width, unsigned int height, + void Load(unsigned int width, unsigned int height, unsigned int expanded_width, unsigned int level); void FromRenderTarget(u32 dstAddr, unsigned int dstFormat, diff --git a/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp b/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp index 017c95d217..f966c4e069 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp @@ -40,6 +40,7 @@ #include "FileUtil.h" #include "Debugger.h" #include "StreamBuffer.h" +#include "PerfQueryBase.h" #include "main.h" @@ -99,21 +100,21 @@ 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(LocalVBuffer, vertex_data_size); + u32 offset = s_vertexBuffer->Upload(GetVertexBuffer(), vertex_data_size); s_baseVertex = offset / stride; s_indexBuffer->Alloc(index_size); if(triangle_index_size) { - s_offset[0] = s_indexBuffer->Upload((u8*)TIBuffer, triangle_index_size * sizeof(u16)); + s_offset[0] = s_indexBuffer->Upload((u8*)GetTriangleIndexBuffer(), triangle_index_size * sizeof(u16)); } if(line_index_size) { - s_offset[1] = s_indexBuffer->Upload((u8*)LIBuffer, line_index_size * sizeof(u16)); + s_offset[1] = s_indexBuffer->Upload((u8*)GetLineIndexBuffer(), line_index_size * sizeof(u16)); } if(point_index_size) { - s_offset[2] = s_indexBuffer->Upload((u8*)PIBuffer, point_index_size * sizeof(u16)); + s_offset[2] = s_indexBuffer->Upload((u8*)GetPointIndexBuffer(), point_index_size * sizeof(u16)); } } @@ -159,7 +160,6 @@ void VertexManager::Draw(u32 stride) void VertexManager::vFlush() { - VideoFifo_CheckEFBAccess(); #if defined(_DEBUG) || defined(DEBUGFAST) PRIM_LOG("frame%d:\n texgen=%d, numchan=%d, dualtex=%d, ztex=%d, cole=%d, alpe=%d, ze=%d", g_ActiveConfig.iSaveTargetId, xfregs.numTexGen.numTexGens, xfregs.numChan.numColorChans, xfregs.dualTexTrans.enabled, bpmem.ztex2.op, @@ -215,6 +215,7 @@ void VertexManager::vFlush() { if (usedtextures & (1 << i)) { + TextureCache::SetNextStage(i); g_renderer->SetSamplerState(i % 4, i / 4); FourTexUnits &tex = bpmem.tex[i >> 2]; TextureCache::TCacheEntryBase* tentry = TextureCache::Load(i, @@ -271,7 +272,10 @@ void VertexManager::vFlush() g_nativeVertexFmt->SetupVertexPointers(); GL_REPORT_ERRORD(); + g_perf_query->EnableQuery(bpmem.zcontrol.early_ztest ? PQG_ZCOMP_ZCOMPLOC : PQG_ZCOMP); Draw(stride); + g_perf_query->DisableQuery(bpmem.zcontrol.early_ztest ? PQG_ZCOMP_ZCOMPLOC : PQG_ZCOMP); + //ERROR_LOG(VIDEO, "PerfQuery result: %d", g_perf_query->GetQueryResult(bpmem.zcontrol.early_ztest ? PQ_ZCOMP_OUTPUT_ZCOMPLOC : PQ_ZCOMP_OUTPUT)); // run through vertex groups again to set alpha if (useDstAlpha && !dualSourcePossible) @@ -299,7 +303,6 @@ void VertexManager::vFlush() } GFX_DEBUGGER_PAUSE_AT(NEXT_FLUSH, true); - ResetBuffer(); #if defined(_DEBUG) || defined(DEBUGFAST) if (g_ActiveConfig.iLog & CONF_SAVESHADERS) { @@ -307,10 +310,12 @@ void VertexManager::vFlush() ProgramShaderCache::PCacheEntry prog = ProgramShaderCache::GetShaderProgram(); char strfile[255]; sprintf(strfile, "%sps%.3d.txt", File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), g_ActiveConfig.iSaveTargetId); - std::ofstream fps(strfile); + std::ofstream fps; + OpenFStream(fps, strfile, std::ios_base::out); fps << prog.shader.strpprog.c_str(); sprintf(strfile, "%svs%.3d.txt", File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), g_ActiveConfig.iSaveTargetId); - std::ofstream fvs(strfile); + std::ofstream fvs; + OpenFStream(fvs, strfile, std::ios_base::out); fvs << prog.shader.strvprog.c_str(); } diff --git a/Source/Plugins/Plugin_VideoOGL/Src/main.cpp b/Source/Plugins/Plugin_VideoOGL/Src/main.cpp index a89b795e68..fde80f90d2 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/main.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/main.cpp @@ -92,6 +92,7 @@ Make AA apply instantly during gameplay if possible #include "Core.h" #include "Host.h" #include "SamplerCache.h" +#include "PerfQuery.h" #include "VideoState.h" #include "VideoBackend.h" @@ -130,6 +131,7 @@ void InitBackendInfo() { g_Config.backend_info.APIType = API_OPENGL; g_Config.backend_info.bUseRGBATextures = true; + g_Config.backend_info.bUseMinimalMipCount = false; g_Config.backend_info.bSupports3DVision = false; //g_Config.backend_info.bSupportsDualSourceBlend = true; // is gpu depenend and must be set in renderer g_Config.backend_info.bSupportsFormatReinterpretation = false; @@ -191,6 +193,7 @@ void VideoBackend::Video_Prepare() BPInit(); g_vertex_manager = new VertexManager; + g_perf_query = new PerfQuery; Fifo_Init(); // must be done before OpcodeDecoder_Init() OpcodeDecoder_Init(); VertexShaderManager::Init(); @@ -203,7 +206,9 @@ void VideoBackend::Video_Prepare() GL_REPORT_ERRORD(); VertexLoaderManager::Init(); TextureConverter::Init(); +#ifndef _M_GENERIC DLCache::Init(); +#endif // Notify the core that the video backend is ready Host_Message(WM_USER_CREATE); @@ -222,7 +227,9 @@ void VideoBackend::Video_Cleanup() { s_efbAccessRequested = false; s_FifoShuttingDown = false; s_swapRequested = false; +#ifndef _M_GENERIC DLCache::Shutdown(); +#endif Fifo_Shutdown(); PostProcessing::Shutdown(); diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/BPMemLoader.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/BPMemLoader.cpp index f05f9f8b57..0d7c77c767 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/BPMemLoader.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/BPMemLoader.cpp @@ -90,6 +90,21 @@ void SWBPWritten(int address, int newvalue) SWPixelEngine::pereg.boxBottom = newvalue >> 10; SWPixelEngine::pereg.boxTop = newvalue & 0x3ff; break; + case BPMEM_CLEAR_PIXEL_PERF: + // TODO: I didn't test if the value written to this register affects the amount of cleared registers + SWPixelEngine::pereg.perfZcompInputZcomplocLo = 0; + SWPixelEngine::pereg.perfZcompInputZcomplocHi = 0; + SWPixelEngine::pereg.perfZcompOutputZcomplocLo = 0; + SWPixelEngine::pereg.perfZcompOutputZcomplocHi = 0; + SWPixelEngine::pereg.perfZcompInputLo = 0; + SWPixelEngine::pereg.perfZcompInputHi = 0; + SWPixelEngine::pereg.perfZcompOutputLo = 0; + SWPixelEngine::pereg.perfZcompOutputHi = 0; + SWPixelEngine::pereg.perfBlendInputLo = 0; + SWPixelEngine::pereg.perfBlendInputHi = 0; + SWPixelEngine::pereg.perfEfbCopyClocksLo = 0; + SWPixelEngine::pereg.perfEfbCopyClocksHi = 0; + break; case BPMEM_LOADTLUT0: // This one updates bpmem.tlutXferSrc, no need to do anything here. break; case BPMEM_LOADTLUT1: // Load a Texture Look Up Table diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/Clipper.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/Clipper.cpp index e9a3525d84..c4755b50bf 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/Clipper.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/Clipper.cpp @@ -65,6 +65,13 @@ namespace Clipper OutputVertexData ClippedVertices[NUM_CLIPPED_VERTICES]; OutputVertexData *Vertices[NUM_INDICES]; + void DoState(PointerWrap &p) + { + p.DoArray(m_ViewOffset,2); + for (int i = 0; i< NUM_CLIPPED_VERTICES; ++i) + ClippedVertices[i].DoState(p); + } + void Init() { for (int i = 0; i < NUM_CLIPPED_VERTICES; ++i) diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/Clipper.h b/Source/Plugins/Plugin_VideoSoftware/Src/Clipper.h index 5e5dd4d02c..babc8b4e88 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/Clipper.h +++ b/Source/Plugins/Plugin_VideoSoftware/Src/Clipper.h @@ -21,6 +21,7 @@ #include "Common.h" #include "NativeVertexFormat.h" +#include "ChunkFile.h" namespace Clipper @@ -36,6 +37,8 @@ namespace Clipper bool CullTest(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2, bool &backface); void PerspectiveDivide(OutputVertexData *vertex); + + void DoState(PointerWrap &p); } diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/EfbInterface.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/EfbInterface.cpp index 6722ec7935..8fdc0425a4 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/EfbInterface.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/EfbInterface.cpp @@ -28,6 +28,7 @@ u8 efb[EFB_WIDTH*EFB_HEIGHT*6]; namespace EfbInterface { + u8 efbColorTexture[EFB_WIDTH*EFB_HEIGHT*4]; inline u32 GetColorOffset(u16 x, u16 y) @@ -40,6 +41,12 @@ namespace EfbInterface return (x + y * EFB_WIDTH) * 3 + DEPTH_BUFFER_START; } + void DoState(PointerWrap &p) + { + p.DoArray(efb, EFB_WIDTH*EFB_HEIGHT*6); + p.DoArray(efbColorTexture, EFB_WIDTH*EFB_HEIGHT*4); + } + void SetPixelAlphaOnly(u32 offset, u8 a) { switch (bpmem.zcontrol.pixel_format) diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/EfbInterface.h b/Source/Plugins/Plugin_VideoSoftware/Src/EfbInterface.h index 15d19e7783..fdad69567c 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/EfbInterface.h +++ b/Source/Plugins/Plugin_VideoSoftware/Src/EfbInterface.h @@ -47,6 +47,7 @@ namespace EfbInterface void UpdateColorTexture(); extern u8 efbColorTexture[EFB_WIDTH*EFB_HEIGHT*4]; // RGBA format + void DoState(PointerWrap &p); } #endif diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/NativeVertexFormat.h b/Source/Plugins/Plugin_VideoSoftware/Src/NativeVertexFormat.h index d19844105f..e2d87e207e 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/NativeVertexFormat.h +++ b/Source/Plugins/Plugin_VideoSoftware/Src/NativeVertexFormat.h @@ -19,6 +19,7 @@ #define _NATIVEVERTEXFORMAT_H #include "Vec3.h" +#include "ChunkFile.h" #ifdef WIN32 #define LOADERDECL __cdecl @@ -92,6 +93,18 @@ struct OutputVertexData #undef LINTERP #undef LINTERP_INT } + void DoState(PointerWrap &p) + { + mvPosition.DoState(p); + p.Do(projectedPosition); + screenPosition.DoState(p); + for (int i = 0; i < 3;++i) + normal[i].DoState(p); + p.DoArray(color, sizeof color); + for (int i = 0; i < 8;++i) + texCoords[i].DoState(p); + } + }; #endif diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/OpcodeDecoder.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/OpcodeDecoder.cpp index 0091e4eaca..4848cb4d43 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/OpcodeDecoder.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/OpcodeDecoder.cpp @@ -35,7 +35,6 @@ typedef void (*DecodingFunction)(u32); namespace OpcodeDecoder { - static DecodingFunction currentFunction = NULL; static u32 minCommandSize; static u16 streamSize; @@ -46,6 +45,20 @@ static bool inObjectStream; static u8 lastPrimCmd; +void DoState(PointerWrap &p) +{ + p.Do(minCommandSize); + // Not sure what is wrong with this. Something(s) in here is causing dolphin to crash/hang when loading states saved from another run of dolphin. Doesn't seem too important anyway... + //vertexLoader.DoState(p); + p.Do(readOpcode); + p.Do(inObjectStream); + p.Do(lastPrimCmd); + p.Do(streamSize); + p.Do(streamAddress); + if (p.GetMode() == PointerWrap::MODE_READ) + ResetDecoding(); +} + void DecodePrimitiveStream(u32 iBufferSize) { u32 vertexSize = vertexLoader.GetVertexSize(); @@ -125,7 +138,9 @@ void DecodeStandard(u32 bufferSize) if (Cmd == GX_NOP) return; - + // Causes a SIGBUS error on Android + // XXX: Investigate +#ifndef ANDROID // check if switching in or out of an object // only used for debuggging if (inObjectStream && (Cmd & 0x87) != lastPrimCmd) @@ -139,7 +154,7 @@ void DecodeStandard(u32 bufferSize) lastPrimCmd = Cmd & 0x87; DebugUtil::OnObjectBegin(); } - +#endif switch(Cmd) { case GX_NOP: diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/OpcodeDecoder.h b/Source/Plugins/Plugin_VideoSoftware/Src/OpcodeDecoder.h index 635fcc24ee..53715b2832 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/OpcodeDecoder.h +++ b/Source/Plugins/Plugin_VideoSoftware/Src/OpcodeDecoder.h @@ -20,6 +20,7 @@ #define _OPCODEDECODER_H_ #include "CommonTypes.h" +#include "ChunkFile.h" namespace OpcodeDecoder { @@ -57,6 +58,8 @@ namespace OpcodeDecoder bool CommandRunnable(u32 iBufferSize); void Run(u32 iBufferSize); + + void DoState(PointerWrap &p); } #endif diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/Rasterizer.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/Rasterizer.cpp index 225400e08b..badb123fa0 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/Rasterizer.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/Rasterizer.cpp @@ -23,6 +23,7 @@ #include "BPMemLoader.h" #include "XFMemLoader.h" #include "Tev.h" +#include "SWPixelEngine.h" #include "SWStatistics.h" #include "SWVideoConfig.h" @@ -62,6 +63,28 @@ s32 scissorBottom = 0; Tev tev; RasterBlock rasterBlock; +void DoState(PointerWrap &p) +{ + ZSlope.DoState(p); + WSlope.DoState(p); + for (int i=0;i<2;++i) + for (int n=0; n<4; ++n) + ColorSlopes[i][n].DoState(p); + for (int i=0;i<8;++i) + for (int n=0; n<3; ++n) + TexSlopes[i][n].DoState(p); + p.Do(vertex0X); + p.Do(vertex0Y); + p.Do(vertexOffsetX); + p.Do(vertexOffsetY); + p.Do(scissorLeft); + p.Do(scissorTop); + p.Do(scissorRight); + p.Do(scissorBottom); + tev.DoState(p); + p.Do(rasterBlock); +} + void Init() { tev.Init(); @@ -127,9 +150,15 @@ inline void Draw(s32 x, s32 y, s32 xi, s32 yi) if (bpmem.zcontrol.early_ztest && bpmem.zmode.testenable && g_SWVideoConfig.bZComploc) { - // early z - if (!EfbInterface::ZCompare(x, y, z)) - return; + // TODO: Test if perf regs are incremented even if test is disabled + SWPixelEngine::pereg.IncZInputQuadCount(true); + if (bpmem.zmode.testenable) + { + // early z + if (!EfbInterface::ZCompare(x, y, z)) + return; + } + SWPixelEngine::pereg.IncZOutputQuadCount(true); } RasterBlockPixel& pixel = rasterBlock.Pixel[xi][yi]; diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/Rasterizer.h b/Source/Plugins/Plugin_VideoSoftware/Src/Rasterizer.h index f8850571a9..784c4a8d62 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/Rasterizer.h +++ b/Source/Plugins/Plugin_VideoSoftware/Src/Rasterizer.h @@ -19,6 +19,7 @@ #define _RASTERIZER_H_ #include "NativeVertexFormat.h" +#include "ChunkFile.h" namespace Rasterizer { @@ -37,6 +38,12 @@ namespace Rasterizer float f0; float GetValue(float dx, float dy) { return f0 + (dfdx * dx) + (dfdy * dy); } + void DoState(PointerWrap &p) + { + p.Do(dfdx); + p.Do(dfdy); + p.Do(f0); + } }; struct RasterBlockPixel @@ -53,6 +60,8 @@ namespace Rasterizer s32 TextureLod[16]; bool TextureLinear[16]; }; + + void DoState(PointerWrap &p); } diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/SWCommandProcessor.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/SWCommandProcessor.cpp index b9afc1abb5..6cc4ee4dc8 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/SWCommandProcessor.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/SWCommandProcessor.cpp @@ -57,6 +57,15 @@ CPReg cpreg; // shared between gfx and emulator thread void DoState(PointerWrap &p) { p.Do(cpreg); + p.DoArray(commandBuffer, commandBufferSize); + p.Do(readPos); + p.Do(writePos); + p.Do(et_UpdateInterrupts); + p.Do(interruptSet); + p.Do(interruptWaiting); + + // Is this right? + p.DoArray(g_pVideoData,writePos); } // does it matter that there is no synchronization between threads during writes? @@ -115,15 +124,15 @@ void RunGpu() if (!SConfig::GetInstance().m_LocalCoreStartupParameter.bCPUThread) { // We are going to do FP math on the main thread so have to save the current state - SaveSSEState(); - LoadDefaultSSEState(); + FPURoundMode::SaveSIMDState(); + FPURoundMode::LoadDefaultSIMDState(); // run the opcode decoder do { RunBuffer(); } while (cpreg.ctrl.GPReadEnable && !AtBreakpoint() && cpreg.readptr != cpreg.writeptr); - LoadSSEState(); + FPURoundMode::LoadSIMDState(); } } diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.cpp index 33a6164b01..118e59629e 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.cpp @@ -53,6 +53,8 @@ void DoState(PointerWrap &p) p.Do(pereg); p.Do(g_bSignalTokenInterrupt); p.Do(g_bSignalFinishInterrupt); + p.Do(et_SetTokenOnMainThread); + p.Do(et_SetFinishOnMainThread); } void UpdateInterrupts(); @@ -77,7 +79,7 @@ void Read16(u16& _uReturnValue, const u32 _iAddress) u16 address = _iAddress & 0xFFF; - if (address <= 0x16) + if (address <= 0x2e) _uReturnValue = ((u16*)&pereg)[address >> 1]; } @@ -109,7 +111,7 @@ void Write16(const u16 _iValue, const u32 _iAddress) } break; default: - if (address <= 0x16) + if (address <= 0x2e) ((u16*)&pereg)[address >> 1] = _iValue; break; } diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.h b/Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.h index 6a87143e8c..351e53456d 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.h +++ b/Source/Plugins/Plugin_VideoSoftware/Src/SWPixelEngine.h @@ -38,6 +38,21 @@ namespace SWPixelEngine PE_BBOX_RIGHT = 0x012, // Flip Right PE_BBOX_TOP = 0x014, // Flip Top PE_BBOX_BOTTOM = 0x016, // Flip Bottom + + // NOTE: Order not verified + // These indicate the number of quads that are being used as input/output for each particular stage + PE_PERF_ZCOMP_INPUT_ZCOMPLOC_L = 0x18, + PE_PERF_ZCOMP_INPUT_ZCOMPLOC_H = 0x1a, + PE_PERF_ZCOMP_OUTPUT_ZCOMPLOC_L = 0x1c, + PE_PERF_ZCOMP_OUTPUT_ZCOMPLOC_H = 0x1e, + PE_PERF_ZCOMP_INPUT_L = 0x20, + PE_PERF_ZCOMP_INPUT_H = 0x22, + PE_PERF_ZCOMP_OUTPUT_L = 0x24, + PE_PERF_ZCOMP_OUTPUT_H = 0x26, + PE_PERF_BLEND_INPUT_L = 0x28, + PE_PERF_BLEND_INPUT_H = 0x2a, + PE_PERF_EFB_COPY_CLOCKS_L = 0x2c, + PE_PERF_EFB_COPY_CLOCKS_H = 0x2e, }; union UPEZConfReg @@ -125,10 +140,72 @@ namespace SWPixelEngine UPECtrlReg ctrl; u16 unk0; u16 token; + u16 boxLeft; u16 boxRight; u16 boxTop; u16 boxBottom; + + u16 perfZcompInputZcomplocLo; + u16 perfZcompInputZcomplocHi; + u16 perfZcompOutputZcomplocLo; + u16 perfZcompOutputZcomplocHi; + u16 perfZcompInputLo; + u16 perfZcompInputHi; + u16 perfZcompOutputLo; + u16 perfZcompOutputHi; + u16 perfBlendInputLo; + u16 perfBlendInputHi; + u16 perfEfbCopyClocksLo; + u16 perfEfbCopyClocksHi; + + // NOTE: hardware doesn't process individual pixels but quads instead. Current software renderer architecture works on pixels though, so we have this "quad" hack here to only increment the registers on every fourth rendered pixel + void IncZInputQuadCount(bool early_ztest) + { + static int quad = 0; + if (++quad != 3) + return; + quad = 0; + + if (early_ztest) + { + if (++perfZcompInputZcomplocLo == 0) + perfZcompInputZcomplocHi++; + } + else + { + if (++perfZcompInputLo == 0) + perfZcompInputHi++; + } + } + void IncZOutputQuadCount(bool early_ztest) + { + static int quad = 0; + if (++quad != 3) + return; + quad = 0; + + if (early_ztest) + { + if (++perfZcompOutputZcomplocLo == 0) + perfZcompOutputZcomplocHi++; + } + else + { + if (++perfZcompOutputLo == 0) + perfZcompOutputHi++; + } + } + void IncBlendInputQuadCount() + { + static int quad = 0; + if (++quad != 3) + return; + quad = 0; + + if (++perfBlendInputLo == 0) + perfBlendInputHi++; + } }; extern PEReg pereg; diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/SWVertexLoader.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/SWVertexLoader.cpp index cc5ee66772..1c1eeb2005 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/SWVertexLoader.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/SWVertexLoader.cpp @@ -328,4 +328,15 @@ void SWVertexLoader::LoadTexCoord(SWVertexLoader *vertexLoader, InputVertexData vertexLoader->m_texCoordLoader[index](); } - +void SWVertexLoader::DoState(PointerWrap &p) +{ + p.DoArray(m_AttributeLoaders, sizeof m_AttributeLoaders); + p.Do(m_VertexSize); + p.Do(*m_CurrentVat); + p.Do(m_positionLoader); + p.Do(m_normalLoader); + p.DoArray(m_colorLoader, sizeof m_colorLoader); + p.Do(m_NumAttributeLoaders); + m_SetupUnit->DoState(p); + p.Do(m_TexGenSpecialCase); +} \ No newline at end of file diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/SWVertexLoader.h b/Source/Plugins/Plugin_VideoSoftware/Src/SWVertexLoader.h index 91a0d8e911..e05346a7a5 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/SWVertexLoader.h +++ b/Source/Plugins/Plugin_VideoSoftware/Src/SWVertexLoader.h @@ -22,6 +22,7 @@ #include "NativeVertexFormat.h" #include "CPMemLoader.h" +#include "ChunkFile.h" class SetupUnit; @@ -69,7 +70,7 @@ public: u32 GetVertexSize() { return m_VertexSize; } void LoadVertex(); - + void DoState(PointerWrap &p); }; #endif diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/SWmain.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/SWmain.cpp index 5899d82c39..b524ded329 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/SWmain.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/SWmain.cpp @@ -39,6 +39,9 @@ #include "FileUtil.h" #include "VideoBackend.h" #include "Core.h" +#include "OpcodeDecoder.h" +#include "SWVertexLoader.h" +#include "SWStatistics.h" #define VSYNC_ENABLED 0 @@ -93,9 +96,33 @@ bool VideoSoftware::Initialize(void *&window_handle) return true; } -void VideoSoftware::DoState(PointerWrap&) +void VideoSoftware::DoState(PointerWrap& p) { - // NYI + bool software = true; + p.Do(software); + if (p.GetMode() == PointerWrap::MODE_READ && software == false) + // change mode to abort load of incompatible save state. + p.SetMode(PointerWrap::MODE_VERIFY); + + // TODO: incomplete? + SWCommandProcessor::DoState(p); + SWPixelEngine::DoState(p); + EfbInterface::DoState(p); + OpcodeDecoder::DoState(p); + Clipper::DoState(p); + p.Do(swxfregs); + p.Do(bpmem); + p.Do(swstats); + + // CP Memory + p.DoArray(arraybases, 16); + p.DoArray(arraystrides, 16); + p.Do(MatrixIndexA); + p.Do(MatrixIndexB); + p.Do(g_VtxDesc.Hex); + p.DoArray(g_VtxAttr, 8); + p.DoMarker("CP Memory"); + } void VideoSoftware::CheckInvalidState() @@ -206,6 +233,12 @@ u32 VideoSoftware::Video_AccessEFB(EFBAccessType type, u32 x, u32 y, u32 InputDa return value; } +u32 VideoSoftware::Video_GetQueryResult(PerfQueryType type) +{ + // TODO: + return 0; +} + bool VideoSoftware::Video_Screenshot(const char *_szFilename) { return false; diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/SetupUnit.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/SetupUnit.cpp index 6e0fab57d8..d2185e31d5 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/SetupUnit.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/SetupUnit.cpp @@ -25,13 +25,13 @@ void SetupUnit::Init(u8 primitiveType) { - m_PrimType = primitiveType; + m_PrimType = primitiveType; - m_VertexCounter = 0; - m_VertPointer[0] = &m_Vertices[0]; - m_VertPointer[1] = &m_Vertices[1]; - m_VertPointer[2] = &m_Vertices[2]; - m_VertWritePointer = m_VertPointer[0]; + m_VertexCounter = 0; + m_VertPointer[0] = &m_Vertices[0]; + m_VertPointer[1] = &m_Vertices[1]; + m_VertPointer[2] = &m_Vertices[2]; + m_VertWritePointer = m_VertPointer[0]; } void SetupUnit::SetupVertex() @@ -169,3 +169,21 @@ void SetupUnit::SetupLineStrip() void SetupUnit::SetupPoint() {} + +void SetupUnit::DoState(PointerWrap &p) +{ + // TODO: some or all of this is making the save states stop working once dolphin is closed...sometimes (usually) + // I have no idea what specifically is wrong, or if this is even important. Disabling it doesn't seem to make any noticible difference... +/* p.Do(m_PrimType); + p.Do(m_VertexCounter); + for (int i = 0; i < 3; ++i) + m_Vertices[i].DoState(p); + + if (p.GetMode() == PointerWrap::MODE_READ) + { + m_VertPointer[0] = &m_Vertices[0]; + m_VertPointer[1] = &m_Vertices[1]; + m_VertPointer[2] = &m_Vertices[2]; + m_VertWritePointer = m_VertPointer[0]; + }*/ +} diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/SetupUnit.h b/Source/Plugins/Plugin_VideoSoftware/Src/SetupUnit.h index 45a575afcb..f337de21a2 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/SetupUnit.h +++ b/Source/Plugins/Plugin_VideoSoftware/Src/SetupUnit.h @@ -21,6 +21,7 @@ #include "Common.h" #include "NativeVertexFormat.h" +#include "ChunkFile.h" class SetupUnit { @@ -45,6 +46,7 @@ public: OutputVertexData* GetVertex() { return m_VertWritePointer; } void SetupVertex(); + void DoState(PointerWrap &p); }; #endif diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/Tev.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/Tev.cpp index 927f8931e9..3d5c0d7724 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/Tev.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/Tev.cpp @@ -20,6 +20,7 @@ #include "Tev.h" #include "EfbInterface.h" #include "TextureSampler.h" +#include "SWPixelEngine.h" #include "SWStatistics.h" #include "SWVideoConfig.h" #include "DebugUtil.h" @@ -787,8 +788,13 @@ void Tev::Draw() bool late_ztest = !bpmem.zcontrol.early_ztest || !g_SWVideoConfig.bZComploc; if (late_ztest && bpmem.zmode.testenable) { - if (!EfbInterface::ZCompare(Position[0], Position[1], Position[2])) - return; + // TODO: Check against hw if these values get incremented even if depth testing is disabled + SWPixelEngine::pereg.IncZInputQuadCount(false); + + if (!EfbInterface::ZCompare(Position[0], Position[1], Position[2])) + return; + + SWPixelEngine::pereg.IncZOutputQuadCount(false); } #if ALLOW_TEV_DUMPS @@ -812,6 +818,7 @@ void Tev::Draw() #endif INCSTAT(swstats.thisFrame.tevPixelsOut); + SWPixelEngine::pereg.IncBlendInputQuadCount(); EfbInterface::BlendTev(Position[0], Position[1], output); } @@ -827,3 +834,31 @@ void Tev::SetRegColor(int reg, int comp, bool konst, s16 color) Reg[reg][comp] = color; } } + +void Tev::DoState(PointerWrap &p) +{ + p.DoArray(Reg, sizeof(Reg)); + + p.DoArray(KonstantColors, sizeof(KonstantColors)); + p.DoArray(TexColor,4); + p.DoArray(RasColor,4); + p.DoArray(StageKonst,4); + p.DoArray(Zero16,4); + + p.DoArray(FixedConstants,9); + p.Do(AlphaBump); + p.DoArray(IndirectTex, sizeof(IndirectTex)); + p.Do(TexCoord); + + p.DoArray(m_BiasLUT,4); + p.DoArray(m_ScaleLShiftLUT,4); + p.DoArray(m_ScaleRShiftLUT,4); + + p.DoArray(Position,3); + p.DoArray(Color, sizeof(Color)); + p.DoArray(Uv, 8); + p.DoArray(IndirectLod,4); + p.DoArray(IndirectLinear,4); + p.DoArray(TextureLod,16); + p.DoArray(TextureLinear,16); +} diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/Tev.h b/Source/Plugins/Plugin_VideoSoftware/Src/Tev.h index bdd265170c..1d1bc8d2ba 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/Tev.h +++ b/Source/Plugins/Plugin_VideoSoftware/Src/Tev.h @@ -19,6 +19,7 @@ #define _TEV_H_ #include "BPMemLoader.h" +#include "ChunkFile.h" class Tev { @@ -96,6 +97,8 @@ public: void SetRegColor(int reg, int comp, bool konst, s16 color); enum { ALP_C, BLU_C, GRN_C, RED_C }; + + void DoState(PointerWrap &p); }; #endif diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/Vec3.h b/Source/Plugins/Plugin_VideoSoftware/Src/Vec3.h index 3a36a13307..80460edd60 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/Vec3.h +++ b/Source/Plugins/Plugin_VideoSoftware/Src/Vec3.h @@ -20,6 +20,7 @@ #include #include +#include "ChunkFile.h" class Vec3 { @@ -111,6 +112,12 @@ public: { memset((void *)this,0,sizeof(float)*3); } + void DoState(PointerWrap &p) + { + p.Do(x); + p.Do(y); + p.Do(z); + } }; #endif diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/VideoBackend.h b/Source/Plugins/Plugin_VideoSoftware/Src/VideoBackend.h index a0826862ce..37fe817f07 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/VideoBackend.h +++ b/Source/Plugins/Plugin_VideoSoftware/Src/VideoBackend.h @@ -27,7 +27,9 @@ class VideoSoftware : public VideoBackend void Video_ExitLoop(); void Video_BeginField(u32, FieldType, u32, u32); void Video_EndField(); + u32 Video_AccessEFB(EFBAccessType, u32, u32, u32); + u32 Video_GetQueryResult(PerfQueryType type); void Video_AddMessage(const char* pstr, unsigned int milliseconds); void Video_ClearMessages(); diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/VideoConfigDialog.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/VideoConfigDialog.cpp index bd085a3edf..e7122d2f71 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/VideoConfigDialog.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/VideoConfigDialog.cpp @@ -34,7 +34,7 @@ IntegerSetting::IntegerSetting(wxWindow* parent, const wxString& label, T& se VideoConfigDialog::VideoConfigDialog(wxWindow* parent, const std::string& title, const std::string& _ininame) : wxDialog(parent, -1, - wxString(wxT("Dolphin ")).append(wxString::FromAscii(title.c_str())).append(wxT(" Graphics Configuration")), + wxString(wxT("Dolphin ")).append(StrToWxStr(title)).append(wxT(" Graphics Configuration")), wxDefaultPosition, wxDefaultSize), vconfig(g_SWVideoConfig), ininame(_ininame) @@ -64,10 +64,10 @@ VideoConfigDialog::VideoConfigDialog(wxWindow* parent, const std::string& title, it = g_available_video_backends.begin(), itend = g_available_video_backends.end(); for (; it != itend; ++it) - choice_backend->AppendString(wxString::FromAscii((*it)->GetName().c_str())); + choice_backend->AppendString(StrToWxStr((*it)->GetName())); // TODO: How to get the translated plugin name? - choice_backend->SetStringSelection(wxString::FromAscii(g_video_backend->GetName().c_str())); + choice_backend->SetStringSelection(StrToWxStr(g_video_backend->GetName())); choice_backend->Bind(wxEVT_COMMAND_CHOICE_SELECTED, &VideoConfigDialog::Event_Backend, this); szr_rendering->Add(label_backend, 1, wxALIGN_CENTER_VERTICAL, 5);